[
  {
    "path": ".dockerignore",
    "content": "**/node_modules\n**/.idea\n**/target"
  },
  {
    "path": ".drone.yml",
    "content": "---\nkind: pipeline\ntype: kubernetes\nname: docker\nconcurrency:\n  limit: 1\ntrigger:\n  branch:\n    - main\n  event:\n    - push\nmetadata:\n  namespace: git\nsteps:\n  - name: Fetch tags\n    image: alpine/git\n    commands:\n      - git fetch --tags\n  - name: Build site\n    image: node:current\n    volumes:\n      - name: cache\n        path: /cache\n    environment:\n      NODE_CONFIG_ENV: default\n    commands:\n      - apt update && apt install -y git curl unzip\n      - curl -fsSL https://bun.sh/install | bash\n      - export PATH=\"$HOME/.bun/bin:$PATH\"\n      - bun install\n      - bun run build\n  - name: build docker image\n    image: docker\n    privileged: true\n    volumes:\n      - name: cache\n        path: /cache\n    environment:\n      TOKEN:\n        from_secret: docker_hub\n    commands:\n      - dockerd &\n      - docker login -u voidic -p $TOKEN\n      - docker buildx create --platform linux/amd64,linux/arm64 --bootstrap --use\n      - docker buildx build -t voidic/snort:latest --platform linux/amd64,linux/arm64 --push -f Dockerfile.prebuilt .\n      - kill $(cat /var/run/docker.pid)\nvolumes:\n  - name: cache\n    claim:\n      name: docker-cache\n---\nkind: pipeline\ntype: kubernetes\nname: test-lint\nconcurrency:\n  limit: 1\nmetadata:\n  namespace: git\nsteps:\n  - name: Test/Lint\n    image: node:current\n    volumes:\n      - name: cache\n        path: /cache\n    environment:\n      NODE_CONFIG_ENV: default\n    commands:\n      - curl -fsSL https://bun.sh/install | bash\n      - export PATH=\"$HOME/.bun/bin:$PATH\"\n      - bun install\n      - bun run build\n      - bun test\n      - bunx --bun biome lint\nvolumes:\n  - name: cache\n    claim:\n      name: docker-cache\n---\nkind: pipeline\ntype: kubernetes\nname: crowdin\nconcurrency:\n  limit: 1\ntrigger:\n  branch:\n    - main\n  event:\n    - push\nmetadata:\n  namespace: git\nsteps:\n  - name: Push/Pull translations\n    image: node:current\n    volumes:\n      - name: cache\n        path: /cache\n    environment:\n      NODE_CONFIG_ENV: default\n      TOKEN:\n        from_secret: gitea\n      CTOKEN:\n        from_secret: crowdin\n    commands:\n      - git config --global user.email drone@v0l.io\n      - git config --global user.name \"Drone CI\"\n      - git remote set-url origin https://drone:$TOKEN@git.v0l.io/Kieran/snort.git\n      - curl -fsSL https://bun.sh/install | bash\n      - export PATH=\"$HOME/.bun/bin:$PATH\"\n      - bun install\n      - bunx @crowdin/cli upload sources -b main -T $CTOKEN\n      - bunx @crowdin/cli pull -b main -T $CTOKEN\n      - bunx --bun biome lint --write\n      - git add .\n      - >\n        if output=$(git status --porcelain) && [ -n \"$output\" ]; then\n          git commit -a -m \"chore: Update translations\"\n          git push -u origin main\n        fi\nvolumes:\n  - name: cache\n    claim:\n      name: docker-cache\n---\nkind: pipeline\ntype: kubernetes\nname: docker-release\nconcurrency:\n  limit: 1\ntrigger:\n  event:\n    - tag\nmetadata:\n  namespace: git\nsteps:\n  - name: Fetch tags\n    image: alpine/git\n    commands:\n      - git fetch --tags\n  - name: Build site\n    image: node:current\n    volumes:\n      - name: cache\n        path: /cache\n    environment:\n      NODE_CONFIG_ENV: default\n    commands:\n      - apt update && apt install -y git curl unzip\n      - curl -fsSL https://bun.sh/install | bash\n      - export PATH=\"$HOME/.bun/bin:$PATH\"\n      - bun install\n      - bun run build\n  - name: build docker image\n    image: docker\n    privileged: true\n    volumes:\n      - name: cache\n        path: /cache\n    environment:\n      TOKEN:\n        from_secret: docker_hub\n    commands:\n      - dockerd &\n      - docker login -u voidic -p $TOKEN\n      - docker buildx create --platform linux/amd64,linux/arm64 --bootstrap --use\n      - docker buildx build -t voidic/snort:$DRONE_TAG --platform linux/amd64,linux/arm64 --push -f Dockerfile.prebuilt .\n      - kill $(cat /var/run/docker.pid)\nvolumes:\n  - name: cache\n    claim:\n      name: docker-cache\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: \"\"\nlabels: \"\"\nassignees: \"\"\n---\n\n**Describe the bug**\n\nA clear and concise description of what the bug is.\n\n**To Reproduce**\n\nSteps to reproduce the behavior:\n\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\n\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\n\nIf applicable, add screenshots to help explain your problem.\n\n**Desktop (please complete the following information):**\n\n- OS: [e.g. iOS]\n- Browser: [e.g. chrome, safari]\n- Version: [e.g. 22]\n\n**Smartphone (please complete the following information):**\n\n- Device: [e.g. iPhone6]\n- OS: [e.g. iOS8.1]\n- Browser: [e.g. stock browser, safari]\n- Version: [e.g. 22]\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: \"\"\nlabels: \"\"\nassignees: \"\"\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/workflows/docker.yml",
    "content": "name: Docker\n\non:\n  push:\n    branches:\n      - main\n    tags:\n      - v[0-9]+.[0-9]+.[0-9]+\n      - v[0-9]+.[0-9]+.[0-9]+-*\n\njobs:\n  docker-latest:\n    runs-on: ubuntu-latest\n    if: github.ref == 'refs/heads/main'\n    permissions:\n      contents: read\n      packages: write\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Setup Bun\n        uses: oven-sh/setup-bun@v2\n\n      - name: Install dependencies\n        run: bun install\n\n      - name: Build site\n        run: bun run build\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@v3\n        with:\n          username: voidic\n          password: ${{ secrets.DOCKER_HUB_TOKEN }}\n\n      - name: Build and push Docker image\n        uses: docker/build-push-action@v6\n        with:\n          context: .\n          file: Dockerfile.prebuilt\n          platforms: linux/amd64,linux/arm64\n          push: true\n          tags: voidic/snort:latest\n\n  docker-release:\n    runs-on: ubuntu-latest\n    if: startsWith(github.ref, 'refs/tags/')\n    permissions:\n      contents: read\n      packages: write\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Setup Bun\n        uses: oven-sh/setup-bun@v2\n\n      - name: Install dependencies\n        run: bun install\n\n      - name: Build site\n        run: bun run build\n\n      - name: Set up Docker Buildx\n        uses: docker/setup-buildx-action@v3\n\n      - name: Login to Docker Hub\n        uses: docker/login-action@v3\n        with:\n          username: voidic\n          password: ${{ secrets.DOCKER_HUB_TOKEN }}\n\n      - name: Build and push Docker image\n        uses: docker/build-push-action@v6\n        with:\n          context: .\n          file: Dockerfile.prebuilt\n          platforms: linux/amd64,linux/arm64\n          push: true\n          tags: voidic/snort:${{ github.ref_name }}\n"
  },
  {
    "path": ".github/workflows/nsite.yml",
    "content": "name: Deploy nsite\non:\n  workflow_dispatch: # temporarily disabled - nsite-cli upload hangs indefinitely\n  # push:\n  #   branches:\n  #     - main\n\njobs:\n  deploy:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout Repo\n        uses: actions/checkout@v4\n\n      - name: Setup Bun\n        uses: oven-sh/setup-bun@v2\n\n      - name: Install Dependencies\n        run: bun install\n\n      - name: Build\n        run: bun run build\n\n      - name: Redirect 404 to Index for SPA\n        run: cp packages/app/build/index.html packages/app/build/404.html\n\n      - name: Deploy nsite\n        run: bunx nsite-cli upload packages/app/build --verbose --purge --privatekey ${{ secrets.NSITE_KEY }} --servers 'https://nostr.download,https://blossom.band'"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\non:\n  push:\n    tags:\n      - v[0-9]+.[0-9]+.[0-9]+\n      - v[0-9]+.[0-9]+.[0-9]+-*\nenv:\n  DOCKER_CLI_EXPERIMENTAL: enabled\n  TAG_FMT: \"^refs/tags/(((.?[0-9]+){3,4}))$\"\njobs:\n  app:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: write\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v4\n\n      - name: Set up JDK 21\n        uses: actions/setup-java@v4\n        with:\n          distribution: temurin\n          java-version: 21\n\n      - name: Setup Bun\n        uses: oven-sh/setup-bun@v2\n\n      - name: Install frontend dependencies\n        run: bun install\n\n      - name: Build Site\n        run: bun run build\n\n      - name: Copy files\n        run: |-\n          git clone --depth 1 --branch ${{ github.ref_name }} https://github.com/v0l/snort_android.git\n          mkdir -p snort_android/app/src/main/assets/\n          cp -r packages/app/build/* snort_android/app/src/main/assets/\n\n      - name: Build AAB\n        working-directory: snort_android\n        run: ./gradlew clean bundleRelease --stacktrace\n      - name: Build APK\n        working-directory: snort_android\n        run: ./gradlew assembleRelease --stacktrace\n\n      - name: Sign AAB\n        uses: r0adkll/sign-android-release@v1\n        with:\n          releaseDirectory: snort_android/app/build/outputs/bundle/release\n          signingKeyBase64: ${{ secrets.SIGNING_KEY }}\n          alias: ${{ secrets.KEY_ALIAS }}\n          keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}\n          keyPassword: ${{ secrets.KEY_PASSWORD }}\n        env:\n          BUILD_TOOLS_VERSION: \"35.0.0\"\n      - name: Sign APK\n        uses: r0adkll/sign-android-release@v1\n        with:\n          releaseDirectory: snort_android/app/build/outputs/apk/release\n          signingKeyBase64: ${{ secrets.SIGNING_KEY }}\n          alias: ${{ secrets.KEY_ALIAS }}\n          keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}\n          keyPassword: ${{ secrets.KEY_PASSWORD }}\n        env:\n          BUILD_TOOLS_VERSION: \"35.0.0\"\n      - name: Rename files\n        run: |-\n          mkdir -p snort_android/app/release\n          mv snort_android/app/build/outputs/bundle/release/app-release.aab snort_android/app/release/snort-${{ github.ref_name }}.aab\n          mv snort_android/app/build/outputs/apk/release/app-universal-release-unsigned-signed.apk snort_android/app/release/snort-universal-${{ github.ref_name }}.apk\n          mv snort_android/app/build/outputs/apk/release/app-arm64-v8a-release-unsigned-signed.apk snort_android/app/release/snort-arm64-v8a-${{ github.ref_name }}.apk\n          mv snort_android/app/build/outputs/apk/release/app-x86_64-release-unsigned-signed.apk snort_android/app/release/snort-x86_64-${{ github.ref_name }}.apk\n          mv snort_android/app/build/outputs/apk/release/app-armeabi-v7a-release-unsigned-signed.apk snort_android/app/release/snort-armeabi-v7a-${{ github.ref_name }}.apk\n      - name: Upload assets\n        uses: softprops/action-gh-release@v1\n        with:\n          files: |\n            snort_android/app/release/snort-${{ github.ref_name }}.aab\n            snort_android/app/release/snort-universal-${{ github.ref_name }}.apk\n            snort_android/app/release/snort-arm64-v8a-${{ github.ref_name }}.apk\n            snort_android/app/release/snort-x86_64-${{ github.ref_name }}.apk\n            snort_android/app/release/snort-armeabi-v7a-${{ github.ref_name }}.apk"
  },
  {
    "path": ".gitignore",
    "content": "node_modules/\n.idea\n.pnp.*\ndist/\n*.tgz\n*.log\n.DS_Store\n.pnp*\ndocs/\n.wrangler/"
  },
  {
    "path": ".vscode/extensions.json",
    "content": "{\n  \"recommendations\": [\n    \"arcanis.vscode-zipfs\",\n    \"biomejs.biome\"\n  ]\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n  \"files.exclude\": {\n    \"**/.git\": true,\n    \"**/.svn\": true,\n    \"**/.hg\": true,\n    \"**/CVS\": true,\n    \"**/.DS_Store\": true,\n    \"**/Thumbs.db\": true,\n    \"**/node_modules\": true\n  },\n  \"search.exclude\": {},\n  \"typescript.tsdk\": \"node_modules/typescript/lib\",\n  \"typescript.enablePromptUseWorkspaceTsdk\": true\n}\n"
  },
  {
    "path": "AGENTS.md",
    "content": "# AGENTS.md - Snort Codebase Guidelines\n\nThis document provides guidelines for AI coding agents working in the Snort codebase.\n\n## Project Overview\n\nSnort is a **Nostr UI client** built with:\n- **Language**: TypeScript (strict mode)\n- **Framework**: React 19 (main app)\n- **Build Tool**: Vite\n- **Package Manager**: Bun (required - do not use npm/yarn/pnpm)\n- **Monorepo**: Bun workspaces\n\n### Package Structure\n```\npackages/\n  app/           # Main React web application (@snort/app)\n  system/        # Core Nostr system library (@snort/system)\n  shared/        # Shared utilities (@snort/shared)\n  wallet/        # Wallet integration (@snort/wallet)\n  worker-relay/  # Service worker relay (@snort/worker-relay)\n  system-react/  # React hooks for system (@snort/system-react)\n```\n\n## Build Commands\n\n```bash\n# Install dependencies\nbun install\n\n# Build all packages (order matters - shared -> system -> wallet -> worker-relay -> app)\nbun run build\n\n# Start dev server\nbun run start\n\n# Build specific package\nbun --cwd=packages/app run build\nbun --cwd=packages/system run build\n```\n\n## Testing\n\n**Framework**: Bun's built-in test runner (`bun:test`)\n\n```bash\n# Run all tests\nbun test\n\n# Run tests in a specific package\ncd packages/system && bun test\n\n# Run a single test file\nbun test packages/system/tests/nip10.test.ts\n\n# Run tests matching a pattern\nbun test --test-name-pattern=\"parseThread\"\n\n# Run test files matching a name\nbun test nip10\n```\n\n**Test file locations**:\n- `packages/system/tests/*.test.ts` (most tests)\n- `packages/app/tests/*.test.ts`\n- `packages/shared/src/**/*.test.ts`\n\n## Linting & Formatting\n\n**Tool**: Biome (not ESLint/Prettier)\n\n```bash\n# Lint and fix\nbunx --bun biome lint --write\n\n# Pre-commit (extract translations + lint)\nbun run pre:commit\n```\n\n## Code Style Guidelines\n\n### Formatting (Biome)\n- **Indentation**: 2 spaces\n- **Line width**: 120 characters\n- **Semicolons**: as needed (omit when optional)\n- **Quotes**: single quotes for JS/TS, double quotes for JSX attributes\n- **Trailing commas**: all\n- **Arrow parentheses**: as needed\n- **Line endings**: LF\n\n### TypeScript\n- **Strict mode** is enabled\n- **Target**: ESNext\n- **Module resolution**: Bundler\n- Use `type` imports for types: `import type { Foo } from './bar'`\n- Path alias in app: `@/*` maps to `./src/*`\n\n### Imports\n- Biome auto-organizes imports\n- Group order: external packages, then internal modules\n- Use workspace packages: `@snort/shared`, `@snort/system`, etc.\n\n### Naming Conventions\n- **Files**: PascalCase for React components (`Note.tsx`, `EventBuilder.ts`)\n- **Files**: kebab-case or camelCase for utilities (`event-builder.ts`, `nostr-link.ts`)\n- **Components**: PascalCase (`function Note()`, `function EventComponent()`)\n- **Hooks**: camelCase with `use` prefix (`useLogin`, `useModeration`)\n- **Types/Interfaces**: PascalCase (`TaggedNostrEvent`, `NoteProps`)\n- **Constants**: UPPER_SNAKE_CASE or PascalCase\n- **Private class fields**: Use `#` prefix (`#kind`, `#content`)\n\n### React Patterns\n- Functional components only\n- Use hooks for state management\n- Custom hooks in `src/Hooks/` directory\n- Components in `src/Components/` with subdirectories by feature\n- Pages in `src/Pages/`\n\n### Error Handling\n- Use try/catch for async operations\n- Prefer optional chaining (`?.`) and nullish coalescing (`??`)\n- Return `undefined` for not-found cases rather than throwing\n\n### Nostr-Specific Patterns\n- Event kinds defined in `packages/system/src/event-kind.ts`\n- NIP implementations in `packages/system/src/impl/nip*.ts`\n- Use `EventBuilder` class for constructing events\n- Use `NostrLink` for referencing events/profiles\n- Tags are arrays: `[\"e\", \"eventId\", \"relay\", \"marker\"]`\n\n## Project-Specific Notes\n\n### Bun Requirements\n- Always use `bun` instead of `node`, `npm`, `yarn`, or `pnpm`\n- Use `bun <file>` instead of `node <file>` or `ts-node <file>`\n- Use `bun test` instead of `jest` or `vitest`\n- Use `bun install` instead of `npm install`\n- Use `bun run <script>` instead of `npm run <script>`\n- Bun automatically loads `.env` files - do not use dotenv\n\n### Internationalization\n- Uses react-intl for i18n\n- Translations in `packages/app/src/translations/`\n- Extract strings: `bun --cwd=packages/app run intl-extract`\n- Compile translations: `bun --cwd=packages/app run intl-compile`\n\n### Desktop App\n- Tauri support in `src-tauri/` (Rust backend)\n\n### Common Imports\n```typescript\n// From system package\nimport { EventKind, NostrLink, type TaggedNostrEvent } from \"@snort/system\"\n\n// From shared package\nimport { NostrPrefix, unixNow, getPublicKey } from \"@snort/shared\"\n\n// App internal imports (using path alias)\nimport { Relay } from \"@/Cache\"\nimport useModeration from \"@/Hooks/useModeration\"\n```\n\n### Test Patterns\n```typescript\nimport { describe, expect, test } from \"bun:test\"\n\ndescribe(\"FeatureName\", () => {\n  test(\"should do something\", () => {\n    expect(result).toBe(expected)\n  })\n})\n```\n\n## Quick Reference\n\n| Task | Command |\n|------|---------|\n| Install deps | `bun install` |\n| Build all | `bun run build` |\n| Dev server | `bun run start` |\n| Run all tests | `bun test` |\n| Run single test | `bun test path/to/file.test.ts` |\n| Lint & fix | `bunx --bun biome lint --write` |\n| Pre-commit | `bun run pre:commit` |\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM oven/bun:latest AS build\nWORKDIR /src\nRUN apt update \\\n    && apt install -y --no-install-recommends git ca-certificates \\\n    && git clone --single-branch -b main https://github.com/v0l/snort \\\n    && cd snort \\\n    && bun install \\\n    && bun run build\n\nFROM nginxinc/nginx-unprivileged:mainline-alpine\nCOPY docker/nginx.conf /etc/nginx/conf.d/default.conf\nCOPY --from=build /src/snort/packages/app/build /usr/share/nginx/html\n"
  },
  {
    "path": "Dockerfile.prebuilt",
    "content": "FROM nginxinc/nginx-unprivileged:mainline-alpine\nCOPY packages/app/build /usr/share/nginx/html\nCOPY docker/nginx.conf /etc/nginx/conf.d/default.conf"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2023 Kieran (v0l)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "## Snort\n\nSnort is a nostr UI built with React aiming for speed and efficiency.\n\nSnort supports the following NIP's:\n\n- [x] NIP-01: Basic protocol flow description\n- [x] NIP-02: Contact List and Petnames (No petname support)\n- [ ] NIP-03: OpenTimestamps Attestations for Events\n- [x] NIP-04: Encrypted Direct Message\n- [x] NIP-05: Mapping Nostr keys to DNS-based internet identifiers\n- [x] NIP-06: Basic key derivation from mnemonic seed phrase\n- [x] NIP-07: `window.nostr` capability for web browsers\n- [x] NIP-08: Handling Mentions\n- [x] NIP-09: Event Deletion\n- [x] NIP-10: Conventions for clients' use of `e` and `p` tags in text events\n- [x] NIP-11: Relay Information Document\n- [x] NIP-13: Proof of Work\n- [ ] NIP-14: Subject tag in text events\n- [x] NIP-18: Reposts\n- [x] NIP-19: bech32-encoded entities\n- [x] NIP-21: `nostr:` Protocol handler (`web+nostr`)\n- [x] NIP-23: Long form content\n- [x] NIP-25: Reactions\n- [x] NIP-26: Delegated Event Signing (Display delegated signings only)\n- [x] NIP-27: Text note references\n- [x] NIP-28: Public Chat\n- [x] NIP-30: Custom Emoji\n- [x] NIP-31: Alt tag for unknown events\n- [x] NIP-36: Sensitive Content\n- [x] NIP-38: User Statuses\n- [ ] NIP-39: External Identities\n- [ ] NIP-40: Expiration Timestamp\n- [x] NIP-42: Authentication of clients to relays\n- [x] NIP-44: Versioned encryption\n- [x] NIP-46: Nostr connect (+bunker)\n- [x] NIP-47: Nostr wallet connect\n- [x] NIP-50: Search\n- [x] NIP-51: Lists\n- [x] NIP-53: Live Events\n- [x] NIP-55: Android signer application\n- [x] NIP-57: Zaps\n- [x] NIP-58: Badges\n- [x] NIP-59: Gift Wrap\n- [x] NIP-65: Relay List Metadata\n- [x] NIP-75: Zap Goals\n- [x] NIP-78: App specific data\n- [x] NIP-89: App handlers\n- [x] NIP-90: Data Vending Machines\n- [x] NIP-94: File Metadata\n- [x] NIP-96: HTTP File Storage Integration (Draft)\n- [x] NIP-98: HTTP Auth\n\n### Translations\n\n[![Crowdin](https://badges.crowdin.net/snort/localized.svg)](https://crowdin.com/project/snort)\n\nTranslations are managed on [Crowdin](https://crowdin.com/project/snort)\n\nTo extract translations run:\n\n```bash\nbun run pre:commit\n```\n\nThis will create the source file `packages/app/src/translations/en.json`\n"
  },
  {
    "path": "biome.json",
    "content": "{\n  \"$schema\": \"https://biomejs.dev/schemas/2.3.9/schema.json\",\n  \"vcs\": {\n    \"enabled\": true,\n    \"clientKind\": \"git\",\n    \"useIgnoreFile\": true\n  },\n  \"files\": {\n    \"ignoreUnknown\": false\n  },\n  \"formatter\": {\n    \"enabled\": true,\n    \"formatWithErrors\": false,\n    \"indentStyle\": \"space\",\n    \"indentWidth\": 2,\n    \"lineEnding\": \"lf\",\n    \"lineWidth\": 120,\n    \"attributePosition\": \"auto\",\n    \"bracketSameLine\": false,\n    \"bracketSpacing\": true,\n    \"expand\": \"auto\",\n    \"useEditorconfig\": true,\n    \"includes\": [\n      \"**\",\n      \"!**/.yarn/\",\n      \"!**/build/\",\n      \"!**/.vscode/\",\n      \"!**/.github/\",\n      \"!**/transifex.yml\",\n      \"!**/dist/\",\n      \"!**/src-tauri/\",\n      \"!**/target/\"\n    ]\n  },\n  \"linter\": {\n    \"enabled\": true,\n    \"rules\": {\n      \"recommended\": true,\n      \"correctness\": {\n        \"useExhaustiveDependencies\": \"off\"\n      }\n    }\n  },\n  \"javascript\": {\n    \"formatter\": {\n      \"jsxQuoteStyle\": \"double\",\n      \"quoteProperties\": \"asNeeded\",\n      \"trailingCommas\": \"all\",\n      \"semicolons\": \"asNeeded\",\n      \"arrowParentheses\": \"asNeeded\",\n      \"bracketSameLine\": false,\n      \"quoteStyle\": \"double\",\n      \"attributePosition\": \"auto\",\n      \"bracketSpacing\": true\n    }\n  },\n  \"html\": {\n    \"formatter\": {\n      \"indentScriptAndStyle\": false,\n      \"selfCloseVoidElements\": \"always\"\n    }\n  },\n  \"assist\": {\n    \"enabled\": true,\n    \"actions\": {\n      \"source\": {\n        \"organizeImports\": \"on\"\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "crowdin.yml",
    "content": "project_id: 568149\npreserve_hierarchy: true\nfiles:\n  - source: packages/app/src/translations/en.json\n    translation: packages/app/src/translations/%locale_with_underscore%.json\n"
  },
  {
    "path": "docker/nginx.conf",
    "content": "server {\n    listen 8080 default_server;\n    server_name _;\n    root /usr/share/nginx/html;\n    index index.html;\n    add_header Content-Security-Policy \"default-src 'self'; manifest-src *; child-src 'none'; worker-src 'self'; frame-src youtube.com www.youtube.com https://platform.twitter.com https://embed.tidal.com https://w.soundcloud.com https://www.mixcloud.com https://open.spotify.com https://player.twitch.tv https://embed.music.apple.com https://embed.wavlake.com https://challenges.cloudflare.com; style-src 'self' 'unsafe-inline'; connect-src *; img-src * data: blob:; font-src 'self'; media-src * blob:; script-src 'self' 'wasm-unsafe-eval' https://platform.twitter.com https://embed.tidal.com https://challenges.cloudflare.com\";\n    add_header Cross-Origin-Opener-Policy same-origin;\n\n    location / {\n        try_files $uri $uri/ /index.html =404;\n    }\n}"
  },
  {
    "path": "functions/_middleware.ts",
    "content": "type Env = {}\n\nconst HOST = \"snort.social\";\n\nexport const onRequest: PagesFunction<Env> = async context => {\n  const u = new URL(context.request.url);\n\n  const prefixes = [\"npub1\", \"nprofile1\", \"naddr1\", \"nevent1\", \"note1\"];\n  const isEntityPath = prefixes.some(\n    a => u.pathname.startsWith(`/${a}`) || u.pathname.startsWith(`/e/${a}`) || u.pathname.startsWith(`/p/${a}`),\n  );\n  const nostrAddress = u.pathname.match(/^\\/([a-zA-Z0-9_]+)$/i);\n  const next = await context.next();\n  if (u.pathname != \"/\" && (isEntityPath || nostrAddress)) {\n    //console.log(\"Handeling path: \", u.pathname, isEntityPath, nostrAddress[1]);\n    try {\n      let id = u.pathname.split(\"/\").at(-1);\n      if (!isEntityPath && nostrAddress) {\n        id = `${id}@${HOST}`;\n      }\n      const fetchApi = `https://nostr-rs-api.v0l.io/opengraph/${id}?canonical=${encodeURIComponent(\n        `https://${HOST}/%s`,\n      )}`;\n      console.log(\"Fetching tags from: \", fetchApi);\n      const rsp = await fetch(fetchApi, {\n        method: \"POST\",\n        body: await next.arrayBuffer(),\n        headers: {\n          \"user-agent\": `SnortFunctions/1.0 (https://${HOST})`,\n          \"content-type\": \"text/html\",\n          accept: \"text/html\",\n        },\n      });\n      if (rsp.ok) {\n        const body = await rsp.text();\n        if (body.length > 0) {\n          return new Response(body, {\n            headers: {\n              ...Object.fromEntries(rsp.headers.entries()),\n              \"cache-control\": \"no-cache\",\n            },\n          });\n        }\n      }\n    } catch (e) {\n      console.error(e);\n    }\n  }\n  return next;\n};\n"
  },
  {
    "path": "functions/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"lib\": [\"esnext\"],\n    \"types\": [\"@cloudflare/workers-types\"]\n  }\n}\n"
  },
  {
    "path": "maintainers.yaml",
    "content": "maintainers:\n  - npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n  - npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\nrelays:\n  - wss://relay.snort.social/\n  - wss://pyramid.fiatjaf.com/\n  - wss://nos.lol/\n  - ws://skzzn6cimfdv5e2phjc4yr5v7ikbxtn5f7dkwn5c7v47tduzlbosqmqd.onion/\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"private\": true,\n  \"workspaces\": [\n    \"packages/*\"\n  ],\n  \"scripts\": {\n    \"start\": \"bun run build && bun --cwd=packages/app run start\",\n    \"build\": \"bun --cwd=packages/shared run build && bun --cwd=packages/system run build && bun --cwd=packages/wallet run build && bun --cwd=packages/worker-relay run build && bun --cwd=packages/app run build\",\n    \"push-prod\": \"git switch snort-prod && git merge --ff-only main && git push && git checkout main\",\n    \"docs\": \"typedoc --entryPointStrategy packages ./packages/* --exclude ./packages/app --exclude ./packages/webrtc-server --name snort.social\",\n    \"pre:commit\": \"bun --cwd=packages/app run intl-extract && bun --cwd=packages/app run intl-compile && bunx --bun biome lint --write\"\n  },\n  \"dependencies\": {\n    \"@cloudflare/workers-types\": \"^4.20251011.0\",\n    \"jiti\": \"^2.6.1\",\n    \"typescript\": \"^5.9.3\"\n  },\n  \"devDependencies\": {\n    \"@biomejs/biome\": \"2.3.9\",\n    \"@noble/curves\": \"^2.0.1\",\n    \"@tauri-apps/cli\": \"^2.8.4\",\n    \"bun\": \"^1.3.1\",\n    \"typedoc\": \"^0.28.14\"\n  }\n}\n"
  },
  {
    "path": "packages/app/.gitignore",
    "content": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pnp\n.pnp.js\n\n# testing\n/coverage\n\n# production\n/build\n\n# misc\n.DS_Store\n.env.local\n.env.development.local\n.env.test.local\n.env.production.local\n\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n.idea\n\ndist/\ndev-dist/\n.wrangler/"
  },
  {
    "path": "packages/app/CHANGELOG.md",
    "content": "# v0.5.0\n\n`+196,739,-43,235`\n\n## Highlights\n\n- **Security Hardening**: Comprehensive audit fixes including Schnorr signature verification, NIP-46 relay message forgery protection, PIN encryption improvements, and NIP-26 delegation trust removal\n- **Performance**: Batched Schnorr verification in WASM, lazy-loaded routes, pre-compiled translations, worker-relay batch optimizations, and eliminated double verification per event\n- **Stability**: Fixed multiple React render loops, hook dependency arrays, stale closures, and lifecycle/memory leaks across the app\n\n## Added\n\n- Comprehensive request processing path tests\n- Priority profile loader with batch loading, priority tiers, and chunking\n- DVM kind:7000 payment-required invoice display (#618)\n- Default relays fallback when pool is empty\n- Zapstore manifest migration (nap.yaml → zapstore.yaml)\n\n## Changed\n\n- Batch event verification in system-wasm for improved throughput\n- Profile loader rewritten with priority tiers, chunking, and O(1) notifications\n- NoteCollection clear() emission and ghost-timer fixes\n- Trace-timeline terminal state runtime tracking improvements\n- Replaced uuid with crypto.randomUUID()\n- All useSyncExternalStore calls now include getServerSnapshot for SSR compatibility (#615)\n- Switched quote style to double quotes (Biome formatting)\n\n## Fixed\n\n- **Security**: Real Schnorr signature verification in isValid (#607)\n- **Security**: PIN encryption security issues (#606)\n- **Security**: NIP-46 hardened against forged relay messages and secret leakage (#609)\n- **Security**: Removed unverified NIP-26 delegation trust in getRootPubKey (#608)\n- **Security**: Wrapped all dangerous JSON.parse calls in try/catch (#610)\n- **Security**: Added timeouts to all hanging promises (#611)\n- **Security**: Added lifecycle management and fixed timer/memory leaks (#612)\n- Render loop in NoteReaction from unstable inline ref callback\n- Render loop on profile page pinned notes\n- Notifications render loop from unstable login object dependency\n- NoteContext render loop from unstable ev/link/translate deps\n- React hook dependency arrays and stale closures across components\n- NoteStore lazy snapshot and OutboxModel input mutation (#614)\n- Queue traces for connecting relays with query system edge-case tests\n- Batch verify in WASM with error logging\n- Build-tools version updated to 35.0.0\n- APK artifact matching patterns\n\n## PRs\n\n* Fix #617: Display DVM kind:7000 payment-required invoices to users (#618)\n* Add getServerSnapshot to all useSyncExternalStore calls for SSR compatibility (#615)\n* Lazy snapshot in NoteStore, type safety improvements, fix OutboxModel input mutation (#614)\n* Replace uuid with crypto.randomUUID(), remove uuid dependency (#613)\n* Add lifecycle management and fix timer/memory leaks (#612)\n* Add timeouts to all hanging promises (#611)\n* Wrap all dangerous JSON.parse calls in try/catch (#610)\n* Harden NIP-46 against forged relay messages and secret leakage (#609)\n* Remove unverified NIP-26 delegation trust in getRootPubKey (#608)\n* Add real Schnorr signature verification to isValid (#607)\n* Fix PIN encryption security issues (#606)\n\n**Full Changelog**: https://github.com/v0l/snort/compare/v0.4.0...v0.5.0\n\n---\n\n# v0.4.0\n\n`+21,991,-31,914`\n\n## Highlights\n\n- **Discover Page**: New discover page with DVM-powered trending posts and content suggestions\n- **Media Posts**: Support for kind 20, 21, 22 media notes with dedicated media tab\n- **Follow Sets**: Browse and filter follow sets from other users\n- **Blossom Storage**: Replaced NIP-96 with Blossom\n- **Bun Migration**: Moved entire build system from Yarn/Node to Bun\n- **Nests Integration**: Audio rooms with chat and speak functionality\n\n## Added\n\n- Discover page with selectable content discovery DVMs\n- Media tab on root page for browsing media content\n- Support for kind 20, 21, 22 (media notes) and kind 1111 replies\n- Follow sets page with filtering options\n- Nests audio rooms integration (linked from live streams)\n- Blossom blob support with fallback image loading\n- Client tags for identifying applications\n- NIP-119 compatibility\n- Auto-translate enabled by default\n- Show NIP-05 handles and USD price in wallet\n- VertexLabs suggested follows\n- Table rendering in markdown\n\n## Changed\n\n- Replaced NIP-96 uploads with Blossom\n- Upgraded to React 19 `use` hook (replacing `useContext`)\n- Upgraded to Vite 7 with ESM imports\n- Improved messages with WoT filter and read status\n- Refactored cache systems, query system, and profile loader\n- Moved imgproxy logic to `@snort/shared`\n- **Removed**: LNC and Cashu wallet integrations\n- **Removed**: NIP-28 public chat support\n\n## Fixed\n\n- Query system race conditions and DVM request handling\n- Profile sync and loading issues\n- Note creator auto-complete and tagging\n- Link previews and quote reposts\n- Negentropy sync missing events\n- Support for `ws://` relays (#600)\n- Search box and various build issues\n\n---\n\n# v0.3.0\n\n`+35,347,-17,720`\n\n## Highlights\n\n- **For You Feed**: Personalized content algorithm based on your social graph\n- **Web of Trust**: Spam filtering based on your network of trust\n- **NIP-46 OAuth**: New login and sign up flow with remote signers\n- **Relay Overhaul**: Detailed relay pages with uptime, stats, and recommendations\n- **NIP-17 Migration**: Dropped NIP-4 in favor of NIP-17 encrypted DMs\n\n## Added\n\n- For You feed with personalized content scoring\n- Web of Trust (WoT) spam filter (enabled for all users)\n- NIP-46 OAuth login and sign up\n- NIP-55 Android signer support\n- NIP-44 v2 encryption\n- NIP-89 application handlers\n- NIP-96 server list with custom server selection\n- Relay management: info pages, uptime tracking, reliable indicators\n- Revamped note creator\n- LiveKit integration for audio/video\n- `@snort/bot` package for building bots\n- `nostr-social-graph` integration\n- Modular right sidebar with articles widget\n- Profile top zappers tab\n- Reply count in feed\n- Quote notes load from multiple relays\n- Npub/nprofile QR selector\n- Embeds from link previews\n- Korean translations\n\n## Changed\n\n- **Breaking**: Dropped NIP-4 DMs, now using NIP-17 only\n- Integrated `nostr-social-graph` for social features\n- Moved zapper to `@snort/wallet` package\n- Refactored outbox model into RequestRouter\n- Improved thread loading and timeline rendering\n- Preload follows list for faster startup\n- **Removed**: Tauri desktop build\n- **Removed**: Dislike reactions\n- **Removed**: Notification summary chart\n\n## Fixed\n\n- NIP-46 now uses NIP-44 encryption\n- NIP-6 mnemonic and nprofile login\n- Note creator, mute buttons, and muted words\n- Connection race conditions and reconnection spam\n- Service worker and startup migration issues\n- Feed glitches and timeline reloads\n- Hashtag parser and topic buttons\n\n---\n\n# v0.2.0\n\n`+16,990,-9,649`\n\n## Added\n\n- Check notification settings page\n- New settings page layout - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Community Leaders / Invite system - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Settings->Tools pages (Check follows relay health etc) - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- New wallet pages design - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Alby OAuth wallet connection - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Cashu wallet support (WIP) - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Followed by friends feed page - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Fuzzysearch profiles everywhere - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Worker Relay package `@snort/worker-relay` - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n  - Replaces all previous caching objects, all caches are handled inside `@snort/system` via worker relay\n- \"View as user\" button - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Play live streams directly in feed with embed iframe - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Negentropy v1 support - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n\n## Changed\n\n- Hidden note styles & preferences - nostr:npub1cz2ve34nk0ukn0ph4yq2qx3ud8rfy5e0ak4epx42dn8gha0sdgpsgra9kv\n- Keybinds for grid modal navigation - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Cache trending sections in browser - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Cache images / nostr.json in service worker - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Add dimensions to `imeta` tag for void.cat uploads - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Check event sigs in `@snort/system-wasm` - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Primary color scheme - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Note creator styles (removed hashtags input) - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Cache link preview results in memory - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Show only 1 task at a time in task list - nostr:\n- Render media in reply to note creator - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Show top zappers inline with footer icons on notes - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Add more search relays - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Moved link previews and opengraph tagging to https://nostr.api.v0l.io - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n\n## Fixed\n\n- Iris account error mesage - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Light theme color fixes - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Notifications page overflow - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n\n# v0.1.24\n\n`+11,573,-3,010`\n\n## Added\n\n- 3 Column layout - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Fuzzy cache search - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Followed by on profile pages - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Show more on long notes - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Better error message page - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Media grid feed - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Mobile fixed footer - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Follow button on profile search results - nostr:npub17q5n2z8naw0xl6vu9lvt560lg33pdpe29k0k09umlfxm3vc4tqrq466f2y\n- Invite codes (WIP Community Program) - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- `imeta` tag insertion for images - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Wallet settings page improvements - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Nostr Wallet Connect upgrade (balance + history) - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Schnorr sig check in WASM binary - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Autoplay videos in feed (muted) - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Followed by friends feed (a feed of your 2nd degree follows posts) - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- imgproxy image integrity check (sha256 from `imeta` passed to imgproxy) - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n\n## Changed\n\n- Removed Twitter embed - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Removed attachment button on DM's - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Note broadcaster dialog changed to toast notification - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Removed npub link from profile (use QR button) - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Render image size from `imeta` tags - nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\n- Style fixes - nostr:npub1cz2ve34nk0ukn0ph4yq2qx3ud8rfy5e0ak4epx42dn8gha0sdgpsgra9kv\n- Zap pool slider tweak - nostr:npub1ltx67888tz7lqnxlrg06x234vjnq349tcfyp52r0lstclp548mcqnuz40t\n- New Malay translations - nostr:npub1cjtt3nywuflj65ftld4v7zzpg0qh3ergycjcym0956vf9eftv7esekxpmn\n- Updated Persian translations - nostr:npub1cpazafytvafazxkjn43zjfwtfzatfz508r54f6z6a3rf2ws8223qc3xxpk\n- Updated Finnish translations - nostr:npub1ust7u0v3qffejwhqee45r49zgcyewrcn99vdwkednd356c9resyqtnn3mj\n- Updated French translations - nostr:npub1x8dzy9xegwmdk2vy30l8u08caspcqq2yzncxehdsa6kvnte9pr3qnt8pg4 & nostr:npub13w02l37gkjwv90lnklfet5653jj0p5ueu976v3dpda5afvxgw3uslcqdnv\n- Updated German translations - nostr:npub19a6x8frkkn2660fw0flz74a7qg8c2jxk5v9p2rsh7tv5e6ftsq3sav63vp\n- Updated Hungarian translations - nostr:npub1ww8kjxz2akn82qptdpl7glywnchhkx3x04hez3d3rye397turrhssenvtp\n- Updated Swedish translations - nostr:npub19jk45jz45gczwfm22y9z69xhaex3nwg47dz84zw096xl6z62amkqj99rv7\n- Updated Japanese translations - nostr:npub1wh69w45awqnlsxw7jt5tkymets87h6t4phplkx6ug2ht2qkssswswntjk0\n\n## Fixed\n\n- Longform note overlfow-x - nostr:npub1g53mukxnjkcmr94fhryzkqutdz2ukq4ks0gvy5af25rgmwsl4ngq43drvk\n- Trim zap content - nostr:npub1u8lnhlw5usp3t9vmpz60ejpyt649z33hu82wc2hpv6m5xdqmuxhs46turz\n\n---\n\n# v0.1.23\n\n## Added\n\n- DeepL translate api (Automatic for PRO subscribers)\n- Add nostr:nprofile1qqsydl97xpj74udw0qg5vkfyujyjxd3l706jd0t0w0turp93d0vvungfgfewr to contributors\n- Proxy LN address type enabled on Nostr Address settings pages\n- Infinite scrol on notifications page\n- Default 0.5% ZapPool rate for Snort donation address\n- Collect relay metrics in `@snort/system` for better relay selection algo in Outbox Model (NIP-65)\n- New sign up / login flow!\n  - Topics / Mute words on sign up for easier onboarding\n- Drag & Drop for uploads on note creator - nostr:nprofile1qqs8tchhwf5smv3r2g0vkswz58c837uu456x59m3dh380gtrhqzydeqz4wlka\n- Mixin topics (hashtags) into timeline feed\n- Language specific trending posts\n- Show following info for hashtags\n- Sync preferences to network (`NIP-78` support)\n- Trending hashtags page\n- Note creator hashtag input\n- Top trending hashtags on note creator\n- Social Graph - nostr:nprofile1qqsy2ga7trfetvd3j65m3jptqw9k39wtq2mg85xz2w542p5dhg06e5qpr9mhxue69uhhyetvv9ujuumwdae8gtnnda3kjctv9uh8am0r\n- New users relay list based off \"close\" relays\n- `NIP-96` support for nostr native image/file uploaders\n- Write replies/reactions to `p` tagged users read relays (Outbox model)\n- Sync joined public chats (`NIP-28`) using `PublicChatList` kind `10_005`\n\n## Changed\n\n- Read/Write relays only on kind `10_002` (NIP-65)\n- Removed `nostr.watch` code for adding new users to random relays\n- Render kind `10_002` on profile relays tab\n- `@snort/system` using eventemitter3 for triggering events\n- Use latest `NIP-51` spec (Bookmarks/Interests/`NIP-28` PublicChatList)\n- `nreq` support (Demo)\n- Write profile/relays to blasters\n- `@snort/system` automated outbox model (automatic fetching of relay metadata)\n\n## Fixes\n\n- Upgrade ephermal connection to non-ephemeral\n- Remove relay tag from zaps (Some zap services dont support it)\n- Fix zap parsing for goals\n- Remove extra chars from quoted events to fix loading (`'s` etc)\n- CSS Fixes for profile card on light theme\n- Zap counting on replacable events\n- `NIP-28` chats loading\n- Overflowing modal UI\n- Live stream widget layout with long titles\n- Notifications marker has returned from its long slumber\n\n---\n\n# v0.1.22\n\n## Fixes\n\n- Note creator too wide on mobile\n- Sending notes dialog duplicated when replying\n\n---\n\n# v0.1.21\n\n## Added\n\n- Add gradients to iris.to domain\n- Render referenced kind-3 (ContactList) as pubkey list\n- List feed page renders the posts of a given list `/list-feed/{naddr-of-nip51-list-or-nevent-of-kind3}`\n- Respond to AUTH when expected (Requesting DM's/GiftWrap)\n- Show reply counts on threads\n- Quote Repost\n- Signature checks can be enabled in preferences\n- NIP-98 auth for void.cat / nostr.build file uploaders\n- Add `E` tag for direct replies\n- File upload progress bar (void.cat only)\n- Long form modal for deck layout (WIP still)\n- Video thumbnails using ImgProxy\n- Renew subscriptions for X months\n- Tailwind CSS migration @mmalmi\n- Seasonal features\n- Profile cards on hover for mentions\n- Dropdown search results on search bar @mmalmi\n- Renew subscription task on task list\n\n## Changed\n\n- Disable highligher.js code blocks (for now)\n- Removed \"Popular Accounts\" from new user flow, replaced with \"Snort Devs\" only\n- Moved \"Show Preview\" on note creator to preview toggle switch\n- Premium subscription renamed to PRO\n- Limit images in posts to 800px high\n- Nostrplebs colors removed\n\n## Fixed\n\n- Use correct hostname when submitting analytics\n- Disable WASM when not supported on device\n- Typo on \"Nostr Address\" in account settings\n- Hide expired user status on profiles\n- Hide muted dm chats\n- Hide blocked replies\n\n---\n\n# v0.1.20\n\n## Added\n\n- Highlight text in search results - @fernandoporazzi\n- Iris/Snort build configuration - @mmalmi\n- Iris free NIP-05 on Profile page - @mmalmi\n- Image galleries on posts - @fernandoporazzi\n- Close modal with ESC - @mmalmi\n- Navigate image spotlight with LR direction keys - @mmalmi\n- Spotlight preview profile/banner on click - @mmalmi\n- Fetch profiles from HTTP cache (Iris) - @mmalmi\n- Animal names for empty profile accounts (Iris) - @mmalmi\n- Redirect to NIP-05 short links for iris/snort accounts - @mmalmi\n- Code block highlighting - @fernandoporazzi\n- Notification summary graph - @Kieran\n- Profile hover cards - @Kieran\n- Keyboard shortcuts for new post/focus/search - @fernandoporazzi\n- Markdown rendering for long form content - @Kieran\n- Show relay response when publishing - @Kieran\n\n## Fixed\n\n- Copy buttons on insecure context - @Kieran\n\n---\n\n# v0.1.19\n\n## Added\n\n- Highlight search results\n\n## Fixes\n\n- Copy to clipboard on insecure context (Umbrel)\n\n---\n\n# v0.1.16\n\n## Fixes\n\n- Login bugs\n\n---\n\n# v0.1.15\n\n## Added\n\n- User status on profile pages (Music only [NIP-38])\n- Following mark on avatars, if you follow the pubkey you will see a green tick on their avatar\n- Pin encryption, encrypted private key storage for nsec login\n- Pubkey (readonly) logins hide buttons which cannot be used (reactions, reply, save profiles, dms etc)\n- Muted words feature (phase 1)\n- NIP-28 public chats\n\n## Changed\n\n- Styles changes for Content warnings\n- Live stream embed styles\n- Cashu token embed styles\n- Snort Deck thread navigation in modal from timeline\n- PoW miner moved to WASM module for faster hashing\n\n## Fixed\n\n- Profile link to dms\n- Long form content loading and replies\n- Search function restored\n\n---\n\n# v0.1.14\n\n## Added\n\n- Timeline cache: faster page loads and much lower data usage\n- WASM module: Some code moved to Rust WASM module for faster execution\n- Zap Splits: NIP-57.G\n- New Languages:\n  - Finnish\n  - Dutch\n  - Portuguese Brazilian\n\n## Changed\n\n- Count polls by pubkey\n\n---\n\n# v0.1.13\n\n# Added\n\n- Snort V2 Design\n- NIP-24 Encrypted secret chats (nsec login only)\n- NIP-13 Proof of Work (POW)\n- NIP-31 Alt tag spec for unknown event kinds\n- Render mentioned zap goals (Kind 9041)\n- Embed fonts in src (No more google fonts requests)\n- Native key storage for Android app (`Nip7os` interface)\n- Swahili translations\n- Thai translations\n\n# Changed\n\n- PWA pre-cache setup (Faster PWA loading)\n- Show note creator button on profile pages\n\n# Fixed\n\n- Umlauts in urls\n- Reject events which don't match request filter\n\n---\n\n# v0.1.12\n\n# Added\n\n- nsecBunker support (connection string `bunker://<pubkey>?relay=wss://realy.com[#token]`)\n\n# Changed\n\n- New snort logo by Bitko\n- Infinite scroll changed to manual action (temperarily to fix performance issues)\n\n# Fixed\n\n- Note to self containing all DMS\n- Media spotlight disabled for poll options containing images\n- Badge image sizes oversize when bypassing imgproxy due to loading error\n\n---\n\n# v0.1.11\n\n## Added\n\n- `@snort/system` package\n- `@snort/system-react` package\n- Live streaming page (NIP-102)\n- Chat system refactor (adding new chat systems much easier now, NIP-29 first candidate)\n- NIP-29 simple group chat support\n\n## Fixed\n\n- Profile links with incorrect hrp fixed in some places\n- `naddr` event loading fixed\n- Relay specific requests fixed (Global tab / Search page)\n- NWC connection responds to AUTH requests now\n\nhttps://git.v0l.io/Kieran/snort/compare/v0.1.10...v0.1.11\n\n---\n\n# v0.1.10\n\n## Added\n\n- Gossip model, query follows write relays for events\n- @snort/system NPM package containing Snort core nostr code\n- NIP-44 Encryption scheme support\n- NIP-59 Gift Wrap support\n\n## Fixed\n\n- Unmarked thread events replies out of order\n\nhttps://git.v0l.io/Kieran/snort/compare/v0.1.9...v0.1.10\n\n---\n\n# v0.1.9\n\n## Added\n\n- Discover tab, shows trending users/posts from nostr.build\n- New DM styles\n- Mentioned Zapstr tracks are previewed on Snort with player\n- Custom emoji rendering in posts (NIP-30)\n- Lanaguage selector on new user flow\n- ZapPool, support nostr ecosystem by donating a percentage of your zaps\n- Alby NWC link added to NWC connect page\n- SemisolDev follow recommendations on Discover tab\n- Pubkey lists (NIP-51) render inline when mentioned in notes\n- Persian language\n- OpenGraph Image/Video media rendered inside link preview box\n- Option to zap everybody on mentioned pubkey list\n- L402 support for inline media (paywall content)\n\n## Changed\n\n- Error page shows actual error message now, also a button to reset app cache\n- Massivly improved profile loading\n- Improved JS bundle size by ejecting CRA and using dynamic modules\n- Switched to `@void-cat/api` package for void.cat uploads\n\n---\n\n# v0.1.8\n\n## Added\n\n- Tamil Language support\n- Quoted notes are rendered embedded\n- Multi-account support for subscribers\n- Zapper key loading processing in background to speed up profile loading\n- Export keys page added to settings\n- NIP-94 support for rendering quoted file metadata events\n- Interactions cache (zaps/likes/reports) for better UX\n- Full screen image/video previews in modal\n- Re-broadcast own events dialog\n- Nostr wallet connect support\n- Cashu token parsing preview with redeem link\n- Trending notes/people tabs added to search page\n\n## Changed\n\n- Profile page loads only 200 latest notes, improving profile load times for accounts with less activity\n- New user flow has been tweaked to be shorter with NIP5 & Twitter import steps removed\n\n## Fixed\n\n- Thread navigation without page reload\n- NIP-42 functionality restored\n- `a` tagged kind 1 replies render properly under root event\n\n**Full Changelog**: https://github.com/v0l/snort/compare/v0.1.7...v0.1.8\n\n---\n\n# v0.1.7\n\n## Added\n\n- Per event zap targets by @v0l\n- Content warning (NIP-36) support by @v0l\n- Polls (NIP-69) by @v0l\n- Snort subscriptions by @v0l\n- NIP-94 File header support by @v0l\n- Link previews by @ghobs91 & @v0l\n- Cmd+Enter to post note by @v0l\n- `nostr:` links (NIP-27) by @v0l\n- Tending users on Search page by @ghobs91 & @v0l\n\n## Changed\n\n- Paste image upload by @vivganes\n- Note creator note preview by @v0l\n- Login private key input masking by @vivganes\n\n## Fixed\n\n- Fix note creator closing on thread when new replies load by @SamSamskies\n- Follow hashtag tab highlighting by @SamSamskies\n- Language dropdown defaults to Arabic by @vivganes\n- Bookmarks showing reactions by @vivganes\n- Single zapper on note only shows name by @vivganes\n- Broken link previews show empty box by @vivganes\n- Render jfif images by @v0l\n\n## PR List\n\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/476\n- `nostr` package: implement NIP-05 by @sistemd in https://github.com/v0l/snort/pull/474\n- `nostr` package: NIP-09 event deletion by @sistemd in https://github.com/v0l/snort/pull/478\n- fix #484 by @vivganes in https://github.com/v0l/snort/pull/486\n- fix #485 by @vivganes in https://github.com/v0l/snort/pull/487\n- Per event zap targets by @v0l in https://github.com/v0l/snort/pull/466\n- feat: nip-36 by @v0l in https://github.com/v0l/snort/pull/497\n- fix #496 by @vivganes in https://github.com/v0l/snort/pull/498\n- use redux for NoteCreator state management by @SamSamskies in https://github.com/v0l/snort/pull/494\n- fix #495 by @vivganes in https://github.com/v0l/snort/pull/499\n- Polls (NIP-69) by @v0l in https://github.com/v0l/snort/pull/489\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/483\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/508\n- add ability to paste image from clipboard by @vivganes in https://github.com/v0l/snort/pull/510\n- Subscriptions by @v0l in https://github.com/v0l/snort/pull/506\n- feat: multi-account system by @v0l in https://github.com/v0l/snort/pull/514\n- fix followed tag active tab highlighting by @SamSamskies in https://github.com/v0l/snort/pull/516\n- NIP-94 file headers by @v0l in https://github.com/v0l/snort/pull/488\n- fix #517 by @vivganes in https://github.com/v0l/snort/pull/518\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/511\n- `nostr` package: get tests passing in the browser by @sistemd in https://github.com/v0l/snort/pull/490\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/519\n- Subscription handle by @v0l in https://github.com/v0l/snort/pull/522\n\n## New Contributors\n\n- @vivganes made their first contribution in https://github.com/v0l/snort/pull/486\n\n**Full Changelog**: https://github.com/v0l/snort/compare/v0.1.6...v0.1.7\n\n---\n\n# v0.1.6\n\n## 🏷️ Summary\n\n- Snort NIP5 management page (for transfers to new pubkeys)\n- Short links for Snort NIP5 owners (ie. https://snort.social/kieran)\n\n## Other Changes\n\n- Update Wavlake embed to support .com links by @blastshielddown in https://github.com/v0l/snort/pull/469\n- Bug fixes for save profile & relay connection on clean browser\n\n**Full Changelog**: https://github.com/v0l/snort/compare/v0.1.5...v0.1.6\n\n---\n\n# v0.1.5\n\n## 🏷️ Short Summary\n\n- Completely rebuilt \"core\" subscription management system\n- Option to rewrite Twitter links to Nitter links\n- Tarui app setup, Mac/Windows/Linux desktop apps (coming soon)\n- OpenGraph tagging for profiles and events (Only for https://snort.social)\n- NIP-27 `nostr:` link parsing\n- Global tab full relay names\n\n## What's Changed\n\n- `nostr` package: add direct messages by @sistemd in https://github.com/v0l/snort/pull/399\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/445\n- Display search property alongside host in relay name by @h3y6e in https://github.com/v0l/snort/pull/452\n- Shorten long relay name by @h3y6e in https://github.com/v0l/snort/pull/455\n- Nostr links by @v0l in https://github.com/v0l/snort/pull/461\n- `nostr` package: vastly simplify the API by @sistemd in https://github.com/v0l/snort/pull/412\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/453\n- Fix: invisible <option> text in dark theme by @jiftechnify in https://github.com/v0l/snort/pull/454\n- add setting for rewriting twitter links to nitter by @w3irdrobot in https://github.com/v0l/snort/pull/459\n- RequestBuilder / Core Refactor by @v0l in https://github.com/v0l/snort/pull/326\n- Tauri setup by @v0l in https://github.com/v0l/snort/pull/462\n- Prevents adding ws relay when over https by @ivanacostarubio in https://github.com/v0l/snort/pull/463\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/465\n- OpenGraph tag injection by @v0l in https://github.com/v0l/snort/pull/470\n\n## New Contributors\n\n- @jiftechnify made their first contribution in https://github.com/v0l/snort/pull/454\n\n**Full Changelog**: https://github.com/v0l/snort/compare/v0.1.4...v0.1.5\n\n---\n\n# v0.1.4\n\n**Full Changelog**: https://github.com/v0l/snort/compare/v0.1.3...v0.1.4\n\n---\n\n# v0.1.3\n\n## What's Changed\n\n- only replace note ID when note ID starts with `@` character by @SamSamskies in https://github.com/v0l/snort/pull/441\n\n**Full Changelog**: https://github.com/v0l/snort/compare/v0.1.2...v0.1.3\n\n---\n\n# v0.1.2\n\n## What's Changed\n\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/309\n- UI bugs by @verbiricha in https://github.com/v0l/snort/pull/301\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/311\n- Add build command to readme by @joshr4 in https://github.com/v0l/snort/pull/300\n- fix(fotter-actions): add highlighting and min-width by @fernandolguevara in https://github.com/v0l/snort/pull/312\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/313\n- `nostr` package part 1 by @fcked in https://github.com/v0l/snort/pull/315\n- Reduce space between the texts for selecting relays by @h3y6e in https://github.com/v0l/snort/pull/316\n- fix(profile): convert page id to npub bech32 by @fernandolguevara in https://github.com/v0l/snort/pull/322\n- Improve overflow menu button by @joshr4 in https://github.com/v0l/snort/pull/304\n- German translations for snort by @gandlafbtc in https://github.com/v0l/snort/pull/323\n- fix: send all relays when zapping by @verbiricha in https://github.com/v0l/snort/pull/324\n- Add default page selector by @jacany in https://github.com/v0l/snort/pull/321\n- UI fixes by @verbiricha in https://github.com/v0l/snort/pull/318\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/319\n- feat: render kind 1 reposts by @kphrx in https://github.com/v0l/snort/pull/314\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/330\n- Use inner note content as comment by @Semisol in https://github.com/v0l/snort/pull/333\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/331\n- Fix stale relays by @SamSamskies in https://github.com/v0l/snort/pull/337\n- Feed cache rework by @v0l in https://github.com/v0l/snort/pull/339\n- fix long zap comment text overflow by @SamSamskies in https://github.com/v0l/snort/pull/344\n- fix links in parentheses by @SamSamskies in https://github.com/v0l/snort/pull/347\n- Revert \"Merge pull request #347 from v0l/fix-links-in-parentheses\" by @SamSamskies in https://github.com/v0l/snort/pull/350\n- Update thread detection to not include mentions by @w3irdrobot in https://github.com/v0l/snort/pull/351\n- Small settings page stuff by @w3irdrobot in https://github.com/v0l/snort/pull/353\n- Change message unread color to purple by @w3irdrobot in https://github.com/v0l/snort/pull/354\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/356\n- Remove unread message dot when messages all read by @w3irdrobot in https://github.com/v0l/snort/pull/355\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/359\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/362\n- `nostr` package part 2 by @fcked in https://github.com/v0l/snort/pull/346\n- feat: add search page field autofocus by @lujakob in https://github.com/v0l/snort/pull/363\n- fix URL parsing edge cases by @SamSamskies in https://github.com/v0l/snort/pull/360\n- Fast Zaps ⚡ by @v0l in https://github.com/v0l/snort/pull/370\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/364\n- Feat/add spinner to button by @lujakob in https://github.com/v0l/snort/pull/368\n- Update mark all read dm button to be disabled when no unreads by @w3irdrobot in https://github.com/v0l/snort/pull/373\n- `nostr` package part 3 by @fcked in https://github.com/v0l/snort/pull/365\n- LNDHub/LNC wallet by @v0l in https://github.com/v0l/snort/pull/219\n- Proposal: Remove SVGs from JSX by @enjikaka in https://github.com/v0l/snort/pull/382\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/374\n- add Nostr Nests embed by @SamSamskies in https://github.com/v0l/snort/pull/377\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/387\n- fix icons by @h3y6e in https://github.com/v0l/snort/pull/392\n- Fix broken note links by @SamSamskies in https://github.com/v0l/snort/pull/380\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/391\n- fix(BackButton): vertical align styles by @lujakob in https://github.com/v0l/snort/pull/397\n- feat(note): open note in new tab on cmd press by @lujakob in https://github.com/v0l/snort/pull/395\n- fix(skeleton): dark theme styles by @lujakob in https://github.com/v0l/snort/pull/393\n- fix HyperText matching by @mattn in https://github.com/v0l/snort/pull/405\n- Makes entire note clickable by @d-r-w in https://github.com/v0l/snort/pull/371\n- render webm links as inline videos by @SamSamskies in https://github.com/v0l/snort/pull/410\n- render embed for youtube live links by @SamSamskies in https://github.com/v0l/snort/pull/407\n- do not render reposts of badge award events in timelines by @SamSamskies in https://github.com/v0l/snort/pull/406\n- `nostr` package: use `EventEmitter` by @fcked in https://github.com/v0l/snort/pull/384\n- `nostr` pacakge: implement basic NIP-20 `OK` functionality by @fcked in https://github.com/v0l/snort/pull/385\n- feat: read nip-58 badges by @verbiricha in https://github.com/v0l/snort/pull/394\n- Add Wavlake embed by @blastshielddown in https://github.com/v0l/snort/pull/416\n- display search results on page load if query in url by @SamSamskies in https://github.com/v0l/snort/pull/415\n- Fix event mention bug by @SamSamskies in https://github.com/v0l/snort/pull/421\n- fix NaN when parsing empty string by @SamSamskies in https://github.com/v0l/snort/pull/422\n- NIP06 support by @w3irdrobot in https://github.com/v0l/snort/pull/425\n- Added key attr to TabSelectors to remove React warning by @w3irdrobot in https://github.com/v0l/snort/pull/424\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/426\n- New Crowdin updates by @v0l in https://github.com/v0l/snort/pull/436\n- Update Wavlake embed URL, add support for album & artist links by @blastshielddown in https://github.com/v0l/snort/pull/439\n- build(deps): bump webpack from 5.75.0 to 5.76.1 by @dependabot in https://github.com/v0l/snort/pull/442\n\n## New Contributors\n\n- @joshr4 made their first contribution in https://github.com/v0l/snort/pull/300\n- @gandlafbtc made their first contribution in https://github.com/v0l/snort/pull/323\n- @jacany made their first contribution in https://github.com/v0l/snort/pull/321\n- @kphrx made their first contribution in https://github.com/v0l/snort/pull/314\n- @lujakob made their first contribution in https://github.com/v0l/snort/pull/363\n- @mattn made their first contribution in https://github.com/v0l/snort/pull/405\n- @d-r-w made their first contribution in https://github.com/v0l/snort/pull/371\n- @blastshielddown made their first contribution in https://github.com/v0l/snort/pull/416\n- @dependabot made their first contribution in https://github.com/v0l/snort/pull/442\n\n**Full Changelog**: https://github.com/v0l/snort/compare/v0.1.1...v0.1.2\n\n---\n\n# v0.1.1\n\n## What's Changed\n\n- React Map Optimization, [missing map keys ] by @ahmedrowaihi in https://github.com/v0l/snort/pull/283\n- Translate '/src/lang.json' in 'ar' by @transifex-integration in https://github.com/v0l/snort/pull/287\n- HTML auto direction for specific textual content by @verbiricha in https://github.com/v0l/snort/pull/286\n- Translate '/src/lang.json' in 'hu' by @transifex-integration in https://github.com/v0l/snort/pull/288\n- feat: twitch embed by @v0l in https://github.com/v0l/snort/pull/289\n- fix: don't show 0 if there is no description by @verbiricha in https://github.com/v0l/snort/pull/290\n- feat: pinned notes and bookmarks by @verbiricha in https://github.com/v0l/snort/pull/255\n- Translate '/src/lang.json' in 'ja' by @transifex-integration in https://github.com/v0l/snort/pull/293\n- fix: set auto to whole text content instead of individual paragraphs by @verbiricha in https://github.com/v0l/snort/pull/292\n- protocol handler by @v0l in https://github.com/v0l/snort/pull/164\n- feat: read global from specific (paid) relays by @v0l in https://github.com/v0l/snort/pull/249\n- SUPPORT RTL/LTR ON LOGIN PAGE by @ahmedrowaihi in https://github.com/v0l/snort/pull/291\n- Add Apple Music embed by @SamSamskies in https://github.com/v0l/snort/pull/294\n- Workspace with decoupled `nostr` package by @ennmichael in https://github.com/v0l/snort/pull/274\n- Translate '/src/lang.json' in 'ar' by @transifex-integration in https://github.com/v0l/snort/pull/296\n- UI fixes + counts on profile page tabs by @verbiricha in https://github.com/v0l/snort/pull/282\n- Fix blackout when selecting global tab by @h3y6e in https://github.com/v0l/snort/pull/297\n- Prevent profile text from overflowing flex container when it is too long by @h3y6e in https://github.com/v0l/snort/pull/298\n\n## New Contributors\n\n- @ahmedrowaihi made their first contribution in https://github.com/v0l/snort/pull/283\n\n**Full Changelog**: https://github.com/v0l/snort/compare/v0.1.0...v0.1.1\n\n---\n\n# v0.1.0\n\n## What's Changed\n\n- Add global tab to Root by @p2pseed in https://github.com/v0l/snort/pull/3\n- UI improvements by @verbiricha in https://github.com/v0l/snort/pull/4\n- fix: dedupe thread pubkeys by @verbiricha in https://github.com/v0l/snort/pull/7\n- Note creator improvement by @verbiricha in https://github.com/v0l/snort/pull/6\n- fix: correctly follow user mention links by @verbiricha in https://github.com/v0l/snort/pull/5\n- fix: force timeline rerender on tab change by @verbiricha in https://github.com/v0l/snort/pull/8\n- feat: add mov to video files by @verbiricha in https://github.com/v0l/snort/pull/9\n- feat: copy npub on profile by @verbiricha in https://github.com/v0l/snort/pull/10\n- fix: display full lightning address, is trimmed if too long by @verbiricha in https://github.com/v0l/snort/pull/12\n- feat: embed youtube videos by @verbiricha in https://github.com/v0l/snort/pull/13\n- feat: add support for positive and negative reactions by @verbiricha in https://github.com/v0l/snort/pull/11\n- feat: nip05 on profile page by @verbiricha in https://github.com/v0l/snort/pull/21\n- UI improvements by @verbiricha in https://github.com/v0l/snort/pull/24\n- Home tabs by @v0l in https://github.com/v0l/snort/pull/25\n- fix: support m.youtube.com subdomain links by @verbiricha in https://github.com/v0l/snort/pull/27\n- fix: use all available width for note creator text area by @verbiricha in https://github.com/v0l/snort/pull/28\n- highlight hashtags by @verbiricha in https://github.com/v0l/snort/pull/29\n- UI tweaks by @verbiricha in https://github.com/v0l/snort/pull/30\n- Improve regexes by @verbiricha in https://github.com/v0l/snort/pull/32\n- Shows QR code first by @ivanacostarubio in https://github.com/v0l/snort/pull/23\n- feat: embed tweets by @verbiricha in https://github.com/v0l/snort/pull/33\n- Nip5 shop by @v0l in https://github.com/v0l/snort/pull/50\n- Activate snort.social NIP-5 service by @v0l in https://github.com/v0l/snort/pull/51\n- feat: add avatar borders with color gradients to partner nip05 providers by @verbiricha in https://github.com/v0l/snort/pull/52\n- DM's by @v0l in https://github.com/v0l/snort/pull/54\n- feat: display banner in profile by @verbiricha in https://github.com/v0l/snort/pull/53\n- add max width to details by @verbiricha in https://github.com/v0l/snort/pull/59\n- Markdown by @verbiricha in https://github.com/v0l/snort/pull/55\n- feat: mentions by @verbiricha in https://github.com/v0l/snort/pull/56\n- Minor UI fixes by @verbiricha in https://github.com/v0l/snort/pull/63\n- add user DB and cache nip-05 verifications by @verbiricha in https://github.com/v0l/snort/pull/65\n- fix: adjust nip05 size by @verbiricha in https://github.com/v0l/snort/pull/66\n- fix: dont display display_name as nip user when username is default by @verbiricha in https://github.com/v0l/snort/pull/67\n- fix: don't retry errored verifications by @verbiricha in https://github.com/v0l/snort/pull/71\n- UI improvements by @verbiricha in https://github.com/v0l/snort/pull/70\n- refactor: TS by @v0l in https://github.com/v0l/snort/pull/69\n- More TSX by @v0l in https://github.com/v0l/snort/pull/74\n- Moar UI fixes by @verbiricha in https://github.com/v0l/snort/pull/73\n- fix: autocomplete colors by @verbiricha in https://github.com/v0l/snort/pull/75\n- feat: query for autocompletion using local db by @verbiricha in https://github.com/v0l/snort/pull/76\n- fix: rerender user timeline on pubkey change by @verbiricha in https://github.com/v0l/snort/pull/77\n- feat: follows you on profile page by @ivanacostarubio in https://github.com/v0l/snort/pull/64\n- autocomplete improvements by @verbiricha in https://github.com/v0l/snort/pull/83\n- filter for self dms by @LiranCohen in https://github.com/v0l/snort/pull/86\n- Notifications by @v0l in https://github.com/v0l/snort/pull/88\n- Theme by @verbiricha in https://github.com/v0l/snort/pull/87\n- Modified self-dm to be a \"Note to Self\" by @LiranCohen in https://github.com/v0l/snort/pull/89\n- note footer ordering by @verbiricha in https://github.com/v0l/snort/pull/91\n- Hashtags by @v0l in https://github.com/v0l/snort/pull/92\n- Make logo cursor a pointer by @w3irdrobot in https://github.com/v0l/snort/pull/99\n- fix: active note colors by @verbiricha in https://github.com/v0l/snort/pull/102\n- Tidal embeds by @v0l in https://github.com/v0l/snort/pull/95\n- UI improvements by @verbiricha in https://github.com/v0l/snort/pull/103\n- User preferences by @v0l in https://github.com/v0l/snort/pull/104\n- Add note context menu by @v0l in https://github.com/v0l/snort/pull/105\n- feat: soundcloud embed by @ivanacostarubio in https://github.com/v0l/snort/pull/112\n- feat: Show latest by @v0l in https://github.com/v0l/snort/pull/113\n- light theme fixes by @verbiricha in https://github.com/v0l/snort/pull/116\n- add Karnage to contributors by @verbiricha in https://github.com/v0l/snort/pull/117\n- feat: note mentions by @verbiricha in https://github.com/v0l/snort/pull/125\n- Preferences & Profile changes by @FlannelDipole in https://github.com/v0l/snort/pull/126\n- sort bug in the event that your pubkey is the 2nd item in the list by @LiranCohen in https://github.com/v0l/snort/pull/137\n- UI updates by @verbiricha in https://github.com/v0l/snort/pull/135\n- fix: hide note creator on send by @verbiricha in https://github.com/v0l/snort/pull/139\n- fix: add bottom margin to thread by @verbiricha in https://github.com/v0l/snort/pull/140\n- adds mixcloud by @ivanacostarubio in https://github.com/v0l/snort/pull/136\n- feat: audio player by @verbiricha in https://github.com/v0l/snort/pull/146\n- feat: in-memory fallback for storing user profiles by @verbiricha in https://github.com/v0l/snort/pull/110\n- Make Markdown more interoperable by @fiatjaf in https://github.com/v0l/snort/pull/153\n- fix: default to in-memory db only on db read fail by @verbiricha in https://github.com/v0l/snort/pull/155\n- bug: logout reply by @ivanacostarubio in https://github.com/v0l/snort/pull/154\n- Search by @v0l in https://github.com/v0l/snort/pull/143\n- Nip42 (AUTH) by @v0l in https://github.com/v0l/snort/pull/144\n- Muted list via NIP-51 by @verbiricha in https://github.com/v0l/snort/pull/151\n- Add more relays (high performance) by @Semisol in https://github.com/v0l/snort/pull/149\n- Show absolute time on hover by @wanacode in https://github.com/v0l/snort/pull/166\n- nostr.build file uploads by @v0l in https://github.com/v0l/snort/pull/162\n- New UI by @v0l in https://github.com/v0l/snort/pull/161\n- fix: send d tags as list by @verbiricha in https://github.com/v0l/snort/pull/169\n- Image proxy service by @v0l in https://github.com/v0l/snort/pull/174\n- Translate notes by @v0l in https://github.com/v0l/snort/pull/179\n- Use standard imgproxy by @v0l in https://github.com/v0l/snort/pull/180\n- Fix races where Socket is closed before Websocket is created by @brugeman in https://github.com/v0l/snort/pull/186\n- feat: nostrimg.com by @v0l in https://github.com/v0l/snort/pull/181\n- Add Spotify embed by @SamSamskies in https://github.com/v0l/snort/pull/188\n- Ln invoice styling by @verbiricha in https://github.com/v0l/snort/pull/187\n- feed cache by @v0l in https://github.com/v0l/snort/pull/184\n- bug: prepends https when missing from website by @ivanacostarubio in https://github.com/v0l/snort/pull/194\n- Use the current embed player via TIDALs OEmbed API. by @enjikaka in https://github.com/v0l/snort/pull/191\n- feat: zaps by @verbiricha in https://github.com/v0l/snort/pull/78\n- display note zaps succintly by @verbiricha in https://github.com/v0l/snort/pull/196\n- nostr-pub.semisol.dev is now atlas.nostr.land by @Semisol in https://github.com/v0l/snort/pull/198\n- Zaps fixes by @verbiricha in https://github.com/v0l/snort/pull/199\n- Note creator improvements by @verbiricha in https://github.com/v0l/snort/pull/193\n- Settings page and UI tweaks by @verbiricha in https://github.com/v0l/snort/pull/200\n- fix avatars by @verbiricha in https://github.com/v0l/snort/pull/203\n- Skeleton component on timeline loading for better user experience by @leotuna in https://github.com/v0l/snort/pull/190\n- Threads by @verbiricha in https://github.com/v0l/snort/pull/170\n- fix: don't stream global feed in notifications tab by @verbiricha in https://github.com/v0l/snort/pull/207\n- Zap modal by @verbiricha in https://github.com/v0l/snort/pull/209\n- Add prettier formatting by @ennmichael in https://github.com/v0l/snort/pull/214\n- react-intl spike by @SamSamskies in https://github.com/v0l/snort/pull/216\n- Add support for zh and ja locales by @SamSamskies in https://github.com/v0l/snort/pull/218\n- feat: reactions modal by @verbiricha in https://github.com/v0l/snort/pull/215\n- Translate '/src/translations/en.json' in 'es' by @transifex-integration in https://github.com/v0l/snort/pull/224\n- Translate '/src/translations/en.json' in 'ja' by @transifex-integration in https://github.com/v0l/snort/pull/227\n- fix: allow zap comments by @verbiricha in https://github.com/v0l/snort/pull/229\n- Eslint by @v0l in https://github.com/v0l/snort/pull/223\n- Translate '/src/translations/en.json' in 'fr' by @transifex-integration in https://github.com/v0l/snort/pull/230\n- add ability to use babel plugins without ejecting by @SamSamskies in https://github.com/v0l/snort/pull/225\n- add prettier pre-commit hook by @SamSamskies in https://github.com/v0l/snort/pull/234\n- oversight of intl by @h3y6e in https://github.com/v0l/snort/pull/231\n- feat: new login page by @v0l in https://github.com/v0l/snort/pull/235\n- feat: onboarding by @verbiricha in https://github.com/v0l/snort/pull/233\n- Translate '/src/translations/en.json' in 'ja' by @transifex-integration in https://github.com/v0l/snort/pull/243\n- Translate '/src/translations/en.json' in 'fr' by @transifex-integration in https://github.com/v0l/snort/pull/242\n- Translate '/src/translations/en.json' in 'es' by @transifex-integration in https://github.com/v0l/snort/pull/241\n- feat: break lang by @v0l in https://github.com/v0l/snort/pull/244\n- fix(missing-event): avoid redirect by @fernandolguevara in https://github.com/v0l/snort/pull/246\n- fix(content): render media content for current pubkey by @fernandolguevara in https://github.com/v0l/snort/pull/240\n- remove follow button from reactions modal by @SamSamskies in https://github.com/v0l/snort/pull/247\n- NIP-65: Relay list metada by @verbiricha in https://github.com/v0l/snort/pull/238\n- Fix DM page UI by @SamSamskies in https://github.com/v0l/snort/pull/250\n- Translate '/src/lang.json' in 'es' by @transifex-integration in https://github.com/v0l/snort/pull/252\n- Translate '/src/lang.json' in 'es' [manual sync] by @transifex-integration in https://github.com/v0l/snort/pull/258\n- Translate '/src/lang.json' in 'fr' [manual sync] by @transifex-integration in https://github.com/v0l/snort/pull/259\n- Translate '/src/lang.json' in 'hu' [manual sync] by @transifex-integration in https://github.com/v0l/snort/pull/260\n- Translate '/src/lang.json' in 'ja' [manual sync] by @transifex-integration in https://github.com/v0l/snort/pull/261\n- Translate '/src/lang.json' in 'zh' [manual sync] by @transifex-integration in https://github.com/v0l/snort/pull/262\n- Translate '/src/lang.json' in 'ja' by @transifex-integration in https://github.com/v0l/snort/pull/275\n- Translate '/src/lang.json' in 'id' by @transifex-integration in https://github.com/v0l/snort/pull/277\n- Translate '/src/lang.json' in 'zh' by @transifex-integration in https://github.com/v0l/snort/pull/278\n- Translate '/src/lang.json' in 'es' by @transifex-integration in https://github.com/v0l/snort/pull/279\n- Translate '/src/lang.json' in 'hu' by @transifex-integration in https://github.com/v0l/snort/pull/280\n- Translate '/src/lang.json' in 'fr' by @transifex-integration in https://github.com/v0l/snort/pull/281\n\n## New Contributors\n\n- @p2pseed made their first contribution in https://github.com/v0l/snort/pull/3\n- @v0l made their first contribution in https://github.com/v0l/snort/pull/25\n- @ivanacostarubio made their first contribution in https://github.com/v0l/snort/pull/23\n- @w3irdrobot made their first contribution in https://github.com/v0l/snort/pull/99\n- @FlannelDipole made their first contribution in https://github.com/v0l/snort/pull/126\n- @fiatjaf made their first contribution in https://github.com/v0l/snort/pull/153\n- @Semisol made their first contribution in https://github.com/v0l/snort/pull/149\n- @wanacode made their first contribution in https://github.com/v0l/snort/pull/166\n- @SamSamskies made their first contribution in https://github.com/v0l/snort/pull/188\n- @enjikaka made their first contribution in https://github.com/v0l/snort/pull/191\n- @leotuna made their first contribution in https://github.com/v0l/snort/pull/190\n- @transifex-integration made their first contribution in https://github.com/v0l/snort/pull/224\n- @h3y6e made their first contribution in https://github.com/v0l/snort/pull/231\n- @fernandolguevara made their first contribution in https://github.com/v0l/snort/pull/246\n\n**Full Changelog**: https://github.com/v0l/snort/commits/v0.1.0\n"
  },
  {
    "path": "packages/app/README.md",
    "content": "# bun-react-template\n\nTo install dependencies:\n\n```bash\nbun install\n```\n\nTo start a development server:\n\n```bash\nbun dev\n```\n\nTo run for production:\n\n```bash\nbun start\n```\n\nThis project was created using `bun init` in bun v1.3.0. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.\n"
  },
  {
    "path": "packages/app/babel.config.json",
    "content": "{\n  \"plugins\": [\n    [\n      \"formatjs\",\n      {\n        \"idInterpolationPattern\": \"[sha512:contenthash:base64:6]\",\n        \"ast\": true\n      }\n    ]\n  ]\n}\n"
  },
  {
    "path": "packages/app/bun-env.d.ts",
    "content": "// Generated by `bun init`\n\ndeclare module \"*.svg\" {\n  /**\n   * A path to the SVG file\n   */\n  const path: `${string}.svg`\n  export = path\n}\n\ndeclare module \"*.module.css\" {\n  /**\n   * A record of class names to their corresponding CSS module classes\n   */\n  const classes: { readonly [key: string]: string }\n  export = classes\n}\n"
  },
  {
    "path": "packages/app/bunfig.toml",
    "content": "[serve.static]\nenv = \"BUN_PUBLIC_*\""
  },
  {
    "path": "packages/app/config/README.md",
    "content": "Choose config with NODE_CONFIG_ENV: `NODE_CONFIG_ENV=iris bun start`\n"
  },
  {
    "path": "packages/app/config/default.json",
    "content": "{\n  \"appName\": \"Snort\",\n  \"appNameCapitalized\": \"Snort\",\n  \"appTitle\": \"Snort - Nostr\",\n  \"hostname\": \"snort.social\",\n  \"nip05Domain\": \"snort.social\",\n  \"icon\": \"/nostrich_512.png\",\n  \"navLogo\": null,\n  \"publicDir\": \"public/snort\",\n  \"httpCache\": \"\",\n  \"animalNamePlaceholders\": false,\n  \"defaultZapPoolFee\": 1,\n  \"features\": {\n    \"analytics\": true,\n    \"subscriptions\": false,\n    \"deck\": false,\n    \"zapPool\": false,\n    \"communityLeaders\": false,\n    \"nostrAddress\": true,\n    \"pushNotifications\": true\n  },\n  \"signUp\": {\n    \"quickStart\": false,\n    \"defaultFollows\": [\"npub1sn0rtcjcf543gj4wsg7fa59s700d5ztys5ctj0g69g2x6802npjqhjjtws\"]\n  },\n  \"defaultPreferences\": {\n    \"hideMutedNotes\": false,\n    \"defaultRootTab\": \"following\"\n  },\n  \"media\": {\n    \"bypassImgProxyError\": false,\n    \"preferLargeMedia\": true\n  },\n  \"communityLeaders\": {\n    \"list\": \"naddr1qq4xc6tnw3ez6vp58y6rywpjxckngdtyxukngwr9vckkze33vcknzcnrxcenje35xqmn2cczyp3lucccm3v9s087z6qslpkap8schltk427zfgqgrn3g2menq5zw6qcyqqq82vqprpmhxue69uhhyetvv9ujuumwdae8gtnnda3kjctv7rajfl\"\n  },\n  \"noteCreatorToast\": false,\n  \"hideFromNavbar\": [],\n  \"deckSubKind\": 1,\n  \"showPowIcon\": true,\n  \"showNip05\": true,\n  \"eventLinkPrefix\": \"nevent\",\n  \"profileLinkPrefix\": \"nprofile\",\n  \"defaultRelays\": {\n    \"wss://relay.snort.social/\": {\n      \"read\": true,\n      \"write\": true\n    },\n    \"wss://nostr.wine/\": {\n      \"read\": true,\n      \"write\": false\n    },\n    \"wss://relay.damus.io/\": {\n      \"read\": true,\n      \"write\": true\n    },\n    \"wss://nos.lol/\": {\n      \"read\": true,\n      \"write\": true\n    }\n  },\n  \"alby\": {\n    \"clientId\": \"pohiJjPhQR\",\n    \"clientSecret\": \"GAl1YKLA3FveK1gLBYok\"\n  },\n  \"chatChannels\": []\n}\n"
  },
  {
    "path": "packages/app/config/iris.json",
    "content": "{\n  \"appName\": \"iris\",\n  \"appNameCapitalized\": \"Iris\",\n  \"appTitle\": \"iris\",\n  \"hostname\": \"iris.to\",\n  \"nip05Domain\": \"iris.to\",\n  \"icon\": \"/img/icon128.png\",\n  \"navLogo\": \"/img/icon128.png\",\n  \"publicDir\": \"public/iris\",\n  \"httpCache\": \"\",\n  \"animalNamePlaceholders\": true,\n  \"defaultZapPoolFee\": 0.5,\n  \"features\": {\n    \"analytics\": true,\n    \"subscriptions\": true,\n    \"deck\": true,\n    \"zapPool\": true,\n    \"communityLeaders\": true\n  },\n  \"defaultPreferences\": {\n    \"hideMutedNotes\": true,\n    \"defaultRootTab\": \"for-you\"\n  },\n  \"signUp\": {\n    \"quickStart\": true,\n    \"defaultFollows\": [\"npub1wnwwcv0a8wx0m9stck34ajlwhzuua68ts8mw3kjvspn42dcfyjxs4n95l8\"]\n  },\n  \"media\": {\n    \"bypassImgProxyError\": true,\n    \"preferLargeMedia\": true\n  },\n  \"communityLeaders\": {\n    \"list\": \"naddr1qq4xc6tnw3ez6vp58y6rywpjxckngdtyxukngwr9vckkze33vcknzcnrxcenje35xqmn2cczyp3lucccm3v9s087z6qslpkap8schltk427zfgqgrn3g2menq5zw6qcyqqq82vqprpmhxue69uhhyetvv9ujuumwdae8gtnnda3kjctv7rajfl\"\n  },\n  \"noteCreatorToast\": false,\n  \"hideFromNavbar\": [],\n  \"eventLinkPrefix\": \"note\",\n  \"profileLinkPrefix\": \"npub\",\n  \"showPowIcon\": false,\n  \"defaultRelays\": {\n    \"wss://relay.snort.social/\": { \"read\": true, \"write\": true },\n    \"wss://nostr.wine/\": { \"read\": true, \"write\": false },\n    \"wss://eden.nostr.land/\": { \"read\": true, \"write\": false },\n    \"wss://relay.nostr.band/\": { \"read\": true, \"write\": true },\n    \"wss://relay.damus.io/\": { \"read\": true, \"write\": true }\n  },\n  \"chatChannels\": [{ \"type\": \"telegram\", \"value\": \"https://t.me/irismessenger\" }],\n  \"alby\": {\n    \"clientId\": \"5rYcHDrlDb\",\n    \"clientSecret\": \"QAI3QmgiaPH3BfTMzzFd\"\n  }\n}\n"
  },
  {
    "path": "packages/app/config/meku.json",
    "content": "{\n  \"appName\": \"めく\",\n  \"appNameCapitalized\": \"めく\",\n  \"appTitle\": \"めく\",\n  \"hostname\": \"meku.app\",\n  \"nip05Domain\": \"meku.app\",\n  \"icon\": \"/nostr.jpg\",\n  \"navLogo\": null,\n  \"publicDir\": \"public/nostr\",\n  \"httpCache\": \"\",\n  \"animalNamePlaceholders\": false,\n  \"defaultZapPoolFee\": 0,\n  \"features\": {\n    \"analytics\": true,\n    \"subscriptions\": false,\n    \"deck\": false,\n    \"zapPool\": false,\n    \"communityLeaders\": false,\n    \"nostrAddress\": false,\n    \"pushNotifications\": true\n  },\n  \"signUp\": {\n    \"quickStart\": false,\n    \"defaultFollows\": []\n  },\n  \"defaultPreferences\": {\n    \"hideMutedNotes\": false,\n    \"defaultRootTab\": \"following\",\n    \"language\": \"ja\"\n  },\n  \"media\": {\n    \"bypassImgProxyError\": false,\n    \"preferLargeMedia\": true\n  },\n  \"communityLeaders\": null,\n  \"noteCreatorToast\": false,\n  \"hideFromNavbar\": [],\n  \"deckSubKind\": 1,\n  \"showPowIcon\": true,\n  \"showNip05\": true,\n  \"eventLinkPrefix\": \"nevent\",\n  \"profileLinkPrefix\": \"nprofile\",\n  \"defaultRelays\": {\n    \"wss://relay.nostr.wirednet.jp/\": { \"read\": true, \"write\": true },\n    \"wss://yabu.me/\": { \"read\": true, \"write\": true },\n    \"wss://nos.lol/\": { \"read\": true, \"write\": true }\n  },\n  \"alby\": null,\n  \"chatChannels\": null\n}\n"
  },
  {
    "path": "packages/app/config/nostr.json",
    "content": "{\n  \"appName\": \"Nostr\",\n  \"appNameCapitalized\": \"Nostr\",\n  \"appTitle\": \"Nostr\",\n  \"hostname\": \"nostr.com\",\n  \"nip05Domain\": \"nostr.com\",\n  \"icon\": \"/nostr.jpg\",\n  \"navLogo\": null,\n  \"publicDir\": \"public/nostr\",\n  \"httpCache\": \"\",\n  \"animalNamePlaceholders\": false,\n  \"defaultZapPoolFee\": 0,\n  \"features\": {\n    \"analytics\": false,\n    \"subscriptions\": false,\n    \"deck\": false,\n    \"zapPool\": false,\n    \"communityLeaders\": false,\n    \"nostrAddress\": false,\n    \"pushNotifications\": false\n  },\n  \"signUp\": {\n    \"quickStart\": false,\n    \"defaultFollows\": []\n  },\n  \"defaultPreferences\": {\n    \"hideMutedNotes\": false,\n    \"defaultRootTab\": \"following\"\n  },\n  \"media\": {\n    \"bypassImgProxyError\": false,\n    \"preferLargeMedia\": true\n  },\n  \"communityLeaders\": null,\n  \"noteCreatorToast\": true,\n  \"hideFromNavbar\": [],\n  \"deckSubKind\": 1,\n  \"showPowIcon\": true,\n  \"showNip05\": true,\n  \"eventLinkPrefix\": \"nevent\",\n  \"profileLinkPrefix\": \"nprofile\",\n  \"defaultRelays\": {\n    \"wss://relay.snort.social/\": { \"read\": true, \"write\": true },\n    \"wss://nostr.wine/\": { \"read\": true, \"write\": false },\n    \"wss://eden.nostr.land/\": { \"read\": true, \"write\": false },\n    \"wss://nos.lol/\": { \"read\": true, \"write\": true }\n  },\n  \"alby\": null,\n  \"chatChannels\": null\n}\n"
  },
  {
    "path": "packages/app/config/phoenix.json",
    "content": "{\n  \"appName\": \"Phoenix\",\n  \"appNameCapitalized\": \"Phoenix\",\n  \"appTitle\": \"Phoenix - Nostr\",\n  \"hostname\": \"phoenix.social\",\n  \"nip05Domain\": \"phoenix.social\",\n  \"icon\": \"/logo_256.png\",\n  \"navLogo\": null,\n  \"publicDir\": \"public/phoenix\",\n  \"httpCache\": \"\",\n  \"animalNamePlaceholders\": false,\n  \"defaultZapPoolFee\": 1,\n  \"features\": {\n    \"analytics\": true,\n    \"subscriptions\": false,\n    \"deck\": false,\n    \"zapPool\": false,\n    \"communityLeaders\": false,\n    \"nostrAddress\": true,\n    \"pushNotifications\": true\n  },\n  \"signUp\": {\n    \"quickStart\": false,\n    \"defaultFollows\": [\"npub1sn0rtcjcf543gj4wsg7fa59s700d5ztys5ctj0g69g2x6802npjqhjjtws\"]\n  },\n  \"defaultPreferences\": {\n    \"hideMutedNotes\": false,\n    \"defaultRootTab\": \"following\"\n  },\n  \"media\": {\n    \"bypassImgProxyError\": false,\n    \"preferLargeMedia\": true\n  },\n  \"communityLeaders\": {\n    \"list\": \"naddr1qq4xc6tnw3ez6vp58y6rywpjxckngdtyxukngwr9vckkze33vcknzcnrxcenje35xqmn2cczyp3lucccm3v9s087z6qslpkap8schltk427zfgqgrn3g2menq5zw6qcyqqq82vqprpmhxue69uhhyetvv9ujuumwdae8gtnnda3kjctv7rajfl\"\n  },\n  \"noteCreatorToast\": false,\n  \"hideFromNavbar\": [],\n  \"deckSubKind\": 1,\n  \"showPowIcon\": true,\n  \"showNip05\": true,\n  \"eventLinkPrefix\": \"nevent\",\n  \"profileLinkPrefix\": \"nprofile\",\n  \"defaultRelays\": {\n    \"wss://relay.phoenix.social/\": {\n      \"read\": true,\n      \"write\": true\n    },\n    \"wss://nostr.wine/\": {\n      \"read\": true,\n      \"write\": false\n    },\n    \"wss://relay.damus.io/\": {\n      \"read\": true,\n      \"write\": true\n    },\n    \"wss://nos.lol/\": {\n      \"read\": true,\n      \"write\": true\n    }\n  },\n  \"alby\": {\n    \"clientId\": \"pohiJjPhQR\",\n    \"clientSecret\": \"GAl1YKLA3FveK1gLBYok\"\n  },\n  \"chatChannels\": []\n}\n"
  },
  {
    "path": "packages/app/config/soloco.json",
    "content": "{\n  \"appName\": \"Soloco\",\n  \"appNameCapitalized\": \"Soloco\",\n  \"appTitle\": \"Soloco\",\n  \"hostname\": \"soloco.nl\",\n  \"nip05Domain\": \"soloco.nl\",\n  \"icon\": \"/nostrich_512.png\",\n  \"favicon\": \"public/favicon.ico\",\n  \"appleTouchIconUrl\": \"/nostrich_512.png\",\n  \"navLogo\": null,\n  \"publicDir\": \"public/snort\",\n  \"httpCache\": \"\",\n  \"animalNamePlaceholders\": false,\n  \"defaultZapPoolFee\": 0,\n  \"features\": {\n    \"analytics\": false,\n    \"subscriptions\": false,\n    \"deck\": false,\n    \"zapPool\": false,\n    \"communityLeaders\": false,\n    \"nostrAddress\": false,\n    \"pushNotifications\": true\n  },\n  \"signUp\": {\n    \"quickStart\": false,\n    \"defaultFollows\": []\n  },\n  \"defaultPreferences\": {\n    \"hideMutedNotes\": false,\n    \"defaultRootTab\": \"following\",\n    \"language\": \"nl\"\n  },\n  \"media\": {\n    \"bypassImgProxyError\": false,\n    \"preferLargeMedia\": true\n  },\n  \"communityLeaders\": null,\n  \"noteCreatorToast\": true,\n  \"hideFromNavbar\": [],\n  \"deckSubKind\": 1,\n  \"showPowIcon\": true,\n  \"showNip05\": true,\n  \"eventLinkPrefix\": \"nevent\",\n  \"profileLinkPrefix\": \"nprofile\",\n  \"defaultRelays\": {\n    \"wss://soloco.nl/\": { \"read\": true, \"write\": false }\n  },\n  \"alby\": null,\n  \"chatChannels\": null\n}\n"
  },
  {
    "path": "packages/app/custom.d.ts",
    "content": "/// <reference types=\"@webbtc/webln-types\" />\n/// <reference types=\"vite/client\" />\n\ndeclare module \"*.jpg\" {\n  const value: unknown\n  export default value\n}\n\ndeclare module \"*.svg\" {\n  const value: unknown\n  export default value\n}\n\ndeclare module \"*.webp\" {\n  const value: string\n  export default value\n}\n\ndeclare module \"*.png\" {\n  const value: string\n  export default value\n}\n\ndeclare module \"*.css\" {\n  const stylesheet: CSSStyleSheet\n  export default stylesheet\n}\n\ndeclare module \"translations/*.json\" {\n  const value: Record<string, string>\n  export default value\n}\n\ndeclare module \"*.md\" {\n  const value: string\n  export default value\n}\n\ndeclare module \"emojilib\" {\n  const value: Record<string, string>\n  export default value\n}\n\ndeclare const CONFIG: {\n  appName: string\n  appNameCapitalized: string\n  appTitle: string\n  hostname: string\n  nip05Domain: string\n  icon: string\n  navLogo: string | null\n  httpCache: string\n  animalNamePlaceholders: boolean\n  defaultZapPoolFee: number\n  features: {\n    analytics: boolean\n    subscriptions: boolean\n    zapPool: boolean\n    deck: boolean\n    communityLeaders: boolean\n    nostrAddress: boolean\n    pushNotifications: boolean\n  }\n  defaultPreferences: {\n    hideMutedNotes: boolean\n    defaultRootTab: \"following\" | \"for-you\"\n    imgProxyConfig: { url: string; key: string; salt: string } | undefined\n  }\n  signUp: {\n    quickStart: boolean\n    defaultFollows: Array<string>\n  }\n  media: {\n    bypassImgProxyError: boolean\n    preferLargeMedia: boolean\n  }\n  communityLeaders?: {\n    list: string\n  }\n\n  // Filter urls from nav sidebar\n  hideFromNavbar: Array<string>\n\n  // Limit deck to certain subscriber tier\n  deckSubKind?: number\n\n  showDeck?: boolean\n\n  // Create toast notifications when publishing notes\n  noteCreatorToast: boolean\n\n  eventLinkPrefix: NostrPrefix\n  profileLinkPrefix: NostrPrefix\n  defaultRelays: Record<string, RelaySettings>\n  showPowIcon: boolean\n  // show nip5 beside usernames\n  showNip05: boolean\n\n  // Alby wallet oAuth config\n  alby?: {\n    clientId: string\n    clientSecret: string\n  }\n\n  // public chat channels for site\n  chatChannels?: Array<{\n    type: \"telegram\"\n    value: string\n  }>\n}\n\n/**\n * Build git hash\n */\ndeclare const __SNORT_VERSION__: string\n"
  },
  {
    "path": "packages/app/index.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <meta\n      name=\"viewport\"\n      content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=yes, viewport-fit=cover\" />\n    <meta name=\"theme-color\" content=\"#000000\" />\n\n    <!-- Primary Meta Tags -->\n    <title>{{APP_TITLE}}</title>\n    <meta name=\"title\" content=\"{{APP_TITLE}}\" />\n    <meta\n      name=\"description\"\n      content=\"{{APP_NAME}} is a feature-packed, decentralized social media client built on Nostr protocol. Fast, censorship-resistant, and open source. Connect with the decentralized web.\" />\n    <meta\n      name=\"keywords\"\n      content=\"nostr, {{APP_NAME}}, fast, decentralized, social media, censorship resistant, open source, web3, decentralized social network, nostr client\" />\n    <meta name=\"author\" content=\"{{APP_NAME}}\" />\n\n    <!-- Open Graph / Facebook -->\n    <meta property=\"og:type\" content=\"website\" />\n    <meta property=\"og:url\" content=\"{{HOSTNAME}}\" />\n    <meta property=\"og:title\" content=\"{{APP_TITLE}}\" />\n    <meta\n      property=\"og:description\"\n      content=\"{{APP_NAME}} is a feature-packed, decentralized social media client built on Nostr protocol. Fast, censorship-resistant, and open source.\" />\n    <meta property=\"og:image\" content=\"{{OG_IMAGE}}\" />\n    <meta property=\"og:site_name\" content=\"{{APP_NAME}}\" />\n\n    <!-- Twitter -->\n    <meta name=\"twitter:card\" content=\"summary_large_image\" />\n    <meta name=\"twitter:url\" content=\"{{HOSTNAME}}\" />\n    <meta name=\"twitter:title\" content=\"{{APP_TITLE}}\" />\n    <meta\n      name=\"twitter:description\"\n      content=\"{{APP_NAME}} is a feature-packed, decentralized social media client built on Nostr protocol. Fast, censorship-resistant, and open source.\" />\n    <meta name=\"twitter:image\" content=\"{{OG_IMAGE}}\" />\n\n    <!-- Canonical URL -->\n    <meta name=\"robots\" content=\"index, follow\" />\n    <link rel=\"canonical\" href=\"{{HOSTNAME}}\" />\n\n    <link rel=\"apple-touch-icon\" href=\"/img/apple-touch-icon.png\" />\n    <link rel=\"manifest\" href=\"/manifest.json\" />\n    <link rel=\"icon\" href=\"/favicon.png\" />\n  </head>\n\n  <body>\n    <div id=\"root\"></div>\n    <script type=\"module\" src=\"/src/index.tsx\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "packages/app/package.json",
    "content": "{\n  \"name\": \"@snort/app\",\n  \"version\": \"0.5.2\",\n  \"type\": \"module\",\n  \"dependencies\": {\n    \"@cashu/cashu-ts\": \"^2.7.2\",\n    \"@livekit/components-react\": \"^2.9.15\",\n    \"@livekit/protocol\": \"^1.42.2\",\n    \"@noble/curves\": \"^2.0.1\",\n    \"@noble/hashes\": \"^2.0.1\",\n    \"@radix-ui/react-dropdown-menu\": \"^2.1.16\",\n    \"@radix-ui/react-hover-card\": \"^1.1.15\",\n    \"@scure/base\": \"^2.0.0\",\n    \"@scure/bip32\": \"^2.0.1\",\n    \"@scure/bip39\": \"^2.0.1\",\n    \"@snort/shared\": \"workspace:*\",\n    \"@snort/system\": \"workspace:*\",\n    \"@snort/system-react\": \"workspace:*\",\n    \"@snort/system-wasm\": \"workspace:*\",\n    \"@snort/wallet\": \"workspace:*\",\n    \"@openai/agents\": \"^0.8.3\",\n    \"@snort/worker-relay\": \"workspace:*\",\n    \"openai\": \"^6.34.0\",\n    \"zod\": \"^4.0.0\",\n    \"@uidotdev/usehooks\": \"^2.4.1\",\n    \"@void-cat/api\": \"^1.0.12\",\n    \"classnames\": \"^2.5.1\",\n    \"comlink\": \"^4.4.2\",\n    \"debug\": \"^4.4.3\",\n    \"emojilib\": \"^4.0.2\",\n    \"eventemitter3\": \"^5.0.1\",\n    \"fuse.js\": \"^7.1.0\",\n    \"latlon-geohash\": \"^2.0.0\",\n    \"light-bolt11-decoder\": \"^3.2.0\",\n    \"livekit-client\": \"^2.15.11\",\n    \"lottie-react\": \"^2.4.1\",\n    \"marked\": \"^16.4.1\",\n    \"marked-footnote\": \"^1.4.0\",\n    \"match-sorter\": \"^8.1.0\",\n    \"qr-code-styling\": \"^1.9.2\",\n    \"react\": \"^19.2.3\",\n    \"react-dom\": \"^19.2.3\",\n    \"react-force-graph-3d\": \"^1.29.0\",\n    \"react-intersection-observer\": \"^9.16.0\",\n    \"react-intl\": \"^7.1.14\",\n    \"react-router-dom\": \"^7.9.4\",\n    \"react-tag-input-component\": \"^2.0.2\",\n    \"react-textarea-autosize\": \"^8.5.9\",\n    \"recharts\": \"^3.3.0\",\n    \"tslib\": \"^2.8.1\",\n    \"typescript-lru-cache\": \"^2.0.0\",\n    \"use-long-press\": \"^3.3.0\",\n    \"use-sync-external-store\": \"^1.6.0\",\n    \"uuid\": \"^13.0.0\",\n    \"workbox-cacheable-response\": \"^7.3.0\",\n    \"workbox-core\": \"^7.3.0\",\n    \"workbox-expiration\": \"^7.3.0\",\n    \"workbox-precaching\": \"^7.3.0\",\n    \"workbox-routing\": \"^7.3.0\",\n    \"workbox-strategies\": \"^7.3.0\"\n  },\n  \"scripts\": {\n    \"start\": \"bunx --bun vite\",\n    \"build\": \"bunx vite build\",\n    \"serve\": \"bunx --bun vite preview\",\n    \"intl-extract\": \"bunx --bun formatjs extract 'src/**/*.ts*' --ignore='**/*.d.ts' --out-file src/lang.json --flatten true\",\n    \"intl-compile\": \"bunx --bun formatjs compile src/lang.json --ast --out-file src/translations/en.json\",\n    \"eslint\": \"bunx --bun eslint .\"\n  },\n  \"browserslist\": {\n    \"production\": [\"chrome >= 67\", \"edge >= 79\", \"firefox >= 68\", \"opera >= 54\", \"safari >= 14\"],\n    \"development\": [\"last 1 chrome version\", \"last 1 firefox version\", \"last 1 safari version\"]\n  },\n  \"devDependencies\": {\n    \"@formatjs/cli\": \"^6.7.4\",\n    \"@types/config\": \"^3.3.5\",\n    \"@types/debug\": \"^4.1.12\",\n    \"@types/latlon-geohash\": \"^2.0.4\",\n    \"@types/node\": \"^24.8.1\",\n    \"@types/react\": \"^19.2.2\",\n    \"@types/react-dom\": \"^19.2.2\",\n    \"@types/three\": \"^0.180.0\",\n    \"@types/use-sync-external-store\": \"^1.5.0\",\n    \"@types/uuid\": \"^11.0.0\",\n    \"@types/webscopeio__react-textarea-autocomplete\": \"^4.7.5\",\n    \"@types/webtorrent\": \"^0.110.1\",\n    \"@vitejs/plugin-basic-ssl\": \"^2.1.0\",\n    \"@vitejs/plugin-react\": \"^5.0.4\",\n    \"@webbtc/webln-types\": \"^3.0.0\",\n    \"@webscopeio/react-textarea-autocomplete\": \"^4.9.2\",\n    \"babel-plugin-formatjs\": \"^10.5.41\",\n    \"@tailwindcss/vite\": \"^4.1.18\",\n    \"config\": \"^4.1.1\",\n    \"prop-types\": \"^15.8.1\",\n    \"rollup-plugin-visualizer\": \"^6.0.5\",\n    \"tailwindcss\": \"^4.1.14\",\n    \"tinybench\": \"^5.0.1\",\n    \"typescript\": \"^5.9.3\",\n    \"vite\": \"^7.1.10\",\n    \"vite-plugin-eslint\": \"^1.8.1\",\n    \"vite-plugin-pwa\": \"^1.1.0\",\n    \"vite-plugin-version-mark\": \"^0.2.2\",\n    \"vitest\": \"^3.2.4\"\n  }\n}\n"
  },
  {
    "path": "packages/app/public/iris/.well-known/assetlinks.json",
    "content": "[\n  {\n    \"relation\": [\"delegate_permission/common.handle_all_urls\"],\n    \"target\": {\n      \"namespace\": \"android_app\",\n      \"package_name\": \"to.iris.twa\",\n      \"sha256_cert_fingerprints\": [\n        \"63:B5:70:E8:F1:75:7E:D6:EF:81:11:66:F4:9D:47:AB:49:3C:2E:00:B9:67:92:40:89:A5:03:0B:96:B9:40:09\"\n      ]\n    }\n  }\n]\n"
  },
  {
    "path": "packages/app/public/iris/_headers",
    "content": "/*\n  Content-Security-Policy: default-src 'self'; manifest-src *; child-src 'none'; worker-src 'self'; frame-src https://youtube.com https://www.youtube.com https://platform.twitter.com https://embed.tidal.com https://w.soundcloud.com https://www.mixcloud.com https://open.spotify.com https://player.twitch.tv https://embed.music.apple.com https://embed.wavlake.com https://challenges.cloudflare.com; style-src 'self' 'unsafe-inline'; connect-src *; img-src * data: blob:; font-src 'self'; media-src * blob:; script-src 'self' 'wasm-unsafe-eval' https://platform.twitter.com https://embed.tidal.com https://challenges.cloudflare.com;\n/service-worker.js\n  Cache-Control: max-age=604800, must-revalidate;"
  },
  {
    "path": "packages/app/public/iris/manifest.json",
    "content": "{\n  \"short_name\": \"Iris\",\n  \"name\": \"Iris\",\n  \"description\": \"Fast nostr web ui\",\n  \"id\": \"/\",\n  \"icons\": [\n    {\n      \"src\": \"/img/android-chrome-192x192.png\",\n      \"sizes\": \"192x192\",\n      \"type\": \"image/png\"\n    },\n    {\n      \"src\": \"/img/android-chrome-512x512.png\",\n      \"sizes\": \"512x512\",\n      \"type\": \"image/png\",\n      \"purpose\": \"any\"\n    },\n    {\n      \"src\": \"/img/maskable_icon.png\",\n      \"sizes\": \"640x640\",\n      \"type\": \"image/png\",\n      \"purpose\": \"maskable\"\n    },\n    {\n      \"src\": \"/img/maskable_icon_x192.png\",\n      \"sizes\": \"192x192\",\n      \"type\": \"image/png\",\n      \"purpose\": \"maskable\"\n    }\n  ],\n  \"start_url\": \"/\",\n  \"display\": \"standalone\",\n  \"theme_color\": \"#000000\",\n  \"background_color\": \"#000000\",\n  \"protocol_handlers\": [\n    {\n      \"protocol\": \"web+nostr\",\n      \"url\": \"/%s\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/public/iris/robots.txt",
    "content": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\n"
  },
  {
    "path": "packages/app/public/nostr/_headers",
    "content": "/*\n  Content-Security-Policy: default-src 'self'; manifest-src *; child-src 'none'; worker-src 'self'; frame-src https://youtube.com https://www.youtube.com https://platform.twitter.com https://embed.tidal.com https://w.soundcloud.com https://www.mixcloud.com https://open.spotify.com https://player.twitch.tv https://embed.music.apple.com https://embed.wavlake.com https://challenges.cloudflare.com; style-src 'self' 'unsafe-inline'; connect-src *; img-src * data: blob:; font-src 'self'; media-src * blob:; script-src 'self' 'wasm-unsafe-eval' https://platform.twitter.com https://embed.tidal.com https://challenges.cloudflare.com;"
  },
  {
    "path": "packages/app/public/phoenix/.well-known/apple-app-site-association",
    "content": "{\n  \"applinks\": {\n    \"details\": [\n      {\n        \"appIDs\": [\n          \"snort.social.app\"\n        ]\n      }\n    ]\n  },\n  \"webcredentials\": {\n    \"apps\": [\n      \"snort.social.app\"\n    ]\n  }\n}\n"
  },
  {
    "path": "packages/app/public/phoenix/.well-known/assetlinks.json",
    "content": "[\n  {\n    \"relation\": [\"delegate_permission/common.handle_all_urls\"],\n    \"target\": {\n      \"namespace\": \"android_app\",\n      \"package_name\": \"social.snort.app\",\n      \"sha256_cert_fingerprints\": [\n        \"78:CE:8A:F7:C1:E2:30:12:77:55:BF:0E:86:E4:5C:BA:99:93:A0:D7:D7:42:F8:27:8B:C9:1B:AC:FC:8A:85:05\",\n        \"FC:C1:CA:02:C0:81:81:0C:1F:EC:1E:38:CA:38:61:62:6B:6E:90:88:62:DE:4A:66:FC:EC:08:33:B6:94:EE:3C\"\n      ]\n    }\n  }\n]\n"
  },
  {
    "path": "packages/app/public/phoenix/_headers",
    "content": "/*\n  Content-Security-Policy: default-src 'self'; manifest-src *; child-src 'none'; worker-src 'self'; frame-src https://youtube.com https://www.youtube.com https://platform.twitter.com https://embed.tidal.com https://w.soundcloud.com https://www.mixcloud.com https://open.spotify.com https://player.twitch.tv https://embed.music.apple.com https://embed.wavlake.com https://challenges.cloudflare.com; style-src 'self' 'unsafe-inline'; connect-src *; img-src * data: blob:; font-src 'self'; media-src * blob:; script-src 'self' 'wasm-unsafe-eval' https://platform.twitter.com https://embed.tidal.com https://challenges.cloudflare.com;\n/service-worker.js\n  Cache-Control: max-age=604800, must-revalidate;"
  },
  {
    "path": "packages/app/public/phoenix/manifest.json",
    "content": "{\n  \"short_name\": \"Phoenix\",\n  \"name\": \"phoenix.social - Nostr interface\",\n  \"description\": \"Fast nostr web ui\",\n  \"id\": \"/\",\n  \"icons\": [\n    {\n      \"src\": \"phoenix_256.png\",\n      \"type\": \"image/png\",\n      \"sizes\": \"256x256\"\n    }\n  ],\n  \"start_url\": \"/\",\n  \"display\": \"standalone\",\n  \"theme_color\": \"#000000\",\n  \"background_color\": \"#000000\",\n  \"protocol_handlers\": [\n    {\n      \"protocol\": \"web+nostr\",\n      \"url\": \"/%s\"\n    }\n  ],\n  \"screenshots\": [],\n  \"display_override\": [\"fullscreen\"],\n  \"related_applications\": [\n    {\n      \"platform\": \"play\",\n      \"url\": \"https://play.google.com/store/apps/details?id=social.snort.app\",\n      \"id\": \"social.snort.app\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/public/phoenix/robots.txt",
    "content": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\nSitemap: https://api.snort.social/api/v1/sitemap/index.xml"
  },
  {
    "path": "packages/app/public/snort/.well-known/apple-app-site-association",
    "content": "{\n  \"applinks\": {\n    \"details\": [\n      {\n        \"appIDs\": [\n          \"snort.social.app\"\n        ]\n      }\n    ]\n  },\n  \"webcredentials\": {\n    \"apps\": [\n      \"snort.social.app\"\n    ]\n  }\n}\n"
  },
  {
    "path": "packages/app/public/snort/.well-known/assetlinks.json",
    "content": "[\n  {\n    \"relation\": [\"delegate_permission/common.handle_all_urls\"],\n    \"target\": {\n      \"namespace\": \"android_app\",\n      \"package_name\": \"social.snort.app\",\n      \"sha256_cert_fingerprints\": [\n        \"78:CE:8A:F7:C1:E2:30:12:77:55:BF:0E:86:E4:5C:BA:99:93:A0:D7:D7:42:F8:27:8B:C9:1B:AC:FC:8A:85:05\",\n        \"FC:C1:CA:02:C0:81:81:0C:1F:EC:1E:38:CA:38:61:62:6B:6E:90:88:62:DE:4A:66:FC:EC:08:33:B6:94:EE:3C\"\n      ]\n    }\n  }\n]\n"
  },
  {
    "path": "packages/app/public/snort/_headers",
    "content": "/*\n  Content-Security-Policy: default-src 'self'; manifest-src *; child-src 'none'; worker-src 'self'; frame-src https://youtube.com https://www.youtube.com https://platform.twitter.com https://embed.tidal.com https://w.soundcloud.com https://www.mixcloud.com https://open.spotify.com https://player.twitch.tv https://embed.music.apple.com https://embed.wavlake.com https://challenges.cloudflare.com; style-src 'self' 'unsafe-inline'; connect-src *; img-src * data: blob:; font-src 'self'; media-src * blob:; script-src 'self' 'wasm-unsafe-eval' https://platform.twitter.com https://embed.tidal.com https://challenges.cloudflare.com;\n/service-worker.js\n  Cache-Control: max-age=604800, must-revalidate;"
  },
  {
    "path": "packages/app/public/snort/manifest.json",
    "content": "{\n  \"short_name\": \"Snort\",\n  \"name\": \"snort.social - Nostr interface\",\n  \"description\": \"Fast nostr web ui\",\n  \"id\": \"/\",\n  \"icons\": [\n    {\n      \"src\": \"nostrich_256.png\",\n      \"type\": \"image/png\",\n      \"sizes\": \"256x256\"\n    },\n    {\n      \"src\": \"nostrich_512.png\",\n      \"type\": \"image/png\",\n      \"sizes\": \"512x512\"\n    }\n  ],\n  \"start_url\": \"/\",\n  \"display\": \"standalone\",\n  \"theme_color\": \"#000000\",\n  \"background_color\": \"#000000\",\n  \"protocol_handlers\": [\n    {\n      \"protocol\": \"web+nostr\",\n      \"url\": \"/%s\"\n    }\n  ],\n  \"screenshots\": [],\n  \"display_override\": [\"fullscreen\"],\n  \"related_applications\": [\n    {\n      \"platform\": \"play\",\n      \"url\": \"https://play.google.com/store/apps/details?id=social.snort.app\",\n      \"id\": \"social.snort.app\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/public/snort/robots.txt",
    "content": "# https://www.robotstxt.org/robotstxt.html\nUser-agent: *\nDisallow:\nSitemap: https://api.snort.social/api/v1/sitemap/index.xml"
  },
  {
    "path": "packages/app/src/Agent/system-prompt.ts",
    "content": "import { unixNow } from \"@snort/shared\"\n\nexport const SnortSystemPrompt = `You are an AI assistant integrated with Snort, a decentralized social media client built on the Nostr protocol. You can perform actions on behalf of the user by using the available tools.\n\n## About Snort\n\nSnort is a web-based Nostr client that allows users to:\n- Post text notes and media\n- Follow other users\n- React to and repost content\n- Send and receive Lightning Network payments (zaps)\n- Manage relays and privacy settings\n- Browse decentralized social content\n\n### User Search\n\nUse **snort_search_username** to find users by name or NIP-05 address:\n- Returns matching profiles with pubkeys, display names, and NIP-05 addresses\n- Use this before following or mentioning users when you only know their name\n- Example: snort_search_username({ query: \"jack\" })\n\n## Querying Nostr Relays with snort_query_nostr\n\nWhen using snort_query_nostr, you need to construct Nostr REQ filter objects. The filters are passed as an array of filter objects.\n\n### Filter Structure\n\nEach filter object can contain these keys:\n- **authors**: Array of 64-character hex pubkeys (NOT npub format). Example: [\"8e9f...\"]\n- **kinds**: Array of event kind numbers. Common kinds:\n  - 1: Text notes\n  - 2: Recommended relays\n  - 3: Contact list (follows)\n  - 4: Direct messages\n  - 6: Reposts\n  - 7: Reactions\n  - 40-41: Channel events\n  - 9734-9735: Zap requests\n- **ids**: Array of event IDs (64-char hex)\n- **#e**: Array of event IDs referenced (for replies/mentions)\n- **#p**: Array of pubkey hex that were mentioned\n- **#t**: Array of hashtags (lowercase, without #)\n- **#a**: Array of replace event tag references ({kind}:{author-pubkey-hex}:{d-tag})\n- **search**: Free-text search string\n- **since**: Unix timestamp (seconds) - only events after this time\n- **until**: Unix timestamp (seconds) - only events before this time\n- **limit**: Maximum number of results (default 50)\n\n### Common Query Patterns\n\n**Get recent posts from specific users:**\n\\`\\`\\`\n[{ \"authors\": [\"hex_pubkey_1\", \"hex_pubkey_2\"], \"kinds\": [1], \"limit\": 50 }]\n\\`\\`\\`\n\n**Search for hashtag:**\n\\`\\`\\`\n[{ \"kinds\": [1], \"#t\": [\"bitcoin\"], \"limit\": 20 }]\n\\`\\`\\`\n\n**Find replies to an event:**\n\\`\\`\\`\n[{ \"kinds\": [1], \"#e\": [\"event_id\"], \"limit\": 50 }]\n\\`\\`\\`\n\n**Find posts mentioning a user:**\n\\`\\`\\`\n[{ \"kinds\": [1], \"#p\": [\"hex_pubkey\"], \"limit\": 20 }]\n\\`\\`\\`\n\n**Text search:**\n\\`\\`\\`\n[{ \"kinds\": [1], \"search\": \"bitcoin price\", \"limit\": 20 }]\n\\`\\`\\`\n\n**Get user's contact list (follows):**\n\\`\\`\\`\n[{ \"authors\": [\"hex_pubkey\"], \"kinds\": [3], \"limit\": 1 }]\n\\`\\`\\`\n\n## Guidelines\n\n- Always verify user is logged in before posting or making changes\n- Use proper Nostr identifiers (hex for filters, npub for displaying to users)\n- Respect privacy - don't expose private keys or sensitive info\n- Be explicit when performing irreversible actions (posting, following, paying)\n- Confirm content with user before publishing posts\n- Handle errors gracefully\n- ALWAYS prefix npub/nprofile/naddr/nevent strings with nostr: for improved rendering\n- When mentioning other users or events in the content of notes, ALWAYS use nostr:npub NIP-21 entities, or use @npub for npub mentions\n\nThe current unix timestamp is ${unixNow()} or ${new Date()}\n`\n"
  },
  {
    "path": "packages/app/src/Cache/CommunityLeadersStore.tsx",
    "content": "import { ExternalStore } from \"@snort/shared\"\n\nclass CommunityLeadersStore extends ExternalStore<Array<string>> {\n  #leaders: Array<string> = []\n\n  setLeaders(arr: Array<string>) {\n    this.#leaders = arr\n    this.notifyChange()\n  }\n\n  takeSnapshot(): string[] {\n    return [...this.#leaders]\n  }\n}\n\nexport const LeadersStore = new CommunityLeadersStore()\n"
  },
  {
    "path": "packages/app/src/Cache/GiftWrapCache.ts",
    "content": "import { EventKind, type EventPublisher, type NostrEvent, type TaggedNostrEvent } from \"@snort/system\"\nimport type { CacheRelay } from \"@snort/system\"\n\nimport { findTag, unwrap } from \"@/Utils\"\n\nimport { RefreshFeedCache, type TWithCreated } from \"./RefreshFeedCache\"\n\nexport interface UnwrappedGift {\n  id: string\n  to: string\n  created_at: number\n  inner: NostrEvent\n  tags?: Array<Array<string>>\n}\n\nconst DecryptedContentCache = new Map<string, string>()\n\nexport function getCachedDecryptedContent(id: string): string | undefined {\n  return DecryptedContentCache.get(id)\n}\n\nexport function setCachedDecryptedContent(id: string, content: string) {\n  DecryptedContentCache.set(id, content)\n}\n\nconst NIP44_MIN_PAYLOAD_LEN = 132\n\nfunction isValidNip44Content(content: string): boolean {\n  return content.length >= NIP44_MIN_PAYLOAD_LEN\n}\n\nexport class GiftWrapCache extends RefreshFeedCache<UnwrappedGift> {\n  #relay: CacheRelay | undefined\n  #persistedIds: Set<string> = new Set()\n\n  constructor() {\n    super(\"GiftWrapCache\")\n  }\n\n  setRelay(relay: CacheRelay) {\n    this.#relay = relay\n  }\n\n  key(of: UnwrappedGift): string {\n    return of.id\n  }\n\n  buildSub(): void {}\n\n  takeSnapshot(): Array<UnwrappedGift> {\n    return [...this.cache.values()]\n  }\n\n  override async preload(): Promise<void> {\n    await super.preload()\n  }\n\n  override async onEvent(evs: Readonly<Array<TaggedNostrEvent>>, _: string, pub?: EventPublisher) {\n    if (!pub) return\n\n    const fresh = evs.filter(v => !this.#persistedIds.has(v.id) && !this.cache.has(v.id))\n    if (fresh.length === 0) return\n\n    const valid = fresh.filter(v => isValidNip44Content(v.content))\n\n    const unwrapped = (\n      await Promise.all(\n        valid.map(async v => {\n          try {\n            return {\n              id: v.id,\n              to: findTag(v, \"p\"),\n              created_at: v.created_at,\n              inner: await pub.unwrapGift(v),\n              raw: v,\n            } as UnwrappedGift & { raw: TaggedNostrEvent }\n          } catch (e) {\n            console.debug(e, v)\n          }\n        }),\n      )\n    )\n      .filter(a => a !== undefined)\n      .map(unwrap)\n\n    const failed = new Set<number>()\n    for (let i = 0; i < unwrapped.length; i++) {\n      const u = unwrapped[i]\n      if (u.inner.kind === EventKind.SealedRumor) {\n        try {\n          if (!isValidNip44Content(u.inner.content)) {\n            failed.add(i)\n            continue\n          }\n          const unsealed = await pub.unsealRumor(u.inner)\n          u.tags = unsealed.tags\n        } catch (e) {\n          console.debug(\"Failed to unseal rumor\", u.id, e)\n          failed.add(i)\n        }\n      }\n    }\n\n    const good = unwrapped.filter((_, i) => !failed.has(i))\n\n    if (this.#relay) {\n      const toPersist = good.filter(u => !this.#persistedIds.has(u.id))\n      if (toPersist.length > 0) {\n        try {\n          await Promise.all(toPersist.map(u => this.#relay?.event(u.raw)))\n          for (const u of toPersist) {\n            this.#persistedIds.add(u.id)\n          }\n        } catch (e) {\n          console.warn(\"GiftWrapCache: failed to persist to worker relay\", e)\n        }\n      }\n    }\n\n    const cleaned = good.map(({ raw, ...rest }) => rest)\n    await this.bulkSet(cleaned)\n  }\n\n  async loadPersistedAndDecrypt(pub: EventPublisher): Promise<void> {\n    if (!this.#relay) return\n    try {\n      const existing = await this.#relay.query([\"REQ\", \"giftwrap-load\", { kinds: [EventKind.GiftWrap] }])\n      for (const ev of existing) {\n        this.#persistedIds.add(ev.id)\n      }\n      const newEvs = existing.filter(a => !this.cache.has(a.id))\n      if (newEvs.length === 0) return\n\n      await this.onEvent(newEvs, \"\", pub)\n    } catch (e) {\n      console.warn(\"GiftWrapCache: failed to load persisted gift wraps\", e)\n    }\n  }\n\n  override async clear(): Promise<void> {\n    if (this.#relay) {\n      try {\n        await this.#relay.delete([\"REQ\", \"giftwrap-clear\", { kinds: [EventKind.GiftWrap] }])\n      } catch (e) {\n        console.warn(\"GiftWrapCache: failed to clear worker relay\", e)\n      }\n    }\n    this.#persistedIds.clear()\n    DecryptedContentCache.clear()\n    await super.clear()\n  }\n\n  search(): Promise<TWithCreated<UnwrappedGift>[]> {\n    throw new Error(\"Method not implemented.\")\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Cache/ProfileWorkerCache.ts",
    "content": "import { type CachedMetadata, type CacheRelay, EventKind, mapEventToProfile, type NostrEvent } from \"@snort/system\"\nimport { WorkerBaseCache } from \"./worker-cached\"\n\nexport class ProfileCacheRelayWorker extends WorkerBaseCache<CachedMetadata> {\n  constructor(relay: CacheRelay) {\n    super(EventKind.SetMetadata, relay)\n  }\n\n  name(): string {\n    return \"Profiles\"\n  }\n\n  maxSize(): number {\n    return 5_000\n  }\n\n  mapper(ev: NostrEvent): CachedMetadata | undefined {\n    return mapEventToProfile(ev)\n  }\n\n  override async preload(follows?: Array<string>) {\n    await super.preload()\n\n    // load relay lists for follows\n    if (follows) {\n      await this.preloadTable(`${this.name()}-preload-follows`, {\n        kinds: [EventKind.SetMetadata],\n        authors: follows,\n      })\n    }\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Cache/RefreshFeedCache.ts",
    "content": "import { FeedCache } from \"@snort/shared\"\nimport type { EventPublisher, RequestBuilder, TaggedNostrEvent } from \"@snort/system\"\n\nimport type { LoginSession } from \"@/Utils/Login\"\n\nexport type TWithCreated<T> = (T | Readonly<T>) & { created_at: number }\n\nexport abstract class RefreshFeedCache<T> extends FeedCache<TWithCreated<T>> {\n  abstract buildSub(session: LoginSession, rb: RequestBuilder): void\n  abstract onEvent(evs: Readonly<Array<TaggedNostrEvent>>, pubKey: string, pub?: EventPublisher): void\n\n  /**\n   * Get latest event\n   */\n  protected newest(filter?: (e: TWithCreated<T>) => boolean) {\n    let ret = 0\n    this.cache.forEach(v => {\n      if (!filter || filter(v)) {\n        ret = v.created_at > ret ? v.created_at : ret\n      }\n    })\n    return ret\n  }\n\n  override async preload(): Promise<void> {\n    await super.preload()\n    await this.buffer([...this.onTable])\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Cache/RelaysWorkerCache.ts",
    "content": "import { unixNowMs } from \"@snort/shared\"\nimport { type CacheRelay, EventKind, type NostrEvent, type UsersRelays, parseRelaysFromKind } from \"@snort/system\"\nimport { WorkerBaseCache } from \"./worker-cached\"\n\nexport class RelaysWorkerCache extends WorkerBaseCache<UsersRelays> {\n  constructor(relay: CacheRelay) {\n    super(EventKind.Relays, relay)\n  }\n\n  name(): string {\n    return \"Relays\"\n  }\n\n  maxSize(): number {\n    return 5_000\n  }\n\n  mapper(ev: NostrEvent): UsersRelays | undefined {\n    const relays = parseRelaysFromKind(ev)\n    if (!relays) return\n\n    return {\n      pubkey: ev.pubkey,\n      loaded: unixNowMs(),\n      created: ev.created_at,\n      relays: relays,\n    }\n  }\n\n  override async preload(follows?: Array<string>) {\n    await super.preload()\n\n    // load relay lists for follows\n    if (follows) {\n      await this.preloadTable(`${this.name()}-preload-follows`, {\n        kinds: [EventKind.Relays],\n        authors: follows,\n      })\n    }\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Cache/UserFollowsWorker.ts",
    "content": "import { unixNowMs } from \"@snort/shared\"\nimport { type CacheRelay, EventKind, type NostrEvent, type UsersFollows } from \"@snort/system\"\nimport { WorkerBaseCache } from \"./worker-cached\"\n\nexport class UserFollowsWorker extends WorkerBaseCache<UsersFollows> {\n  constructor(relay: CacheRelay) {\n    super(EventKind.ContactList, relay)\n  }\n\n  name(): string {\n    return \"Follows\"\n  }\n\n  maxSize(): number {\n    return 5_000\n  }\n\n  mapper(ev: NostrEvent): UsersFollows | undefined {\n    if (ev.kind !== EventKind.ContactList) return\n\n    return {\n      pubkey: ev.pubkey,\n      loaded: unixNowMs(),\n      created: ev.created_at,\n      follows: ev.tags,\n    }\n  }\n\n  override async preload(follows?: Array<string>) {\n    await super.preload()\n\n    // load relay lists for follows\n    if (follows) {\n      await this.preloadTable(`${this.name()}-preload-follows`, {\n        kinds: [EventKind.ContactList],\n        authors: follows,\n      })\n    }\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Cache/index.ts",
    "content": "import {\n  type CacheRelay,\n  Connection,\n  ConnectionCacheRelay,\n  UserFollowsCache,\n  UserProfileCache,\n  UserRelaysCache,\n} from \"@snort/system\"\nimport { WorkerRelayInterface } from \"@snort/worker-relay\"\nimport WorkerVite from \"@snort/worker-relay/src/worker?worker\"\n\nimport { GiftWrapCache } from \"./GiftWrapCache\"\nimport { ProfileCacheRelayWorker } from \"./ProfileWorkerCache\"\nimport { UserFollowsWorker } from \"./UserFollowsWorker\"\nimport { RelaysWorkerCache } from \"./RelaysWorkerCache\"\nimport { hasWasm } from \"@/Utils/wasm\"\n\nconst cacheRelay = localStorage.getItem(\"cache-relay\")\n\nconst workerRelay = hasWasm\n  ? new WorkerRelayInterface(\n      import.meta.env.DEV ? new URL(\"@snort/worker-relay/dist/esm/worker.mjs\", import.meta.url) : new WorkerVite(),\n    )\n  : undefined\n\nexport const Relay: CacheRelay | undefined = cacheRelay\n  ? new ConnectionCacheRelay(new Connection(cacheRelay, { read: true, write: true }))\n  : workerRelay\n\nasync function tryUseCacheRelay(url: string) {\n  try {\n    const conn = new Connection(url, { read: true, write: true })\n    await conn.connect(true)\n    localStorage.setItem(\"cache-relay\", url)\n    return conn\n  } catch (e) {\n    console.warn(e)\n  }\n}\n\nexport async function tryUseLocalRelay() {\n  let conn = await tryUseCacheRelay(\"ws://localhost:4869\")\n  if (!conn) {\n    conn = await tryUseCacheRelay(\"ws://umbrel:4848\")\n  }\n  return conn\n}\n\nexport async function initRelayWorker() {\n  try {\n    if (Relay instanceof ConnectionCacheRelay) {\n      await Relay.connection.connect(true)\n      return\n    }\n  } catch (e) {\n    localStorage.removeItem(\"cache-relay\")\n    console.error(e)\n    if (cacheRelay) {\n      window.location.reload()\n    }\n  }\n\n  try {\n    if (workerRelay) {\n      await workerRelay.debug(\"*\")\n      await workerRelay.init({\n        databasePath: \"relay.db\",\n        insertBatchSize: 100,\n      })\n      await workerRelay.configureSearchIndex({\n        1: [], // add index for kind 1, dont index tags\n      })\n    }\n  } catch (e) {\n    console.error(e)\n  }\n}\n\nexport const UserRelays = Relay ? new RelaysWorkerCache(Relay) : new UserRelaysCache()\nexport const UserFollows = Relay ? new UserFollowsWorker(Relay) : new UserFollowsCache()\nexport const ProfilesCache = Relay ? new ProfileCacheRelayWorker(Relay) : new UserProfileCache()\nexport const GiftsCache = new GiftWrapCache()\nif (Relay) {\n  GiftsCache.setRelay(Relay)\n}\n\nexport async function preload(follows?: Array<string>) {\n  const preloads = [\n    ProfilesCache.preload(follows),\n    GiftsCache.preload(),\n    UserRelays.preload(follows),\n    UserFollows.preload(follows),\n  ]\n  await Promise.all(preloads)\n}\n"
  },
  {
    "path": "packages/app/src/Cache/worker-cached.ts",
    "content": "import { type CachedTable, type CacheEvents, removeUndefined, unixNowMs } from \"@snort/shared\"\nimport type { CachedBase, CacheRelay, NostrEvent, ReqFilter } from \"@snort/system\"\nimport debug from \"debug\"\nimport { EventEmitter } from \"eventemitter3\"\nimport { LRUCache } from \"typescript-lru-cache\"\n\n/**\n * Generic worker relay based cache, key by pubkey\n */\nexport abstract class WorkerBaseCache<T extends CachedBase>\n  extends EventEmitter<CacheEvents<T>>\n  implements CachedTable<T>\n{\n  #relay: CacheRelay\n  #cache = new LRUCache<string, T>({ maxSize: this.maxSize() })\n  #keys = new Set<string>()\n  #log = debug(this.name())\n  /** Per-key subscribers for O(1) targeted notifications */\n  #keyListeners = new Map<string, Set<() => void>>()\n\n  constructor(\n    readonly kind: number,\n    relay: CacheRelay,\n  ) {\n    super()\n    this.#relay = relay\n  }\n\n  async clear() {\n    this.#cache.clear()\n    this.emit(\"change\", [])\n  }\n\n  key(of: T): string {\n    return of.pubkey\n  }\n\n  abstract name(): string\n  abstract maxSize(): number\n  abstract mapper(ev: NostrEvent): T | undefined\n\n  /**\n   * Preload only the ids from the worker relay\n   */\n  async preload() {\n    await this.preloadTable(`${this.name()}-preload-ids`, { kinds: [this.kind], ids_only: true })\n  }\n\n  /**\n   * Reload the table with a request filter\n   */\n  protected async preloadTable(id: string, f: ReqFilter) {\n    const start = unixNowMs()\n    const data = await this.#relay.query([\"REQ\", id, f])\n    if (f.ids_only === true) {\n      this.#keys = new Set(data as unknown as Array<string>)\n    } else {\n      const mapped = removeUndefined(data.map(a => this.mapper(a)))\n      for (const o of mapped) {\n        this.#cache.set(o.pubkey, o)\n      }\n    }\n    this.#log(`Loaded %d/%d in %d ms`, this.#cache.size, this.#keys.size, (unixNowMs() - start).toLocaleString())\n  }\n\n  async search(q: string) {\n    const results = await this.#relay.query([\n      \"REQ\",\n      `${this.name()}-search`,\n      {\n        kinds: [this.kind],\n        search: q,\n      },\n    ])\n    return removeUndefined(results.map(this.mapper))\n  }\n\n  keysOnTable(): string[] {\n    return [...this.#keys]\n  }\n\n  getFromCache(key?: string | undefined) {\n    if (key) {\n      return this.#cache.get(key) || undefined\n    }\n  }\n\n  discover(ev: NostrEvent) {\n    this.#keys.add(ev.pubkey)\n  }\n\n  async get(key?: string | undefined): Promise<T | undefined> {\n    if (key) {\n      const res = await this.bulkGet([key])\n      if (res.length > 0) {\n        return res[0]\n      }\n    }\n  }\n\n  async bulkGet(keys: string[]) {\n    if (keys.length === 0) return []\n\n    const results = await this.#relay.query([\n      \"REQ\",\n      `${this.name()}-bulk`,\n      {\n        authors: keys,\n        kinds: [this.kind],\n      },\n    ])\n    const mapped = removeUndefined(results.map(this.mapper))\n    for (const pf of mapped) {\n      this.#cache.set(pf.pubkey, pf)\n    }\n    this.emit(\n      \"change\",\n      mapped.map(a => a.pubkey),\n    )\n    return mapped\n  }\n\n  /**\n   * Because the internal type is different than T we cannot actually persist this value into the worker relay\n   * meaning that we can only update our internal cache, implementations must ensure that their data is externally\n   * persisted into the worker relay\n   */\n  private setInternal(obj: T) {\n    const k = this.key(obj)\n    const cached = this.#cache.get(k)\n    if (cached?.loaded && cached?.loaded >= obj.loaded) {\n      return //skip if newer is in cache\n    }\n\n    this.#keys.add(k)\n    this.#cache.set(k, obj)\n  }\n\n  async set(obj: T) {\n    const k = this.key(obj)\n    this.setInternal(obj)\n    this.emit(\"change\", [k])\n    this.#notifyKeyListeners(k)\n  }\n\n  async bulkSet(obj: T[] | readonly T[]) {\n    obj.map(a => this.setInternal(a))\n    this.emit(\"change\", obj.map(this.key))\n    for (const v of obj) {\n      this.#notifyKeyListeners(this.key(v))\n    }\n  }\n\n  async update(obj: T): Promise<\"new\" | \"refresh\" | \"updated\" | \"no_change\"> {\n    const k = this.key(obj)\n    const existing = this.getFromCache(k) as (T & { created: number; loaded: number }) | undefined\n    if (existing) {\n      const typedObj = obj as T & { created?: number; loaded?: number }\n      // If we have a newer or same-age entry already cached, skip the overwrite\n      if (existing.created !== undefined && typedObj.created !== undefined && existing.created > typedObj.created) {\n        return \"no_change\"\n      }\n      if (existing.loaded !== undefined && typedObj.loaded !== undefined && existing.loaded >= typedObj.loaded) {\n        return \"no_change\"\n      }\n    }\n    await this.set(obj)\n    return existing ? \"updated\" : \"new\"\n  }\n\n  /**\n   * Subscribe to changes for a specific key only.\n   * O(1) per notification — more efficient than listening to the broad \"change\" event.\n   * Returns an unsubscribe function.\n   */\n  subscribe(key: string, cb: () => void): () => void {\n    let listeners = this.#keyListeners.get(key)\n    if (!listeners) {\n      listeners = new Set()\n      this.#keyListeners.set(key, listeners)\n    }\n    listeners.add(cb)\n    return () => {\n      const s = this.#keyListeners.get(key)\n      if (s) {\n        s.delete(cb)\n        if (s.size === 0) {\n          this.#keyListeners.delete(key)\n        }\n      }\n    }\n  }\n\n  #notifyKeyListeners(key: string) {\n    const listeners = this.#keyListeners.get(key)\n    if (listeners) {\n      for (const cb of listeners) {\n        cb()\n      }\n    }\n  }\n\n  async buffer(keys: string[]): Promise<string[]> {\n    const missing = keys.filter(a => !this.#cache.has(a))\n    const res = await this.bulkGet(missing)\n    return missing.filter(a => !res.some(b => this.key(b) === a))\n  }\n\n  snapshot(): T[] {\n    return [...this.#cache.values()]\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/AskSnort/AskSnortInput.tsx",
    "content": "import { useState } from \"react\"\nimport { useNavigate } from \"react-router-dom\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\n\nimport { AsyncIcon } from \"@/Components/Button/AsyncIcon\"\nimport Textarea from \"@/Components/Textarea/Textarea\"\nimport Icon from \"@/Components/Icons/Icon\"\n\nexport function AskSnortInput() {\n  const navigate = useNavigate()\n  const [input, setInput] = useState(\"\")\n  const { formatMessage } = useIntl();\n\n  function handleSubmit() {\n    if (!input.trim()) return\n    navigate(\"/agent\", { state: { initialMessage: input } })\n  }\n\n  function handleKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>) {\n    if (e.key === \"Enter\" && !e.shiftKey) {\n      e.preventDefault()\n      e.stopPropagation()\n      handleSubmit()\n    }\n  }\n\n  return (\n    <div className=\"p-3 bg-layer-1 rounded-lg\">\n      <div className=\"flex items-center gap-2 mb-2\">\n        <Icon name=\"lightbulb\" className=\"text-primary flex-shrink-0\" size={16} />\n        <span className=\"font-semibold text-sm flex-shrink-0\">\n          <FormattedMessage defaultMessage=\"Ask {appName} AI\" values={{ appName: CONFIG.appNameCapitalized }} />\n        </span>\n      </div>\n      <div className=\"flex items-center gap-2\">\n        <div className=\"flex-1 min-w-0\">\n          <Textarea\n            autoFocus={false}\n            placeholder={formatMessage({ defaultMessage: \"Try: Summarize my timeline\" })}\n            value={input}\n            onChange={e => setInput(e.target.value)}\n            onKeyDown={handleKeyDown}\n            onFocus={() => { }}\n            className=\"!border-0 !resize-none !p-2 !bg-transparent !text-sm min-h-[32px] max-h-[48px] overflow-hidden\"\n          />\n        </div>\n        <AsyncIcon\n          className=\"rounded-full flex items-center button shrink-0\"\n          iconName=\"arrow-right\"\n          onClick={handleSubmit}\n          disabled={!input.trim()}\n        />\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Button/AsyncButton.tsx",
    "content": "import classNames from \"classnames\"\nimport React, { type ForwardedRef } from \"react\"\n\nimport Spinner from \"@/Components/Icons/Spinner\"\nimport useLoading from \"@/Hooks/useLoading\"\n\nexport interface AsyncButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n  onClick?: (e: React.MouseEvent) => Promise<void> | void\n}\n\nconst AsyncButton = React.forwardRef<HTMLButtonElement, AsyncButtonProps>((props, ref) => {\n  const { handle, loading } = useLoading(props.onClick, props.disabled)\n\n  return (\n    <button\n      ref={ref as ForwardedRef<HTMLButtonElement>}\n      type=\"button\"\n      disabled={loading || props.disabled}\n      {...props}\n      className={classNames(\n        \"light:border light:border-border light:text-neutral-400 light:shadow-sm light:hover:shadow-md\",\n        props.className,\n      )}\n      onClick={handle}\n    >\n      <span\n        className=\"flex items-center justify-center gap-2 light:text-black\"\n        style={{ visibility: loading ? \"hidden\" : \"visible\" }}\n      >\n        {props.children}\n      </span>\n      {loading && (\n        <span className=\"absolute inset-0\">\n          <div className=\"w-full h-full flex items-center justify-center\">\n            <Spinner />\n          </div>\n        </span>\n      )}\n    </button>\n  )\n})\n\nAsyncButton.displayName = \"AsyncButton\"\n\nexport default AsyncButton\n"
  },
  {
    "path": "packages/app/src/Components/Button/AsyncIcon.tsx",
    "content": "import Icon from \"@/Components/Icons/Icon\"\nimport Spinner from \"@/Components/Icons/Spinner\"\nimport useLoading from \"@/Hooks/useLoading\"\n\nexport type AsyncIconProps = React.HTMLProps<HTMLDivElement> & {\n  iconName: string\n  iconSize?: number\n  onClick?: (e: React.MouseEvent) => Promise<void> | void\n}\n\nexport function AsyncIcon(props: AsyncIconProps) {\n  const { loading, handle } = useLoading(props.onClick, props.disabled)\n\n  const mergedProps = { ...props } as Record<string, unknown>\n  delete mergedProps.iconName\n  delete mergedProps.iconSize\n  delete mergedProps.loading\n  return (\n    <div {...mergedProps} onClick={handle} className={props.className}>\n      {loading ? <Spinner /> : <Icon name={props.iconName} size={props.iconSize} />}\n      {props.children}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Button/BackButton.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport type { ReactNode } from \"react\"\n\ninterface BackButtonProps {\n  text?: ReactNode\n  onClick?(): void\n}\n\nexport default function BackButton({ text, onClick }: BackButtonProps) {\n  return (\n    <div\n      className=\"flex gap-2 items-center cursor-pointer hover:underline\"\n      onClick={() => {\n        onClick?.()\n      }}\n    >\n      <Icon name=\"arrowBack\" />\n      <span>{text || <FormattedMessage defaultMessage=\"Back\" />}</span>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Button/CloseButton.tsx",
    "content": "import classNames from \"classnames\"\n\nimport Icon from \"@/Components/Icons/Icon\"\n\nexport default function CloseButton({ onClick, className }: { onClick?: () => void; className?: string }) {\n  return (\n    <div\n      onClick={onClick}\n      className={classNames(\n        \"self-center rounded-full flex flex-shrink-0 flex-grow-0 items-center justify-center hover:opacity-80 bg-dark p-2 cursor-pointer\",\n        className,\n      )}\n    >\n      <Icon name=\"close\" size={12} />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Button/IconButton.tsx",
    "content": "import classNames from \"classnames\"\nimport type { ReactNode } from \"react\"\n\nimport Icon, { type IconProps } from \"@/Components/Icons/Icon\"\n\ninterface IconButtonProps {\n  onClick?: () => void\n  icon: IconProps\n  className?: string\n  children?: ReactNode\n}\n\nconst IconButton = ({ onClick, icon, children, className }: IconButtonProps) => {\n  return (\n    <button\n      className={classNames(\n        \"flex items-center justify-center aspect-square w-10 h-10 !p-0 !m-0 bg-neutral-800 text-white\",\n        className,\n      )}\n      onClick={onClick}\n    >\n      <Icon {...icon} />\n      {children}\n    </button>\n  )\n}\n\nexport default IconButton\n"
  },
  {
    "path": "packages/app/src/Components/Button/LogoutButton.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport useLogin from \"@/Hooks/useLogin\"\nimport { logout } from \"@/Utils/Login\"\n\nimport messages from \"../messages\"\n\nexport default function LogoutButton() {\n  const navigate = useNavigate()\n  const login = useLogin(s => ({ publicKey: s.publicKey, id: s.id }))\n\n  if (!login.publicKey) return\n  return (\n    <button\n      className=\"secondary\"\n      type=\"button\"\n      onClick={() => {\n        logout(login.id)\n        navigate(\"/\")\n      }}\n    >\n      <FormattedMessage {...messages.Logout} />\n    </button>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Button/NavLink.tsx",
    "content": "import { NavLink as RouterNavLink, type NavLinkProps, useLocation } from \"react-router-dom\"\n\nexport default function NavLink(props: NavLinkProps) {\n  const { to, onClick, ...rest } = props\n  const location = useLocation()\n\n  const isActive = location.pathname === to.toString()\n\n  return (\n    <RouterNavLink\n      to={to}\n      onClick={e => {\n        onClick?.(e)\n        if (isActive) {\n          window.scrollTo({ top: 0, behavior: \"instant\" })\n        }\n      }}\n      {...rest}\n    />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Collapsed.tsx",
    "content": "import classNames from \"classnames\"\nimport { type ReactNode, useState } from \"react\"\n\nimport Icon from \"@/Components/Icons/Icon\"\n\ninterface CollapsedProps {\n  text?: ReactNode\n  children: ReactNode\n  collapsed: boolean\n  setCollapsed(b: boolean): void\n}\n\nconst Collapsed = ({ text, children, collapsed, setCollapsed }: CollapsedProps) => {\n  return collapsed ? (\n    <div className=\"text-nostr-purple px-4 pb-3 cursor-pointer hover:underline\" onClick={() => setCollapsed(false)}>\n      {text}\n    </div>\n  ) : (\n    <div className=\"uncollapsed\">{children}</div>\n  )\n}\n\ninterface CollapsedIconProps {\n  icon: ReactNode\n  collapsed: boolean\n}\n\ninterface CollapsedSectionProps {\n  title: ReactNode\n  children: ReactNode\n  className?: string\n  startClosed?: boolean\n}\n\nexport const CollapsedSection = ({ title, children, className, startClosed }: CollapsedSectionProps) => {\n  const [collapsed, setCollapsed] = useState(startClosed ?? true)\n  return (\n    <div>\n      <div\n        className={classNames(\n          \"flex gap-4 items-center justify-between cursor-pointer layer-1 select-none\",\n          { \"rounded-b-none\": !collapsed },\n          className,\n        )}\n        onClick={() => setCollapsed(!collapsed)}\n      >\n        {title}\n        <Icon name=\"arrowFront\" className={`transition-transform ${collapsed ? \"rotate-90\" : \"\"}`} />\n      </div>\n      {!collapsed && <div className=\"layer-2 rounded-t-none\">{children}</div>}\n    </div>\n  )\n}\n\nexport default Collapsed\n"
  },
  {
    "path": "packages/app/src/Components/CommunityLeaders/Award.tsx",
    "content": "export default function AwardIcon({ size }: { size?: number }) {\n  return (\n    <svg width={size} height={size} viewBox=\"0 0 62 62\" fill=\"none\" className=\"award\">\n      <defs>\n        <linearGradient\n          id=\"paint0_linear_2660_40043\"\n          x1=\"31\"\n          y1=\"3.57143\"\n          x2=\"31\"\n          y2=\"58.4286\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stopColor=\"#5B2CB3\" />\n          <stop offset=\"1\" stopColor=\"#811EFF\" />\n        </linearGradient>\n        <linearGradient\n          id=\"paint1_linear_2660_40043\"\n          x1=\"15.5594\"\n          y1=\"24.305\"\n          x2=\"46.433\"\n          y2=\"24.305\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stopColor=\"#AC88FF\" />\n          <stop offset=\"1\" stopColor=\"#7234FF\" />\n        </linearGradient>\n      </defs>\n      <g id=\"award-02\">\n        <rect x=\"1.85713\" y=\"1.85714\" width=\"58.2857\" height=\"58.2857\" rx=\"29.1429\" fill=\"#AC88FF\" fillOpacity=\"0.2\" />\n        <rect\n          x=\"1.85713\"\n          y=\"1.85714\"\n          width=\"58.2857\"\n          height=\"58.2857\"\n          rx=\"29.1429\"\n          stroke=\"url(#paint0_linear_2660_40043)\"\n          strokeWidth=\"3.42857\"\n        />\n        <path\n          id=\"Solid\"\n          d=\"M23.2006 52.4983L22.5639 50.9066L23.2006 52.4983L30.9963 49.38L38.7919 52.4983C39.8813 52.934 41.116 52.801 42.0876 52.1432C43.0592 51.4854 43.6412 50.3885 43.6412 49.2151V38.1015C46.467 35.038 48.1957 30.9408 48.1957 26.4427C48.1957 16.9437 40.4952 9.24329 30.9963 9.24329C21.4973 9.24329 13.7968 16.9437 13.7968 26.4427C13.7968 30.9408 15.5255 35.038 18.3513 38.1015V49.2151C18.3513 50.3885 18.9333 51.4854 19.9049 52.1432C20.8765 52.801 22.1112 52.934 23.2006 52.4983ZM27.2967 43.2429L25.4234 43.9922V42.7187C26.0332 42.9275 26.6584 43.1029 27.2967 43.2429ZM34.6958 43.2429C35.3341 43.1029 35.9593 42.9275 36.5691 42.7187V43.9922L34.6958 43.2429Z\"\n          fill=\"url(#paint1_linear_2660_40043)\"\n          stroke=\"#251250\"\n          strokeWidth=\"3.42857\"\n          strokeLinecap=\"round\"\n        />\n        <path\n          id=\"Ellipse 1595\"\n          d=\"M24.2557 14.6002C17.7766 18.3409 15.5567 26.6257 19.2974 33.1049L42.7604 19.5585C39.0196 13.0794 30.7348 10.8595 24.2557 14.6002Z\"\n          fill=\"white\"\n          fillOpacity=\"0.1\"\n        />\n      </g>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/CommunityLeaders/LeaderBadge.tsx",
    "content": "import { useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport CloseButton from \"../Button/CloseButton\"\nimport Modal from \"../Modal/Modal\"\nimport AwardIcon from \"./Award\"\n\nexport function LeaderBadge() {\n  const [showModal, setShowModal] = useState(false)\n  return (\n    <>\n      <div\n        className=\"flex gap-1 p-1 pr-2 items-center border border-[#5B2CB3] rounded-full\"\n        onClick={e => {\n          e.preventDefault()\n          e.stopPropagation()\n          setShowModal(true)\n        }}\n      >\n        <AwardIcon size={16} />\n        <div className=\"text-xs font-medium text-[#AC88FF]\">\n          <FormattedMessage defaultMessage=\"Community Leader\" />\n        </div>\n      </div>\n      {showModal && (\n        <Modal onClose={() => setShowModal(false)} id=\"leaders\">\n          <div className=\"flex flex-col gap-4 items-center relative\">\n            <CloseButton className=\"absolute right-2 top-2\" onClick={() => setShowModal(false)} />\n            <AwardIcon size={80} />\n            <div className=\"text-3xl font-semibold\">\n              <FormattedMessage defaultMessage=\"Community Leader\" />\n            </div>\n            <p className=\"text-neutral-400\">\n              <FormattedMessage defaultMessage=\"Community leaders are individuals who grow the nostr ecosystem by being active in their local communities and helping onboard new users. Anyone can become a community leader, but few hold the current honorary title.\" />\n            </p>\n            <Link to=\"/settings/invite\">\n              <button className=\"primary\">\n                <FormattedMessage defaultMessage=\"Become a leader\" />\n              </button>\n            </Link>\n          </div>\n        </Modal>\n      )}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Copy/Copy.tsx",
    "content": "import classNames from \"classnames\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport { useCopy } from \"@/Hooks/useCopy\"\n\nexport interface CopyProps {\n  text: string\n  maxSize?: number\n  className?: string\n  showText?: boolean\n  mask?: string\n}\nexport default function Copy({ text, maxSize = 32, className, showText, mask }: CopyProps) {\n  const { copy, copied } = useCopy()\n  const sliceLength = maxSize / 2\n  const displayText = mask ? mask.repeat(text.length) : text\n  const trimmed =\n    displayText.length > maxSize\n      ? `${displayText.slice(0, sliceLength)}...${displayText.slice(-sliceLength)}`\n      : displayText\n\n  return (\n    <span\n      className={classNames(\"flex cursor-pointer gap-2 items-center\", className)}\n      onClick={e => {\n        e.stopPropagation()\n        copy(text)\n      }}\n    >\n      {(showText ?? true) && <span className=\"text-sm text-font-color\">{trimmed}</span>}\n      <span className=\"icon\" style={{ color: copied ? \"var(--success)\" : \"var(--highlight)\" }}>\n        {copied ? <Icon name=\"check\" size={14} /> : <Icon name=\"copy-solid\" size={14} />}\n      </span>\n    </span>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/DvmSelector.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\nimport type { EventKind } from \"@snort/system\"\n\nimport Modal from \"@/Components/Modal/Modal\"\nimport useAppHandler from \"@/Hooks/useAppHandler\"\nimport Avatar from \"@/Components/User/Avatar\"\nimport DisplayName from \"@/Components/User/DisplayName\"\nimport Icon from \"@/Components/Icons/Icon\"\n\ninterface DvmSelectorProps {\n  kind: number\n  onClose: () => void\n  onSelect: (pubkey: string) => void\n  currentProvider?: string\n}\n\nexport default function DvmSelector({ kind, onClose, onSelect, currentProvider }: DvmSelectorProps) {\n  const apps = useAppHandler(kind as EventKind)\n\n  const handleSelect = (providerPubkey: string) => {\n    onSelect(providerPubkey)\n    onClose()\n  }\n\n  return (\n    <Modal id=\"dvm-selector\" onClose={onClose}>\n      <div className=\"flex flex-col gap-4\">\n        <div className=\"flex justify-between items-center\">\n          <h2 className=\"text-xl font-semibold\">\n            <FormattedMessage defaultMessage=\"Select Provider\" />\n          </h2>\n        </div>\n\n        <div className=\"text-sm text-neutral-400\">\n          <FormattedMessage defaultMessage=\"Choose a DVM (Data Vending Machine) to provide content.\" />\n        </div>\n\n        <div className=\"flex flex-col gap-2 max-h-96 overflow-y-auto\">\n          {apps.length === 0 ? (\n            <div className=\"text-center py-8 text-neutral-400\">\n              <FormattedMessage defaultMessage=\"No DVM providers found\" />\n            </div>\n          ) : (\n            apps\n              .sort((a, _) => (currentProvider === a.event.pubkey ? -1 : 0))\n              .map(app => {\n                const isSelected = currentProvider === app.event.pubkey\n\n                return (\n                  <div\n                    key={app.event.id}\n                    onClick={() => handleSelect(app.event.pubkey)}\n                    className={`flex items-start gap-3 layer-1-hover mr-1`}\n                  >\n                    <Avatar pubkey={app.event.pubkey} user={app.metadata} size={48} />\n                    <div className=\"flex flex-col flex-1\">\n                      <div className=\"flex items-center gap-2\">\n                        <DisplayName pubkey={app.event.pubkey} user={app.metadata} />\n                        {isSelected && <Icon name=\"check\" size={16} className=\"text-highlight\" />}\n                      </div>\n                      <div className=\"flex items-center gap-2 text-sm text-neutral-400 mt-1\">\n                        {app.reccomendations.length > 0 && (\n                          <>\n                            <Icon name=\"thumbs-up\" size={14} />\n                            {app.reccomendations.length}{\" \"}\n                            {app.reccomendations.length === 1 ? \"recommendation\" : \"recommendations\"}\n                          </>\n                        )}\n                      </div>\n                      {app.metadata?.about && <div className=\"text-sm text-neutral-400 mt-1\">{app.metadata.about}</div>}\n                    </div>\n                  </div>\n                )\n              })\n          )}\n        </div>\n      </div>\n    </Modal>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Embed/AppleMusicEmbed.tsx",
    "content": "const AppleMusicEmbed = ({ link }: { link: string }) => {\n  const convertedUrl = link.replace(\"music.apple.com\", \"embed.music.apple.com\")\n  const isSongLink = /\\?i=\\d+$/.test(convertedUrl)\n\n  return (\n    <iframe\n      allow=\"autoplay *; encrypted-media *; fullscreen *; clipboard-write\"\n      frameBorder=\"0\"\n      height={isSongLink ? 175 : 450}\n      style={{ width: \"100%\", maxWidth: 660, overflow: \"hidden\", background: \"transparent\" }}\n      sandbox=\"allow-forms allow-popups allow-same-origin allow-scripts allow-storage-access-by-user-activation allow-top-navigation-by-user-activation\"\n      src={convertedUrl}\n      loading=\"lazy\"\n    />\n  )\n}\n\nexport default AppleMusicEmbed\n"
  },
  {
    "path": "packages/app/src/Components/Embed/BlossomBlob.tsx",
    "content": "import useBlossomServers from \"@/Hooks/useBlossomServers\"\nimport { appendDedupe, dedupe, isHex, NostrPrefix, removeUndefined } from \"@snort/shared\"\nimport { type NostrLink, tryParseNostrLink } from \"@snort/system\"\nimport { randomSample } from \"@/Utils\"\nimport RevealMedia from \"../Event/RevealMedia\"\nimport Icon from \"../Icons/Icon\"\nimport { useState } from \"react\"\nimport Modal from \"../Modal/Modal\"\nimport { FormattedMessage } from \"react-intl\"\nimport ProfilePreview from \"../User/ProfilePreview\"\nimport UrlStatusCheck from \"./UrlStatusCheck\"\n\ninterface BlossomLink {\n  hash: string\n  extension: string\n  authors?: Array<NostrLink>\n  servers?: Array<string>\n  size?: number\n}\n\nfunction parseBlossomLink(link: string) {\n  const url = new URL(link)\n  const [hash, extension] = url.pathname.split(\".\")\n  if (!extension) {\n    throw new Error(\"Invalid blossom link, no extension set\")\n  }\n  if (!isHex(hash) || hash.length !== 64) {\n    throw new Error(\"Invalid blossom link, hash is not hex or has the wrong size\")\n  }\n\n  const q = new URLSearchParams(url.search)\n  const authors = removeUndefined(q.getAll(\"as\").map(a => tryParseNostrLink(a, NostrPrefix.PublicKey)))\n  const servers = q.getAll(\"xs\").map(a => (a.startsWith(\"http\") ? a : `https://${a}`))\n  const size = Number(q.get(\"sz\"))\n  return {\n    hash,\n    extension,\n    authors: authors.length > 0 ? authors : undefined,\n    servers: servers.length > 0 ? servers : undefined,\n    size: Number.isNaN(size) ? undefined : size,\n  } as BlossomLink\n}\n\nexport default function BlossomBlob({ creator, link }: { creator: string; link: string }) {\n  const blob = parseBlossomLink(link)\n  const servers = useBlossomServers(blob.authors)\n  const [showModal, setShowModal] = useState(false)\n\n  // convert into media element\n  // random sample up to maxServers urls\n  const maxServers = 10\n  const authorUrls = dedupe(Object.values(servers).flat())\n  const explicitUrls = dedupe(blob.servers ?? [])\n\n  const mapBlobUrl = (a: string) => `${a}${a.endsWith(\"/\") ? \"\" : \"/\"}${blob.hash}.${blob.extension}`\n  const allUrls = appendDedupe(authorUrls.map(mapBlobUrl), explicitUrls.map(mapBlobUrl))\n  const urls = randomSample(allUrls, maxServers)\n  return (\n    <div className=\"relative min-h-12 border\">\n      <RevealMedia\n        creator={creator}\n        src={urls[0]}\n        meta={{\n          fallback: urls.slice(1),\n          hash: blob.hash,\n          size: blob.size,\n        }}\n      />\n      <Icon\n        name=\"info-outline\"\n        className=\"absolute top-4 left-4 cursor-pointer opacity-50 hover:opacity-100\"\n        onClick={() => setShowModal(true)}\n      />\n      {showModal && (\n        <Modal id={`blossom-modal-${blob.hash}`} onClose={() => setShowModal(false)}>\n          <div className=\"flex flex-col gap-4\">\n            <h2 className=\"text-xl font-bold\">\n              <FormattedMessage defaultMessage=\"Blossom Blob Debug Info\" />\n            </h2>\n\n            <div className=\"flex flex-col gap-2\">\n              <div>\n                <strong>\n                  <FormattedMessage defaultMessage=\"Hash\" />:\n                </strong>\n                <code className=\"ml-2 font-mono text-sm break-all\">{blob.hash}</code>\n              </div>\n\n              <div>\n                <strong>\n                  <FormattedMessage defaultMessage=\"Extension\" />:\n                </strong>\n                <code className=\"ml-2 font-mono text-sm\">{blob.extension}</code>\n              </div>\n\n              {blob.size && (\n                <div>\n                  <strong>\n                    <FormattedMessage defaultMessage=\"Size\" />:\n                  </strong>\n                  <span className=\"ml-2\">\n                    <FormattedMessage\n                      defaultMessage=\"{size} bytes ({kb} KB)\"\n                      values={{\n                        size: blob.size.toLocaleString(),\n                        kb: (blob.size / 1024).toFixed(2),\n                      }}\n                    />\n                  </span>\n                </div>\n              )}\n            </div>\n\n            {blob.authors && blob.authors.length > 0 && (\n              <div>\n                <strong>\n                  <FormattedMessage defaultMessage=\"Authors ({count})\" values={{ count: blob.authors.length }} />:\n                </strong>\n                <div className=\"flex flex-col gap-2 mt-2\">\n                  {blob.authors.map(author => (\n                    <ProfilePreview key={author.id} pubkey={author.id} actions={<></>} className=\"layer-2\" />\n                  ))}\n                </div>\n              </div>\n            )}\n\n            {explicitUrls.length > 0 && (\n              <div>\n                <strong>\n                  <FormattedMessage\n                    defaultMessage=\"Explicit Servers ({count})\"\n                    values={{ count: explicitUrls.length }}\n                  />\n                  :\n                </strong>\n                <ul className=\"list-disc\">\n                  {explicitUrls.map(url => (\n                    <li key={url} className=\"text-sm break-all\">\n                      <a href={url} target=\"_blank\" rel=\"noopener noreferrer\" className=\"text-blue-500 hover:underline\">\n                        {url}\n                      </a>\n                    </li>\n                  ))}\n                </ul>\n              </div>\n            )}\n\n            {authorUrls.length > 0 && (\n              <div>\n                <strong>\n                  <FormattedMessage\n                    defaultMessage=\"Author-Derived Servers ({count})\"\n                    values={{ count: authorUrls.length }}\n                  />\n                  :\n                </strong>\n                <ul className=\"list-disc max-h-48 overflow-y-auto\">\n                  {authorUrls.map(url => (\n                    <li key={url} className=\"text-sm break-all\">\n                      <a href={url} target=\"_blank\" rel=\"noopener noreferrer\" className=\"text-blue-500 hover:underline\">\n                        {url}\n                      </a>\n                    </li>\n                  ))}\n                </ul>\n              </div>\n            )}\n\n            <div>\n              <strong>\n                <FormattedMessage\n                  defaultMessage=\"Active URLs ({active}/{max})\"\n                  values={{ active: urls.length, max: maxServers }}\n                />\n                :\n              </strong>\n              <div>\n                {urls.map(url => (\n                  <div key={url} className=\"text-sm break-all flex items-center gap-2\">\n                    <UrlStatusCheck url={url} />\n                    <a\n                      href={url}\n                      target=\"_blank\"\n                      rel=\"noopener noreferrer\"\n                      className=\"text-blue-500 hover:underline break-all\"\n                    >\n                      {url}\n                    </a>\n                  </div>\n                ))}\n              </div>\n            </div>\n          </div>\n        </Modal>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Embed/CashuNuts.tsx",
    "content": "import { useUserProfile } from \"@snort/system-react\"\nimport { useEffect, useState } from \"react\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport ECashIcon from \"@/Components/Icons/ECash\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport { useCopy } from \"@/Hooks/useCopy\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { WarningNotice } from \"../WarningNotice/WarningNotice\"\nimport { getDecodedToken, type Token } from \"@cashu/cashu-ts\"\n\nexport default function CashuNuts({ token }: { token: string }) {\n  const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }))\n  const profile = useUserProfile(publicKey)\n  const { copy } = useCopy()\n\n  async function redeemToken(token: string) {\n    const lnurl = profile?.lud16 ?? \"\"\n    const url = `https://redeem.cashu.me?token=${encodeURIComponent(token)}&lightning=${encodeURIComponent(\n      lnurl,\n    )}&autopay=yes`\n    window.open(url, \"_blank\")\n  }\n\n  const [cashu, setCashu] = useState<Token>()\n  useEffect(() => {\n    try {\n      if (!token.startsWith(\"cashuA\") || token.length < 10) {\n        return\n      }\n      const tkn = getDecodedToken(token)\n      setCashu(tkn)\n    } catch (e) {\n      // ignored\n      console.warn(e)\n    }\n  }, [token])\n\n  if (!cashu)\n    return (\n      <WarningNotice>\n        <FormattedMessage defaultMessage=\"Invalid cashu token\" />\n      </WarningNotice>\n    )\n\n  const amount = cashu.proofs.reduce((acc, v) => acc + v.amount, 0)\n  return (\n    <div\n      className=\"flex justify-between p-6 rounded-lg items-center\"\n      style={{\n        backgroundImage: \"linear-gradient(90deg, #40b039, #adff2a)\",\n      }}\n    >\n      <div className=\"flex flex-col gap-2 min-w-0 truncate overflow-hidden text-ellipsis\">\n        <div className=\"flex items-center gap-4\">\n          <ECashIcon width={30} />\n          <FormattedMessage\n            defaultMessage=\"{n} eSats\"\n            id=\"yAztTU\"\n            values={{\n              n: (\n                <span className=\"text-3xl\">\n                  <FormattedNumber value={amount} />\n                </span>\n              ),\n            }}\n          />\n        </div>\n      </div>\n      <div className=\"flex gap-2 items-center\">\n        <AsyncButton onClick={() => copy(token)}>\n          <Icon name=\"copy\" />\n        </AsyncButton>\n        <AsyncButton onClick={() => redeemToken(token)}>\n          <FormattedMessage defaultMessage=\"Redeem\" />\n        </AsyncButton>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Embed/GenericPlayer.tsx",
    "content": "import { useState } from \"react\"\n\nimport Icon from \"../Icons/Icon\"\nimport { ProxyImg } from \"../ProxyImg\"\n\nexport default function GenericPlayer({ url, poster }: { url: string; poster: string }) {\n  const [play, setPlay] = useState(false)\n\n  if (!play) {\n    return (\n      <div\n        className=\"relative aspect-video\"\n        onClick={e => {\n          e.preventDefault()\n          e.stopPropagation()\n          setPlay(true)\n        }}\n      >\n        <ProxyImg className=\"absolute\" src={poster} />\n        <div className=\"absolute w-full h-full opacity-0 hover:opacity-100 hover:bg-black/30 flex items-center justify-center transition\">\n          <Icon name=\"play-square-outline\" size={50} />\n        </div>\n      </div>\n    )\n  }\n  return (\n    <iframe\n      className=\"aspect-video w-full\"\n      src={url}\n      frameBorder=\"0\"\n      allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"\n      allowFullScreen={true}\n    />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Embed/Hashtag.tsx",
    "content": "import { Link } from \"react-router-dom\"\n\nconst Hashtag = ({ tag }: { tag: string }) => {\n  return (\n    <span className=\"text-highlight\">\n      <Link to={`/t/${tag}`} onClick={e => e.stopPropagation()} className=\"hover:underline\">\n        #{tag}\n      </Link>\n    </span>\n  )\n}\n\nexport default Hashtag\n"
  },
  {
    "path": "packages/app/src/Components/Embed/HyperText.tsx",
    "content": "import type { ReactNode } from \"react\"\n\nimport AppleMusicEmbed from \"@/Components/Embed/AppleMusicEmbed\"\nimport LinkPreview from \"@/Components/Embed/LinkPreview\"\nimport MixCloudEmbed from \"@/Components/Embed/MixCloudEmbed\"\nimport SoundCloudEmbed from \"@/Components/Embed/SoundCloudEmded\"\nimport SpotifyEmbed from \"@/Components/Embed/SpotifyEmbed\"\nimport TidalEmbed from \"@/Components/Embed/TidalEmbed\"\nimport TwitchEmbed from \"@/Components/Embed/TwitchEmbed\"\nimport WavlakeEmbed from \"@/Components/Embed/WavlakeEmbed\"\nimport YoutubeEmbed from \"@/Components/Embed/YoutubeEmbed\"\nimport {\n  AppleMusicRegex,\n  MixCloudRegex,\n  SoundCloudRegex,\n  SpotifyRegex,\n  TidalRegex,\n  TwitchRegex,\n  WavlakeRegex,\n  YoutubeUrlRegex,\n} from \"@/Utils/Const\"\n\ninterface HypeTextProps {\n  link: string\n  children?: ReactNode | Array<ReactNode> | null\n  showLinkPreview?: boolean\n}\n\nexport default function HyperText({ link, showLinkPreview, children }: HypeTextProps) {\n  if (link.match(YoutubeUrlRegex)) {\n    return <YoutubeEmbed link={link} />\n  } else if (link.match(TidalRegex)) {\n    return <TidalEmbed link={link} />\n  } else if (link.match(SoundCloudRegex)) {\n    return <SoundCloudEmbed link={link} />\n  } else if (link.match(MixCloudRegex)) {\n    return <MixCloudEmbed link={link} />\n  } else if (link.match(SpotifyRegex)) {\n    return <SpotifyEmbed link={link} />\n  } else if (link.match(TwitchRegex)) {\n    return <TwitchEmbed link={link} />\n  } else if (link.match(AppleMusicRegex)) {\n    return <AppleMusicEmbed link={link} />\n  } else if (link.match(WavlakeRegex)) {\n    return <WavlakeEmbed link={link} />\n  } else if (showLinkPreview ?? true) {\n    return <LinkPreview url={link} />\n  }\n  return (\n    <a\n      href={link}\n      onClick={e => e.stopPropagation()}\n      target=\"_blank\"\n      rel=\"noreferrer\"\n      className=\"text-highlight no-underline hover:underline\"\n    >\n      {children ?? link}\n    </a>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Embed/Invoice.tsx",
    "content": "import { decodeInvoice } from \"@snort/shared\"\nimport { useState } from \"react\"\nimport { useMemo } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport ZapModal from \"@/Components/ZapModal/ZapModal\"\nimport { useWallet } from \"@/Wallet\"\n\nimport messages from \"../messages\"\n\nexport interface InvoiceProps {\n  invoice: string\n}\n\nexport default function Invoice(props: InvoiceProps) {\n  const invoice = props.invoice\n  const { formatMessage } = useIntl()\n  const [showInvoice, setShowInvoice] = useState(false)\n  const walletState = useWallet()\n  const wallet = walletState.wallet\n\n  const info = useMemo(() => decodeInvoice(invoice), [invoice])\n  const [isPaid, setIsPaid] = useState(false)\n  const isExpired = info?.expired\n  const amount = info?.amount ?? 0\n  const description = info?.description\n\n  function header() {\n    return (\n      <>\n        <h4 className=\"m-0 p-0 font-normal text-base leading-[19px] mb-2.5\">\n          <FormattedMessage {...messages.Invoice} />\n        </h4>\n        <Icon name=\"zapCircle\" className=\"absolute top-[26px] right-5 text-font-color\" />\n        <ZapModal\n          title={formatMessage(messages.PayInvoice)}\n          invoice={invoice}\n          show={showInvoice}\n          onClose={() => setShowInvoice(false)}\n        />\n      </>\n    )\n  }\n\n  async function payInvoice(e: React.MouseEvent<HTMLButtonElement>) {\n    e.stopPropagation()\n    if (wallet?.isReady) {\n      try {\n        await wallet.payInvoice(invoice)\n        setIsPaid(true)\n      } catch (_error) {\n        setShowInvoice(true)\n      }\n    } else {\n      setShowInvoice(true)\n    }\n  }\n\n  return (\n    <div className=\"border rounded-lg p-6 flex-col items-start relative bg-[image:var(--invoice-gradient)]\">\n        <div>{header()}</div>\n\n        <p className=\"font-normal text-[37px] leading-[45px] mb-4\">\n          {amount > 0 && (\n            <>\n              {(amount / 1_000).toLocaleString()}{\" \"}\n              <span className=\"text-font-secondary-color uppercase text-[21px]\">sat{amount === 1_000 ? \"\" : \"s\"}</span>\n            </>\n          )}\n        </p>\n\n        <div className=\"text-font-secondary-color w-full text-base leading-[19px]\">\n          {description && <p className=\"mb-4\">{description}</p>}\n          {isPaid ? (\n            <div className=\"w-full h-11 font-semibold text-[19px] leading-[23px] flex items-center justify-center bg-success text-white rounded-lg\">\n              <FormattedMessage defaultMessage=\"Paid\" />\n            </div>\n          ) : (\n            <button\n              disabled={isExpired}\n              type=\"button\"\n              onClick={payInvoice}\n              className=\"w-full h-11 font-semibold text-[19px] leading-[23px]\"\n            >\n              {isExpired ? <FormattedMessage {...messages.Expired} /> : <FormattedMessage {...messages.Pay} />}\n            </button>\n          )}\n        </div>\n      </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Embed/LinkPreview.tsx",
    "content": "import { useEffect, useState } from \"react\"\nimport { LRUCache } from \"typescript-lru-cache\"\n\nimport { MediaElement } from \"@/Components/Embed/MediaElement\"\nimport Spinner from \"@/Components/Icons/Spinner\"\nimport { type LinkPreviewData, NostrServices } from \"@/External\"\n\nimport { ProxyImg } from \"../ProxyImg\"\nimport GenericPlayer from \"./GenericPlayer\"\n\nasync function fetchUrlPreviewInfo(url: string) {\n  const api = new NostrServices()\n  try {\n    return await api.linkPreview(url.endsWith(\")\") ? url.slice(0, -1) : url)\n  } catch (_e) {\n    console.warn(`Failed to load link preview`, url)\n  }\n}\n\nconst cache = new LRUCache<string, LinkPreviewData>({\n  maxSize: 1000,\n})\n\nconst LinkPreview = ({ url }: { url: string }) => {\n  const uu = new URL(url)\n  const [preview, setPreview] = useState<LinkPreviewData | null>(cache.get(url))\n\n  useEffect(() => {\n    if (cache.get(url)) return\n    let cancelled = false\n    ;(async () => {\n      const data = await fetchUrlPreviewInfo(url)\n      if (cancelled) return\n      if (data) {\n        const type = data.og_tags?.find(a => a[0].toLowerCase() === \"og:type\")\n        const canPreviewType = type?.[1].startsWith(\"image\") || type?.[1].startsWith(\"video\") || false\n        if (canPreviewType || data.image) {\n          setPreview(data)\n          cache.set(url, data)\n          return\n        }\n      }\n\n      setPreview(null)\n    })()\n    return () => {\n      cancelled = true\n    }\n  }, [url])\n\n  if (preview === null)\n    return (\n      <a href={url} onClick={e => e.stopPropagation()} target=\"_blank\" rel=\"noreferrer\" className=\"text-highlight\">\n        {url}\n      </a>\n    )\n\n  function previewElement() {\n    const type = preview?.og_tags?.find(a => a[0].toLowerCase() === \"og:type\")?.[1]\n    if (type?.startsWith(\"video\")) {\n      const urlTags = [\"og:video:secure_url\", \"og:video:url\", \"og:video\"]\n      const link = preview?.og_tags?.find(a => urlTags.includes(a[0].toLowerCase()))?.[1]\n      const videoType = preview?.og_tags?.find(a => a[0].toLowerCase() === \"og:video:type\")?.[1] ?? \"video/mp4\"\n      if (link && videoType.startsWith(\"video/\")) {\n        return <MediaElement src={link} mime={videoType} />\n      }\n      if (link && videoType.startsWith(\"text/html\") && preview?.image) {\n        return <GenericPlayer url={link} poster={preview?.image} />\n      }\n    }\n    if (type?.startsWith(\"image\")) {\n      const urlTags = [\"og:image:secure_url\", \"og:image:url\", \"og:image\"]\n      const link = preview?.og_tags?.find(a => urlTags.includes(a[0].toLowerCase()))?.[1]\n      const videoType = preview?.og_tags?.find(a => a[0].toLowerCase() === \"og:image:type\")?.[1] ?? \"image/png\"\n      if (link) {\n        return <MediaElement src={link} mime={videoType} />\n      }\n    }\n    if (preview?.image) {\n      let src = preview?.image\n      if (!preview.image.startsWith(\"http\")) {\n        src = `${uu.protocol}//${uu.hostname}/${preview.image}`\n      }\n      return <ProxyImg src={src} className=\"w-full object-cover aspect-video\" />\n    }\n    return null\n  }\n\n  return (\n    <div className=\"rounded-lg bg-layer-1 overflow-hidden hover:cursor-pointer light:border light:hover:shadow-md\">\n      {preview && (\n        <a href={url} onClick={e => e.stopPropagation()} target=\"_blank\" rel=\"noreferrer\" className=\"!no-underline\">\n          <div className=\"lg:min-h-[342px]\">{previewElement()}</div>\n          <div className=\"px-3 pb-2 leading-[21px]\">\n            <div className=\"font-bold leading-normal my-2\">{preview?.title}</div>\n            {preview?.description && (\n              <small className=\"text-neutral-800 text-sm\">{preview.description.slice(0, 160)}</small>\n            )}\n            <small className=\"text-xs\">{uu.host}</small>\n          </div>\n        </a>\n      )}\n      {!preview && <Spinner className=\"items-center\" />}\n    </div>\n  )\n}\n\nexport default LinkPreview\n"
  },
  {
    "path": "packages/app/src/Components/Embed/MagnetLink.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nimport type { Magnet } from \"@/Utils\"\nimport Icon from \"../Icons/Icon\"\n\ninterface MagnetLinkProps {\n  magnet: Magnet\n}\n\nconst MagnetLink = ({ magnet }: MagnetLinkProps) => {\n  return (\n    <div className=\"border rounded-lg p-6 flex-col items-start relative bg-[image:var(--invoice-gradient)]\">\n      <h4>\n        <FormattedMessage defaultMessage=\"Magnet Link\" />\n      </h4>\n      <a href={magnet.raw} rel=\"noreferrer\" className=\"flex gap-2 items-center\">\n        <Icon name=\"link\" size={16} />\n        {magnet.dn ?? magnet.infoHash}\n      </a>\n    </div>\n  )\n}\n\nexport default MagnetLink\n"
  },
  {
    "path": "packages/app/src/Components/Embed/MediaElement.tsx",
    "content": "import type { Nip94Tags } from \"@snort/system\"\nimport classNames from \"classnames\"\nimport type React from \"react\"\nimport { type CSSProperties, useEffect, useRef, useState } from \"react\"\nimport { useInView } from \"react-intersection-observer\"\n\nimport { ProxyImg, type ProxyImgProps } from \"@/Components/ProxyImg\"\nimport useImgProxy from \"@/Hooks/useImgProxy\"\nimport { randomSample } from \"@/Utils\"\n\nexport interface MediaElementProps {\n  mime: string\n  src: string\n  meta?: Nip94Tags\n  onMediaClick?: (e: React.MouseEvent<HTMLImageElement>) => void\n  onFallback?: (url: string) => void\n  size?: number\n  style?: CSSProperties\n}\n\ninterface AudioElementProps {\n  src: string\n}\n\ninterface VideoElementProps {\n  src: string\n  meta?: Nip94Tags\n}\n\nexport type ImageElementProps = ProxyImgProps & {\n  meta?: Nip94Tags\n  onMediaClick?: (e: React.MouseEvent<HTMLImageElement>) => void\n  onFallback?: (url: string) => void\n}\n\nconst AudioElement = ({ src }: AudioElementProps) => {\n  return <audio key={src} src={src} controls />\n}\n\nconst ImageElement = ({ src, meta, onMediaClick, size, onFallback, ...props }: ImageElementProps) => {\n  const imageRef = useRef<HTMLImageElement | null>(null)\n  const urlsRef = useRef<Array<string>>()\n  if (!urlsRef.current) {\n    urlsRef.current = randomSample([src, ...(meta?.fallback ?? [])], 10)\n  }\n  const [alternatives, setAlternatives] = useState<Array<string>>(urlsRef.current.slice(1))\n  const [currentUrl, setCurrentUrl] = useState(urlsRef.current[0])\n  if (\"creator\" in props) {\n    delete props.creator\n  }\n  if (\"mime\" in props) {\n    delete props.mime\n  }\n  return (\n    <ProxyImg\n      {...props}\n      key={currentUrl}\n      src={currentUrl}\n      sha256={meta?.hash}\n      onClick={onMediaClick}\n      className={classNames(\"relative max-h-[80vh] w-full h-full object-contain object-center\", {\n        \"md:max-h-[510px]\": !meta && !CONFIG.media.preferLargeMedia,\n      })}\n      ref={imageRef}\n      onError={() => {\n        const next = alternatives.at(0)\n        if (next) {\n          console.warn(\"IMG FALLBACK\", \"Failed to load url, trying next: \", next)\n          setAlternatives(z => z.filter(y => y !== next))\n          setCurrentUrl(next)\n          onFallback?.(next)\n        }\n      }}\n    />\n  )\n}\n\nconst VideoElement = ({ src }: VideoElementProps) => {\n  const { proxy } = useImgProxy()\n  const videoRef = useRef<HTMLVideoElement | null>(null)\n  const { ref: videoContainerRef, inView } = useInView({ threshold: 0.33 })\n  const isMobile = window.innerWidth < 768\n\n  useEffect(() => {\n    if (isMobile || !videoRef.current) {\n      return\n    }\n    if (inView) {\n      videoRef.current.play()\n    } else {\n      videoRef.current.pause()\n    }\n  }, [inView, isMobile])\n\n  return (\n    <div\n      ref={videoContainerRef}\n      className={classNames(\"flex justify-center items-center\", {\n        \"md:h-[510px]\": !CONFIG.media.preferLargeMedia,\n        \"-mx-3\": CONFIG.media.preferLargeMedia,\n      })}\n    >\n      <video\n        crossOrigin=\"anonymous\"\n        ref={videoRef}\n        loop={true}\n        muted={!isMobile}\n        src={src}\n        controls\n        poster={proxy(src)}\n        className={classNames(\"max-h-[80vh]\", { \"md:max-h-[510px]\": !CONFIG.media.preferLargeMedia })}\n        onClick={e => e.stopPropagation()}\n      />\n    </div>\n  )\n}\n\nexport function MediaElement(props: MediaElementProps) {\n  if (props.mime.startsWith(\"image/\")) {\n    return <ImageElement {...props} />\n  } else if (props.mime.startsWith(\"audio/\")) {\n    return <AudioElement {...props} />\n  } else if (props.mime.startsWith(\"video/\")) {\n    return <VideoElement {...props} />\n  } else {\n    return (\n      <a\n        key={props.src}\n        href={props.src}\n        onClick={e => e.stopPropagation()}\n        target=\"_blank\"\n        rel=\"noreferrer\"\n        className=\"text-highlight no-underline hover:underline\"\n      >\n        {props.src}\n      </a>\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Embed/Mention.tsx",
    "content": "import { NostrPrefix } from \"@snort/shared\"\nimport type { NostrLink } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport classNames from \"classnames\"\nimport { type ReactNode, useRef } from \"react\"\nimport DisplayName from \"@/Components/User/DisplayName\"\nimport { ProfileCardWrapper } from \"@/Components/User/ProfileCardWrapper\"\nimport { ProfileLink } from \"@/Components/User/ProfileLink\"\n\nexport default function Mention({\n  link,\n  prefix,\n  className,\n}: {\n  link: NostrLink\n  prefix?: ReactNode\n  className?: string\n}) {\n  const ref = useRef<HTMLSpanElement>(null)\n  const profile = useUserProfile(link.id, ref)\n\n  if (link.type !== NostrPrefix.Profile && link.type !== NostrPrefix.PublicKey) return\n\n  return (\n    <ProfileCardWrapper pubkey={link.id} user={profile}>\n      <span ref={ref} className={classNames(\"text-highlight\", className)}>\n        <ProfileLink pubkey={link.id} user={profile} onClick={e => e.stopPropagation()}>\n          {prefix ?? \"@\"}\n          <DisplayName user={profile} pubkey={link.id} />\n        </ProfileLink>\n      </span>\n    </ProfileCardWrapper>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Embed/MixCloudEmbed.tsx",
    "content": "import usePreferences from \"@/Hooks/usePreferences\"\nimport { MixCloudRegex } from \"@/Utils/Const\"\n\nconst MixCloudEmbed = ({ link }: { link: string }) => {\n  const match = link.match(MixCloudRegex)\n  if (!match) return\n  const feedPath = `${match[1]}%2F${match[2]}`\n\n  const theme = usePreferences(s => s.theme)\n  const lightParams = theme === \"light\" ? \"light=1\" : \"light=0\"\n  return (\n    <iframe\n      title=\"SoundCloud player\"\n      width=\"100%\"\n      height=\"120\"\n      frameBorder=\"0\"\n      src={`https://www.mixcloud.com/widget/iframe/?hide_cover=1&${lightParams}&feed=%2F${feedPath}%2F`}\n      loading=\"lazy\"\n    />\n  )\n}\n\nexport default MixCloudEmbed\n"
  },
  {
    "path": "packages/app/src/Components/Embed/NostrLink.tsx",
    "content": "import { tryParseNostrLink } from \"@snort/system\"\nimport { Link } from \"react-router-dom\"\n\nimport Mention from \"@/Components/Embed/Mention\"\nimport NoteQuote from \"@/Components/Event/Note/NoteQuote\"\nimport { NostrPrefix } from \"@snort/shared\"\nimport classNames from \"classnames\"\n\nexport default function NostrLink({ link, depth, className }: { link: string; depth?: number; className?: string }) {\n  const nav = tryParseNostrLink(link)\n\n  if (nav?.type === NostrPrefix.PublicKey || nav?.type === NostrPrefix.Profile) {\n    return <Mention link={nav} className={className} />\n  } else if (nav?.type === NostrPrefix.Note || nav?.type === NostrPrefix.Event || nav?.type === NostrPrefix.Address) {\n    if ((depth ?? 0) > 1) {\n      const evLink = nav.encode()\n      return (\n        <Link\n          to={`/${evLink}`}\n          onClick={e => e.stopPropagation()}\n          state={{ from: location.pathname }}\n          className={className}\n        >\n          #{evLink.substring(0, 12)}\n        </Link>\n      )\n    } else {\n      return <NoteQuote link={nav} depth={depth} className={className} />\n    }\n  } else {\n    return (\n      <a\n        href={link}\n        onClick={e => e.stopPropagation()}\n        target=\"_blank\"\n        rel=\"noreferrer\"\n        className={classNames(\"text-highlight no-underline hover:underline\", className)}\n      >\n        {link}\n      </a>\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Embed/NostrNestsEmbed.tsx",
    "content": "const NostrNestsEmbed = ({ link }: { link: string }) => (\n  <iframe src={link} allow=\"microphone\" width=\"480\" height=\"680\" style={{ maxHeight: 680 }}></iframe>\n)\n\nexport default NostrNestsEmbed\n"
  },
  {
    "path": "packages/app/src/Components/Embed/PubkeyList.tsx",
    "content": "import { hexToBech32, LNURL } from \"@snort/shared\"\nimport type { NostrEvent } from \"@snort/system\"\nimport { WalletInvoiceState } from \"@snort/wallet\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport { Toastore } from \"@/Components/Toaster/Toaster\"\nimport FollowListBase from \"@/Components/User/FollowListBase\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { dedupe, findTag, getDisplayName } from \"@/Utils\"\nimport { useWallet } from \"@/Wallet\"\n\nimport { ProxyImg } from \"../ProxyImg\"\n\nexport default function PubkeyList({ ev, className }: { ev: NostrEvent; className?: string }) {\n  const wallet = useWallet()\n  const defaultZapAmount = usePreferences(s => s.defaultZapAmount)\n  const { publisher, system } = useEventPublisher()\n  const ids = dedupe(ev.tags.filter(a => a[0] === \"p\").map(a => a[1]))\n\n  async function zapAll() {\n    for (const pk of ids) {\n      try {\n        const profile = await system.config.profiles.get(pk)\n        const amtSend = defaultZapAmount\n        const lnurl = profile?.lud16 || profile?.lud06\n        if (lnurl) {\n          const svc = new LNURL(lnurl)\n          await svc.load()\n\n          const relays = await system.requestRouter?.forReplyTo(pk)\n          const zap = await publisher?.zap(\n            amtSend * 1000,\n            pk,\n            relays ?? [],\n            undefined,\n            `Zap from ${hexToBech32(\"note\", ev.id)}`,\n          )\n          const invoice = await svc.getInvoice(amtSend, undefined, zap)\n          if (invoice.pr) {\n            const rsp = await wallet.wallet?.payInvoice(invoice.pr)\n            if (rsp?.state === WalletInvoiceState.Paid) {\n              Toastore.push({\n                element: (\n                  <FormattedMessage\n                    defaultMessage=\"Sent {n} sats to {name}\"\n                    id=\"Ig9/a1\"\n                    values={{\n                      n: amtSend,\n                      name: getDisplayName(profile, pk),\n                    }}\n                  />\n                ),\n                icon: \"zap\",\n              })\n            }\n          }\n        }\n      } catch (e) {\n        console.debug(\"Failed to zap\", pk, e)\n      }\n    }\n  }\n\n  const picture = findTag(ev, \"image\")\n  return (\n    <>\n      {picture && <ProxyImg src={picture} className=\"rounded-lg max-h-44 w-full object-cover mb-4\" />}\n      <FollowListBase\n        pubkeys={ids}\n        className={className}\n        title={findTag(ev, \"title\") ?? findTag(ev, \"d\")}\n        actions={<AsyncButton className=\"mr5 secondary\" onClick={() => zapAll()}>\n              <FormattedMessage\n                defaultMessage=\"Zap all {n} sats\"\n                id=\"IVbtTS\"\n                values={{\n                  n: <FormattedNumber value={defaultZapAmount * ids.length} />,\n                }}\n              />\n            </AsyncButton>}\n        profilePreviewProps={{\n          options: {\n            about: true,\n          },\n        }}\n      />\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Embed/SoundCloudEmded.tsx",
    "content": "const SoundCloudEmbed = ({ link }: { link: string }) => {\n  return (\n    <iframe\n      width=\"100%\"\n      height=\"166\"\n      allow=\"autoplay\"\n      src={`https://w.soundcloud.com/player/?url=${link}`}\n      loading=\"lazy\"\n    />\n  )\n}\n\nexport default SoundCloudEmbed\n"
  },
  {
    "path": "packages/app/src/Components/Embed/SpotifyEmbed.tsx",
    "content": "const SpotifyEmbed = ({ link }: { link: string }) => {\n  const convertedUrl = link.replace(/\\/(track|album|playlist|episode)\\/([a-zA-Z0-9]+)/, \"/embed/$1/$2\")\n\n  return (\n    <iframe\n      style={{ borderRadius: 12 }}\n      src={convertedUrl}\n      width=\"100%\"\n      height=\"352\"\n      frameBorder=\"0\"\n      allow=\"autoplay; clipboard-write; encrypted-media; fullscreen; picture-in-picture\"\n      loading=\"lazy\"\n    />\n  )\n}\n\nexport default SpotifyEmbed\n"
  },
  {
    "path": "packages/app/src/Components/Embed/TidalEmbed.tsx",
    "content": "import { useEffect, useState } from \"react\"\n\nimport { TidalRegex } from \"@/Utils/Const\"\n\n// Re-use dom parser across instances of TidalEmbed\nconst domParser = new DOMParser()\n\nasync function oembedLookup(link: string) {\n  // Regex + re-construct to handle both tidal.com/type/id and tidal.com/browse/type/id links.\n  const regexResult = TidalRegex.exec(link)\n\n  if (!regexResult) {\n    return Promise.reject(\"Not a TIDAL link.\")\n  }\n\n  const [, productType, productId] = regexResult\n  const oembedApi = `https://oembed.tidal.com/?url=https://tidal.com/browse/${productType}/${productId}`\n\n  const apiResponse = await fetch(oembedApi)\n  const json = await apiResponse.json()\n\n  const doc = domParser.parseFromString(json.html, \"text/html\")\n  const iframe = doc.querySelector(\"iframe\")\n\n  if (!iframe) {\n    return Promise.reject(\"No iframe delivered.\")\n  }\n\n  return {\n    source: iframe.getAttribute(\"src\"),\n    height: json.height,\n  }\n}\n\nconst TidalEmbed = ({ link }: { link: string }) => {\n  const [source, setSource] = useState<string>()\n  const [height, setHeight] = useState<number>()\n  const extraStyles = link.includes(\"video\") ? { aspectRatio: \"16 / 9\" } : { height }\n\n  useEffect(() => {\n    oembedLookup(link)\n      .then(data => {\n        setSource(data.source || undefined)\n        setHeight(data.height)\n      })\n      .catch(console.error)\n  }, [link])\n\n  if (!source) {\n    return (\n      <a\n        href={link}\n        target=\"_blank\"\n        rel=\"noreferrer\"\n        onClick={e => e.stopPropagation()}\n        className=\"text-highlight no-underline hover:underline\"\n      >\n        {link}\n      </a>\n    )\n  }\n  return (\n    <iframe\n      src={source}\n      style={extraStyles}\n      width=\"100%\"\n      allow=\"encrypted-media *; clipboard-write *; clipboard-read *\"\n      sandbox=\"allow-scripts allow-popups allow-forms allow-same-origin\"\n      title=\"TIDAL Embed\"\n      frameBorder={0}\n      loading=\"lazy\"\n    />\n  )\n}\n\nexport default TidalEmbed\n"
  },
  {
    "path": "packages/app/src/Components/Embed/TwitchEmbed.tsx",
    "content": "const TwitchEmbed = ({ link }: { link: string }) => {\n  const channel = link.split(\"/\").slice(-1)\n\n  const args = `?channel=${channel}&parent=${window.location.hostname}&muted=true`\n  return (\n    <iframe\n      src={`https://player.twitch.tv/${args}`}\n      className=\"aspect-video w-full\"\n      allowFullScreen={true}\n      loading=\"lazy\"\n    />\n  )\n}\n\nexport default TwitchEmbed\n"
  },
  {
    "path": "packages/app/src/Components/Embed/UrlStatusCheck.tsx",
    "content": "import { useEffect, useState } from \"react\"\nimport Icon from \"../Icons/Icon\"\nimport Spinner from \"../Icons/Spinner\"\n\ninterface UrlStatusCheckProps {\n  url: string\n}\n\nexport default function UrlStatusCheck({ url }: UrlStatusCheckProps) {\n  const [status, setStatus] = useState<\"loading\" | \"success\" | \"error\">(\"loading\")\n\n  useEffect(() => {\n    const controller = new AbortController()\n    setStatus(\"loading\")\n\n    fetch(url, {\n      method: \"HEAD\",\n      signal: controller.signal,\n    })\n      .then(response => {\n        if (response.ok) {\n          setStatus(\"success\")\n        } else {\n          setStatus(\"error\")\n        }\n      })\n      .catch(() => {\n        setStatus(\"error\")\n      })\n\n    return () => controller.abort()\n  }, [url])\n\n  if (status === \"loading\") {\n    return <Spinner width={16} />\n  }\n\n  if (status === \"success\") {\n    return <Icon name=\"check\" className=\"text-green-500\" size={16} />\n  }\n\n  return <Icon name=\"close\" className=\"text-red-500\" size={16} />\n}\n"
  },
  {
    "path": "packages/app/src/Components/Embed/WavlakeEmbed.tsx",
    "content": "const WavlakeEmbed = ({ link }: { link: string }) => {\n  const convertedUrl = link.replace(/(?:player\\.|www\\.)?wavlake\\.com/, \"embed.wavlake.com\")\n\n  return (\n    <iframe style={{ borderRadius: 12 }} src={convertedUrl} width=\"100%\" height=\"380\" frameBorder=\"0\" loading=\"lazy\" />\n  )\n}\n\nexport default WavlakeEmbed\n"
  },
  {
    "path": "packages/app/src/Components/Embed/YoutubeEmbed.tsx",
    "content": "import { YoutubeUrlRegex } from \"@/Utils/Const\"\n\nexport default function YoutubeEmbed({ link }: { link: string }) {\n  const m = link.match(YoutubeUrlRegex)\n  if (!m) return\n\n  return (\n    <iframe\n      className=\"aspect-video w-full\"\n      src={`https://www.youtube.com/embed/${m[1]}${m[3] ? `?list=${m[3].slice(6)}` : \"\"}`}\n      title=\"YouTube video player\"\n      frameBorder=\"0\"\n      allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"\n      allowFullScreen={true}\n    />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Embed/ZapstrEmbed.css",
    "content": ".zapstr {\n}\n\n.zapstr > img {\n  margin: 0 10px 0 0;\n}\n\n.zapstr audio {\n  margin: 0;\n  height: 2em;\n}\n\n.zapstr .pfp .avatar {\n  width: 35px;\n  height: 35px;\n}\n\n.zapstr .pfp .subheader {\n  text-transform: capitalize;\n}\n"
  },
  {
    "path": "packages/app/src/Components/Embed/ZapstrEmbed.tsx",
    "content": "import \"./ZapstrEmbed.css\"\n\nimport { type NostrEvent, NostrLink } from \"@snort/system\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport { ProxyImg } from \"@/Components/ProxyImg\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\n\nexport default function ZapstrEmbed({ ev }: { ev: NostrEvent }) {\n  const media = ev.tags.find(a => a[0] === \"media\")\n  const cover = ev.tags.find(a => a[0] === \"cover\")\n  const subject = ev.tags.find(a => a[0] === \"subject\")\n  const refPersons = ev.tags.filter(a => a[0] === \"p\")\n\n  const link = NostrLink.fromEvent(ev).encode(CONFIG.eventLinkPrefix)\n  return (\n    <>\n      <div className=\"flex mb-2.5 layer-1\">\n        <ProxyImg src={cover?.[1] ?? \"\"} size={100} className=\"mr-2.5\" />\n        <div className=\"flex flex-col\">\n          <div>\n            <h3>{subject?.[1] ?? \"\"}</h3>\n          </div>\n          <audio src={media?.[1] ?? \"\"} controls={true} className=\"m-0 h-8\" />\n          <div className=\"zapstr\">\n            {refPersons.map(a => (\n              <ProfileImage key={a[1]} pubkey={a[1]} subHeader={a[2] ?? \"\"} className=\"pfp\" defaultNip=\" \" />\n            ))}\n          </div>\n        </div>\n      </div>\n      <Link to={`https://zapstr.live/?track=${link}`} target=\"_blank\">\n        <button>\n          <FormattedMessage defaultMessage=\"Open on Zapstr\" />\n        </button>\n      </Link>\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/ErrorBoundary.tsx",
    "content": "import React from \"react\"\n\nimport { trackEvent } from \"@/Utils\"\n\ninterface ErrorBoundaryState {\n  hasError: boolean\n  error?: Error\n}\n\ninterface ErrorBoundaryProps {\n  children: React.ReactNode\n}\n\nexport default class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n  constructor(props: ErrorBoundaryProps) {\n    super(props)\n    this.state = { hasError: false }\n  }\n\n  static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n    return { hasError: true, error }\n  }\n\n  componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {\n    console.error(\"Caught an error:\", error, errorInfo)\n    trackEvent(\"error\", { error: error.message, errorInfo: JSON.stringify(errorInfo) })\n  }\n\n  render() {\n    if (this.state.hasError) {\n      // Render any custom fallback UI with the error message\n      return (\n        <div className=\"m-4 layer-1 text-xs font-mono overflow-auto\">\n          <h2>Something went wrong.</h2>\n          <b>{this.state.error?.message}</b>\n          <pre>{this.state.error?.stack}</pre>\n        </div>\n      )\n    }\n\n    return this.props.children\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/ErrorOrOffline.tsx",
    "content": "import { OfflineError } from \"@snort/shared\"\nimport classNames from \"classnames\"\n\nimport Icon from \"@/Components/Icons/Icon\"\n\nimport { Offline } from \"./Offline\"\n\nexport function ErrorOrOffline({\n  error,\n  onRetry,\n  className,\n}: {\n  error: Error\n  onRetry?: () => void | Promise<void>\n  className?: string\n}) {\n  if (error instanceof OfflineError) {\n    return <Offline onRetry={onRetry} className={className} />\n  } else {\n    return (\n      <div className={classNames(\"flex flex-row items-center px-4 py-3 gap-2\", className)}>\n        <Icon name=\"alert-circle\" size={24} />\n        <b>{error.message}</b>\n      </div>\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Application.tsx",
    "content": "import { mapEventToProfile, type TaggedNostrEvent } from \"@snort/system\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport KindName from \"../kind-name\"\nimport Avatar from \"../User/Avatar\"\nimport DisplayName from \"../User/DisplayName\"\nimport ProfileImage from \"../User/ProfileImage\"\nimport Icon from \"../Icons/Icon\"\n\nexport function ApplicationHandler({ ev }: { ev: TaggedNostrEvent }) {\n  const profile = mapEventToProfile(ev)\n  const kinds = ev.tags\n    .filter(a => a[0] === \"k\")\n    .map(a => Number(a[1]))\n    .sort((a, b) => a - b)\n  const sourceLink = ev.tags.find(a => a[0] === \"r\" && a[2] === \"source\")?.[1]\n  return (\n    <div className=\"px-3 py-2 flex gap-2 flex-col\">\n      <div className=\"flex items-center gap-2 text-xl\">\n        <Avatar user={profile} pubkey={\"\"} size={120} />\n        <div className=\"flex flex-col gap-2\">\n          <DisplayName user={profile} pubkey={\"\"} />\n          <div className=\"text-sm flex flex-col gap-2\">\n            <div className=\"text-neutral-400\">\n              <FormattedMessage defaultMessage=\"Published by\" />\n            </div>\n            <ProfileImage pubkey={ev.pubkey} size={30} />\n            {sourceLink && (\n              <a href={sourceLink} className=\"flex items-center gap-1\" target=\"_blank\">\n                <Icon name=\"link\" size={14} />\n                <FormattedMessage defaultMessage=\"Source Code\" />\n              </a>\n            )}\n          </div>\n        </div>\n      </div>\n      <FormattedMessage defaultMessage=\"Supported Kinds:\" />\n      <div className=\"flex flex-wrap gap-1\">\n        {kinds.map(a => (\n          <div key={a} className=\"bg-layer-1 px-2 py-1 rounded-lg\">\n            <KindName kind={a} />\n          </div>\n        ))}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Create/NoteCreator.tsx",
    "content": "/* eslint-disable max-lines */\nimport { fetchNip05Pubkey, NostrPrefix, unixNow } from \"@snort/shared\"\nimport {\n  type EventBuilder,\n  EventKind,\n  LinkScope,\n  Nip18,\n  type Nip94Tags,\n  nip94TagsToIMeta,\n  NostrLink,\n  readNip94Tags,\n  type TaggedNostrEvent,\n  tryParseNostrLink,\n} from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport type { ZapTarget } from \"@snort/wallet\"\nimport * as DropdownMenu from \"@radix-ui/react-dropdown-menu\"\nimport classNames from \"classnames\"\nimport { type ClipboardEventHandler, type DragEvent, useEffect } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport { AsyncIcon } from \"@/Components/Button/AsyncIcon\"\nimport CloseButton from \"@/Components/Button/CloseButton\"\nimport IconButton from \"@/Components/Button/IconButton\"\nimport { sendEventToRelays } from \"@/Components/Event/Create/util\"\nimport Note, { type NotePropsOptions } from \"@/Components/Event/EventComponent\"\nimport Flyout from \"@/Components/flyout\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport { ToggleSwitch } from \"@/Components/Icons/Toggle\"\nimport Modal from \"@/Components/Modal/Modal\"\nimport Textarea from \"@/Components/Textarea/Textarea\"\nimport { Toastore } from \"@/Components/Toaster/Toaster\"\nimport { MediaServerFileList } from \"@/Components/Upload/file-picker\"\nimport Avatar from \"@/Components/User/Avatar\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport useRelays from \"@/Hooks/useRelays\"\nimport { useNoteCreator } from \"@/State/NoteCreator\"\nimport { openFile, trackEvent } from \"@/Utils\"\nimport useFileUpload from \"@/Utils/Upload\"\nimport { GetPowWorker } from \"@/Utils/wasm\"\n\nimport { OkResponseRow } from \"./OkResponseRow\"\n\nconst previewNoteOptions = {\n  showContextMenu: false,\n  showFooter: false,\n  canClick: false,\n  showTime: false,\n} as NotePropsOptions\n\nconst replyToNoteOptions = {\n  showFooter: false,\n  showContextMenu: false,\n  showProfileCard: false,\n  showTime: false,\n  canClick: false,\n  longFormPreview: true,\n  showMedia: false,\n} as NotePropsOptions\n\nexport function NoteCreator() {\n  const { formatMessage } = useIntl()\n  const uploader = useFileUpload()\n  const publicKey = useLogin(s => s.publicKey)\n  const profile = useUserProfile(publicKey)\n  const pow = usePreferences(s => s.pow)\n  const relays = useRelays()\n  const { system, publisher: pub } = useEventPublisher()\n  const publisher = pow ? pub?.pow(pow, GetPowWorker()) : pub\n  const note = useNoteCreator()\n\n  useEffect(() => {\n    const draft = localStorage.getItem(\"msgDraft\")\n    if (draft) {\n      note.update(n => (n.note = draft))\n    }\n  }, [note.update])\n\n  async function buildNote() {\n    try {\n      note.update(v => (v.error = \"\"))\n      if (note && publisher) {\n        let extraTags: Array<Array<string>> | undefined\n        if (note.zapSplits) {\n          const parsedSplits = [] as Array<ZapTarget>\n          for (const s of note.zapSplits) {\n            if (s.value.startsWith(NostrPrefix.PublicKey) || s.value.startsWith(NostrPrefix.Profile)) {\n              const link = tryParseNostrLink(s.value)\n              if (link) {\n                parsedSplits.push({ ...s, value: link.id })\n              } else {\n                throw new Error(\n                  formatMessage(\n                    {\n                      defaultMessage: \"Failed to parse zap split: {input}\",\n                    },\n                    {\n                      input: s.value,\n                    },\n                  ),\n                )\n              }\n            } else if (s.value.includes(\"@\")) {\n              const [name, domain] = s.value.split(\"@\")\n              const pubkey = await fetchNip05Pubkey(name, domain)\n              if (pubkey) {\n                parsedSplits.push({ ...s, value: pubkey })\n              } else {\n                throw new Error(\n                  formatMessage(\n                    {\n                      defaultMessage: \"Failed to parse zap split: {input}\",\n                    },\n                    {\n                      input: s.value,\n                    },\n                  ),\n                )\n              }\n            } else {\n              throw new Error(\n                formatMessage(\n                  {\n                    defaultMessage: \"Invalid zap split: {input}\",\n                  },\n                  {\n                    input: s.value,\n                  },\n                ),\n              )\n            }\n          }\n          extraTags = parsedSplits.map(v => [\"zap\", v.value, \"\", String(v.weight)])\n        }\n\n        if (note.sensitive) {\n          extraTags ??= []\n          extraTags.push([\"content-warning\", note.sensitive])\n        }\n        if (note.pollOptions) {\n          extraTags ??= []\n          extraTags.push(...note.pollOptions.map((a, i) => [\"poll_option\", i.toString(), a]))\n        }\n        if (note.hashTags.length > 0) {\n          extraTags ??= []\n          extraTags.push(...note.hashTags.map(a => [\"t\", a.toLowerCase()]))\n        }\n\n        // attach 1 link and use other duplicates as fallback urls\n        for (const [, v] of Object.entries(note.attachments ?? {})) {\n          const at = v[0]\n          note.note += note.note.length > 0 ? `\\n${at.url}` : at.url\n          const n94 =\n            (at.nip94?.length ?? 0) > 0\n              ? readNip94Tags(at.nip94!)\n              : ({\n                  url: at.url,\n                  hash: at.sha256,\n                  size: at.size,\n                  mimeType: at.type,\n                } as Nip94Tags)\n\n          // attach fallbacks\n          n94.fallback ??= []\n          n94.fallback.push(\n            ...v\n              .slice(1)\n              .filter(a => a.url)\n              .map(a => a.url!),\n          )\n\n          extraTags ??= []\n          extraTags.push(nip94TagsToIMeta(n94))\n        }\n\n        // add quote repost\n        if (note.quote) {\n          if (!note.note.endsWith(\"\\n\")) {\n            note.note += \"\\n\"\n          }\n          const link = NostrLink.fromEvent(note.quote)\n          link.scope = LinkScope.Quote\n\n          note.note += `nostr:${link.encode(CONFIG.eventLinkPrefix)}`\n          const quoteTag = Nip18.linkToTag(link)\n          extraTags ??= []\n          extraTags.push(quoteTag)\n        }\n        const hk = (eb: EventBuilder) => {\n          extraTags?.forEach(t => eb.tag(t))\n          note.extraTags?.forEach(t => eb.tag(t))\n          if (note.pollOptions) {\n            eb.kind(EventKind.Polls)\n          }\n          return eb\n        }\n        const ev = note.replyTo\n          ? await publisher.reply(note.replyTo, note.note, hk)\n          : await publisher.note(note.note, hk)\n        return ev\n      }\n    } catch (e) {\n      note.update(v => {\n        if (e instanceof Error) {\n          v.error = e.message\n        } else {\n          v.error = e as string\n        }\n      })\n    }\n  }\n\n  async function sendNote() {\n    const ev = await buildNote()\n    if (ev) {\n      let props: Record<string, boolean> | undefined\n      if (ev.tags.find(a => a[0] === \"content-warning\")) {\n        props ??= {}\n        props[\"content-warning\"] = true\n      }\n      if (ev.tags.find(a => a[0] === \"poll_option\")) {\n        props ??= {}\n        props.poll = true\n      }\n      if (ev.tags.find(a => a[0] === \"zap\")) {\n        props ??= {}\n        props[\"zap-split\"] = true\n      }\n      if (note.hashTags.length > 0) {\n        props ??= {}\n        props.hashtags = true\n      }\n      if (props) {\n        props[\"content-warning\"] ??= false\n        props.poll ??= false\n        props[\"zap-split\"] ??= false\n        props.hashtags ??= false\n      }\n      trackEvent(\"PostNote\", props)\n\n      sendEventToRelays(system, ev, note.selectedCustomRelays, r => {\n        if (CONFIG.noteCreatorToast) {\n          r.forEach(rr => {\n            Toastore.push({\n              element: c => <OkResponseRow rsp={rr} close={c} />,\n              expire: unixNow() + (rr.ok ? 5 : 55555),\n            })\n          })\n        }\n      })\n      note.update(n => n.reset())\n      localStorage.removeItem(\"msgDraft\")\n    }\n  }\n\n  async function attachFile() {\n    try {\n      const file = await openFile()\n      if (file) {\n        uploadFile(file)\n      }\n    } catch (e) {\n      note.update(v => {\n        if (e instanceof Error) {\n          v.error = e.message\n        } else {\n          v.error = e as string\n        }\n      })\n    }\n  }\n\n  async function uploadFile(file: File) {\n    try {\n      if (file && uploader) {\n        const rx = await uploader.upload(file)\n        note.update(v => {\n          if (rx.url) {\n            v.attachments ??= {}\n            v.attachments[rx.sha256] ??= []\n            v.attachments[rx.sha256].push(rx)\n          }\n        })\n      }\n    } catch (e) {\n      note.update(v => {\n        if (e instanceof Error) {\n          v.error = e.message\n        } else {\n          v.error = e as string\n        }\n      })\n    }\n  }\n\n  function onChange(ev: React.ChangeEvent<HTMLTextAreaElement>) {\n    const { value } = ev.target\n    note.update(n => (n.note = value))\n    localStorage.setItem(\"msgDraft\", value)\n  }\n\n  function cancel() {\n    note.update(v => {\n      v.show = false\n      v.reset()\n    })\n  }\n\n  async function onSubmit(ev: React.MouseEvent) {\n    ev.stopPropagation()\n    await sendNote()\n  }\n\n  async function loadPreview() {\n    if (note.preview) {\n      note.update(v => (v.preview = undefined))\n    } else if (publisher) {\n      const tmpNote = await buildNote()\n      trackEvent(\"PostNotePreview\")\n      note.update(v => (v.preview = tmpNote))\n    }\n  }\n\n  function getPreviewNote() {\n    if (note.preview) {\n      return (\n        <Note className=\"hover:bg-transparent\" data={note.preview as TaggedNostrEvent} options={previewNoteOptions} />\n      )\n    }\n  }\n\n  function renderPollOptions() {\n    if (note.pollOptions) {\n      return (\n        <>\n          <h4>\n            <FormattedMessage defaultMessage=\"Poll Options\" />\n          </h4>\n          {note.pollOptions?.map((a, i) => (\n            <div className=\"w-max\" key={`po-${i}`}>\n              <div>\n                <FormattedMessage defaultMessage=\"Option: {n}\" values={{ n: i + 1 }} />\n              </div>\n              <div>\n                <input type=\"text\" value={a} onChange={e => changePollOption(i, e.target.value)} />\n                {i > 1 && <CloseButton className=\"ml5\" onClick={() => removePollOption(i)} />}\n              </div>\n            </div>\n          ))}\n          <button onClick={() => note.update(v => (v.pollOptions = [...(note.pollOptions ?? []), \"\"]))}>\n            <Icon name=\"plus\" size={14} />\n          </button>\n        </>\n      )\n    }\n  }\n\n  function changePollOption(i: number, v: string) {\n    if (note.pollOptions) {\n      const copy = [...note.pollOptions]\n      copy[i] = v\n      note.update(v => (v.pollOptions = copy))\n    }\n  }\n\n  function removePollOption(i: number) {\n    if (note.pollOptions) {\n      const copy = [...note.pollOptions]\n      copy.splice(i, 1)\n      note.update(v => (v.pollOptions = copy))\n    }\n  }\n\n  function renderRelayCustomisation() {\n    return (\n      <div className=\"flex flex-col gap-2\">\n        {Object.entries(relays)\n          .filter(el => el[1].write)\n          .map(a => a[0])\n          .map((r, _i, a) => (\n            <div className=\"px-3 py-2 flex items-center justify-between bg-neutral-600 rounded-lg\" key={r}>\n              <div>{r}</div>\n              <div>\n                <input\n                  type=\"checkbox\"\n                  checked={!note.selectedCustomRelays || note.selectedCustomRelays.includes(r)}\n                  onChange={e => {\n                    note.update(\n                      v =>\n                        (v.selectedCustomRelays =\n                          // set false if all relays selected\n                          e.target.checked &&\n                          note.selectedCustomRelays &&\n                          note.selectedCustomRelays.length === a.length - 1\n                            ? undefined\n                            : // otherwise return selectedCustomRelays with target relay added / removed\n                              a.filter(el =>\n                                el === r\n                                  ? e.target.checked\n                                  : !note.selectedCustomRelays || note.selectedCustomRelays.includes(el),\n                              )),\n                    )\n                  }}\n                />\n              </div>\n            </div>\n          ))}\n      </div>\n    )\n  }\n\n  /*function listAccounts() {\n    return LoginStore.getSessions().map(a => (\n      <MenuItem\n        onClick={ev => {\n          ev.stopPropagation = true;\n          LoginStore.switchAccount(a);\n        }}>\n        <ProfileImage pubkey={a} link={\"\"} />\n      </MenuItem>\n    ));\n  }*/\n\n  function noteCreatorAdvanced() {\n    return (\n      <>\n        <div>\n          <h4>\n            <FormattedMessage defaultMessage=\"Custom Relays\" />\n          </h4>\n          <p>\n            <FormattedMessage defaultMessage=\"Send note to a subset of your write relays\" />\n          </p>\n          {renderRelayCustomisation()}\n        </div>\n        <div className=\"flex flex-col gap-2\">\n          <h4>\n            <FormattedMessage defaultMessage=\"Zap Splits\" />\n          </h4>\n          <FormattedMessage defaultMessage=\"Zaps on this note will be split to the following users.\" />\n          <div className=\"flex flex-col gap-2\">\n            {[...(note.zapSplits ?? [])].map((v: ZapTarget, i, arr) => (\n              <div className=\"flex items-center gap-2\" key={`${v.name}-${v.value}`}>\n                <div className=\"flex flex-col flex-4 gap-1\">\n                  <h4>\n                    <FormattedMessage defaultMessage=\"Recipient\" />\n                  </h4>\n                  <input\n                    type=\"text\"\n                    value={v.value}\n                    onChange={e =>\n                      note.update(\n                        v => (v.zapSplits = arr.map((vv, ii) => (ii === i ? { ...vv, value: e.target.value } : vv))),\n                      )\n                    }\n                    placeholder={formatMessage({ defaultMessage: \"npub / nprofile / nostr address\", id: \"WvGmZT\" })}\n                  />\n                </div>\n                <div className=\"flex flex-col flex-1 gap-1\">\n                  <h4>\n                    <FormattedMessage defaultMessage=\"Weight\" />\n                  </h4>\n                  <input\n                    type=\"number\"\n                    min={0}\n                    value={v.weight}\n                    onChange={e =>\n                      note.update(\n                        v =>\n                          (v.zapSplits = arr.map((vv, ii) =>\n                            ii === i ? { ...vv, weight: Number(e.target.value) } : vv,\n                          )),\n                      )\n                    }\n                  />\n                </div>\n                <div className=\"flex flex-col gap-1\">\n                  <div>&nbsp;</div>\n                  <Icon\n                    name=\"close\"\n                    onClick={() => note.update(v => (v.zapSplits = (v.zapSplits ?? []).filter((_v, ii) => ii !== i)))}\n                  />\n                </div>\n              </div>\n            ))}\n            <button\n              type=\"button\"\n              onClick={() =>\n                note.update(v => (v.zapSplits = [...(v.zapSplits ?? []), { type: \"pubkey\", value: \"\", weight: 1 }]))\n              }\n            >\n              <FormattedMessage defaultMessage=\"Add\" />\n            </button>\n          </div>\n          <span className=\"text-warning\">\n            <FormattedMessage defaultMessage=\"Not all clients support this, you may still receive some zaps as if zap splits was not configured\" />\n          </span>\n        </div>\n        <div className=\"flex flex-col gap-2\">\n          <h4>\n            <FormattedMessage defaultMessage=\"Sensitive Content\" />\n          </h4>\n          <FormattedMessage defaultMessage=\"Users must accept the content warning to show the content of your note.\" />\n          <input\n            className=\"w-full\"\n            type=\"text\"\n            value={note.sensitive}\n            onChange={e => note.update(v => (v.sensitive = e.target.value))}\n            maxLength={50}\n            minLength={1}\n            placeholder={formatMessage({\n              defaultMessage: \"Reason\",\n            })}\n          />\n          <span className=\"text-warning\">\n            <FormattedMessage defaultMessage=\"Not all clients support this yet\" />\n          </span>\n        </div>\n      </>\n    )\n  }\n\n  function noteCreatorFooter() {\n    return (\n      <div className=\"flex justify-between\">\n        <div className=\"flex items-center gap-4 text-gray-light cursor-pointer\">\n          <Avatar pubkey={publicKey ?? \"\"} user={profile} size={28} showTitle={true} />\n          <DropdownMenu.Root>\n            <DropdownMenu.Trigger asChild>\n              <span>\n                <AsyncIcon\n                  iconName=\"attachment\"\n                  iconSize={24}\n                  className=\"hover:text-gray-superlight transition cursor-pointer\"\n                />\n              </span>\n            </DropdownMenu.Trigger>\n            <DropdownMenu.Portal>\n              <DropdownMenu.Content className=\"bg-layer-2 rounded-lg overflow-hidden z-[9999] min-w-48\" sideOffset={5}>\n                <DropdownMenu.Item\n                  className=\"px-6 py-2 text-base font-semibold bg-layer-2 light:bg-white hover:bg-layer-3 light:hover:bg-neutral-200 cursor-pointer outline-none\"\n                  onClick={e => {\n                    e.stopPropagation()\n                    note.update(s => (s.filePicker = \"compact\"))\n                  }}\n                >\n                  <FormattedMessage defaultMessage=\"From Server\" />\n                </DropdownMenu.Item>\n                <DropdownMenu.Item\n                  className=\"px-6 py-2 text-base font-semibold bg-layer-2 light:bg-white hover:bg-layer-3 light:hover:bg-neutral-200 cursor-pointer outline-none\"\n                  onClick={e => {\n                    e.stopPropagation()\n                    attachFile()\n                  }}\n                >\n                  <FormattedMessage defaultMessage=\"From File\" />\n                </DropdownMenu.Item>\n              </DropdownMenu.Content>\n            </DropdownMenu.Portal>\n          </DropdownMenu.Root>\n\n          {note.pollOptions === undefined && !note.replyTo && (\n            <AsyncIcon\n              iconName=\"bar-chart\"\n              iconSize={24}\n              onClick={() => note.update(v => (v.pollOptions = [\"A\", \"B\"]))}\n              className={classNames(\"hover:text-gray-superlight transition\", {\n                \"text-white\": note.pollOptions !== undefined,\n              })}\n            />\n          )}\n          <AsyncIcon\n            iconName=\"settings-outline\"\n            iconSize={24}\n            onClick={() => note.update(v => (v.advanced = !v.advanced))}\n            className={classNames(\"hover:text-gray-superlight transition\", { \"text-white\": note.advanced })}\n          />\n          <span className=\"sm:inline hidden\">\n            <FormattedMessage defaultMessage=\"Preview\" />\n          </span>\n          <ToggleSwitch\n            onClick={() => loadPreview()}\n            size={40}\n            className={classNames({ active: Boolean(note.preview) })}\n          />\n        </div>\n        <AsyncButton onClick={onSubmit} className=\"bg-primary\">\n          {note.replyTo ? <FormattedMessage defaultMessage=\"Reply\" /> : <FormattedMessage defaultMessage=\"Send\" />}\n        </AsyncButton>\n      </div>\n    )\n  }\n\n  const handlePaste: ClipboardEventHandler<HTMLDivElement> = evt => {\n    if (evt.clipboardData) {\n      const clipboardItems = evt.clipboardData.items\n      const items: DataTransferItem[] = Array.from(clipboardItems).filter((item: DataTransferItem) => {\n        // Filter the image items only\n        return /^image\\//.test(item.type)\n      })\n      if (items.length === 0) {\n        return\n      }\n\n      const item = items[0]\n      const blob = item.getAsFile()\n      if (blob) {\n        uploadFile(blob)\n      }\n    }\n  }\n\n  const handleDragOver = (event: DragEvent<HTMLTextAreaElement>) => {\n    event.preventDefault()\n  }\n\n  const handleDragLeave = (event: DragEvent<HTMLTextAreaElement>) => {\n    event.preventDefault()\n  }\n\n  const handleDrop = (event: DragEvent<HTMLTextAreaElement>) => {\n    event.preventDefault()\n\n    const droppedFiles = Array.from(event.dataTransfer.files)\n\n    droppedFiles.forEach(async file => {\n      await uploadFile(file)\n    })\n  }\n\n  function noteCreatorForm() {\n    return (\n      <div className=\"flex flex-col gap-4\">\n        {note.replyTo && (\n          <>\n            <h4>\n              <FormattedMessage defaultMessage=\"Reply To\" />\n            </h4>\n            <div className=\"max-h-64 overflow-y-auto\">\n              <Note data={note.replyTo} options={replyToNoteOptions} />\n            </div>\n            <hr />\n          </>\n        )}\n        {note.quote && (\n          <>\n            <h4>\n              <FormattedMessage defaultMessage=\"Quote Repost\" />\n            </h4>\n            <div className=\"max-h-64 overflow-y-auto\">\n              <Note data={note.quote} options={replyToNoteOptions} />\n            </div>\n            <hr />\n          </>\n        )}\n        {note.preview && getPreviewNote()}\n        {!note.preview && (\n          <div className=\"flex flex-col gap-4\">\n            <div className=\"font-medium flex justify-between items-center\">\n              <FormattedMessage defaultMessage=\"Compose a note\" />\n              <AsyncIcon\n                iconName=\"x\"\n                className=\"bg-neutral-600 rounded-full items-center justify-center flex p-1 cursor-pointer\"\n                onClick={cancel}\n              />\n            </div>\n            <div onPaste={handlePaste} className={classNames({ poll: Boolean(note.pollOptions) })}>\n              <Textarea\n                className=\"!border-none !resize-none !p-0 !rounded-none !text-sm\"\n                onDragOver={handleDragOver}\n                onDragLeave={handleDragLeave}\n                onDrop={handleDrop}\n                autoFocus={true}\n                onChange={c => onChange(c)}\n                value={note.note}\n                onFocus={() => note.update(v => (v.active = true))}\n                onKeyDown={e => {\n                  if (e.key === \"Enter\" && e.metaKey) {\n                    sendNote().catch(console.warn)\n                  }\n                }}\n              />\n              {renderPollOptions()}\n            </div>\n          </div>\n        )}\n        {Object.entries(note.attachments ?? {}).length > 0 && !note.preview && (\n          <div className=\"flex gap-2 flex-wrap\">\n            {Object.entries(note.attachments ?? {}).map(([k, v]) => (\n              <div key={k} className=\"relative\">\n                <img className=\"object-cover w-[80px] h-[80px] !mt-0 rounded-lg\" src={v[0].url} />\n                <Icon\n                  name=\"x\"\n                  className=\"absolute -top-1 -right-1 bg-neutral-600 rounded-full cursor-pointer\"\n                  onClick={() =>\n                    note.update(n => {\n                      if (n.attachments?.[k]) {\n                        delete n.attachments[k]\n                      }\n                      return n\n                    })\n                  }\n                />\n              </div>\n            ))}\n          </div>\n        )}\n        {noteCreatorFooter()}\n        {note.error && <span className=\"text-error\">{note.error}</span>}\n        {note.advanced && noteCreatorAdvanced()}\n        <Flyout\n          show={note.filePicker !== \"hidden\"}\n          width={note.filePicker !== \"compact\" ? \"70vw\" : undefined}\n          onClose={() => note.update(v => (v.filePicker = \"hidden\"))}\n          side=\"right\"\n          title={\n            <div className=\"text-xl font-medium\">\n              <FormattedMessage defaultMessage=\"Attach Media\" />\n            </div>\n          }\n          actions=<IconButton\n                className=\"max-lg:!hidden\"\n                icon={{\n                  name: \"expand\",\n                }}\n                onClick={() => note.update(n => (n.filePicker = n.filePicker === \"wide\" ? \"compact\" : \"wide\"))}\n              />\n        >\n          <div className=\"overflow-y-auto h-[calc(100%-2rem)]\">\n            {note.filePicker !== \"hidden\" && (\n              <MediaServerFileList\n                onPicked={files => {\n                  note.update(n => {\n                    for (const x of files) {\n                      n.attachments ??= {}\n                      n.attachments[x.sha256] ??= []\n                      n.attachments[x.sha256].push(x)\n                    }\n                    n.filePicker = \"hidden\"\n                  })\n                }}\n                cols={note.filePicker === \"compact\" ? 2 : 6}\n              />\n            )}\n          </div>\n        </Flyout>\n      </div>\n    )\n  }\n\n  function reset() {\n    note.update(v => {\n      v.show = false\n    })\n  }\n\n  if (!note.show) return null\n  return (\n    <Modal id=\"note-creator\" onClose={reset}>\n      {noteCreatorForm()}\n    </Modal>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Create/NoteCreatorButton.tsx",
    "content": "import classNames from \"classnames\"\nimport { useMemo, useRef } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useLocation } from \"react-router-dom\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport useKeyboardShortcut from \"@/Hooks/useKeyboardShortcut\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { useNoteCreator } from \"@/State/NoteCreator\"\nimport { isFormElement } from \"@/Utils\"\n\nimport { NoteCreator } from \"./NoteCreator\"\n\nexport const NoteCreatorButton = ({\n  className,\n  alwaysShow,\n  showText,\n  withModal,\n}: {\n  className?: string\n  alwaysShow?: boolean\n  showText?: boolean\n  withModal: boolean\n}) => {\n  const buttonRef = useRef<HTMLButtonElement>(null)\n  const location = useLocation()\n  const { readonly } = useLogin(s => ({ readonly: s.readonly }))\n  const { show, replyTo, update } = useNoteCreator(v => ({ show: v.show, replyTo: v.replyTo, update: v.update }))\n\n  useKeyboardShortcut(\"n\", event => {\n    // if event happened in a form element, do nothing, otherwise focus on search input\n    if (event.target && !isFormElement(event.target as HTMLElement)) {\n      event.preventDefault()\n      if (buttonRef.current) {\n        buttonRef.current.click()\n      }\n    }\n  })\n\n  const shouldHideNoteCreator = useMemo(() => {\n    if (alwaysShow) {\n      return false\n    }\n    const isReply = replyTo && show\n    const hideOn = [\n      \"/settings\",\n      \"/messages\",\n      \"/new\",\n      \"/login\",\n      \"/about\",\n      \"/e\",\n      \"/nevent\",\n      \"/note1\",\n      \"/naddr\",\n      \"/subscribe\",\n    ]\n    return (readonly || hideOn.some(a => location.pathname.startsWith(a))) && !isReply\n  }, [location, readonly, alwaysShow, replyTo, show])\n\n  return (\n    <>\n      {!shouldHideNoteCreator && (\n        <button\n          ref={buttonRef}\n          className={classNames(\n            \"aspect-square flex flex-row items-center primary rounded-full\",\n            { \"xl:aspect-auto\": showText },\n            className,\n          )}\n          onClick={() =>\n            update(v => {\n              v.replyTo = undefined\n              v.show = true\n            })\n          }\n        >\n          <Icon name=\"plus\" size={16} />\n          {showText && (\n            <span className=\"ml-2 hidden xl:inline\">\n              <FormattedMessage defaultMessage=\"New Note\" />\n            </span>\n          )}\n        </button>\n      )}\n      {withModal && <NoteCreator key=\"global-note-creator\" />}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Create/OkResponseRow.tsx",
    "content": "import { sanitizeRelayUrl, unwrap } from \"@snort/shared\"\nimport type { OkResponse } from \"@snort/system\"\nimport { useState } from \"react\"\nimport { useIntl } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport IconButton from \"@/Components/Button/IconButton\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { getRelayName } from \"@/Utils\"\n\nexport function OkResponseRow({ rsp, close }: { rsp: OkResponse; close: () => void }) {\n  const [r, setResult] = useState(rsp)\n  const { formatMessage } = useIntl()\n  const { system } = useEventPublisher()\n  const login = useLogin()\n\n  async function removeRelayFromResult(r: OkResponse) {\n    login.state.removeRelay(unwrap(sanitizeRelayUrl(r.relay)))\n    await login.state.saveRelays()\n    close()\n  }\n\n  async function retryPublish(r: OkResponse) {\n    const rsp = await system.WriteOnceToRelay(unwrap(sanitizeRelayUrl(r.relay)), r.event)\n    setResult(rsp)\n  }\n\n  return (\n    <div className=\"flex items-center gap-4\">\n      <div className=\"flex flex-col grow gap-1\">\n        <b>{getRelayName(r.relay)}</b>\n        {r.message && <small>{r.message}</small>}\n      </div>\n      {!r.ok && (\n        <div className=\"flex gap-2\">\n          <AsyncButton\n            onClick={() => retryPublish(r)}\n            className=\"p-1 rounded-lg flex items-center secondary\"\n            title={formatMessage({\n              defaultMessage: \"Retry publishing\",\n              id: \"9kSari\",\n            })}\n          >\n            <Icon name=\"refresh-ccw-01\" />\n          </AsyncButton>\n          <AsyncButton\n            onClick={() => removeRelayFromResult(r)}\n            className=\"p-1 rounded-lg flex items-center secondary\"\n            title={formatMessage({\n              defaultMessage: \"Remove from my relays\",\n              id: \"UJTWqI\",\n            })}\n          >\n            <Icon name=\"trash-01\" className=\"trash-icon\" />\n          </AsyncButton>\n        </div>\n      )}\n      <IconButton icon={{ name: \"x\" }} onClick={close} />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Create/util.ts",
    "content": "import { removeUndefined } from \"@snort/shared\"\nimport type { NostrEvent, OkResponse, SystemInterface } from \"@snort/system\"\n\nexport async function sendEventToRelays(\n  system: SystemInterface,\n  ev: NostrEvent,\n  customRelays?: Array<string>,\n  setResults?: (x: Array<OkResponse>) => void,\n) {\n  if (customRelays) {\n    system.HandleEvent(\"*\", { ...ev, relays: [] })\n    return removeUndefined(\n      await Promise.all(\n        customRelays.map(async r => {\n          try {\n            return await system.WriteOnceToRelay(r, ev)\n          } catch (e) {\n            console.error(e)\n          }\n        }),\n      ),\n    )\n  } else {\n    const responses: OkResponse[] = await system.BroadcastEvent(ev)\n    setResults?.(responses)\n    return responses\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/DVMJobFeedback.tsx",
    "content": "import { findTag, type TaggedNostrEvent } from \"@snort/system\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\n\nexport interface DVMJobFeedbackProps {\n  ev: TaggedNostrEvent\n}\n\nexport default function DVMJobFeedback({ ev }: DVMJobFeedbackProps) {\n  const status = findTag(ev, \"status\")?.toLowerCase()\n\n  function renderStatusMessage() {\n    switch (status) {\n      case \"payment-required\":\n        return (\n          <div className=\"flex items-center gap-2 mb-3\">\n            <Icon name=\"zap\" className=\"text-yellow-500\" />\n            <span className=\"font-semibold\">\n              <FormattedMessage defaultMessage=\"Payment Required\" />\n            </span>\n          </div>\n        )\n      case \"processing\":\n        return (\n          <div className=\"flex items-center gap-2 mb-3\">\n            <Icon name=\"fingerprint\" className=\"text-blue-500\" />\n            <span className=\"font-semibold\">\n              <FormattedMessage defaultMessage=\"Processing\" />\n            </span>\n          </div>\n        )\n      case \"success\":\n        return (\n          <div className=\"flex items-center gap-2 mb-3\">\n            <Icon name=\"check\" className=\"text-green-500\" />\n            <span className=\"font-semibold\">\n              <FormattedMessage defaultMessage=\"Success\" />\n            </span>\n          </div>\n        )\n      case \"error\":\n        return (\n          <div className=\"flex items-center gap-2 mb-3\">\n            <Icon name=\"close\" className=\"text-red-500\" />\n            <span className=\"font-semibold\">\n              <FormattedMessage defaultMessage=\"Error\" />\n            </span>\n          </div>\n        )\n      case \"partial\":\n        return (\n          <div className=\"flex items-center gap-2 mb-3\">\n            <Icon name=\"close\" className=\"text-orange-500\" />\n            <span className=\"font-semibold\">\n              <FormattedMessage defaultMessage=\"Partial\" />\n            </span>\n          </div>\n        )\n      default:\n        return null\n    }\n  }\n\n  return (\n    <div className=\"dvm-job-feedback\">\n      {renderStatusMessage()}\n\n      {ev.content && (\n        <div className=\"mt-3 text-sm whitespace-pre-wrap\">{ev.content}</div>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/EventComponent.tsx",
    "content": "import { EventKind, parseIMeta, type TaggedNostrEvent } from \"@snort/system\"\nimport type { ReactNode } from \"react\"\n\nimport PubkeyList from \"@/Components/Embed/PubkeyList\"\nimport ZapstrEmbed from \"@/Components/Embed/ZapstrEmbed\"\nimport ErrorBoundary from \"@/Components/ErrorBoundary\"\nimport { ApplicationHandler } from \"@/Components/Event/Application\"\nimport { LongFormText } from \"@/Components/Event/LongFormText\"\nimport { NostrFileElement } from \"@/Components/Event/NostrFileHeader\"\nimport { Note } from \"@/Components/Event/Note/Note\"\nimport NoteReaction from \"@/Components/Event/NoteReaction\"\nimport { ZapGoal } from \"@/Components/Event/ZapGoal\"\nimport { LiveEvent } from \"@/Components/LiveStream/LiveEvent\"\nimport ProfilePreview from \"@/Components/User/ProfilePreview\"\n\nexport interface NotePropsOptions {\n  isRoot?: boolean\n  showHeader?: boolean\n  showContextMenu?: boolean\n  showProfileCard?: boolean\n  showTime?: boolean\n  showPinned?: boolean\n  showBookmarked?: boolean\n  showFooter?: boolean\n  showReactionsLink?: boolean\n  showMedia?: boolean\n  canUnpin?: boolean\n  canUnbookmark?: boolean\n  canClick?: boolean\n  showMediaSpotlight?: boolean\n  longFormPreview?: boolean\n  truncate?: boolean\n  threadLines?: {\n    /** The inset value from the left side of the note */\n    inset: string\n    /** Renders the line joining to the previous note */\n    topLine?: boolean\n    /** Renders the line joining to the next note */\n    bottomLine?: boolean\n  }\n}\n\nexport interface NoteProps {\n  data: TaggedNostrEvent\n  className?: string\n  highlight?: boolean\n  ignoreModeration?: boolean\n  onClick?: (e: TaggedNostrEvent) => void\n  depth?: number\n  highlightText?: string\n  threadChains?: Map<string, Array<string>>\n  context?: ReactNode\n  options?: NotePropsOptions\n  waitUntilInView?: boolean\n  /**\n   * Special classname to apply to the note text and footer\n   */\n  inset?: string\n}\n\nexport default function EventComponent(props: NoteProps) {\n  const { data: ev, className } = props\n\n  function inner() {\n    switch (ev.kind) {\n      case EventKind.Reaction:\n      case EventKind.Repost:\n        return <NoteReaction data={ev} key={ev.id} root={undefined} depth={(props.depth ?? 0) + 1} />\n      case EventKind.FileHeader:\n        return <NostrFileElement ev={ev} />\n      case EventKind.ZapstrTrack:\n        return <ZapstrEmbed ev={ev} />\n      case EventKind.StarterPackSet:\n      case EventKind.FollowSet:\n      case EventKind.ContactList:\n        return <PubkeyList ev={ev} className={className} />\n      case EventKind.LiveEvent:\n        return <LiveEvent ev={ev} />\n      case EventKind.SetMetadata:\n        return <ProfilePreview actions={<></>} pubkey={ev.pubkey} />\n      case 9041: // Assuming 9041 is a valid EventKind\n        return <ZapGoal ev={ev} />\n      case EventKind.ApplicationHandler: {\n        return <ApplicationHandler ev={ev} />\n      }\n      case EventKind.Photo:\n      case EventKind.Video:\n      case EventKind.ShortVideo: {\n        // append media to note as if kind1 post\n        const media = parseIMeta(ev.tags)\n        // Sometimes we cann call this twice so check the URL's are not already\n        // in the content\n        const urls = Object.entries(media ?? {}).map(([k]) => k)\n        if (!urls.every(u => ev.content.includes(u))) {\n          const newContent = `${ev.content} ${urls.join(\"\\n\")}`\n          props.data.content = newContent\n        }\n        return <Note {...props} />\n      }\n      case EventKind.LongFormTextNote:\n        return (\n          <LongFormText\n            ev={ev}\n            isPreview={props.options?.longFormPreview ?? false}\n            onClick={() => props.onClick?.(ev)}\n            truncate={props.options?.truncate}\n          />\n        )\n      default:\n        return <Note {...props} />\n    }\n  }\n  return <ErrorBoundary>{inner()}</ErrorBoundary>\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/FileUpload.tsx",
    "content": "import Progress from \"@/Components/Progress/Progress\"\nimport type { UploadProgress } from \"@/Utils/Upload\"\n\nexport default function FileUploadProgress({ progress }: { progress: Array<UploadProgress> }) {\n  return (\n    <div className=\"flex flex-col gap-2\">\n      {progress.map(p => (\n        <div key={p.id} className=\"flex flex-col gap-0.5\" id={p.id}>\n          {\"name\" in p.file ? p.file.name : \"\"}\n          <Progress value={p.progress} status={p.stage} />\n        </div>\n      ))}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/HiddenNote.tsx",
    "content": "import { useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport usePreferences from \"@/Hooks/usePreferences\"\n\nconst HiddenNote = ({ children }: { children: React.ReactNode }) => {\n  const hideMutedNotes = usePreferences(s => s.hideMutedNotes)\n  const [show, setShow] = useState(false)\n  if (hideMutedNotes) return\n\n  return show ? (\n    children\n  ) : (\n    <div className=\"bb px-3 py-2 flex items-center justify-between\">\n      <div className=\"text-sm text-neutral-400\">\n        <FormattedMessage defaultMessage=\"This note has been muted\" />\n      </div>\n      <button className=\"btn btn-sm btn-neutral\" onClick={() => setShow(true)}>\n        <FormattedMessage defaultMessage=\"Show\" />\n      </button>\n    </div>\n  )\n}\n\nexport default HiddenNote\n"
  },
  {
    "path": "packages/app/src/Components/Event/LoadMore.tsx",
    "content": "import { useEffect } from \"react\"\nimport { useInView } from \"react-intersection-observer\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport usePageDimensions from \"@/Hooks/usePageDimensions\"\nimport { debounce } from \"@/Utils\"\n\ninterface ShowMoreProps {\n  text?: string\n  className?: string\n  onClick: () => void\n}\n\nconst LoadMore = ({ text, onClick, className = \"\" }: ShowMoreProps) => {\n  return (\n    <button type=\"button\" className={className} onClick={onClick}>\n      {text || <FormattedMessage defaultMessage=\"Load more\" />}\n    </button>\n  )\n}\n\nexport default LoadMore\n\nexport function AutoLoadMore({ text, onClick, className }: ShowMoreProps) {\n  const { ref, inView } = useInView({ rootMargin: \"1000px\" })\n  const { height } = usePageDimensions()\n\n  useEffect(() => {\n    if (inView) {\n      // TODO improve feed performance. Something in image grid makes it slow when feed size grows.\n      return debounce(100, onClick)\n    }\n  }, [inView, onClick])\n\n  return (\n    <div ref={ref}>\n      <LoadMore onClick={onClick} text={text} className={className} />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/LongFormText.tsx",
    "content": "import type { TaggedNostrEvent } from \"@snort/system\"\nimport classNames from \"classnames\"\nimport { useCallback, useMemo, useRef, useState } from \"react\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\n\nimport Text from \"@/Components/Text/Text\"\nimport ProfilePreview from \"@/Components/User/ProfilePreview\"\nimport useImgProxy from \"@/Hooks/useImgProxy\"\nimport { findTag } from \"@/Utils\"\n\nimport { Markdown } from \"./Markdown\"\nimport { NoteProvider } from \"./Note/NoteContext\"\nimport { NoteContextMenu } from \"./Note/NoteContextMenu\"\nimport NoteFooter from \"./Note/NoteFooter/NoteFooter\"\nimport NoteTime from \"./Note/NoteTime\"\n\ninterface LongFormTextProps {\n  ev: TaggedNostrEvent\n  isPreview: boolean\n  onClick?: () => void\n  truncate?: boolean\n}\n\nconst TEXT_TRUNCATE_LENGTH = 400\n\nexport function LongFormText(props: LongFormTextProps) {\n  const title = findTag(props.ev, \"title\")\n  const summary = findTag(props.ev, \"summary\")\n  const image = findTag(props.ev, \"image\")\n  const { proxy } = useImgProxy()\n  const [reading, setReading] = useState(false)\n  const readingRef = useRef(false)\n  const [showMore, setShowMore] = useState(false)\n  const ref = useRef<HTMLDivElement>(null)\n\n  function previewText() {\n    return (\n      <Text\n        id={props.ev.id}\n        content={props.ev.content}\n        tags={props.ev.tags}\n        creator={props.ev.pubkey}\n        truncate={props.isPreview ? 250 : undefined}\n        disableLinkPreview={props.isPreview}\n      />\n    )\n  }\n\n  const readTime = useMemo(() => {\n    const wpm = 225\n    const words = props.ev.content.trim().split(/\\s+/).length\n    return {\n      words,\n      wpm,\n      mins: Math.ceil(words / wpm),\n    }\n  }, [props.ev.content])\n\n  const readAsync = useCallback((text: string) => {\n    return new Promise<void>(resolve => {\n      const ut = new SpeechSynthesisUtterance(text)\n      ut.onend = () => {\n        resolve()\n      }\n      window.speechSynthesis.speak(ut)\n    })\n  }, [])\n\n  const readArticle = useCallback(async () => {\n    if (ref.current && !readingRef.current) {\n      readingRef.current = true\n      setReading(true)\n      const paragraphs = ref.current.querySelectorAll(\"p,h1,h2,h3,h4,h5,h6\")\n      for (const p of paragraphs) {\n        if (p.textContent) {\n          p.classList.add(\"reading\")\n          await readAsync(p.textContent)\n          p.classList.remove(\"reading\")\n        }\n      }\n      readingRef.current = false\n      setReading(false)\n    }\n  }, [readAsync])\n\n  const stopReading = () => {\n    setReading(false)\n    if (ref.current) {\n      const paragraphs = ref.current.querySelectorAll(\"p,h1,h2,h3,h4,h5,h6\")\n      paragraphs.forEach(a => a.classList.remove(\"reading\"))\n      window.speechSynthesis.cancel()\n    }\n  }\n\n  const ToggleShowMore = () => (\n    <a\n      className=\"highlight cursor-pointer\"\n      onClick={e => {\n        e.preventDefault()\n        e.stopPropagation()\n        setShowMore(!showMore)\n      }}\n    >\n      {showMore ? <FormattedMessage defaultMessage=\"Show less\" /> : <FormattedMessage defaultMessage=\"Show more\" />}\n    </a>\n  )\n\n  const shouldTruncate = props.truncate && props.ev.content.length > TEXT_TRUNCATE_LENGTH\n  const content = shouldTruncate && !showMore ? props.ev.content.slice(0, TEXT_TRUNCATE_LENGTH) : props.ev.content\n\n  function fullText() {\n    return (\n      <>\n        <NoteFooter />\n        <hr className=\"h-px my-1\" />\n        <div className=\"flex gap-2\">\n          <div>\n            <FormattedMessage\n              defaultMessage=\"{n} mins to read\"\n              values={{\n                n: <FormattedNumber value={readTime.mins} />,\n              }}\n            />\n          </div>\n          <div>‧</div>\n          {!reading && (\n            <div className=\"cursor-pointer\" onClick={() => readArticle()}>\n              <FormattedMessage defaultMessage=\"Listen to this article\" />\n            </div>\n          )}\n          {reading && (\n            <div className=\"cursor-pointer\" onClick={() => stopReading()}>\n              <FormattedMessage defaultMessage=\"Stop listening\" />\n            </div>\n          )}\n        </div>\n        <hr className=\"h-px my-1\" />\n        {shouldTruncate && showMore && <ToggleShowMore />}\n        <Markdown content={content} tags={props.ev.tags} ref={ref} className=\"font-[Georgia]\" />\n        {shouldTruncate && !showMore && <ToggleShowMore />}\n        <hr className=\"h-px my-1\" />\n        <NoteFooter />\n      </>\n    )\n  }\n\n  return (\n    <NoteProvider ev={props.ev}>\n      <div\n        className={classNames(\"flex flex-col gap-4 p-4 break-words leading-6\", {\n          \"cursor-pointer\": props.isPreview,\n        })}\n        onClick={props.onClick}\n      >\n        <ProfilePreview\n          pubkey={props.ev.pubkey}\n          actions={\n            <div className=\"flex items-center gap-1\">\n              <NoteTime from={props.ev.created_at * 1000} />\n              <NoteContextMenu />\n            </div>\n          }\n          options={{\n            about: false,\n          }}\n        />\n        <h1 className=\"text-xl font-bold leading-10 m-0\">{title}</h1>\n        <small className=\"\">{summary}</small>\n        {image && <div className=\"h-[360px] bg-center bg-cover\" style={{ backgroundImage: `url(${proxy(image)})` }} />}\n        {props.isPreview ? previewText() : fullText()}\n      </div>\n    </NoteProvider>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Markdown.tsx",
    "content": "import { transformText } from \"@snort/system\"\nimport { marked, type Token, type Tokens } from \"marked\"\nimport markedFootnote, { type Footnote, type FootnoteRef, type Footnotes } from \"marked-footnote\"\nimport { forwardRef, type ReactNode, useMemo } from \"react\"\nimport { Link } from \"react-router-dom\"\n\nimport NostrLink from \"@/Components/Embed/NostrLink\"\nimport { ProxyImg } from \"@/Components/ProxyImg\"\n\ninterface MarkdownProps {\n  content: string\n  tags?: Array<Array<string>>\n  className?: string\n}\n\nfunction renderToken(t: Token | Footnotes | Footnote | FootnoteRef, tags: Array<Array<string>>): ReactNode {\n  try {\n    switch (t.type) {\n      case \"paragraph\": {\n        return <p>{t.tokens ? t.tokens.map(a => renderToken(a, tags)) : t.raw}</p>\n      }\n      case \"image\": {\n        return <ProxyImg src={t.href} />\n      }\n      case \"heading\": {\n        switch (t.depth) {\n          case 1:\n            return <h1>{t.tokens ? t.tokens.map(a => renderToken(a, tags)) : t.raw}</h1>\n          case 2:\n            return <h2>{t.tokens ? t.tokens.map(a => renderToken(a, tags)) : t.raw}</h2>\n          case 3:\n            return <h3>{t.tokens ? t.tokens.map(a => renderToken(a, tags)) : t.raw}</h3>\n          case 4:\n            return <h4>{t.tokens ? t.tokens.map(a => renderToken(a, tags)) : t.raw}</h4>\n          case 5:\n            return <h5>{t.tokens ? t.tokens.map(a => renderToken(a, tags)) : t.raw}</h5>\n          case 6:\n            return <h6>{t.tokens ? t.tokens.map(a => renderToken(a, tags)) : t.raw}</h6>\n        }\n        throw new Error(\"Invalid heading\")\n      }\n      case \"codespan\": {\n        return <code className=\"bg-neutral-600 light:bg-neutral-300 px-2 py-0.5 rounded-lg text-sm\">{t.text}</code>\n      }\n      case \"code\": {\n        return <pre className=\"bg-neutral-600 light:bg-neutral-300 px-2 py-0.5 rounded-lg text-sm\">{t.text}</pre>\n      }\n      case \"br\": {\n        return <br />\n      }\n      case \"hr\": {\n        return <hr />\n      }\n      case \"blockquote\": {\n        return <blockquote>{t.tokens ? t.tokens.map(a => renderToken(a, tags)) : t.raw}</blockquote>\n      }\n      case \"link\": {\n        return (\n          <Link to={t.href as string} className=\"text-highlight no-underline hover:underline\" target=\"_blank\">\n            {t.tokens ? t.tokens.map(a => renderToken(a, tags)) : t.raw}\n          </Link>\n        )\n      }\n      case \"list\": {\n        if (t.ordered) {\n          return <ol className=\"list-decimal ml-4\">{(t.items as Token[]).map(a => renderToken(a, tags))}</ol>\n        } else {\n          return <ul className=\"list-disc\">{(t.items as Token[]).map(a => renderToken(a, tags))}</ul>\n        }\n      }\n      case \"list_item\": {\n        return <li>{t.tokens ? t.tokens.map(a => renderToken(a, tags)) : t.raw}</li>\n      }\n      case \"em\": {\n        return <em>{t.tokens ? t.tokens.map(a => renderToken(a, tags)) : t.raw}</em>\n      }\n      case \"del\": {\n        return <s>{t.tokens ? t.tokens.map(a => renderToken(a, tags)) : t.raw}</s>\n      }\n      case \"footnoteRef\": {\n        return (\n          <sup>\n            <Link to={`#fn-${t.label}`} className=\"super\">\n              [{t.label}]\n            </Link>\n          </sup>\n        )\n      }\n      case \"footnotes\":\n      case \"footnote\": {\n        return\n      }\n      case \"table\": {\n        return (\n          <table className=\"table-auto border-collapse\">\n            <thead>\n              <tr>\n                {(t.header as Tokens.TableCell[]).map(v => (\n                  <th className=\"border\">{v.tokens ? v.tokens.map(a => renderToken(a, tags)) : v.text}</th>\n                ))}\n              </tr>\n            </thead>\n            <tbody>\n              {(t.rows as Tokens.TableCell[][]).map(v => (\n                <tr>\n                  {v.map((d, d_key) => (\n                    <td className=\"border px-2 py-1\" key={d_key}>\n                      {d.tokens ? d.tokens.map(a => renderToken(a, tags)) : d.text}\n                    </td>\n                  ))}\n                </tr>\n              ))}\n            </tbody>\n          </table>\n        )\n      }\n      default: {\n        if (\"tokens\" in t) {\n          return (t.tokens as Array<Token>).map(a => renderToken(a, tags))\n        }\n        return transformText(t.raw, tags).map(v => {\n          switch (v.type) {\n            case \"link\": {\n              if (v.content.startsWith(\"nostr:\")) {\n                return <NostrLink link={v.content} />\n              } else {\n                return v.content\n              }\n            }\n            case \"mention\": {\n              return <NostrLink link={v.content} />\n            }\n            default: {\n              return v.content\n            }\n          }\n        })\n      }\n    }\n  } catch (e) {\n    console.error(e)\n  }\n}\n\nconst Markdown = forwardRef<HTMLDivElement, MarkdownProps>((props: MarkdownProps, ref) => {\n  const parsed = useMemo(() => {\n    return marked.use(markedFootnote()).lexer(props.content)\n  }, [props.content])\n\n  return (\n    <div className={props.className} ref={ref}>\n      {parsed.filter(a => a.type !== \"footnote\" && a.type !== \"footnotes\").map(a => renderToken(a, props.tags ?? []))}\n    </div>\n  )\n})\n\nMarkdown.displayName = \"Markdown\"\n\nexport { Markdown }\n"
  },
  {
    "path": "packages/app/src/Components/Event/NostrFileHeader.tsx",
    "content": "import type { NostrEvent, NostrLink } from \"@snort/system\"\nimport { useEventFeed } from \"@snort/system-react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport { MediaElement } from \"@/Components/Embed/MediaElement\"\nimport Reveal from \"@/Components/Event/Reveal\"\nimport PageSpinner from \"@/Components/PageSpinner\"\nimport { findTag } from \"@/Utils\"\n\nexport default function NostrFileHeader({ link }: { link: NostrLink }) {\n  const ev = useEventFeed(link)\n\n  if (!ev) return <PageSpinner />\n  return <NostrFileElement ev={ev} />\n}\n\nexport function NostrFileElement({ ev }: { ev: NostrEvent }) {\n  // assume image or embed which can be rendered by the hypertext kind\n  // todo: make use of hash\n  // todo: use magnet or other links if present\n  const u = findTag(ev, \"url\")\n  const x = findTag(ev, \"x\")\n  const m = findTag(ev, \"m\")\n  const blurHash = findTag(ev, \"blurhash\")\n  const magnet = findTag(ev, \"magnet\")\n\n  if (u && m) {\n    return (\n      <Reveal message={<FormattedMessage defaultMessage=\"Click to load content from {link}\" values={{ link: u }} />}>\n        <MediaElement\n          mime={m}\n          src={u}\n          meta={{\n            hash: x,\n            magnet: magnet,\n            blurHash: blurHash,\n          }}\n        />\n      </Reveal>\n    )\n  } else {\n    return (\n      <b className=\"error\">\n        <FormattedMessage defaultMessage=\"Unknown file header: {name}\" values={{ name: ev.content }} />\n      </b>\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/ClientFingerprinting.tsx",
    "content": "import type { NostrEvent } from \"@snort/system\"\nimport type { ReactNode } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nexport interface CheckResult {\n  id: string\n  passed: boolean\n  weight: number\n  description: ReactNode\n}\n\nexport interface ClientEvaluation {\n  score: number\n  checks: CheckResult[]\n}\n\nexport interface FingerprintResult {\n  name: string\n  score: number\n  minScore: number\n  allResults: ClientResult[]\n}\n\nexport interface ClientResult {\n  clientName: string\n  score: number\n  checks: CheckResult[]\n}\n\nexport abstract class FingerprintCheck {\n  abstract readonly weight: number\n  abstract readonly id: string\n\n  abstract evaluate(ev: NostrEvent): boolean\n  abstract getDescription(): ReactNode\n\n  getResult(ev: NostrEvent): CheckResult {\n    return {\n      id: this.id,\n      passed: this.evaluate(ev),\n      weight: this.weight,\n      description: this.getDescription(),\n    }\n  }\n}\n\nexport class AltTagCheck extends FingerprintCheck {\n  readonly weight = 4\n  readonly id = \"alt-tag-a-short-note\"\n\n  evaluate(ev: NostrEvent): boolean {\n    const altTag = ev.tags.find(a => a[0] === \"alt\")?.[1]\n    return altTag?.startsWith(\"A short note: \") ?? false\n  }\n\n  getDescription(): ReactNode {\n    return <FormattedMessage defaultMessage='Alt tag starts with \"A short note: \"' />\n  }\n}\n\nexport class PTagNicknameCheck extends FingerprintCheck {\n  readonly weight = 3\n  readonly id = \"p-tag-nickname\"\n\n  evaluate(ev: NostrEvent): boolean {\n    return ev.tags.some(a => a[0] === \"p\" && a.length > 3 && ![\"root\", \"reply\", \"mention\"].includes(a[3]))\n  }\n\n  getDescription(): ReactNode {\n    return <FormattedMessage defaultMessage=\"P-tag with non-standard marker (nickname)\" />\n  }\n}\n\nexport class DoubleNewlinesBeforeImagesCheck extends FingerprintCheck {\n  readonly weight = 1\n  readonly id = \"double-newlines-images\"\n\n  evaluate(ev: NostrEvent): boolean {\n    const hasImages = ev.content.includes(\".jpg\") || ev.content.includes(\".webp\")\n    return ev.content.includes(\"\\n\\nhttp\") && hasImages\n  }\n\n  getDescription(): ReactNode {\n    return <FormattedMessage defaultMessage=\"Double newlines before image URLs\" />\n  }\n}\n\nexport class RootTagLastCheck extends FingerprintCheck {\n  readonly weight = 3\n  readonly id = \"root-tag-last\"\n\n  evaluate(ev: NostrEvent): boolean {\n    const eTags = ev.tags.filter(a => a[0] === \"e\")\n    const rootTagIndex = ev.tags.findIndex(a => a[0] === \"e\" && a[3] === \"root\")\n    return rootTagIndex !== -1 && rootTagIndex === ev.tags.length - 1 && eTags.length > 1\n  }\n\n  getDescription(): ReactNode {\n    return <FormattedMessage defaultMessage=\"Root e-tag is last in tags array (with multiple e-tags)\" />\n  }\n}\n\nexport class HasIMetaNoRTagsCheck extends FingerprintCheck {\n  readonly weight = 1\n  readonly id = \"imeta-no-r-tags\"\n\n  evaluate(ev: NostrEvent): boolean {\n    const hasImages = ev.content.includes(\".jpg\") || ev.content.includes(\".webp\")\n    const hasIMeta = ev.tags.some(a => a[0] === \"imeta\")\n    const rTagToImages = ev.tags.some(a => a[0] === \"r\" && a[1].startsWith(\"http\")) && hasImages\n    return !rTagToImages && hasIMeta\n  }\n\n  getDescription(): ReactNode {\n    return <FormattedMessage defaultMessage=\"Has imeta tags for images, but no r tags\" />\n  }\n}\n\nexport class SingleNewlineBeforeImagesCheck extends FingerprintCheck {\n  readonly weight = 1\n  readonly id = \"single-newline-images\"\n\n  evaluate(ev: NostrEvent): boolean {\n    const hasImages = ev.content.includes(\".jpg\") || ev.content.includes(\".webp\")\n    const doubleNewlines = ev.content.includes(\"\\n\\nhttp\") && hasImages\n    return ev.content.includes(\"\\nhttp\") && hasImages && !doubleNewlines\n  }\n\n  getDescription(): ReactNode {\n    return <FormattedMessage defaultMessage=\"Single newline only before image URLs\" />\n  }\n}\n\nexport class NoIMetaWithImagesCheck extends FingerprintCheck {\n  readonly weight = 2\n  readonly id = \"no-imeta-with-images\"\n\n  evaluate(ev: NostrEvent): boolean {\n    const hasImages = ev.content.includes(\".jpg\") || ev.content.includes(\".webp\")\n    const hasIMeta = ev.tags.some(a => a[0] === \"imeta\")\n    return !hasIMeta && hasImages\n  }\n\n  getDescription(): ReactNode {\n    return <FormattedMessage defaultMessage=\"Has images but no imeta tags\" />\n  }\n}\n\nexport class NoRTagsWithImagesCheck extends FingerprintCheck {\n  readonly weight = 1\n  readonly id = \"no-r-tags-with-images\"\n\n  evaluate(ev: NostrEvent): boolean {\n    const hasImages = ev.content.includes(\".jpg\") || ev.content.includes(\".webp\")\n    const rTagToImages = ev.tags.some(a => a[0] === \"r\" && a[1].startsWith(\"http\")) && hasImages\n    return !rTagToImages && hasImages\n  }\n\n  getDescription(): ReactNode {\n    return <FormattedMessage defaultMessage=\"Has images but no r tags\" />\n  }\n}\n\nexport class HasRTagsAndIMetaCheck extends FingerprintCheck {\n  readonly weight = 2\n  readonly id = \"r-tags-and-imeta\"\n\n  evaluate(ev: NostrEvent): boolean {\n    const hasImages = ev.content.includes(\".jpg\") || ev.content.includes(\".webp\")\n    const hasIMeta = ev.tags.some(a => a[0] === \"imeta\")\n    const rTagToImages = ev.tags.some(a => a[0] === \"r\" && a[1].startsWith(\"http\")) && hasImages\n    return rTagToImages && hasIMeta\n  }\n\n  getDescription(): ReactNode {\n    return <FormattedMessage defaultMessage=\"Has both r tags and imeta tags for images\" />\n  }\n}\n\nexport class NewlinesBeforeQuotesCheck extends FingerprintCheck {\n  readonly weight = 1\n  readonly id = \"newlines-before-quotes\"\n\n  evaluate(ev: NostrEvent): boolean {\n    return ev.tags.some(a => a[0] === \"q\") && ev.content.includes(\"\\n\\nnostr:\")\n  }\n\n  getDescription(): ReactNode {\n    return <FormattedMessage defaultMessage=\"Double newlines before quoted notes\" />\n  }\n}\n\nexport class EndsDoubleNewlineCheck extends FingerprintCheck {\n  readonly weight = 1\n  readonly id = \"ends-double-newline\"\n\n  evaluate(ev: NostrEvent): boolean {\n    return ev.content.endsWith(\"\\n\\n\")\n  }\n\n  getDescription(): ReactNode {\n    return <FormattedMessage defaultMessage=\"Content ends with double newline\" />\n  }\n}\n\nexport class ClientFingerprint {\n  constructor(\n    public readonly name: string,\n    public readonly checks: FingerprintCheck[],\n  ) {}\n\n  evaluate(ev: NostrEvent): ClientEvaluation {\n    let score = 0\n    const checkResults = this.checks.map(check => {\n      const result = check.getResult(ev)\n      if (result.passed) {\n        score += result.weight\n      }\n      return result\n    })\n\n    return { score, checks: checkResults }\n  }\n}\n\nexport class FingerprintEngine {\n  private readonly minScore = 3\n  private readonly clients: ClientFingerprint[]\n\n  constructor() {\n    this.clients = [\n      new ClientFingerprint(\"Amethyst\", [new AltTagCheck()]),\n      new ClientFingerprint(\"Coracle\", [new PTagNicknameCheck()]),\n      new ClientFingerprint(\"Primal Android\", [\n        new DoubleNewlinesBeforeImagesCheck(),\n        new RootTagLastCheck(),\n        new HasIMetaNoRTagsCheck(),\n      ]),\n      new ClientFingerprint(\"Primal iOS\", [new SingleNewlineBeforeImagesCheck()]),\n      new ClientFingerprint(\"Damus iOS\", [\n        new DoubleNewlinesBeforeImagesCheck(),\n        new HasRTagsAndIMetaCheck(),\n        new NewlinesBeforeQuotesCheck(),\n        new EndsDoubleNewlineCheck(),\n      ]),\n    ]\n  }\n\n  fingerprint(ev: NostrEvent): FingerprintResult | undefined {\n    let highestScore = 0\n    let detectedClient: string | undefined\n    const allResults: ClientResult[] = this.clients.map(client => {\n      const result = client.evaluate(ev)\n      if (result.score >= this.minScore && result.score > highestScore) {\n        highestScore = result.score\n        detectedClient = client.name\n      }\n      return {\n        clientName: client.name,\n        score: result.score,\n        checks: result.checks,\n      }\n    })\n\n    if (!detectedClient) return undefined\n\n    return {\n      name: detectedClient,\n      minScore: this.minScore,\n      score: highestScore,\n      allResults,\n    }\n  }\n\n  getMinScore(): number {\n    return this.minScore\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/ClientTag.tsx",
    "content": "import Icon from \"@/Components/Icons/Icon\"\nimport { EventKind, type NostrEvent, NostrLink, type TaggedNostrEvent } from \"@snort/system\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\nimport { useState } from \"react\"\nimport Modal from \"@/Components/Modal/Modal\"\nimport { FingerprintEngine, type FingerprintResult } from \"./ClientFingerprinting\"\n\nexport function ClientTag({ ev }: { ev: TaggedNostrEvent }) {\n  const info = getClientInfo(ev)\n\n  if (!info) return\n\n  return (\n    <span className=\"text-xs text-neutral-400 light:text-neutral-500\">\n        {info.fingerprintDetails ? <FingerprintClientTag info={info} /> : <ViaTag info={info} />}\n      </span>\n  )\n}\n\nfunction ViaTag({ info }: { info: ClientInfo }) {\n  return (\n    <FormattedMessage\n      defaultMessage=\"via {client}\"\n      description=\"via {client name} tag\"\n      values={{\n        client: (\n          <span\n            title={info.fingerprintDetails ? `Fingerprinted with score ${info.fingerprintDetails.score}` : undefined}\n            className={info.fingerprintDetails ? \"cursor-pointer\" : undefined}\n          >\n            {info.link ? (\n              <Link to={`/${info.link.encode()}`} onClick={e => e.stopPropagation()}>\n                {info.name}\n              </Link>\n            ) : (\n              info.name\n            )}\n            {info.fingerprintDetails && <Icon name=\"fingerprint\" size={12} className=\"inline ml-1 mb-0.5\" />}\n          </span>\n        ),\n      }}\n    />\n  )\n}\n\nfunction FingerprintClientTag({ info }: { info: ClientInfo }) {\n  const [showModal, setShowModal] = useState(false)\n\n  if (!info.fingerprintDetails) return //never should hit this\n\n  return (\n    <>\n      <span\n        onClick={e => {\n          e.preventDefault()\n          e.stopPropagation()\n          setShowModal(true)\n        }}\n      >\n        <ViaTag info={info} />\n      </span>\n      {showModal && (\n        <Modal id=\"fingerprint-breakdown\" onClose={() => setShowModal(false)}>\n          <h2 className=\"text-xl font-bold mb-4 flex gap-2 items-center\">\n            <Icon name=\"fingerprint\" size={32} />\n            <FormattedMessage defaultMessage=\"Client Fingerprint\" />\n          </h2>\n          <div className=\"mb-4\">\n            <div className=\"font-semibold\">Detected: {info.name}</div>\n            <div className=\"text-sm text-neutral-500\">\n              Score: {info.fingerprintDetails.score} (minimum: {info.fingerprintDetails.minScore})\n            </div>\n          </div>\n          <div className=\"space-y-4\">\n            {info.fingerprintDetails.allResults\n              .filter(client => client.score > 0)\n              .sort((a, b) => b.score - a.score)\n              .map(client => (\n                <div\n                  key={client.clientName}\n                  className={`p-3 rounded border ${\n                    client.clientName === info.name\n                      ? \"border-primary bg-primary/5\"\n                      : \"border-neutral-200 dark:border-neutral-700\"\n                  }`}\n                >\n                  <div className=\"flex justify-between items-center mb-2 font-semibold text-lg\">\n                    <div>{client.clientName}</div>\n                    <div>{client.score}</div>\n                  </div>\n                  <div className=\"\">\n                    {client.checks\n                      .filter(check => check.passed)\n                      .map(check => (\n                        <div\n                          key={check.id}\n                          className={`text-sm leading-6 flex items-start gap-2 ${\n                            check.passed ? \"text-green-600 dark:text-green-400\" : \"text-neutral-400\"\n                          }`}\n                        >\n                          <span className=\"w-6\">{check.passed ? `+${check.weight}` : \"\"}</span>\n                          <span>{check.description}</span>\n                        </div>\n                      ))}\n                  </div>\n                </div>\n              ))}\n          </div>\n        </Modal>\n      )}\n    </>\n  )\n}\n\nconst fingerprintEngine = new FingerprintEngine()\n\ninterface ClientInfo {\n  name: string\n  link?: NostrLink\n  fingerprintDetails?: FingerprintResult\n}\n\nexport function getClientInfo(ev: NostrEvent): ClientInfo | undefined {\n  const tag = ev.tags.find(a => a[0] === \"client\")\n  if (tag) {\n    const link = tag[2]?.includes(\":\") ? NostrLink.tryFromTag([\"a\", tag[2]]) : undefined\n    return {\n      name: tag[1],\n      link,\n    }\n  }\n\n  // try fingerprinting note when no client tag set\n  if (!tag && ev.kind === EventKind.TextNote) {\n    const result = fingerprintEngine.fingerprint(ev)\n    if (result) {\n      return {\n        name: result.name,\n        fingerprintDetails: result,\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/Note.tsx",
    "content": "import { EventKind, NostrLink, type TaggedNostrEvent } from \"@snort/system\"\nimport { WorkerRelayInterface } from \"@snort/worker-relay\"\nimport classNames from \"classnames\"\nimport { useCallback, useEffect } from \"react\"\nimport { useInView } from \"react-intersection-observer\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport { Relay } from \"@/Cache\"\nimport { NoteProvider } from \"@/Components/Event/Note/NoteContext\"\nimport useModeration from \"@/Hooks/useModeration\"\n\nimport type { NoteProps, NotePropsOptions } from \"../EventComponent\"\nimport HiddenNote from \"../HiddenNote\"\nimport NoteAppHandler from \"./NoteAppHandler\"\nimport { NoteContent } from \"./NoteContent\"\n\nconst defaultOptions = {\n  showHeader: true,\n  showTime: true,\n  showFooter: true,\n  canUnpin: false,\n  canUnbookmark: false,\n  showContextMenu: true,\n}\n\nconst canRenderAsTextNote = [\n  EventKind.TextNote,\n  EventKind.Polls,\n  EventKind.Photo,\n  EventKind.Video,\n  EventKind.ShortVideo,\n  EventKind.Comment,\n]\n\nexport function Note(props: NoteProps) {\n  const { data: ev, highlight, options: opt, ignoreModeration = false, waitUntilInView } = props\n  const { isEventMuted } = useModeration()\n  const { ref, inView } = useInView({ triggerOnce: true })\n  const { ref: setSeenAtRef, inView: setSeenAtInView } = useInView({ rootMargin: \"0px\", threshold: 1 })\n\n  useEffect(() => {\n    let timeout: ReturnType<typeof setTimeout>\n    if (setSeenAtInView && Relay instanceof WorkerRelayInterface) {\n      const r = Relay as WorkerRelayInterface\n      timeout = setTimeout(() => {\n        r.setEventMetadata(ev.id, { seen_at: Math.round(Date.now() / 1000) })\n      }, 1000)\n    }\n    return () => clearTimeout(timeout)\n  }, [setSeenAtInView, ev.id])\n\n  const optionsMerged = { ...defaultOptions, ...opt }\n  const goToEvent = useGoToEvent(props, optionsMerged)\n\n  if (!canRenderAsTextNote.includes(ev.kind)) {\n    return <NoteAppHandler ev={ev} />\n  }\n\n  function threadLines() {\n    if (!props.options?.threadLines) return\n    const tl = props.options.threadLines\n    const topLine = tl.topLine ?? false\n    const bottomLine = tl.bottomLine ?? false\n    if (!topLine && !bottomLine) return\n\n    return (\n      <div\n        className={classNames(tl.inset, \"absolute border-l z-1\", {\n          \"top-0\": topLine,\n          \"top-2\": !topLine,\n          \"bottom-0\": bottomLine,\n          \"h-4\": !bottomLine,\n        })}\n      />\n    )\n  }\n\n  const noteElement = (\n    <NoteProvider ev={ev}>\n      <div className=\"relative border-b\">\n        <div\n          className={classNames(\"min-h-[110px] flex flex-col gap-4 px-3 py-2\", {\n            \"outline-highlight outline-2\": highlight,\n            \"hover:bg-neutral-950 light:hover:bg-neutral-50 cursor-pointer\": !opt?.isRoot,\n          })}\n          onClick={e => goToEvent(e, ev)}\n          ref={ref}\n        >\n          <NoteContent\n            props={props}\n            options={optionsMerged}\n            goToEvent={goToEvent}\n            setSeenAtRef={setSeenAtRef}\n            waitUntilInView={waitUntilInView}\n            inView={inView}\n          />\n        </div>\n        {threadLines()}\n      </div>\n    </NoteProvider>\n  )\n\n  return !ignoreModeration && isEventMuted(ev) ? <HiddenNote>{noteElement}</HiddenNote> : noteElement\n}\n\nfunction useGoToEvent(props: NoteProps, options: NotePropsOptions) {\n  const navigate = useNavigate()\n  return useCallback(\n    (e: React.MouseEvent, eTarget: TaggedNostrEvent) => {\n      if (options?.canClick === false) {\n        return\n      }\n\n      let target = e.target as HTMLElement | null\n      while (target) {\n        if (\n          target.tagName === \"A\" ||\n          target.tagName === \"BUTTON\" ||\n          target.classList.contains(\"reaction-pill\") ||\n          target.classList.contains(\"szh-menu-container\")\n        ) {\n          return\n        }\n        target = target.parentElement\n      }\n\n      e.stopPropagation()\n\n      // prevent navigation if selecting text\n      const cellText = document.getSelection()\n      if (cellText?.type === \"Range\") {\n        return\n      }\n\n      // custom onclick handler\n      if (props.onClick) {\n        props.onClick(eTarget)\n        return\n      }\n\n      // link to event\n      const link = NostrLink.fromEvent(eTarget)\n      if (e.metaKey) {\n        window.open(`/${link.encode(CONFIG.eventLinkPrefix)}`, \"_blank\")\n      } else {\n        navigate(`/${link.encode(CONFIG.eventLinkPrefix)}`, { state: eTarget })\n      }\n    },\n    [navigate, props, options],\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteAppHandler.tsx",
    "content": "import { NostrLink, type TaggedNostrEvent } from \"@snort/system\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport NostrIcon from \"@/Components/Icons/Nostrich\"\nimport KindName from \"@/Components/kind-name\"\nimport Avatar from \"@/Components/User/Avatar\"\nimport DisplayName from \"@/Components/User/DisplayName\"\nimport useAppHandler from \"@/Hooks/useAppHandler\"\n\nexport default function NoteAppHandler({ ev }: { ev: TaggedNostrEvent | undefined }) {\n  const kind = ev?.kind\n  const apps = useAppHandler(kind)\n\n  if (!ev || !ev.id || !ev.pubkey) {\n    return <div className=\"text-gray-500 text-sm\">Invalid event</div>\n  }\n\n  const link = NostrLink.fromEvent(ev)\n\n  const profiles = apps\n    .filter(a => a.event.tags.find(b => b[0] === \"web\" && b[2] === \"nevent\"))\n    .filter(a => a.metadata)\n    .slice(0, 5)\n\n  return (\n    <div className=\"layer-1 flex flex-col gap-3\">\n      <small>\n        <FormattedMessage\n          defaultMessage=\"Sorry, we dont understand this event kind ({name}), please try one of the following apps instead!\"\n          values={{\n            name: <KindName kind={ev.kind} />,\n          }}\n        />\n      </small>\n      <button\n        className=\"flex justify-between items-center cursor-pointer bg-transparent border-none p-0 w-full\"\n        onClick={() => {\n          window.open(`nostr:${link.encode()}`, \"_blank\")\n        }}\n        onKeyUp={e => {\n          if (e.key === \"Enter\" || e.key === \" \") {\n            window.open(`nostr:${link.encode()}`, \"_blank\")\n          }\n        }}\n      >\n        <div className=\"flex items-center gap-2\">\n          <NostrIcon width={40} />\n          <FormattedMessage defaultMessage=\"Native App\" />\n        </div>\n        <Icon name=\"link\" />\n      </button>\n      {profiles.map(a => (\n        <button\n          key={a.event.id}\n          className=\"flex justify-between items-center cursor-pointer bg-transparent border-none p-0 w-full\"\n          onClick={() => {\n            const webHandler = a.event.tags.find(a => a[0] === \"web\" && a[2] === \"nevent\")?.[1]\n            if (webHandler) {\n              window.open(webHandler.replace(\"<bech32>\", link.encode()), \"_blank\")\n            }\n          }}\n          onKeyUp={e => {\n            const webHandler = a.event.tags.find(a => a[0] === \"web\" && a[2] === \"nevent\")?.[1]\n            if (webHandler && (e.key === \"Enter\" || e.key === \" \")) {\n              window.open(webHandler.replace(\"<bech32>\", link.encode()), \"_blank\")\n            }\n          }}\n        >\n          <div className=\"flex items-center gap-2\">\n            <Avatar size={40} pubkey={a.event.pubkey} user={a.metadata} />\n            <div>\n              <DisplayName pubkey={a.event.pubkey} user={a.metadata} />\n            </div>\n          </div>\n          <Icon name=\"link\" />\n        </button>\n      ))}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteContent.tsx",
    "content": "import { EventExt, EventKind, type TaggedNostrEvent } from \"@snort/system\"\nimport classNames from \"classnames\"\n\nimport type { NotePropsOptions, NoteProps } from \"@/Components/Event/EventComponent\"\nimport Poll from \"@/Components/Event/Poll\"\nimport NoteHeader from \"@/Components/Event/Note/NoteHeader\"\nimport { NoteText } from \"@/Components/Event/Note/NoteText\"\nimport { TranslationInfo } from \"@/Components/Event/Note/TranslationInfo\"\nimport NoteFooter from \"@/Components/Event/Note/NoteFooter/NoteFooter\"\nimport { useNoteContext } from \"@/Components/Event/Note/NoteContext\"\n\ninterface NoteContentProps {\n  props: NoteProps\n  options: NotePropsOptions\n  goToEvent: (e: React.MouseEvent, eTarget: TaggedNostrEvent) => void\n  setSeenAtRef: (node?: Element | null) => void\n  waitUntilInView?: boolean\n  inView: boolean\n}\n\nexport function NoteContent({ props, options, goToEvent, setSeenAtRef, waitUntilInView, inView }: NoteContentProps) {\n  const { ev, translated, showTranslation } = useNoteContext()\n\n  if (waitUntilInView && !inView) return null\n\n  return (\n    <>\n      {options.showHeader && <NoteHeader options={options} />}\n      <div onClick={e => goToEvent(e, ev)} className={classNames(\"min-h-0\", props.inset)} ref={setSeenAtRef}>\n        <NoteText {...props} translated={translated} showTranslation={showTranslation} />\n        {translated && <TranslationInfo />}\n        {ev.kind === EventKind.Polls && <Poll ev={ev} zaps={[]} />}\n        {options.showFooter && (\n          <div className=\"mt-4\">\n            <NoteFooter replyCount={props.threadChains?.get(EventExt.keyOf(ev))?.length} />\n          </div>\n        )}\n      </div>\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteContext.tsx",
    "content": "import { NostrLink, type TaggedNostrEvent } from \"@snort/system\"\nimport { useEventReactions, useReactions } from \"@snort/system-react\"\nimport { createContext, type ReactNode, use, useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport { LRUCache } from \"typescript-lru-cache\"\nimport SnortApi from \"@/External/SnortApi\"\nimport useModeration from \"@/Hooks/useModeration\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport ReactionsModal from \"./ReactionsModal\"\nimport type { NoteTranslation } from \"./types\"\n\nconst translationCache = new LRUCache<string, NoteTranslation>({ maxSize: 1_000 })\n\ninterface NoteContextType {\n  ev: TaggedNostrEvent\n  link: NostrLink\n  related: ReadonlyArray<TaggedNostrEvent>\n  reactions: ReturnType<typeof useEventReactions>\n  showReactionsModal: boolean\n  setShowReactionsModal: (show: boolean) => void\n\n  translated: NoteTranslation | undefined\n  setTranslated: (translation: NoteTranslation) => void\n  showTranslation: boolean\n  toggleTranslation: () => void\n  translate: () => Promise<void>\n}\n\nconst NoteContext = createContext<NoteContextType | undefined>(undefined)\n\nexport interface NoteProviderProps {\n  ev: TaggedNostrEvent\n  children: ReactNode\n}\n\nexport function NoteProvider({ ev, children }: NoteProviderProps) {\n  const [showReactionsModal, setShowReactionsModal] = useState(false)\n  const [showTranslation, setShowTranslation] = useState(true)\n  const [translated, setTranslatedState] = useState<NoteTranslation | undefined>(\n    translationCache.get(ev.id) ?? undefined,\n  )\n  const { isMuted } = useModeration()\n\n  // biome-ignore lint/correctness/useExhaustiveDependencies: ev.id is the stable identity key for a Nostr event\n  const link = useMemo(() => NostrLink.fromEvent(ev), [ev.id])\n  const relatedRaw = useReactions(`reactions:${link.tagKey}`, link)\n  const related = useMemo(() => relatedRaw.filter(a => !isMuted(a.pubkey)), [relatedRaw, isMuted])\n  const reactions = useEventReactions(link, related)\n  const autoTranslate = usePreferences(s => s.autoTranslate)\n\n  const toggleTranslation = useCallback(() => {\n    setShowTranslation(prev => !prev)\n  }, [])\n\n  const evContentRef = useRef(ev.content)\n  evContentRef.current = ev.content\n\n  // biome-ignore lint/correctness/useExhaustiveDependencies: translate is stable; translated guard is in the effect\n  const translate = useCallback(async () => {\n    const lang = window.navigator.language\n    const langNames = new Intl.DisplayNames([...window.navigator.languages], {\n      type: \"language\",\n    })\n\n    const api = new SnortApi()\n    const targetLang = lang.split(\"-\")[0].toUpperCase()\n    const result = await api.translate({\n      text: [evContentRef.current],\n      target_lang: targetLang,\n    })\n\n    if (\n      \"translations\" in result &&\n      result.translations.length > 0 &&\n      targetLang !== result.translations[0].detected_source_language\n    ) {\n      setTranslatedState({\n        text: result.translations[0].text,\n        fromLanguage: langNames.of(result.translations[0].detected_source_language),\n        confidence: 1,\n      } as NoteTranslation)\n    } else {\n      setTranslatedState({\n        text: \"\",\n        fromLanguage: \"\",\n        confidence: 0,\n        skipped: true,\n      })\n    }\n  }, [])\n\n  useEffect(() => {\n    if (translated || !autoTranslate) return\n    let cancelled = false\n    translate().catch(e => {\n      if (!cancelled) console.warn(e)\n    })\n    return () => {\n      cancelled = true\n    }\n  }, [translated, translate, autoTranslate])\n\n  const value = useMemo(\n    () => ({\n      ev,\n      link,\n      related,\n      reactions,\n      showReactionsModal,\n      setShowReactionsModal,\n      translated,\n      setTranslated: setTranslatedState,\n      showTranslation,\n      toggleTranslation,\n      translate,\n    }),\n    [ev, link, related, reactions, showReactionsModal, translated, showTranslation, toggleTranslation, translate],\n  )\n\n  return (\n    <NoteContext.Provider value={value}>\n      {children}\n      {showReactionsModal && <ReactionsModal onClose={() => setShowReactionsModal(false)} />}\n    </NoteContext.Provider>\n  )\n}\n\nexport function useNoteContext() {\n  const context = use(NoteContext)\n  if (!context) {\n    throw new Error(\"useNoteContext must be used within a NoteProvider\")\n  }\n  return context\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteContextMenu.tsx",
    "content": "import { EventKind, type NostrEvent, NostrLink } from \"@snort/system\"\nimport * as DropdownMenu from \"@radix-ui/react-dropdown-menu\"\nimport { useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport messages from \"@/Components/messages\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport useModeration from \"@/Hooks/useModeration\"\n\nimport { ReBroadcaster } from \"../../ReBroadcaster\"\nimport { useNoteContext } from \"./NoteContext\"\n\nexport function NoteContextMenu() {\n  const { formatMessage } = useIntl()\n  const login = useLogin()\n  const { mute } = useModeration()\n  const { publisher, system } = useEventPublisher()\n  const [showBroadcast, setShowBroadcast] = useState(false)\n  const { ev, translate, setShowReactionsModal } = useNoteContext()\n  const lang = window.navigator.language\n  const langNames = new Intl.DisplayNames([...window.navigator.languages], {\n    type: \"language\",\n  })\n  const isMine = ev.pubkey === login.publicKey\n  const link = NostrLink.fromEvent(ev)\n\n  async function deleteEvent() {\n    if (window.confirm(formatMessage(messages.ConfirmDeletion, { id: ev.id.substring(0, 8) })) && publisher) {\n      const evDelete = await publisher.delete(ev.id)\n      system.BroadcastEvent(evDelete)\n    }\n  }\n\n  async function share() {\n    const link = NostrLink.fromEvent(ev).encode(CONFIG.eventLinkPrefix)\n    const url = `${window.location.protocol}//${window.location.host}/${link}`\n    if (\"share\" in window.navigator) {\n      await window.navigator.share({\n        title: CONFIG.appNameCapitalized,\n        url: url,\n      })\n    } else {\n      await navigator.clipboard.writeText(url)\n    }\n  }\n\n  async function copyId() {\n    const link = NostrLink.fromEvent(ev).encode(CONFIG.eventLinkPrefix)\n    await navigator.clipboard.writeText(link)\n  }\n\n  async function pin(ev: NostrEvent) {\n    login.state.addToList(EventKind.PinList, NostrLink.fromEvent(ev))\n    await login.state.saveList(EventKind.PinList)\n  }\n\n  async function unpin(ev: NostrEvent) {\n    login.state.removeFromList(EventKind.PinList, NostrLink.fromEvent(ev))\n    await login.state.saveList(EventKind.PinList)\n  }\n\n  async function bookmark(ev: NostrEvent) {\n    login.state.addToList(EventKind.BookmarksList, NostrLink.fromEvent(ev))\n    await login.state.saveList(EventKind.BookmarksList)\n  }\n\n  async function copyEvent() {\n    await navigator.clipboard.writeText(JSON.stringify(ev, undefined, \"  \"))\n  }\n\n  const handleReBroadcastButtonClick = () => {\n    setShowBroadcast(true)\n  }\n\n  const itemClassName =\n    \"grid grid-cols-[2rem_auto] gap-2 px-6 py-2 text-base font-semibold bg-layer-2 light:bg-white hover:bg-layer-3 light:hover:bg-neutral-200 cursor-pointer outline-none\"\n\n  function menuItems() {\n    return (\n      <>\n        <DropdownMenu.Item\n          className={itemClassName}\n          onClick={e => {\n            e.stopPropagation()\n            setShowReactionsModal(true)\n          }}\n        >\n          <Icon name=\"heart\" />\n          <FormattedMessage {...messages.Reactions} />\n        </DropdownMenu.Item>\n        <DropdownMenu.Item\n          className={itemClassName}\n          onClick={e => {\n            e.stopPropagation()\n            share()\n          }}\n        >\n          <Icon name=\"share\" />\n          <FormattedMessage {...messages.Share} />\n        </DropdownMenu.Item>\n        {!login.state.isOnList(EventKind.PinList, link) && !login.readonly && (\n          <DropdownMenu.Item\n            className={itemClassName}\n            onClick={e => {\n              e.stopPropagation()\n              pin(ev)\n            }}\n          >\n            <Icon name=\"pin\" />\n            <FormattedMessage {...messages.Pin} />\n          </DropdownMenu.Item>\n        )}\n        {login.state.isOnList(EventKind.PinList, link) && !login.readonly && (\n          <DropdownMenu.Item\n            className={itemClassName}\n            onClick={e => {\n              e.stopPropagation()\n              unpin(ev)\n            }}\n          >\n            <Icon name=\"pin\" />\n            <FormattedMessage defaultMessage=\"Unpin\" />\n          </DropdownMenu.Item>\n        )}\n        {!login.state.isOnList(EventKind.BookmarksList, link) && !login.readonly && (\n          <DropdownMenu.Item\n            className={itemClassName}\n            onClick={e => {\n              e.stopPropagation()\n              bookmark(ev)\n            }}\n          >\n            <Icon name=\"bookmark\" />\n            <FormattedMessage {...messages.Bookmark} />\n          </DropdownMenu.Item>\n        )}\n        <DropdownMenu.Item\n          className={itemClassName}\n          onClick={e => {\n            e.stopPropagation()\n            copyId()\n          }}\n        >\n          <Icon name=\"copy\" />\n          <FormattedMessage {...messages.CopyID} />\n        </DropdownMenu.Item>\n        {!login.readonly && !isMine && (\n          <DropdownMenu.Item\n            className={itemClassName}\n            onClick={e => {\n              e.stopPropagation()\n              mute(ev.pubkey)\n            }}\n          >\n            <Icon name=\"mute\" />\n            <FormattedMessage {...messages.Mute} />\n          </DropdownMenu.Item>\n        )}\n        <DropdownMenu.Item\n          className={itemClassName}\n          onClick={e => {\n            e.stopPropagation()\n            handleReBroadcastButtonClick()\n          }}\n        >\n          <Icon name=\"relay\" />\n          <FormattedMessage defaultMessage=\"Broadcast Event\" />\n        </DropdownMenu.Item>\n        <DropdownMenu.Item\n          className={itemClassName}\n          onClick={e => {\n            e.stopPropagation()\n            translate()\n          }}\n        >\n          <Icon name=\"translate\" />\n          <FormattedMessage {...messages.TranslateTo} values={{ lang: langNames.of(lang.split(\"-\")[0]) }} />\n        </DropdownMenu.Item>\n        <DropdownMenu.Item\n          className={itemClassName}\n          onClick={e => {\n            e.stopPropagation()\n            copyEvent()\n          }}\n        >\n          <Icon name=\"json\" />\n          <FormattedMessage {...messages.CopyJSON} />\n        </DropdownMenu.Item>\n        {isMine && !login.readonly && (\n          <DropdownMenu.Item\n            className={itemClassName}\n            onClick={e => {\n              e.stopPropagation()\n              deleteEvent()\n            }}\n          >\n            <Icon name=\"trash\" className=\"text-error\" />\n            <FormattedMessage {...messages.Delete} />\n          </DropdownMenu.Item>\n        )}\n      </>\n    )\n  }\n\n  return (\n    <>\n      <DropdownMenu.Root>\n        <DropdownMenu.Trigger asChild>\n          <span className=\"cursor-pointer text-neutral-500 px-1 py-0.5\">\n            <Icon name=\"dots\" size={15} />\n          </span>\n        </DropdownMenu.Trigger>\n        <DropdownMenu.Portal>\n          <DropdownMenu.Content className=\"bg-layer-2 rounded-lg overflow-hidden z-[9999] min-w-48\" sideOffset={5}>\n            {menuItems()}\n          </DropdownMenu.Content>\n        </DropdownMenu.Portal>\n      </DropdownMenu.Root>\n      {showBroadcast && <ReBroadcaster ev={ev} onClose={() => setShowBroadcast(false)} />}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteFooter/AsyncFooterIcon.tsx",
    "content": "import classNames from \"classnames\"\n\nimport { AsyncIcon, type AsyncIconProps } from \"@/Components/Button/AsyncIcon\"\nimport { formatShort } from \"@/Utils/Number\"\n\nexport const AsyncFooterIcon = (props: AsyncIconProps & { value: number }) => {\n  const mergedProps = {\n    ...props,\n    iconSize: 18,\n    className: classNames(\n      \"transition duration-200 ease-in-out flex flex-row reaction-pill cursor-pointer gap-2 items-center\",\n      props.className,\n    ),\n  }\n\n  return (\n    <AsyncIcon {...mergedProps}>\n      {props.value > 0 && <div className=\"reaction-pill-number\">{formatShort(props.value)}</div>}\n    </AsyncIcon>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteFooter/FooterZapButton.tsx",
    "content": "import { barrierQueue } from \"@snort/shared\"\nimport { NostrLink, type ParsedZap, type TaggedNostrEvent } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport { Zapper, type ZapTarget } from \"@snort/wallet\"\nimport type React from \"react\"\nimport { useCallback, useEffect, useRef, useState } from \"react\"\nimport { useIntl } from \"react-intl\"\nimport { useLongPress } from \"use-long-press\"\n\nimport { AsyncFooterIcon } from \"@/Components/Event/Note/NoteFooter/AsyncFooterIcon\"\nimport { ZapperQueue } from \"@/Components/Event/Note/NoteFooter/ZapperQueue\"\nimport { ZapsSummary } from \"@/Components/Event/ZapsSummary\"\nimport ZapModal from \"@/Components/ZapModal/ZapModal\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { getDisplayName } from \"@/Utils\"\nimport { ZapPoolController } from \"@/Utils/ZapPoolController\"\nimport { useWallet } from \"@/Wallet\"\n\nexport interface ZapIconProps {\n  ev: TaggedNostrEvent\n  zaps: Array<ParsedZap>\n  onClickZappers?: () => void\n}\n\nexport const FooterZapButton = ({ ev, zaps, onClickZappers }: ZapIconProps) => {\n  const { publicKey, readonly } = useLogin(s => ({\n    publicKey: s.publicKey,\n    readonly: s.readonly,\n  }))\n  const preferences = usePreferences(s => ({ autoZap: s.autoZap, defaultZapAmount: s.defaultZapAmount }))\n  const walletState = useWallet()\n  const wallet = walletState.wallet\n  const link = NostrLink.fromEvent(ev)\n  const zapTotal = zaps.reduce((acc, z) => acc + z.amount, 0)\n  const didZap = zaps.some(a => a.sender === publicKey)\n  const [showZapModal, setShowZapModal] = useState(false)\n  const { formatMessage } = useIntl()\n  const [zapping, setZapping] = useState(false)\n  const { publisher, system } = useEventPublisher()\n  const zapRef = useRef<HTMLDivElement>(null)\n  const author = useUserProfile(ev.pubkey, zapRef)\n  const isMine = ev.pubkey === publicKey\n\n  const longPress = useLongPress(() => setShowZapModal(true), { captureEvent: true })\n\n  const getZapTarget = useCallback((): Array<ZapTarget> | undefined => {\n    if (ev.tags.some(v => v[0] === \"zap\")) {\n      return Zapper.fromEvent(ev)\n    }\n\n    const authorTarget = author?.lud16 || author?.lud06\n    if (authorTarget) {\n      return [\n        {\n          type: \"lnurl\",\n          value: authorTarget,\n          weight: 1,\n          name: getDisplayName(author, ev.pubkey),\n          zap: {\n            pubkey: ev.pubkey,\n            event: link,\n          },\n        } as ZapTarget,\n      ]\n    }\n  }, [ev, author, link])\n\n  const fastZap = async (e: React.MouseEvent) => {\n    if (zapping || e?.isPropagationStopped()) return\n\n    const lnurl = getZapTarget()\n    if (canFastZap && lnurl) {\n      setZapping(true)\n      try {\n        await fastZapInner(lnurl, preferences.defaultZapAmount)\n      } catch (e) {\n        console.warn(\"Fast zap failed\", e)\n        if (!(e instanceof Error) || e.message !== \"User rejected\") {\n          setShowZapModal(true)\n        }\n      } finally {\n        setZapping(false)\n      }\n    } else {\n      setShowZapModal(true)\n    }\n  }\n\n  const fastZapInner = useCallback(\n    async (targets: Array<ZapTarget>, amount: number) => {\n      if (wallet) {\n        // only allow 1 invoice req/payment at a time to avoid hitting rate limits\n        await barrierQueue(ZapperQueue, async () => {\n          const zapper = new Zapper(system, publisher)\n          const result = await zapper.send(wallet, targets, amount)\n          const totalSent = result.reduce((acc, v) => acc + v.sent, 0)\n          if (totalSent > 0) {\n            if (CONFIG.features.zapPool) {\n              ZapPoolController?.allocate(totalSent)\n            }\n          }\n        })\n      }\n    },\n    [wallet, system, publisher],\n  )\n\n  const canFastZap = wallet?.isReady() && !readonly\n\n  const targets = getZapTarget()\n\n  useEffect(() => {\n    if (preferences.autoZap && !didZap && !isMine && !zapping) {\n      const lnurl = getZapTarget()\n      if (wallet?.isReady() && lnurl) {\n        setZapping(true)\n        queueMicrotask(async () => {\n          try {\n            await fastZapInner(lnurl, preferences.defaultZapAmount)\n          } catch {\n            // ignored\n          } finally {\n            setZapping(false)\n          }\n        })\n      }\n    }\n  }, [preferences.autoZap, preferences.defaultZapAmount, didZap, isMine, wallet, zapping, getZapTarget, fastZapInner])\n\n  return (\n    <>\n      {targets && (\n        <>\n          <div ref={zapRef} className=\"flex flex-row flex-none min-w-[50px] md:min-w-[80px] gap-4 items-center\">\n            <AsyncFooterIcon\n              className={didZap ? \"reacted text-zap\" : \"hover:text-zap\"}\n              {...longPress()}\n              title={formatMessage({ defaultMessage: \"Zap\", id: \"fBI91o\" })}\n              iconName={canFastZap ? \"zapFast\" : \"zap\"}\n              value={zapTotal}\n              onClick={fastZap}\n            />\n            <ZapsSummary zaps={zaps} onClick={onClickZappers ?? (() => {})} />\n          </div>\n          {showZapModal && (\n            <ZapModal targets={getZapTarget()} onClose={() => setShowZapModal(false)} show={true} allocatePool={true} />\n          )}\n        </>\n      )}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteFooter/LikeButton.tsx",
    "content": "import { normalizeReaction } from \"@snort/shared\"\nimport type { TaggedNostrEvent } from \"@snort/system\"\nimport classNames from \"classnames\"\nimport { useIntl } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport { AsyncFooterIcon } from \"@/Components/Event/Note/NoteFooter/AsyncFooterIcon\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\n\nexport const LikeButton = ({\n  ev,\n  positiveReactions,\n}: {\n  ev: TaggedNostrEvent\n  positiveReactions: TaggedNostrEvent[]\n}) => {\n  const { formatMessage } = useIntl()\n  const navigate = useNavigate()\n  const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }))\n  const { publisher, system } = useEventPublisher()\n\n  const hasReacted = (emoji: string) => {\n    return positiveReactions?.some(\n      ({ pubkey, content }) => normalizeReaction(content) === emoji && pubkey === publicKey,\n    )\n  }\n\n  const react = async (content: string) => {\n    if (!hasReacted(content) && publisher) {\n      const evLike = await publisher.react(ev, content)\n      system.BroadcastEvent(evLike)\n    }\n    if (!publisher) {\n      navigate(\"/login\")\n    }\n  }\n\n  const reacted = hasReacted(\"+\")\n\n  return (\n    <AsyncFooterIcon\n      className={classNames(\n        \"flex-none min-w-[50px] md:min-w-[80px]\",\n        reacted ? \"reacted text-heart\" : \"hover:text-heart\",\n      )}\n      iconName={reacted ? \"heart-solid\" : \"heart\"}\n      title={formatMessage({ defaultMessage: \"Like\", id: \"qtWLmt\" })}\n      value={positiveReactions.length}\n      onClick={() => react(\"+\")}\n    />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteFooter/NoteFooter.tsx",
    "content": "import { EventKind, RequestFilterBuilder } from \"@snort/system\"\nimport { SnortContext } from \"@snort/system-react\"\nimport { WorkerRelayInterface } from \"@snort/worker-relay\"\nimport classNames from \"classnames\"\nimport { use, useEffect, useState } from \"react\"\nimport { useNoteContext } from \"@/Components/Event/Note/NoteContext\"\nimport { FooterZapButton } from \"@/Components/Event/Note/NoteFooter/FooterZapButton\"\nimport { LikeButton } from \"@/Components/Event/Note/NoteFooter/LikeButton\"\nimport { PowIcon } from \"@/Components/Event/Note/NoteFooter/PowIcon\"\nimport { ReplyButton } from \"@/Components/Event/Note/NoteFooter/ReplyButton\"\nimport { RepostButton } from \"@/Components/Event/Note/NoteFooter/RepostButton\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport usePreferences from \"@/Hooks/usePreferences\"\n\nexport interface NoteFooterProps {\n  replyCount?: number\n  className?: string\n}\n\nexport default function NoteFooter(props: NoteFooterProps) {\n  const { ev, link, reactions, setShowReactionsModal } = useNoteContext()\n  const [replyCount, setReplyCount] = useState(props.replyCount)\n\n  const system = use(SnortContext)\n\n  const { reactions: reactionGroups, zaps, reposts } = reactions\n  const { positive } = reactionGroups\n\n  const readonly = useLogin(s => s.readonly)\n  const enableReactions = usePreferences(s => s.enableReactions)\n  useEffect(() => {\n    const cacheRelay = system.cacheRelay\n    // try to count replies from cache relay when props doesnt provide the count\n    // this normally is the case for timelines views\n    // thread views are the only ones which have the true reply count\n    if (cacheRelay instanceof WorkerRelayInterface && !props.replyCount) {\n      const fx = new RequestFilterBuilder().kinds([EventKind.TextNote, EventKind.Comment]).replyToLink([link])\n\n      cacheRelay.count([\"REQ\", \"\", fx.filter]).then(setReplyCount)\n    }\n  }, [system, link, props.replyCount])\n\n  return (\n    <div className={classNames(\"flex flex-row gap-4 overflow-hidden max-w-full h-6 items-center\", props.className)}>\n      <ReplyButton ev={ev} replyCount={props.replyCount ?? replyCount} readonly={readonly} />\n      <RepostButton ev={ev} reposts={reposts} />\n      {enableReactions && <LikeButton ev={ev} positiveReactions={positive} />}\n      {CONFIG.showPowIcon && <PowIcon ev={ev} />}\n      <FooterZapButton ev={ev} zaps={zaps} onClickZappers={() => setShowReactionsModal(true)} />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteFooter/PowIcon.tsx",
    "content": "import { countLeadingZeros, type TaggedNostrEvent } from \"@snort/system\"\nimport { useIntl } from \"react-intl\"\n\nimport { AsyncFooterIcon } from \"@/Components/Event/Note/NoteFooter/AsyncFooterIcon\"\nimport { findTag } from \"@/Utils\"\n\nexport const PowIcon = ({ ev }: { ev: TaggedNostrEvent }) => {\n  const { formatMessage } = useIntl()\n\n  const powValue = findTag(ev, \"nonce\") ? countLeadingZeros(ev.id) : undefined\n  if (!powValue) return null\n\n  return (\n    <AsyncFooterIcon\n      className=\"hidden md:flex flex-none min-w-[50px] md:min-w-[80px]\"\n      title={formatMessage({ defaultMessage: \"Proof of Work\", id: \"grQ+mI\" })}\n      iconName=\"diamond\"\n      value={powValue}\n    />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteFooter/ReplyButton.tsx",
    "content": "import type { TaggedNostrEvent } from \"@snort/system\"\nimport classNames from \"classnames\"\nimport { useIntl } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport { AsyncFooterIcon } from \"@/Components/Event/Note/NoteFooter/AsyncFooterIcon\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { useNoteCreator } from \"@/State/NoteCreator\"\n\nexport const ReplyButton = ({\n  ev,\n  replyCount,\n  readonly,\n}: {\n  ev: TaggedNostrEvent\n  replyCount?: number\n  readonly: boolean\n}) => {\n  const { formatMessage } = useIntl()\n  const navigate = useNavigate()\n  const publicKey = useLogin(s => s.publicKey)\n  const note = useNoteCreator(n => ({\n    show: n.show,\n    replyTo: n.replyTo,\n    update: n.update,\n    quote: n.quote,\n  }))\n\n  const handleReplyButtonClick = () => {\n    if (!publicKey) {\n      navigate(\"/login\")\n      return\n    }\n    if (readonly) {\n      return\n    }\n    note.update(v => {\n      if (v.replyTo?.id !== ev.id) {\n        v.reset()\n      }\n      v.show = true\n      v.replyTo = ev\n    })\n  }\n\n  return (\n    <AsyncFooterIcon\n      className={classNames(\n        \"flex-none min-w-[50px] md:min-w-[80px]\",\n        note.show ? \"reacted text-nostr-purple\" : \"hover:text-nostr-purple\",\n      )}\n      iconName=\"reply\"\n      title={formatMessage({ defaultMessage: \"Reply\", id: \"9HU8vw\" })}\n      value={replyCount ?? 0}\n      onClick={handleReplyButtonClick}\n    />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteFooter/RepostButton.tsx",
    "content": "import type { TaggedNostrEvent } from \"@snort/system\"\nimport * as DropdownMenu from \"@radix-ui/react-dropdown-menu\"\nimport classNames from \"classnames\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport { AsyncFooterIcon } from \"@/Components/Event/Note/NoteFooter/AsyncFooterIcon\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport messages from \"@/Components/messages\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { useNoteCreator } from \"@/State/NoteCreator\"\n\nexport const RepostButton = ({ ev, reposts }: { ev: TaggedNostrEvent; reposts: TaggedNostrEvent[] }) => {\n  const { formatMessage } = useIntl()\n  const navigate = useNavigate()\n  const { publisher, system } = useEventPublisher()\n  const publicKey = useLogin(s => s.publicKey)\n  const confirmReposts = usePreferences(s => s.confirmReposts)\n  const note = useNoteCreator(n => ({ show: n.show, replyTo: n.replyTo, update: n.update, quote: n.quote }))\n\n  const hasReposted = () => {\n    return reposts.some(a => a.pubkey === publicKey)\n  }\n\n  const repost = async () => {\n    if (!hasReposted() && publisher) {\n      if (!confirmReposts || window.confirm(formatMessage(messages.ConfirmRepost, { id: ev.id }))) {\n        const evRepost = await publisher.repost(ev)\n        system.BroadcastEvent(evRepost)\n      }\n    }\n    if (!publisher) {\n      navigate(\"/login\")\n    }\n  }\n\n  const itemClassName =\n    \"grid grid-cols-[2rem_auto] gap-2 px-6 py-2 text-base font-semibold bg-layer-2 light:bg-white hover:bg-layer-3 light:hover:bg-neutral-200 cursor-pointer outline-none disabled:opacity-50 disabled:cursor-not-allowed\"\n\n  return (\n    <DropdownMenu.Root>\n      <DropdownMenu.Trigger asChild>\n        <span>\n          <AsyncFooterIcon\n            className={classNames(\n              \"flex-none min-w-[50px] md:min-w-[80px]\",\n              hasReposted() ? \"reacted text-nostr-blue\" : \"hover:text-nostr-blue\",\n            )}\n            iconName=\"repeat\"\n            title={formatMessage({ defaultMessage: \"Repost\", id: \"JeoS4y\" })}\n            value={reposts.length}\n          />\n        </span>\n      </DropdownMenu.Trigger>\n      <DropdownMenu.Portal>\n        <DropdownMenu.Content\n          className=\"bg-layer-2 rounded-lg overflow-hidden z-[9999] min-w-48\"\n          sideOffset={5}\n          align=\"start\"\n        >\n          <DropdownMenu.Item\n            className={itemClassName}\n            onClick={e => {\n              e.stopPropagation()\n              repost()\n            }}\n            disabled={hasReposted()}\n          >\n            <Icon name=\"repeat\" />\n            <FormattedMessage defaultMessage=\"Repost\" />\n          </DropdownMenu.Item>\n          <DropdownMenu.Item\n            className={itemClassName}\n            onClick={e => {\n              e.stopPropagation()\n              note.update(n => {\n                n.reset()\n                n.quote = ev\n                n.show = true\n              })\n            }}\n          >\n            <Icon name=\"edit\" />\n            <FormattedMessage defaultMessage=\"Quote Repost\" />\n          </DropdownMenu.Item>\n        </DropdownMenu.Content>\n      </DropdownMenu.Portal>\n    </DropdownMenu.Root>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteFooter/ZapperQueue.tsx",
    "content": "import { processWorkQueue, type WorkQueueItem } from \"@snort/shared\"\n\nexport const ZapperQueue: Array<WorkQueueItem> = []\n\nprocessWorkQueue(ZapperQueue)\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteHeader.tsx",
    "content": "import { EventKind, NostrLink } from \"@snort/system\"\nimport type React from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\n\nimport type { NotePropsOptions } from \"@/Components/Event/EventComponent\"\nimport { NoteContextMenu } from \"@/Components/Event/Note/NoteContextMenu\"\nimport NoteTime from \"@/Components/Event/Note/NoteTime\"\nimport ReplyTag from \"@/Components/Event/Note/ReplyTag\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport messages from \"@/Components/messages\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { useNoteContext } from \"./NoteContext\"\n\nexport default function NoteHeader(props: { options: NotePropsOptions; context?: React.ReactNode }) {\n  const { options } = props\n  const { formatMessage } = useIntl()\n  const { publisher } = useEventPublisher()\n  const { ev } = useNoteContext()\n  const login = useLogin()\n\n  async function unpin() {\n    if (options.canUnpin && publisher) {\n      if (window.confirm(formatMessage(messages.ConfirmUnpin))) {\n        login.state.removeFromList(EventKind.PinList, NostrLink.fromEvent(ev))\n      }\n    }\n  }\n\n  async function unbookmark() {\n    if (options.canUnbookmark && publisher) {\n      if (window.confirm(formatMessage(messages.ConfirmUnbookmark))) {\n        login.state.removeFromList(EventKind.BookmarksList, NostrLink.fromEvent(ev))\n      }\n    }\n  }\n\n  return (\n    <div className=\"flex justify-between\">\n      <ProfileImage\n        pubkey={ev.pubkey}\n        subHeader={<ReplyTag ev={ev} />}\n        link={options.canClick === undefined ? undefined : \"\"}\n        showProfileCard={options.showProfileCard ?? true}\n      />\n      <div className=\"flex items-center gap-2\">\n        {props.context}\n        {(options.showTime || options.showBookmarked) && (\n          <>\n            {options.showBookmarked && (\n              <div className=\"text-sm text-neutral-500 flex gap-1\" onClick={() => unbookmark()}>\n                <Icon name=\"bookmark\" />\n                <FormattedMessage {...messages.Bookmarked} />\n              </div>\n            )}\n            {!options.showBookmarked && <NoteTime from={ev.created_at * 1000} />}\n          </>\n        )}\n        {options.showPinned && (\n          <div className=\"text-sm text-neutral-500 flex gap-1\" onClick={() => unpin()}>\n            <Icon name=\"pin\" />\n            <FormattedMessage {...messages.Pinned} />\n          </div>\n        )}\n        {options.showContextMenu && <NoteContextMenu />}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteQuote.tsx",
    "content": "import { dedupe, NostrPrefix, sanitizeRelayUrl } from \"@snort/shared\"\nimport { NostrLink } from \"@snort/system\"\nimport { useEventFeed } from \"@snort/system-react\"\nimport { useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport Copy from \"@/Components/Copy/Copy\"\nimport Note, { type NotePropsOptions } from \"@/Components/Event/EventComponent\"\nimport Spinner from \"@/Components/Icons/Spinner\"\nimport classNames from \"classnames\"\n\nexport default function NoteQuote({\n  link,\n  depth,\n  className,\n  options,\n}: {\n  link: NostrLink\n  depth?: number\n  className?: string\n  options?: NotePropsOptions\n}) {\n  const [tryLink, setLink] = useState<NostrLink>(link)\n  const [tryRelay, setTryRelay] = useState(\"\")\n  const { formatMessage } = useIntl()\n\n  const ev = useEventFeed(tryLink)\n  if (!ev)\n    return (\n      <div className={classNames(\"layer-2 flex flex-col gap-2\", className)}>\n        <Spinner />\n        <div className=\"flex items-center gap-2 leading-0\">\n          <span>\n            <FormattedMessage defaultMessage=\"Looking for: \" />\n          </span>\n          <Copy text={tryLink.encode()} />\n        </div>\n        <div className=\"flex gap-2\">\n          <input\n            type=\"text\"\n            value={tryRelay}\n            onChange={e => setTryRelay(e.target.value)}\n            placeholder={formatMessage({ defaultMessage: \"Try another relay\" })}\n          />\n          <AsyncButton\n            onClick={() => {\n              const u = sanitizeRelayUrl(tryRelay)\n              if (u) {\n                const relays = tryLink.relays ?? []\n                relays.push(u)\n                setLink(\n                  new NostrLink(\n                    tryLink.type !== NostrPrefix.Address ? NostrPrefix.Event : NostrPrefix.Address,\n                    tryLink.id,\n                    tryLink.kind,\n                    tryLink.author,\n                    dedupe(relays),\n                    tryLink.scope,\n                  ),\n                )\n                setTryRelay(\"\")\n              }\n            }}\n          >\n            <FormattedMessage defaultMessage=\"Add\" />\n          </AsyncButton>\n        </div>\n      </div>\n    )\n  return (\n    <div className={className ?? \"rounded-lg border\"}>\n      <Note\n        data={ev}\n        depth={(depth ?? 0) + 1}\n        options={\n          options ?? {\n            showFooter: false,\n            truncate: true,\n          }\n        }\n      />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteText.tsx",
    "content": "import { memo, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport type { NoteProps } from \"@/Components/Event/EventComponent\"\nimport type { NoteTranslation } from \"@/Components/Event/Note/types\"\nimport Reveal from \"@/Components/Event/Reveal\"\nimport Text from \"@/Components/Text/Text\"\nimport usePreferences from \"@/Hooks/usePreferences\"\n\nconst TEXT_TRUNCATE_LENGTH = 400\nexport const NoteText = memo(function InnerContent(\n  props: NoteProps & { translated: NoteTranslation | undefined; showTranslation?: boolean },\n) {\n  const { data: ev, options, translated, showTranslation } = props\n  const showContentWarningPosts = usePreferences(s => s.showContentWarningPosts)\n  const [showMore, setShowMore] = useState(false)\n  const body = translated && !translated.skipped && showTranslation ? translated.text : (ev?.content ?? \"\")\n  const id = translated && !translated.skipped && showTranslation ? `${ev.id}-translated` : ev.id\n  const shouldTruncate = options?.truncate && body.length > TEXT_TRUNCATE_LENGTH\n\n  const ToggleShowMore = () => (\n    <a\n      className=\"text-highlight\"\n      onClick={e => {\n        e.preventDefault()\n        e.stopPropagation()\n        setShowMore(!showMore)\n      }}\n    >\n      {showMore ? <FormattedMessage defaultMessage=\"Show less\" /> : <FormattedMessage defaultMessage=\"Show more\" />}\n    </a>\n  )\n\n  const innerContent = (\n    <>\n      {shouldTruncate && showMore && <ToggleShowMore />}\n      <Text\n        id={id}\n        highlightText={props.highlightText}\n        className={props.className}\n        content={body}\n        tags={ev.tags}\n        creator={ev.pubkey}\n        depth={props.depth}\n        disableMedia={!(options?.showMedia ?? true)}\n        disableMediaSpotlight={!(props.options?.showMediaSpotlight ?? true)}\n        truncate={shouldTruncate && !showMore ? TEXT_TRUNCATE_LENGTH : undefined}\n      />\n      {shouldTruncate && !showMore && <ToggleShowMore />}\n    </>\n  )\n\n  if (!showContentWarningPosts) {\n    const contentWarning = ev.tags.find(a => a[0] === \"content-warning\")\n    if (contentWarning) {\n      return (\n        <Reveal\n          message={\n            <>\n              <FormattedMessage\n                defaultMessage=\"The author has marked this note as a <i>sensitive topic</i>\"\n                id=\"StKzTE\"\n                values={{\n                  i: c => <i>{c}</i>,\n                }}\n              />\n              {contentWarning[1] && (\n                <>\n                  &nbsp;\n                  <FormattedMessage\n                    defaultMessage=\"Reason: <i>{reason}</i>\"\n                    id=\"6OSOXl\"\n                    values={{\n                      i: c => <i>{c}</i>,\n                      reason: contentWarning[1],\n                    }}\n                  />\n                </>\n              )}\n              . <FormattedMessage defaultMessage=\"Click here to load anyway\" />.{\" \"}\n              <Link to=\"/settings/moderation\">\n                <i>\n                  <FormattedMessage defaultMessage=\"Settings\" />\n                </i>\n              </Link>\n            </>\n          }\n        >\n          {innerContent}\n        </Reveal>\n      )\n    }\n  }\n  return innerContent\n})\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/NoteTime.tsx",
    "content": "import type React from \"react\"\nimport { type ReactNode, useCallback, useMemo, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nexport interface NoteTimeProps {\n  from: number\n  fallback?: string\n  className?: string\n}\n\nconst secondsInAMinute = 60\nconst secondsInAnHour = secondsInAMinute * 60\nconst secondsInADay = secondsInAnHour * 24\n\nconst NoteTime: React.FC<NoteTimeProps> = ({ from, fallback, className }) => {\n  const calcTime = useCallback((fromTime: number) => {\n    const currentTime = new Date()\n    const timeDifference = Math.floor((currentTime.getTime() - fromTime) / 1000)\n\n    if (timeDifference < secondsInAMinute) {\n      return <FormattedMessage defaultMessage=\"now\" />\n    } else if (timeDifference < secondsInAnHour) {\n      return `${Math.floor(timeDifference / secondsInAMinute)}m`\n    } else if (timeDifference < secondsInADay) {\n      return `${Math.floor(timeDifference / secondsInAnHour)}h`\n    } else {\n      const fromDate = new Date(fromTime)\n      if (fromDate.getFullYear() === currentTime.getFullYear()) {\n        return fromDate.toLocaleDateString(undefined, {\n          month: \"short\",\n          day: \"numeric\",\n        })\n      } else {\n        return fromDate.toLocaleDateString(undefined, {\n          year: \"numeric\",\n          month: \"short\",\n          day: \"numeric\",\n        })\n      }\n    }\n  }, [])\n\n  const [time] = useState<string | ReactNode>(calcTime(from))\n\n  const absoluteTime = useMemo(\n    () =>\n      new Intl.DateTimeFormat(undefined, {\n        dateStyle: \"medium\",\n        timeStyle: \"long\",\n      }).format(from),\n    [from],\n  )\n\n  const isoDate = useMemo(() => new Date(from).toISOString(), [from])\n\n  return (\n    <time dateTime={isoDate} title={absoluteTime} className={className ?? \"text-sm text-neutral-500 font-medium\"}>\n      {time || fallback}\n    </time>\n  )\n}\n\nexport default NoteTime\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/ReactionsModal.tsx",
    "content": "import type { TaggedNostrEvent } from \"@snort/system\"\nimport { Fragment, useMemo, useState } from \"react\"\nimport { FormattedMessage, type MessageDescriptor, useIntl } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport Modal from \"@/Components/Modal/Modal\"\nimport { useNoteContext } from \"@/Components/Event/Note/NoteContext\"\nimport TabSelectors, { type Tab } from \"@/Components/TabSelectors/TabSelectors\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport ZapAmount from \"@/Components/zap-amount\"\nimport useWoT from \"@/Hooks/useWoT\"\n\nimport messages from \"../../messages\"\n\ninterface ReactionsModalProps {\n  onClose(): void\n  initialTab?: number\n}\n\nconst ReactionsModal = ({ onClose, initialTab = 0 }: ReactionsModalProps) => {\n  const { formatMessage } = useIntl()\n  const { reactions } = useNoteContext()\n\n  const { reactions: reactionGroups, zaps, reposts } = reactions\n  const { positive, negative } = reactionGroups\n\n  const { sortEvents } = useWoT()\n\n  const likes = useMemo(() => sortEvents([...positive]), [positive, sortEvents])\n  const dislikes = useMemo(() => sortEvents([...negative]), [negative, sortEvents])\n  const sortedReposts = useMemo(() => sortEvents([...reposts]), [reposts, sortEvents])\n\n  const total = positive.length + negative.length + zaps.length + reposts.length\n\n  const createTab = (message: MessageDescriptor, count: number, value: number, disabled = false) =>\n    ({\n      text: formatMessage(message, { n: count }),\n      value,\n      disabled,\n    }) as Tab\n\n  const tabs = useMemo(() => {\n    const baseTabs = [\n      createTab(messages.Likes, likes.length, 0),\n      createTab(messages.Zaps, zaps.length, 1, zaps.length === 0),\n      createTab(messages.Reposts, reposts.length, 2, reposts.length === 0),\n    ]\n\n    return dislikes.length !== 0 ? baseTabs.concat(createTab(messages.Dislikes, dislikes.length, 3)) : baseTabs\n  }, [likes.length, zaps.length, reposts.length, dislikes.length, createTab])\n\n  const [tab, setTab] = useState(tabs[initialTab])\n\n  const renderReactionItem = (ev: TaggedNostrEvent, icon: string, iconClass?: string, size?: number) => (\n    <Fragment key={ev.id}>\n      <div className=\"mx-auto\">\n        <Icon name={icon} size={size} className={iconClass} />\n      </div>\n      <ProfileImage pubkey={ev.pubkey} showProfileCard={true} />\n    </Fragment>\n  )\n\n  return (\n    <Modal id=\"reactions\" onClose={onClose}>\n      <div className=\"text-lg font-semibold mb-2\">\n        <FormattedMessage defaultMessage=\"Reactions ({n})\" values={{ n: total }} />\n      </div>\n      <TabSelectors tabs={tabs} tab={tab} setTab={setTab} />\n      <div className=\"h-[50dvh] overflow-y-auto\">\n        <div className=\"grid grid-cols-[90px_auto] gap-y-2 items-center py-2\" key={tab.value}>\n          {tab.value === 0 && likes.map(ev => renderReactionItem(ev, \"heart-solid\", \"text-heart\"))}\n          {tab.value === 1 &&\n            zaps.map(\n              z =>\n                z.sender && (\n                  <Fragment key={z.id}>\n                    <ZapAmount n={z.amount} />\n                    <ProfileImage\n                      showProfileCard={true}\n                      pubkey={z.sender}\n                      subHeader={<div title={z.content}>{z.content}</div>}\n                      link={z.anonZap ? \"\" : undefined}\n                      overrideUsername={z.anonZap ? formatMessage({ defaultMessage: \"Anonymous\" }) : undefined}\n                    />\n                  </Fragment>\n                ),\n            )}\n          {tab.value === 2 && sortedReposts.map(ev => renderReactionItem(ev, \"repost\", \"text-repost\", 16))}\n          {tab.value === 3 && dislikes.map(ev => renderReactionItem(ev, \"dislike\"))}\n        </div>\n      </div>\n    </Modal>\n  )\n}\n\nexport default ReactionsModal\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/ReplyTag.tsx",
    "content": "import { EventExt, type TaggedNostrEvent } from \"@snort/system\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport { ClientTag } from \"@/Components/Event/Note/ClientTag\"\nimport Mention from \"@/Components/Embed/Mention\"\n\nexport default function ReplyTag({ ev }: { ev: TaggedNostrEvent }) {\n  const thread = EventExt.extractThread(ev)\n  if (thread === undefined) {\n    return <ClientTag ev={ev} />\n  }\n  const maxMentions = 2\n  const replyLink = thread?.replyTo ?? thread?.root\n  const link = replyLink?.encode(CONFIG.eventLinkPrefix)\n\n  function renderMentions() {\n    const elms = []\n    for (const pk of (thread?.pubKeys ?? []).slice(0, maxMentions)) {\n      elms.push(<Mention link={pk} />)\n      elms.push(\", \")\n    }\n    elms.pop()\n    return elms\n  }\n\n  return (\n    <small className=\"text-xs\">\n      re:&nbsp;\n      {renderMentions()}\n      {thread.pubKeys.length > maxMentions && (\n        <>\n          {\" \"}\n          <FormattedMessage\n            defaultMessage=\"& {n} {n, plural, =1 {other} other {others}}\"\n            values={{\n              n: thread.pubKeys.length - maxMentions,\n            }}\n          />\n        </>\n      )}\n      {thread.pubKeys.length === 0 && link && <Link to={`/${link}`}>{link.slice(0, 12)}</Link>}\n      <ClientTag ev={ev} />\n    </small>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/TranslationInfo.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nimport { useNoteContext } from \"@/Components/Event/Note/NoteContext\"\n\nexport function TranslationInfo() {\n  const { translated, toggleTranslation } = useNoteContext()\n  if (translated && translated.confidence > 0.5) {\n    return (\n      <small\n          className=\"select-none cursor-pointer\"\n          onClick={e => {\n            e.stopPropagation()\n            toggleTranslation()\n          }}\n        >\n          <FormattedMessage defaultMessage=\"Translated from {lang}\" values={{ lang: translated.fromLanguage }} />\n        </small>\n    )\n  } else if (translated && !translated.skipped) {\n    return (\n      <small>\n        <FormattedMessage defaultMessage=\"Translation failed\" />\n      </small>\n    )\n  }\n  return null\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Note/types.tsx",
    "content": "export interface NoteTranslation {\n  text: string\n  fromLanguage: string\n  confidence: number\n  skipped?: boolean\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/NoteReaction.tsx",
    "content": "import { NostrPrefix } from \"@snort/shared\"\nimport { EventKind, NostrLink, type TaggedNostrEvent } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport { useCallback, useMemo, useRef } from \"react\"\nimport { useInView } from \"react-intersection-observer\"\nimport { FormattedMessage } from \"react-intl\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport useModeration from \"@/Hooks/useModeration\"\nimport { getDisplayName } from \"@/Utils\"\nimport NoteQuote from \"./Note/NoteQuote\"\n\nexport interface NoteReactionProps {\n  data: TaggedNostrEvent\n  root?: TaggedNostrEvent\n  depth?: number\n}\nexport default function NoteReaction(props: NoteReactionProps) {\n  const { data: ev } = props\n  const { isMuted } = useModeration()\n  const { inView, ref: inViewRef } = useInView({ triggerOnce: true, rootMargin: \"2000px\" })\n  const rootRef = useRef<HTMLDivElement>(null)\n  const profile = useUserProfile(ev.pubkey, rootRef)\n\n  const _opt = useMemo(\n    () => ({\n      showHeader: ev?.kind === EventKind.Repost || ev?.kind === EventKind.TextNote,\n      showFooter: false,\n      truncate: true,\n    }),\n    [ev],\n  )\n  const links = NostrLink.fromTags(ev.tags)\n  const refEvent = links.find(a => [NostrPrefix.Event, NostrPrefix.Note, NostrPrefix.Address].includes(a.type))\n  const isOpMuted = refEvent?.author && isMuted(refEvent.author)\n  if (isOpMuted) {\n    return\n  }\n\n  function action() {\n    switch (ev.kind) {\n      case EventKind.Repost: {\n        return (\n          <>\n            <Icon name=\"repeat\" size={18} />\n            <FormattedMessage\n              defaultMessage=\"{name} reposted\"\n              values={{\n                name: getDisplayName(profile, ev.pubkey),\n              }}\n            />\n          </>\n        )\n      }\n      case EventKind.Reaction: {\n        return (\n          <FormattedMessage\n            defaultMessage=\"{name} liked\"\n            values={{\n              name: getDisplayName(profile, ev.pubkey),\n            }}\n          />\n        )\n      }\n    }\n  }\n\n  function inner() {\n    return (\n      <>\n        <div className=\"flex gap-1 text-base font-semibold px-3 py-2 border-b\">{action()}</div>\n        {refEvent && (\n          <NoteQuote\n            link={refEvent}\n            className=\"\"\n            depth={props.depth}\n            options={{\n              showFooter: true,\n              truncate: true,\n            }}\n          />\n        )}\n      </>\n    )\n  }\n\n  const setRef = useCallback(\n    (el: HTMLDivElement | null) => {\n      rootRef.current = el\n      inViewRef(el)\n    },\n    [inViewRef],\n  )\n\n  return (\n    <div className=\"flex flex-col gap-2\" ref={setRef}>\n      {inView && inner()}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Poll.tsx",
    "content": "import { LNURL } from \"@snort/shared\"\nimport { NostrLink, type ParsedZap, type TaggedNostrEvent } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport { useRef, useState } from \"react\"\nimport { FormattedMessage, FormattedNumber, useIntl } from \"react-intl\"\n\nimport Spinner from \"@/Components/Icons/Spinner\"\nimport ZapModal from \"@/Components/ZapModal/ZapModal\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { unwrap } from \"@/Utils\"\nimport { formatShort } from \"@/Utils/Number\"\nimport { useWallet } from \"@/Wallet\"\n\ninterface PollProps {\n  ev: TaggedNostrEvent\n  zaps: Array<ParsedZap>\n}\n\ntype PollTally = \"zaps\" | \"pubkeys\"\n\nexport default function Poll(props: PollProps) {\n  const { formatMessage } = useIntl()\n  const { publisher, system } = useEventPublisher()\n  const { wallet } = useWallet()\n  const defaultZapAmount = usePreferences(s => s.defaultZapAmount)\n  const myPubKey = useLogin(s => s.publicKey)\n  const pollRef = useRef<HTMLDivElement>(null)\n  const pollerProfile = useUserProfile(props.ev.pubkey, pollRef)\n  const [tallyBy, setTallyBy] = useState<PollTally>(\"pubkeys\")\n  const [error, setError] = useState(\"\")\n  const [invoice, setInvoice] = useState(\"\")\n  const [voting, setVoting] = useState<number>()\n  const didVote = props.zaps?.some(a => a.sender === myPubKey)\n  const isMyPoll = props.ev.pubkey === myPubKey\n  const showResults = didVote || isMyPoll\n\n  const options = props.ev.tags\n    ?.filter(a => a[0] === \"poll_option\")\n    .sort((a, b) => (Number(a[1]) > Number(b[1]) ? 1 : -1))\n\n  async function zapVote(ev: React.MouseEvent, opt: number) {\n    ev.stopPropagation()\n    if (voting || !publisher) return\n\n    const amount = defaultZapAmount\n    try {\n      if (amount <= 0) {\n        throw new Error(\n          formatMessage(\n            {\n              defaultMessage: \"Can't vote with {amount} sats, please set a different default zap amount\",\n              id: \"NepkXH\",\n            },\n            {\n              amount,\n            },\n          ),\n        )\n      }\n\n      setVoting(opt)\n      const r = await system.requestRouter?.forReplyTo(props.ev.pubkey)\n      const zap = await publisher.zap(\n        amount * 1000,\n        props.ev.pubkey,\n        r ?? [],\n        NostrLink.fromEvent(props.ev),\n        undefined,\n        eb => eb.tag([\"poll_option\", opt.toString()]),\n      )\n\n      const lnurl = props.ev.tags.find(a => a[0] === \"zap\")?.[1] || pollerProfile?.lud16 || pollerProfile?.lud06\n      if (!lnurl) return\n\n      const svc = new LNURL(lnurl)\n      await svc.load()\n\n      if (!svc.canZap) {\n        throw new Error(\n          formatMessage({\n            defaultMessage: \"Can't vote because LNURL service does not support zaps\",\n            id: \"fOksnD\",\n          }),\n        )\n      }\n\n      const invoice = await svc.getInvoice(amount, undefined, zap)\n      if (wallet?.isReady()) {\n        await wallet?.payInvoice(unwrap(invoice.pr))\n      } else {\n        setInvoice(unwrap(invoice.pr))\n      }\n    } catch (e) {\n      if (e instanceof Error) {\n        setError(e.message)\n      } else {\n        setError(\n          formatMessage({\n            defaultMessage: \"Failed to send vote\",\n            id: \"g985Wp\",\n          }),\n        )\n      }\n    } finally {\n      setVoting(undefined)\n    }\n  }\n\n  const totalVotes = (() => {\n    switch (tallyBy) {\n      case \"zaps\":\n        return props.zaps?.filter(a => a.pollOption !== undefined).reduce((acc, v) => (acc += v.amount), 0) ?? 0\n      case \"pubkeys\":\n        return new Set(props.zaps?.filter(a => a.pollOption !== undefined).map(a => unwrap(a.sender)) ?? []).size\n    }\n  })()\n\n  return (\n    <>\n      <div className=\"flex justify-between px-3 py-2\">\n        <small>\n          <FormattedMessage\n            defaultMessage=\"You are voting with {amount} sats\"\n            id=\"3qnJlS\"\n            values={{\n              amount: formatShort(defaultZapAmount),\n            }}\n          />\n        </small>\n        <button type=\"button\" onClick={() => setTallyBy(s => (s !== \"zaps\" ? \"zaps\" : \"pubkeys\"))}>\n          <FormattedMessage\n            defaultMessage=\"Votes by {type}\"\n            id=\"xIcAOU\"\n            values={{\n              type:\n                tallyBy === \"zaps\" ? (\n                  <FormattedMessage defaultMessage=\"zap\" />\n                ) : (\n                  <FormattedMessage defaultMessage=\"user\" />\n                ),\n            }}\n          />\n        </button>\n      </div>\n      <div ref={pollRef} className=\"poll-body\">\n        {options?.map(a => {\n          const opt = Number(a[1])\n          const desc = a[2]\n          const zapsOnOption = props.zaps?.filter(b => b.pollOption === opt) ?? []\n          const total = (() => {\n            switch (tallyBy) {\n              case \"zaps\":\n                return zapsOnOption.reduce((acc, v) => (acc += v.amount), 0)\n              case \"pubkeys\":\n                return new Set(zapsOnOption.map(a => unwrap(a.sender))).size\n            }\n          })()\n          const weight = totalVotes === 0 ? 0 : total / totalVotes\n          return (\n            <div key={a[1]} className=\"flex\" onClick={e => zapVote(e, opt)}>\n              <div className=\"grow\">{opt === voting ? <Spinner /> : desc}</div>\n              {showResults && (\n                <>\n                  <div className=\"flex\">\n                    <FormattedNumber value={weight * 100} maximumFractionDigits={0} />% &nbsp;\n                    <small>({formatShort(total)})</small>\n                  </div>\n                  <div style={{ width: `${weight * 100}%` }} className=\"progress\"></div>\n                </>\n              )}\n            </div>\n          )\n        })}\n        {error && <b className=\"error\">{error}</b>}\n      </div>\n\n      <ZapModal show={invoice !== \"\"} onClose={() => setInvoice(\"\")} invoice={invoice} />\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Reveal.tsx",
    "content": "import { useState } from \"react\"\n\nimport { WarningNotice } from \"@/Components/WarningNotice/WarningNotice\"\n\ninterface RevealProps {\n  message: React.ReactNode\n  children: React.ReactNode\n}\n\nexport default function Reveal(props: RevealProps) {\n  const [reveal, setReveal] = useState(false)\n\n  if (!reveal) {\n    return <WarningNotice onClick={() => setReveal(true)}>{props.message}</WarningNotice>\n  } else if (props.children) {\n    return props.children\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/RevealMedia.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport { MediaElement, type MediaElementProps } from \"@/Components/Embed/MediaElement\"\nimport Reveal from \"@/Components/Event/Reveal\"\nimport useFollowsControls from \"@/Hooks/useFollowControls\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { extensionToMime } from \"@snort/system\"\nimport { FileExtensionRegex } from \"@/Utils/Const\"\n\nexport type RevealMediaProps = Omit<MediaElementProps, \"mime\"> & {\n  creator: string\n}\n\nexport default function RevealMedia(props: RevealMediaProps) {\n  const publicKey = useLogin(s => s.publicKey)\n  const autoLoadMedia = usePreferences(s => s.autoLoadMedia)\n  const { isFollowing } = useFollowsControls()\n\n  const hideNonFollows = autoLoadMedia === \"follows-only\" && !isFollowing(props.creator)\n  const isMine = props.creator === publicKey\n  const hideMedia = autoLoadMedia === \"none\" || (!isMine && hideNonFollows)\n\n  const url = new URL(props.src)\n  const hostname = url.hostname\n  const ext = url.pathname.match(FileExtensionRegex)\n  const mime = extensionToMime(ext?.[1] ?? \"\") ?? props.meta?.mimeType ?? \"unknown\"\n\n  if (hideMedia) {\n    return (\n      <Reveal\n        message={\n          <FormattedMessage\n            defaultMessage=\"You don't follow this person, click here to load media from <i>{link}</i>, or update <a><i>your preferences</i></a> to always load media from everybody.\"\n            values={{\n              i: i => <i>{i}</i>,\n              a: a => <Link to=\"/settings/preferences\">{a}</Link>,\n              link: hostname,\n            }}\n          />\n        }\n      >\n        <MediaElement mime={mime} {...props} />\n      </Reveal>\n    )\n  } else {\n    return <MediaElement mime={mime} {...props} />\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Thread/Subthread.tsx",
    "content": "import { EventExt, type TaggedNostrEvent } from \"@snort/system\"\n\nimport Note from \"@/Components/Event/EventComponent\"\nimport { getReplies } from \"@/Components/Event/Thread/util\"\n\nexport interface SubthreadProps {\n  isLastSubthread?: boolean\n  active: string\n  notes: readonly TaggedNostrEvent[]\n  allNotes: readonly TaggedNostrEvent[]\n  chains: Map<string, Array<string>>\n  onNavigate: (e: TaggedNostrEvent) => void\n}\n\nexport const Subthread = ({ active, notes, allNotes, chains, onNavigate }: SubthreadProps) => {\n  const renderNote = (\n    note: TaggedNostrEvent,\n    idx: number,\n    siblings: readonly TaggedNostrEvent[],\n    depth: number,\n    parentContinues: boolean,\n  ): React.ReactNode => {\n    const noteKey = EventExt.keyOf(note)\n    const replies = getReplies(noteKey, allNotes, chains)\n    const hasReplies = replies.length > 0\n    const isLast = idx === siblings.length - 1\n\n    // Pass to children: only pass true if this note isn't last (has siblings after it)\n    const continuesAfterThisNote = !isLast\n\n    // Root level (depth 0): only show bottomLine to connect to nested replies\n    // Depth 1 (direct replies to root): show bottomLine if has replies OR not last\n    // Depth > 1 (nested replies): show bottomLine if has replies OR not last OR parent continues\n    const threadLines =\n      depth === 0\n        ? hasReplies\n          ? {\n              inset: \"left-9\",\n              topLine: false,\n              bottomLine: true,\n            }\n          : undefined\n        : {\n            inset: \"left-9\",\n            topLine: true,\n            bottomLine: hasReplies || !isLast || (depth > 1 && parentContinues),\n          }\n\n    return (\n      <>\n        <Note\n          highlight={active === noteKey}\n          inset={`ml-14`}\n          data={note}\n          key={noteKey}\n          onClick={onNavigate}\n          threadChains={chains}\n          waitUntilInView={idx > 5}\n          options={{\n            threadLines,\n          }}\n        />\n        {replies.map((reply, y) => renderNote(reply, y, replies, depth + 1, continuesAfterThisNote))}\n      </>\n    )\n  }\n\n  return <div>{notes.map((note, idx) => renderNote(note, idx, notes, 0, false))}</div>\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Thread/Thread.tsx",
    "content": "import { EventExt, type TaggedNostrEvent } from \"@snort/system\"\nimport { type ReactNode, useCallback, use, useMemo, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport BackButton from \"@/Components/Button/BackButton\"\nimport Note from \"@/Components/Event/EventComponent\"\nimport { ThreadContext, type ThreadContextState } from \"@/Utils/Thread\"\nimport Modal from \"@/Components/Modal/Modal\"\nimport JsonBlock from \"@/Components/json\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport { getReplies } from \"./util\"\nimport { Subthread } from \"./Subthread\"\nimport { WarningNotice } from \"@/Components/WarningNotice/WarningNotice\"\n\ninterface ThreadProps {\n  onBack?: () => void\n  disableSpotlight?: boolean\n}\n\nexport function ThreadElement(props: ThreadProps) {\n  const thread = use(ThreadContext)\n\n  if (!thread) {\n    return (\n      <WarningNotice>\n        <FormattedMessage defaultMessage=\"Not a thread!\" />\n      </WarningNotice>\n    )\n  }\n\n  return <ThreadInner {...props} thread={thread} />\n}\n\nfunction ThreadInner({ thread, ...props }: ThreadProps & { thread: ThreadContextState }) {\n  const navigate = useNavigate()\n\n  const rootOptions = useMemo(\n    () => ({ showReactionsLink: true, showMediaSpotlight: !props.disableSpotlight, isRoot: true }),\n    [props.disableSpotlight],\n  )\n\n  const navigateThread = useCallback(\n    (e: TaggedNostrEvent) => {\n      thread?.setCurrent(EventExt.keyOf(e))\n      // navigate(`/${NostrLink.fromEvent(e).encode()}`, { replace: true });\n    },\n    [thread],\n  )\n\n  function renderChain(from: string): ReactNode {\n    if (!from || thread.chains.size === 0) {\n      return\n    }\n    const replies = getReplies(from, thread.data, thread.chains)\n    if (replies.length > 0) {\n      return (\n        <Subthread\n          active={thread.current}\n          notes={replies}\n          allNotes={thread.data}\n          onNavigate={navigateThread}\n          chains={thread.chains}\n        />\n      )\n    }\n  }\n\n  function renderCurrent() {\n    if (thread.current) {\n      const note = thread.data.find(n => EventExt.keyOf(n) === thread.current)\n      if (note) {\n        return (\n          <Note\n            data={note}\n            options={{ showReactionsLink: true, showMediaSpotlight: true }}\n            threadChains={thread.chains}\n            onClick={navigateThread}\n            className=\"text-lg\"\n          />\n        )\n      } else {\n        return (\n          <div className=\"px-3 py-2 break-all\">\n            <FormattedMessage\n              defaultMessage=\"Loading note: {id}\"\n              values={{\n                id: <code className=\"font-mono bg-layer-1 px-1.5 py-0.5 rounded-lg\">{thread.current}</code>,\n              }}\n            />\n          </div>\n        )\n      }\n    }\n  }\n\n  function goBack() {\n    if (thread.parent) {\n      thread.setCurrent(EventExt.keyOf(thread.parent))\n    } else if (props.onBack) {\n      props.onBack()\n    } else {\n      navigate(-1)\n    }\n  }\n\n  return (\n    <>\n      {thread.parent && (\n        <div className=\"px-3 py-2\">\n          <BackButton\n            onClick={goBack}\n            text={<FormattedMessage defaultMessage=\"Parent\" description=\"Link to parent note in thread\" />}\n          />\n        </div>\n      )}\n      <div>\n        {thread.root && (\n          <>\n            <Note\n              className={\"text-lg\"}\n              key={EventExt.keyOf(thread.root)}\n              data={thread.root}\n              options={rootOptions}\n              onClick={navigateThread}\n              threadChains={thread.chains}\n              waitUntilInView={false}\n            />\n            {renderChain(EventExt.keyOf(thread.root))}\n          </>\n        )}\n        {!thread.root && renderCurrent()}\n        {thread.mutedData.length > 0 && (\n          <div className=\"layer-1 mx-2 my-3 font-medium cursor-pointer\">\n            <FormattedMessage\n              defaultMessage=\"{n} notes have been muted\"\n              values={{\n                n: thread.mutedData.length,\n              }}\n            />\n          </div>\n        )}\n        <ThreadDebug />\n      </div>\n    </>\n  )\n}\n\nfunction ThreadDebug() {\n  const thread = use(ThreadContext)\n  const [show, setShow] = useState(false)\n\n  if (!thread) return\n  if (!show)\n    return (\n      <div\n        onClick={() => setShow(true)}\n        className=\"flex items-center justify-center gap-2 text-neutral-500 cursor-pointer select-none leading-12 border\"\n      >\n        <Icon name=\"json\" size={16} />\n        <FormattedMessage defaultMessage=\"Show Thread Data\" />\n      </div>\n    )\n  return (\n    <Modal id=\"thread-dump\" onClose={() => setShow(false)}>\n      <JsonBlock\n        obj={{\n          ...thread,\n          chains: Object.fromEntries(thread.chains.entries().map(([k, v]) => [k, v])),\n        }}\n      />\n    </Modal>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Thread/ThreadRoute.tsx",
    "content": "import { NostrLink, parseNostrLink } from \"@snort/system\"\nimport { useParams } from \"react-router-dom\"\n\nimport { ThreadElement } from \"@/Components/Event/Thread/Thread\"\nimport { ThreadContextWrapper } from \"@/Utils/Thread/ThreadContextWrapper\"\nimport { NostrPrefix } from \"@snort/shared\"\n\nexport function ThreadRoute({ id }: { id?: string | NostrLink }) {\n  const params = useParams()\n  const link = id instanceof NostrLink ? id : parseNostrLink(id ?? params.id ?? \"\", NostrPrefix.Note)\n\n  return (\n    <ThreadContextWrapper link={link}>\n      <ThreadElement />\n    </ThreadContextWrapper>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Thread/util.ts",
    "content": "import { removeUndefined } from \"@snort/shared\"\nimport { EventExt, type TaggedNostrEvent } from \"@snort/system\"\n\nexport function getReplies(\n  from: string,\n  replies: ReadonlyArray<TaggedNostrEvent>,\n  chains?: Map<string, Array<string>>,\n): ReadonlyArray<TaggedNostrEvent> {\n  if (!from || !chains) {\n    return []\n  }\n  const replyIds = chains.get(from) ?? []\n  return removeUndefined(replyIds.map(r => replies.find(x => EventExt.keyOf(x) === r)))\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/Zap.tsx",
    "content": "import type { ParsedZap } from \"@snort/system\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport Text from \"@/Components/Text/Text\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { unwrap } from \"@/Utils\"\nimport { formatShort } from \"@/Utils/Number\"\n\nimport messages from \"../messages\"\n\nconst Zap = ({ zap, showZapped = true }: { zap: ParsedZap; showZapped?: boolean }) => {\n  const { amount, content, sender, valid, receiver } = zap\n  const pubKey = useLogin().publicKey\n\n  return valid && sender ? (\n    <div className=\"layer-1\">\n      <div className=\"flex justify-between\">\n        <ProfileImage pubkey={sender} showProfileCard={true} />\n        {receiver !== pubKey && showZapped && <ProfileImage pubkey={unwrap(receiver)} />}\n        <h3>\n          <FormattedMessage {...messages.Sats} values={{ n: formatShort(amount ?? 0) }} />\n        </h3>\n      </div>\n      {(content?.length ?? 0) > 0 && sender && (\n        <Text id={zap.id} creator={sender} content={unwrap(content)} tags={[]} />\n      )}\n    </div>\n  ) : null\n}\n\nexport default Zap\n"
  },
  {
    "path": "packages/app/src/Components/Event/ZapButton.tsx",
    "content": "import type { NostrLink } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport type { ZapTarget } from \"@snort/wallet\"\nimport { useState } from \"react\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport ZapModal from \"@/Components/ZapModal/ZapModal\"\n\nconst ZapButton = ({\n  pubkey,\n  lnurl,\n  children,\n  event,\n}: {\n  pubkey: string\n  lnurl?: string\n  children?: React.ReactNode\n  event?: NostrLink\n}) => {\n  const profile = useUserProfile(pubkey)\n  const [zap, setZap] = useState(false)\n  const service = lnurl ?? (profile?.lud16 || profile?.lud06)\n  if (!service) return null\n\n  return (\n    <>\n      <button type=\"button\" className=\"flex gap-2\" onClick={() => setZap(true)}>\n        <Icon name=\"zap-solid\" />\n        {children}\n      </button>\n      <ZapModal\n        targets={[\n          {\n            type: \"lnurl\",\n            value: service,\n            weight: 1,\n            name: profile?.display_name || profile?.name,\n            zap: { pubkey: pubkey, event },\n          } as ZapTarget,\n        ]}\n        show={zap}\n        onClose={() => setZap(false)}\n      />\n    </>\n  )\n}\n\nexport default ZapButton\n"
  },
  {
    "path": "packages/app/src/Components/Event/ZapGoal.tsx",
    "content": "import { type NostrEvent, NostrLink } from \"@snort/system\"\nimport { Zapper } from \"@snort/wallet\"\nimport { useState } from \"react\"\nimport { FormattedNumber } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport Progress from \"@/Components/Progress/Progress\"\nimport ZapModal from \"@/Components/ZapModal/ZapModal\"\nimport useZapsFeed from \"@/Feed/ZapsFeed\"\nimport { findTag } from \"@/Utils\"\nimport { formatShort } from \"@/Utils/Number\"\n\nexport function ZapGoal({ ev }: { ev: NostrEvent }) {\n  const [zap, setZap] = useState(false)\n  const zaps = useZapsFeed(NostrLink.fromEvent(ev))\n  const target = Number(findTag(ev, \"amount\"))\n  const amount = zaps.reduce((acc, v) => (acc += v.amount * 1000), 0)\n  const progress = amount / target\n\n  return (\n    <div className=\"layer-1\">\n      <div className=\"flex items-center justify-between\">\n        <h2 className=\"leading-[1em]\">{ev.content}</h2>\n        <div\n          className=\"text-[var(--bg-color)] bg-highlight px-2 py-1 rounded-lg cursor-pointer flex\"\n          onClick={() => setZap(true)}\n        >\n          <Icon name=\"zap\" size={15} />\n        </div>\n        <ZapModal targets={Zapper.fromEvent(ev)} show={zap} onClose={() => setZap(false)} />\n      </div>\n\n      <div className=\"flex justify-between\">\n        <div>\n          <FormattedNumber value={progress} style=\"percent\" />\n        </div>\n        <div>\n          {formatShort(amount / 1000)}/{formatShort(target / 1000)}\n        </div>\n      </div>\n      <Progress value={progress} />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Event/ZapsSummary.tsx",
    "content": "import type { ParsedZap } from \"@snort/system\"\nimport type React from \"react\"\nimport { useMemo } from \"react\"\n\nimport { AvatarGroup } from \"@/Components/User/AvatarGroup\"\nimport { dedupe } from \"@/Utils\"\n\ninterface ZapsSummaryProps {\n  zaps: ParsedZap[]\n  onClick: () => void\n}\nexport const ZapsSummary = ({ zaps, onClick }: ZapsSummaryProps) => {\n  const sortedZappers = useMemo(() => {\n    const pub = [...zaps.filter(z => z.sender && z.valid)]\n    const priv = [...zaps.filter(z => !z.sender && z.valid)]\n    pub.sort((a, b) => b.amount - a.amount)\n    return dedupe(pub.concat(priv).map(z => z.sender)).slice(0, 3)\n  }, [zaps]) as string[]\n\n  if (zaps.length === 0) {\n    return null\n  }\n\n  const myOnClick = (e: React.MouseEvent) => {\n    e.stopPropagation()\n    onClick()\n  }\n\n  return (\n    <div className=\"flex items-center cursor-pointer\" onClick={myOnClick}>\n      <AvatarGroup ids={sortedZappers} onClick={() => {}} showUsername={false} size={24} showFollowDistance={false} />\n      {zaps.length > 3 && <div className=\"hidden md:inline-flex\">+{zaps.length - 3}</div>}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Feed/ImageGridItem.tsx",
    "content": "import { EventKind, NostrLink, type TaggedNostrEvent } from \"@snort/system\"\nimport { memo, type MouseEvent, type ReactNode } from \"react\"\nimport { useInView } from \"react-intersection-observer\"\nimport { Link } from \"react-router-dom\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport { ProxyImg } from \"@/Components/ProxyImg\"\nimport getEventMedia from \"@/Utils/getEventMedia\"\n\ninterface ImageGridItemProps {\n  event: TaggedNostrEvent\n  onClick?: (event: MouseEvent) => void\n  waitUntilInView?: boolean\n}\n\nconst ImageGridItem = memo((props: ImageGridItemProps) => {\n  const { event, onClick, waitUntilInView } = props\n  const { ref, inView } = useInView({ triggerOnce: true, rootMargin: \"0px 0px 3000px 0px\" })\n\n  // skip reposts in image grid\n  if (event.kind === EventKind.Repost) return null\n\n  const media = getEventMedia(event)\n  if (media.length === 0) return null\n\n  const multiple = media.length > 1\n  const isVideo = media[0].mimeType?.startsWith(\"video/\")\n  const noteId = NostrLink.fromEvent(event).encode(CONFIG.eventLinkPrefix)\n\n  const myOnClick = (clickEvent: MouseEvent) => {\n    if (onClick && window.innerWidth >= 768) {\n      onClick(clickEvent)\n      clickEvent.preventDefault()\n    }\n  }\n\n  const renderContent = (): ReactNode | undefined => {\n    if (waitUntilInView && !inView) return undefined\n    return (\n      <>\n        <ProxyImg src={media[0].content} alt=\"Note Media\" size={311} className=\"w-full h-full object-cover\" />\n        <div className=\"absolute right-2 top-2 flex flex-col gap-2\">\n          {multiple && <Icon name=\"copy-solid\" className=\"text-white opacity-80 drop-shadow-md\" />}\n          {isVideo && <Icon name=\"play-square-outline\" className=\"text-white opacity-80 drop-shadow-md\" />}\n        </div>\n      </>\n    )\n  }\n\n  return (\n    <Link\n      to={`/${noteId}`}\n      className=\"aspect-square cursor-pointer hover:opacity-80 relative\"\n      onClick={myOnClick}\n      ref={ref}\n    >\n      {renderContent()}\n    </Link>\n  )\n})\n\nImageGridItem.displayName = \"ImageGridItem\"\n\nexport default ImageGridItem\n"
  },
  {
    "path": "packages/app/src/Components/Feed/LoadMore.tsx",
    "content": "import { useEffect, useState } from \"react\"\nimport { useInView } from \"react-intersection-observer\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport messages from \"../messages\"\n\nexport default function LoadMore({\n  onLoadMore,\n  shouldLoadMore,\n  children,\n}: {\n  onLoadMore: () => void\n  shouldLoadMore: boolean\n  children?: React.ReactNode\n}) {\n  const { ref, inView } = useInView({ rootMargin: \"2000px\" })\n  const [_tick, setTick] = useState<number>(0)\n\n  useEffect(() => {\n    if (inView === true && shouldLoadMore === true) {\n      onLoadMore()\n    }\n  }, [inView, shouldLoadMore, onLoadMore])\n\n  useEffect(() => {\n    const t = setInterval(() => {\n      setTick(x => (x += 1))\n    }, 500)\n    return () => clearInterval(t)\n  }, [])\n\n  return (\n    <div ref={ref} className=\"mb10\">\n      {children ?? <FormattedMessage {...messages.Loading} />}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Feed/RootTabItems.tsx",
    "content": "import type { ReactNode } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport type { RootTabRoutePath } from \"@/Pages/Root/RootTabRoutes\"\n\nexport function rootTabItems(base: string, pubKey: string | undefined, tags: Array<string>) {\n  const menuItems = [\n    {\n      tab: \"for-you\",\n      path: `${base}/for-you`,\n      show: Boolean(pubKey),\n      element: (\n        <>\n          <Icon name=\"user-v2\" />\n          <FormattedMessage defaultMessage=\"For you\" />\n        </>\n      ),\n    },\n    {\n      tab: \"following\",\n      path: `${base}/following`,\n      show: Boolean(pubKey),\n      element: (\n        <>\n          <Icon name=\"user-v2\" />\n          <FormattedMessage defaultMessage=\"Following\" />\n        </>\n      ),\n    },\n    {\n      tab: \"trending/notes\",\n      path: `${base}/trending/notes`,\n      show: true,\n      element: (\n        <>\n          <Icon name=\"fire\" />\n          <FormattedMessage defaultMessage=\"Trending Notes\" />\n        </>\n      ),\n    },\n    {\n      tab: \"conversations\",\n      path: `${base}/conversations`,\n      show: Boolean(pubKey),\n      element: (\n        <>\n          <Icon name=\"message-chat-circle\" />\n          <FormattedMessage defaultMessage=\"Conversations\" />\n        </>\n      ),\n    },\n    {\n      tab: \"followed-by-friends\",\n      path: `${base}/followed-by-friends`,\n      show: Boolean(pubKey),\n      element: (\n        <>\n          <Icon name=\"user-v2\" />\n          <FormattedMessage defaultMessage=\"Followed by friends\" />\n        </>\n      ),\n    },\n    {\n      tab: \"trending/hashtags\",\n      path: `${base}/trending/hashtags`,\n      show: true,\n      element: (\n        <>\n          <Icon name=\"hash\" />\n          <FormattedMessage defaultMessage=\"Trending Hashtags\" />\n        </>\n      ),\n    },\n    {\n      tab: \"tags\",\n      path: `${base}/topics`,\n      show: tags.length > 0,\n      element: (\n        <>\n          <Icon name=\"hash\" />\n          <FormattedMessage defaultMessage=\"Topics\" />\n        </>\n      ),\n    },\n    {\n      tab: \"media\",\n      path: `${base}/media`,\n      show: true,\n      element: (\n        <>\n          <Icon name=\"camera-plus\" />\n          <FormattedMessage defaultMessage=\"Media\" />\n        </>\n      ),\n    },\n    {\n      tab: \"follow-sets\",\n      path: `${base}/follow-sets`,\n      show: true,\n      element: (\n        <>\n          <Icon name=\"thumbs-up\" />\n          <FormattedMessage defaultMessage=\"Follow Sets\" />\n        </>\n      ),\n    },\n  ] as Array<{\n    tab: RootTabRoutePath\n    path: string\n    show: boolean\n    element: ReactNode\n  }>\n  return menuItems\n}\n"
  },
  {
    "path": "packages/app/src/Components/Feed/RootTabs.tsx",
    "content": "import { unwrap } from \"@snort/shared\"\nimport { EventKind } from \"@snort/system\"\nimport * as DropdownMenu from \"@radix-ui/react-dropdown-menu\"\nimport { useEffect, useMemo, useState } from \"react\"\nimport { useLocation, useNavigate } from \"react-router-dom\"\n\nimport { rootTabItems } from \"@/Components/Feed/RootTabItems\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport type { RootTabRoutePath } from \"@/Pages/Root/RootTabRoutes\"\n\nexport function RootTabs({ base = \"/\" }: { base: string }) {\n  const navigate = useNavigate()\n  const location = useLocation()\n  const { publicKey: pubKey, tags } = useLogin(s => ({\n    publicKey: s.publicKey,\n    tags: s.state.getList(EventKind.InterestSet),\n  }))\n  const defaultRootTab = usePreferences(s => s.defaultRootTab)\n\n  const hashTags = tags.filter(a => a.toEventTag()?.[0] === \"t\").map(a => unwrap(a.toEventTag())[1])\n  const menuItems = useMemo(() => rootTabItems(base, pubKey, hashTags), [base, pubKey, hashTags])\n\n  let defaultTab: RootTabRoutePath\n  if (pubKey) {\n    defaultTab = defaultRootTab\n  } else {\n    defaultTab = `trending/notes`\n  }\n  const initialPathname = location.pathname === \"/\" ? defaultTab : location.pathname\n  const initialRootType = menuItems.find(a => a.path === initialPathname)?.tab || defaultTab\n\n  const [rootType, setRootType] = useState<RootTabRoutePath>(initialRootType)\n\n  useEffect(() => {\n    const currentTab = menuItems.find(a => a.path === location.pathname)?.tab\n    if (currentTab && currentTab !== rootType) {\n      setRootType(currentTab)\n    }\n  }, [location.pathname, menuItems, rootType])\n\n  function currentMenuItem() {\n    if (location.pathname.startsWith(`${base}/t/`)) {\n      return (\n        <>\n          <Icon name=\"hash\" />\n          {location.pathname.split(\"/\").slice(-1)}\n        </>\n      )\n    }\n    return menuItems.find(a => a.tab === rootType)?.element ?? menuItems[0].element\n  }\n\n  const itemClassName =\n    \"px-6 py-2 text-base font-semibold bg-layer-2 light:bg-white hover:bg-layer-3 light:hover:bg-neutral-200 cursor-pointer outline-none flex gap-3 items-center\"\n\n  return (\n    <div className=\"root-type flex items-center justify-center flex-grow\">\n      <DropdownMenu.Root>\n        <DropdownMenu.Trigger asChild>\n          <button\n            type=\"button\"\n            className=\"bg-transparent text-font-color text-base px-4 py-2.5 flex items-center justify-center gap-3 border-none shadow-none hover:!shadow-none\"\n          >\n            {currentMenuItem()}\n            <Icon name=\"chevronDown\" />\n          </button>\n        </DropdownMenu.Trigger>\n        <DropdownMenu.Portal>\n          <DropdownMenu.Content\n            className=\"bg-layer-2 rounded-lg overflow-hidden z-[9999] min-w-48\"\n            sideOffset={5}\n            align=\"center\"\n          >\n            {menuItems\n              .filter(a => a.show)\n              .map(a => (\n                <DropdownMenu.Item\n                  key={a.tab}\n                  className={itemClassName}\n                  onClick={e => {\n                    e.stopPropagation()\n                    navigate(a.path)\n                    window.scrollTo({ top: 0, behavior: \"instant\" })\n                  }}\n                >\n                  {a.element}\n                </DropdownMenu.Item>\n              ))}\n          </DropdownMenu.Content>\n        </DropdownMenu.Portal>\n      </DropdownMenu.Root>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Feed/Timeline.tsx",
    "content": "import { unixNow } from \"@snort/shared\"\nimport type { TaggedNostrEvent } from \"@snort/system\"\nimport { useCallback, useMemo } from \"react\"\n\nimport { TimelineRenderer } from \"@/Components/Feed/TimelineRenderer\"\nimport useTimelineFeed, { type TimelineFeed, type TimelineSubject } from \"@/Feed/TimelineFeed\"\nimport useHistoryState from \"@/Hooks/useHistoryState\"\nimport useWoT from \"@/Hooks/useWoT\"\nimport { dedupeByPubkey } from \"@/Utils\"\n\nexport interface TimelineProps {\n  postsOnly: boolean\n  subject: TimelineSubject\n  method: \"TIME_RANGE\" | \"LIMIT_UNTIL\"\n  followDistance?: number\n  ignoreModeration?: boolean\n  window?: number\n  now?: number\n  noSort?: boolean\n}\n\n/**\n * A list of notes by \"subject\"\n */\nconst Timeline = (props: TimelineProps) => {\n  const [openedAt] = useHistoryState(unixNow(), \"openedAt\")\n  const feedOptions = useMemo(\n    () => ({\n      method: props.method,\n      window: props.window,\n      now: props.now ?? openedAt,\n    }),\n    [props.method, props.window, props.now, openedAt],\n  )\n  const feed: TimelineFeed = useTimelineFeed(props.subject, feedOptions)\n  const wot = useWoT()\n\n  const filterPosts = useCallback(\n    (nts: readonly TaggedNostrEvent[]) => {\n      const checkFollowDistance = (a: TaggedNostrEvent) => {\n        if (props.followDistance === undefined) {\n          return true\n        }\n        const followDistance = wot.followDistance(a.pubkey)\n        return followDistance === props.followDistance\n      }\n      return nts\n        ?.filter(a => (props.postsOnly ? !a.tags.some(b => b[0] === \"e\") : true))\n        .filter(a => props.ignoreModeration || checkFollowDistance(a))\n    },\n    [props.postsOnly, props.ignoreModeration, props.followDistance, wot],\n  )\n\n  const mainFeed = useMemo(() => {\n    return filterPosts(feed.main ?? [])\n  }, [feed.main, filterPosts])\n  const latestFeed = useMemo(() => {\n    return filterPosts(feed.latest ?? []).filter(a => !mainFeed.some(b => b.id === a.id))\n  }, [feed.latest, mainFeed, filterPosts])\n\n  const latestAuthors = useMemo(() => {\n    return dedupeByPubkey(latestFeed).map(e => e.pubkey)\n  }, [latestFeed])\n\n  function onShowLatest(scrollToTop = false) {\n    feed.showLatest()\n    if (scrollToTop) {\n      window.scrollTo(0, 0)\n    }\n  }\n\n  return (\n    <TimelineRenderer\n      frags={[\n        {\n          events: mainFeed,\n          refTime: 0,\n        },\n      ]}\n      latest={latestAuthors}\n      showLatest={t => onShowLatest(t)}\n      loadMore={() => feed.loadMore()}\n      highlightText={props.subject.type === \"post_keyword\" ? props.subject.items[0] : undefined}\n    />\n  )\n}\nexport default Timeline\n"
  },
  {
    "path": "packages/app/src/Components/Feed/TimelineChunk.tsx",
    "content": "import { type NostrEvent, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { type ReactNode, useMemo } from \"react\"\n\nimport type { WindowChunk } from \"@/Hooks/useTimelineChunks\"\nimport { TimelineRenderer } from \"./TimelineRenderer\"\n\nexport interface TimelineChunkProps {\n  id: string\n  chunk: WindowChunk\n  builder: (rb: RequestBuilder) => void\n  noteFilter?: (ev: NostrEvent) => boolean\n  noteRenderer?: (ev: NostrEvent) => ReactNode\n  noteOnClick?: (ev: NostrEvent) => void\n}\n\n/**\n * Simple chunk of a timeline using absoliute time ranges\n */\nexport default function TimelineChunk(props: TimelineChunkProps) {\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(`timeline-chunk:${props.id}:${props.chunk.since}-${props.chunk.until}`)\n    props.builder(rb)\n    for (const f of rb.filterBuilders) {\n      f.since(props.chunk.since).until(props.chunk.until)\n    }\n    return rb\n  }, [props.id, props.chunk.until, props.builder, props.chunk.since])\n\n  const feed = useRequestBuilder(sub)\n\n  return (\n    <TimelineRenderer\n      frags={{\n        events: feed.filter(a => props.noteFilter?.(a) ?? true),\n        refTime: props.chunk.until,\n      }}\n      noteOnClick={props.noteOnClick}\n      noteRenderer={props.noteRenderer}\n      latest={[]}\n      showLatest={() => {}}\n    />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Feed/TimelineFollows.tsx",
    "content": "import { unixNow } from \"@snort/shared\"\nimport { EventKind, type NostrEvent, type RequestBuilder } from \"@snort/system\"\nimport { type ReactNode, useCallback } from \"react\"\n\nimport useFollowsControls from \"@/Hooks/useFollowControls\"\nimport useHistoryState from \"@/Hooks/useHistoryState\"\nimport useTimelineChunks from \"@/Hooks/useTimelineChunks\"\nimport { Hour } from \"@/Utils/Const\"\n\nimport { AutoLoadMore } from \"../Event/LoadMore\"\nimport TimelineChunk from \"./TimelineChunk\"\n\nexport interface TimelineFollowsProps {\n  id?: string\n  postsOnly: boolean\n  noteFilter?: (ev: NostrEvent) => boolean\n  noteRenderer?: (ev: NostrEvent) => ReactNode\n  noteOnClick?: (ev: NostrEvent) => void\n  kinds?: Array<EventKind>\n  firstChunkSize?: number\n  windowSize?: number\n}\n\n/**\n * A list of notes by your follows\n */\nconst TimelineFollows = (props: TimelineFollowsProps) => {\n  const [openedAt] = useHistoryState(unixNow(), \"openedAt\")\n  const { isFollowing, followList } = useFollowsControls()\n  const { chunks, showMore } = useTimelineChunks({\n    now: openedAt,\n    window: props.windowSize,\n    firstChunkSize: props.firstChunkSize ?? Hour * 2,\n  })\n\n  const builder = useCallback(\n    (rb: RequestBuilder) => {\n      rb.withFilter()\n        .authors(followList)\n        .kinds(props.kinds ?? [EventKind.TextNote, EventKind.Repost, EventKind.Polls])\n    },\n    [followList, props.kinds],\n  )\n\n  const filterEvents = useCallback(\n    (a: NostrEvent) =>\n      (props.noteFilter?.(a) ?? true) &&\n      (props.postsOnly ? !a.tags.some(b => b[0] === \"e\" || b[0] === \"a\") : true) &&\n      (isFollowing(a.pubkey) || a.tags.filter(a => a[0] === \"t\").length < 5),\n    [props.noteFilter, props.postsOnly, isFollowing],\n  )\n\n  return (\n    <>\n      {chunks.map(c => (\n        <TimelineChunk\n          key={c.until}\n          id={`follows${props.id ? `:${props.id}` : \"\"}`}\n          chunk={c}\n          builder={builder}\n          noteFilter={filterEvents}\n          noteOnClick={props.noteOnClick}\n          noteRenderer={props.noteRenderer}\n        />\n      ))}\n      <AutoLoadMore onClick={() => showMore()} />\n    </>\n  )\n}\n\nexport default TimelineFollows\n"
  },
  {
    "path": "packages/app/src/Components/Feed/TimelineFragment.tsx",
    "content": "import type { TaggedNostrEvent } from \"@snort/system\"\nimport type { ReactNode } from \"react\"\n\nimport Note from \"@/Components/Event/EventComponent\"\n\nexport interface TimelineFragment {\n  events: Array<TaggedNostrEvent>\n  refTime: number\n  title?: ReactNode\n}\n\nexport interface TimelineFragProps {\n  frag: TimelineFragment\n  noteRenderer?: (ev: TaggedNostrEvent) => ReactNode\n  noteOnClick?: (ev: TaggedNostrEvent) => void\n  noteContext?: (ev: TaggedNostrEvent) => ReactNode\n  highlightText?: string\n}\n\nconst options = {\n  truncate: true,\n}\n\nexport function TimelineFragment(props: TimelineFragProps) {\n  return (\n    <>\n      {props.frag.title}\n      {props.frag.events.map(\n        (e, index) =>\n          props.noteRenderer?.(e) ?? (\n            <Note\n              data={e}\n              key={e.id}\n              depth={0}\n              onClick={props.noteOnClick}\n              context={props.noteContext?.(e)}\n              options={options}\n              waitUntilInView={index > 5}\n              highlightText={props.highlightText}\n            />\n          ),\n      )}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Feed/TimelineRenderer.tsx",
    "content": "import type { TaggedNostrEvent } from \"@snort/system\"\nimport { type ReactNode, useEffect, useRef } from \"react\"\nimport { useInView } from \"react-intersection-observer\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport ErrorBoundary from \"@/Components/ErrorBoundary\"\nimport { AutoLoadMore } from \"@/Components/Event/LoadMore\"\nimport { TimelineFragment } from \"@/Components/Feed/TimelineFragment\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport { AvatarGroup } from \"../User/AvatarGroup\"\nimport useWoT from \"@/Hooks/useWoT\"\n\nexport interface TimelineRendererProps {\n  frags: Array<TimelineFragment> | TimelineFragment\n  /**\n   * List of pubkeys who have posted recently\n   */\n  latest: Array<string>\n  showLatest: (toTop: boolean) => void\n  noteRenderer?: (ev: TaggedNostrEvent) => ReactNode\n  noteOnClick?: (ev: TaggedNostrEvent) => void\n  noteContext?: (ev: TaggedNostrEvent) => ReactNode\n  loadMore?: () => void\n  highlightText?: string\n}\n\nexport function TimelineRenderer(props: TimelineRendererProps) {\n  const containerRef = useRef<HTMLDivElement | null>(null)\n  const latestNotesFixedRef = useRef<HTMLDivElement | null>(null)\n  const { ref, inView } = useInView()\n  const wot = useWoT()\n\n  const updateLatestNotesPosition = () => {\n    if (containerRef.current && latestNotesFixedRef.current) {\n      const parentRect = containerRef.current.getBoundingClientRect()\n      const childWidth = latestNotesFixedRef.current.offsetWidth\n\n      const leftPosition = parentRect.left + (parentRect.width - childWidth) / 2\n      latestNotesFixedRef.current.style.left = `${leftPosition}px`\n    }\n  }\n\n  useEffect(() => {\n    updateLatestNotesPosition()\n    window.addEventListener(\"resize\", updateLatestNotesPosition)\n\n    return () => {\n      window.removeEventListener(\"resize\", updateLatestNotesPosition)\n    }\n  }, [updateLatestNotesPosition])\n\n  const renderNotes = () => {\n    const frags = Array.isArray(props.frags) ? props.frags : [props.frags]\n    return frags.map((frag, index) => (\n      <ErrorBoundary key={frag.events[0]?.id + index}>\n        <TimelineFragment\n          frag={frag}\n          noteRenderer={props.noteRenderer}\n          noteOnClick={props.noteOnClick}\n          noteContext={props.noteContext}\n          highlightText={props.highlightText}\n        />\n      </ErrorBoundary>\n    ))\n  }\n\n  function latestInner() {\n    return (\n      <div className=\"cursor-pointer flex flex-row justify-center items-center py-1.5 px-6 gap-2 text-white bg-highlight rounded-full\">\n        <div className=\"flex\">\n          <AvatarGroup ids={wot.sortPubkeys(props.latest).slice(0, 3)} />\n        </div>\n        <FormattedMessage\n          defaultMessage=\"{n} new {n, plural, =1 {note} other {notes}}\"\n          id=\"3t3kok\"\n          values={{ n: props.latest.length }}\n        />\n        <Icon name=\"arrowUp\" />\n      </div>\n    )\n  }\n\n  return (\n    <div ref={containerRef}>\n      {props.latest.length > 0 && (\n        <>\n          <div className=\"flex justify-center\" onClick={() => props.showLatest(false)} ref={ref}>\n            {latestInner()}\n          </div>\n          {!inView && (\n            <div\n              ref={latestNotesFixedRef}\n              className=\"fixed top-[50px] z-3 opacity-90 shadow-md animate-fade-in\"\n              onClick={() => props.showLatest(true)}\n            >\n              {latestInner()}\n            </div>\n          )}\n        </>\n      )}\n      {renderNotes()}\n      {props.loadMore && <AutoLoadMore className=\"mx-3 my-4\" onClick={props.loadMore} />}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Feed/UsersFeed.tsx",
    "content": "import type { TaggedNostrEvent } from \"@snort/system\"\nimport { useCallback, useMemo } from \"react\"\n\nimport PageSpinner from \"@/Components/PageSpinner\"\nimport FollowListBase from \"@/Components/User/FollowListBase\"\nimport useTimelineFeed, { type TimelineFeed } from \"@/Feed/TimelineFeed\"\nimport useModeration from \"@/Hooks/useModeration\"\n\nexport default function UsersFeed({ keyword, sortPopular = true }: { keyword: string; sortPopular?: boolean }) {\n  const feed: TimelineFeed = useTimelineFeed(\n    {\n      type: \"profile_keyword\",\n      items: [keyword + (sortPopular ? \" sort:popular\" : \"\")],\n      discriminator: keyword,\n    },\n    { method: \"LIMIT_UNTIL\" },\n  )\n\n  const { isEventMuted } = useModeration()\n  const filterPosts = useCallback(\n    (nts: readonly TaggedNostrEvent[]) => {\n      return nts.filter(a => !isEventMuted(a))\n    },\n    [isEventMuted],\n  )\n  const usersFeed = useMemo(() => filterPosts(feed.main ?? []).map(p => p.pubkey), [feed, filterPosts])\n\n  if (!usersFeed) return <PageSpinner />\n\n  return (\n    <FollowListBase\n      pubkeys={usersFeed}\n      profilePreviewProps={{\n        options: {\n          about: true,\n        },\n      }}\n    />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Icons/Alby.tsx",
    "content": "export default function AlbyIcon(props: { size?: number }) {\n  return (\n    <svg width={props.size ?? 400} height={props.size ?? 578} viewBox=\"0 0 400 578\" fill=\"none\">\n      <path\n        opacity=\"0.1\"\n        d=\"M201.283 577.511C255.405 577.511 299.281 569.411 299.281 559.419C299.281 549.427 255.405 541.327 201.283 541.327C147.16 541.327 103.285 549.427 103.285 559.419C103.285 569.411 147.16 577.511 201.283 577.511Z\"\n        fill=\"black\"\n      />\n      <path\n        d=\"M295.75 471.344C346.377 471.344 369.42 359.242 369.42 316.736C369.42 283.606 346.56 263.528 316.507 263.528C286.641 263.528 262.394 276.371 262.093 292.275C262.092 334.246 254.705 471.344 295.75 471.344Z\"\n        fill=\"white\"\n        stroke=\"black\"\n        strokeWidth=\"15.0766\"\n      />\n      <path\n        d=\"M110.837 471.344C60.2098 471.344 37.1665 359.242 37.1665 316.736C37.1665 283.606 60.0269 263.528 90.0803 263.528C119.946 263.528 144.193 276.371 144.494 292.275C144.495 334.246 151.882 471.344 110.837 471.344Z\"\n        fill=\"white\"\n        stroke=\"black\"\n        strokeWidth=\"15.0766\"\n      />\n      <path\n        d=\"M68.8309 303.262L68.8307 303.26C68.7764 302.741 68.8817 302.44 68.9894 302.244C69.1165 302.012 69.3578 301.736 69.7632 301.506C70.6022 301.029 71.7772 300.943 72.8713 301.582C110.474 323.624 153.847 336.26 201.001 336.26C248.164 336.26 292.34 323.379 330.185 300.953C331.272 300.308 332.445 300.388 333.287 300.862C333.694 301.091 333.937 301.366 334.066 301.599C334.175 301.796 334.282 302.098 334.229 302.618C328.375 360.632 296.907 408.595 254.611 430.672C240.642 437.965 231.035 450.634 222.598 461.761C222.447 461.961 222.296 462.16 222.146 462.358L222.144 462.36C215.287 471.406 209.081 479.507 201.496 485.476C193.912 479.507 187.705 471.406 180.848 462.36L180.847 462.358C180.697 462.16 180.546 461.961 180.395 461.761C171.958 450.634 162.352 437.965 148.382 430.672C106.247 408.68 74.8589 360.995 68.8309 303.262Z\"\n        fill=\"#FFDF6F\"\n        stroke=\"black\"\n        strokeWidth=\"15\"\n      />\n      <path\n        d=\"M201.786 346.338C275.06 346.338 334.46 326.538 334.46 302.113C334.46 277.688 275.06 257.888 201.786 257.888C128.512 257.888 69.1118 277.688 69.1118 302.113C69.1118 326.538 128.512 346.338 201.786 346.338Z\"\n        fill=\"black\"\n        stroke=\"black\"\n        strokeWidth=\"15.0766\"\n      />\n      <path\n        d=\"M95.2446 376.491C95.2446 376.491 160.685 398.603 202.791 398.603C244.896 398.603 310.337 376.491 310.337 376.491\"\n        stroke=\"black\"\n        strokeWidth=\"15.0766\"\n        strokeLinecap=\"round\"\n      />\n      <path\n        d=\"M77 143C60.4315 143 47 129.569 47 113C47 96.4315 60.4315 83 77 83C93.5685 83 107 96.4315 107 113C107 129.569 93.5685 143 77 143Z\"\n        fill=\"black\"\n      />\n      <path d=\"M72 108.5L128 164.5\" stroke=\"black\" strokeWidth=\"15\" />\n      <path\n        d=\"M322 143C338.569 143 352 129.569 352 113C352 96.4315 338.569 83 322 83C305.431 83 292 96.4315 292 113C292 129.569 305.431 143 322 143Z\"\n        fill=\"black\"\n      />\n      <path d=\"M327.5 108.5L271.5 164.5\" stroke=\"black\" strokeWidth=\"15\" />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M85.5155 292.019C69.3466 284.321 59.9364 267.036 63.0886 249.407C76.6177 173.747 133 117 200.5 117C268.163 117 324.655 174.023 338.009 249.958C341.115 267.618 331.628 284.895 315.404 292.53C280.687 308.868 241.91 318 201 318C159.665 318 120.507 308.677 85.5155 292.019Z\"\n        fill=\"#FFDF6F\"\n      />\n      <path\n        d=\"M70.4715 250.728C83.5443 177.62 137.582 124.5 200.5 124.5V109.5C128.418 109.5 69.6912 169.875 55.7057 248.087L70.4715 250.728ZM200.5 124.5C263.569 124.5 317.718 177.879 330.622 251.257L345.396 248.659C331.592 170.166 272.758 109.5 200.5 109.5V124.5ZM312.21 285.744C278.472 301.621 240.783 310.5 201 310.5V325.5C243.037 325.5 282.902 316.114 318.597 299.317L312.21 285.744ZM201 310.5C160.804 310.5 122.745 301.436 88.7393 285.247L82.2918 298.791C118.269 315.918 158.526 325.5 201 325.5V310.5ZM330.622 251.257C333.112 265.416 325.531 279.476 312.21 285.744L318.597 299.317C337.725 290.315 349.117 269.82 345.396 248.659L330.622 251.257ZM55.7057 248.087C51.9285 269.211 63.2298 289.716 82.2918 298.791L88.7393 285.247C75.4633 278.927 67.9443 264.86 70.4715 250.728L55.7057 248.087Z\"\n        fill=\"black\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M114.365 273.209C101.35 267.908 93.6293 254.06 98.1392 240.75C112.047 199.704 152.618 170 200.5 170C248.382 170 288.953 199.704 302.861 240.75C307.371 254.06 299.65 267.908 286.635 273.209C260.053 284.035 230.973 290 200.5 290C170.027 290 140.947 284.035 114.365 273.209Z\"\n        fill=\"black\"\n      />\n      <path\n        d=\"M235 254C248.807 254 260 245.046 260 234C260 222.954 248.807 214 235 214C221.193 214 210 222.954 210 234C210 245.046 221.193 254 235 254Z\"\n        fill=\"white\"\n      />\n      <path\n        d=\"M163.432 254.012C177.239 254.012 188.432 245.058 188.432 234.012C188.432 222.966 177.239 214.012 163.432 214.012C149.625 214.012 138.432 222.966 138.432 234.012C138.432 245.058 149.625 254.012 163.432 254.012Z\"\n        fill=\"white\"\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Icons/BlueWallet.tsx",
    "content": "export const BlueWallet = (props: { width?: number; height?: number }) => {\n  return (\n    <svg viewBox=\"0 0 58 58\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" {...props}>\n      <title>logo-bluewallet</title>\n      <defs>\n        <filter x=\"-14.0%\" y=\"-13.8%\" width=\"128.1%\" height=\"127.6%\" filterUnits=\"objectBoundingBox\" id=\"filter-1\">\n          <feOffset dx=\"0\" dy=\"2\" in=\"SourceAlpha\" result=\"shadowOffsetOuter1\"></feOffset>\n          <feGaussianBlur stdDeviation=\"1\" in=\"shadowOffsetOuter1\" result=\"shadowBlurOuter1\"></feGaussianBlur>\n          <feColorMatrix\n            values=\"0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.137729458 0\"\n            type=\"matrix\"\n            in=\"shadowBlurOuter1\"\n            result=\"shadowMatrixOuter1\"\n          ></feColorMatrix>\n          <feMerge>\n            <feMergeNode in=\"shadowMatrixOuter1\"></feMergeNode>\n            <feMergeNode in=\"SourceGraphic\"></feMergeNode>\n          </feMerge>\n        </filter>\n        <linearGradient x1=\"50%\" y1=\"2.83824061%\" x2=\"50%\" y2=\"100%\" id=\"linearGradient-2\">\n          <stop stopColor=\"#174697\" offset=\"0%\"></stop>\n          <stop stopColor=\"#0C2550\" offset=\"100%\"></stop>\n        </linearGradient>\n        <linearGradient x1=\"50%\" y1=\"0%\" x2=\"50%\" y2=\"97.8843027%\" id=\"linearGradient-3\">\n          <stop stopColor=\"#3F78DC\" offset=\"0%\"></stop>\n          <stop stopColor=\"#2F5FB3\" offset=\"100%\"></stop>\n        </linearGradient>\n        <linearGradient x1=\"50%\" y1=\"2.72534321%\" x2=\"50%\" y2=\"100%\" id=\"linearGradient-4\">\n          <stop stopColor=\"#8BD7F9\" offset=\"0%\"></stop>\n          <stop stopColor=\"#68BBE1\" offset=\"100%\"></stop>\n        </linearGradient>\n      </defs>\n      <g id=\"bluewallet\" stroke=\"none\" strokeWidth=\"1\" fill=\"none\" fillRule=\"evenodd\">\n        <g id=\"bluewallet-site-copy-2\">\n          <g id=\"logo-bluewallet\">\n            <g id=\"Group-Copy\" filter=\"url(#filter-1)\">\n              <path\n                d=\"M16.6652538,-1.58013034e-15 L39.9523933,-2.33537939e-16 C45.7472651,1.35692268e-16 47.8486256,0.603366472 49.9671441,1.73636257 C52.0856627,2.86935868 53.7482884,4.53198441 54.8812845,6.65050293 C56.0142806,8.76902145 56.6176471,10.870382 56.6176471,16.6652538 L56.6176471,39.9523933 C56.6176471,45.7472651 56.0142806,47.8486256 54.8812845,49.9671441 C53.7482884,52.0856627 52.0856627,53.7482884 49.9671441,54.8812845 C47.8486256,56.0142806 45.7472651,56.6176471 39.9523933,56.6176471 L16.6652538,56.6176471 C10.870382,56.6176471 8.76902145,56.0142806 6.65050293,54.8812845 C4.53198441,53.7482884 2.86935868,52.0856627 1.73636257,49.9671441 C0.603366472,47.8486256 2.60802988e-16,45.7472651 -4.48864133e-16,39.9523933 L-4.57970006e-16,16.6652538 C2.66093762e-16,10.870382 0.603366472,8.76902145 1.73636257,6.65050293 C2.86935868,4.53198441 4.53198441,2.86935868 6.65050293,1.73636257 C8.76902145,0.603366472 10.870382,9.18101232e-16 16.6652538,-1.58013034e-15 Z\"\n                id=\"Rectangle-Copy\"\n                fill=\"url(#linearGradient-2)\"\n              ></path>\n              <path\n                d=\"M16.6652538,13.2352941 L39.9523933,13.2352941 C45.7472651,13.2352941 47.8486256,13.8386606 49.9671441,14.9716567 C52.0856627,16.1046528 53.7482884,17.7672785 54.8812845,19.885797 C56.0142806,22.0043156 56.6176471,24.1056761 56.6176471,29.9005479 L56.6176471,39.2170991 C56.6176471,45.011971 56.0142806,47.1133315 54.8812845,49.23185 C53.7482884,51.3503685 52.0856627,53.0129943 49.9671441,54.1459904 C47.8486256,55.2789865 45.7472651,55.8823529 39.9523933,55.8823529 L16.6652538,55.8823529 C10.870382,55.8823529 8.76902145,55.2789865 6.65050293,54.1459904 C4.53198441,53.0129943 2.86935868,51.3503685 1.73636257,49.23185 C0.603366472,47.1133315 2.60802988e-16,45.011971 -4.48864133e-16,39.2170991 L-1.36480415e-15,29.9005479 C7.92990512e-16,24.1056761 0.603366472,22.0043156 1.73636257,19.885797 C2.86935868,17.7672785 4.53198441,16.1046528 6.65050293,14.9716567 C8.76902145,13.8386606 10.870382,13.2352941 16.6652538,13.2352941 Z\"\n                id=\"Rectangle-Copy-2\"\n                fill=\"url(#linearGradient-3)\"\n              ></path>\n              <path\n                d=\"M13.2492834,27.2058824 L43.3683637,27.2058824 C47.2492145,27.2058824 49.1977058,27.7164232 50.9902984,28.6751122 C52.782891,29.6338012 54.1897282,31.0406384 55.1484172,32.833231 C56.1071062,34.6258236 56.6176471,36.5743149 56.6176471,40.4551657 L56.6176471,44.1036578 C56.6176471,47.9845086 56.1071062,49.933 55.1484172,51.7255925 C54.1897282,53.5181851 52.782891,54.9250223 50.9902984,55.8837113 C49.1977058,56.8424003 47.2492145,57.3529412 43.3683637,57.3529412 L13.2492834,57.3529412 C9.36843258,57.3529412 7.41994122,56.8424003 5.62734863,55.8837113 C3.83475604,54.9250223 2.42791888,53.5181851 1.46922987,51.7255925 C0.510540861,49.933 -2.77257755e-16,47.9845086 3.82228307e-16,44.1036578 L2.75457766e-16,40.4551657 C-1.99809382e-16,36.5743149 0.510540861,34.6258236 1.46922987,32.833231 C2.42791888,31.0406384 3.83475604,29.6338012 5.62734863,28.6751122 C7.41994122,27.7164232 9.36843258,27.2058824 13.2492834,27.2058824 Z\"\n                id=\"Rectangle-Copy-3\"\n                fill=\"url(#linearGradient-4)\"\n              ></path>\n              <path\n                d=\"M30.8453034,44.2612592 C30.8453034,44.8309235 30.7830721,45.343135 30.6586077,45.797909 C30.5341432,46.252683 30.3546298,46.6404319 30.1200622,46.9611673 C29.8854945,47.2819026 29.5970764,47.5284343 29.2547991,47.7007698 C28.9125218,47.8731052 28.5235761,47.9592716 28.0879505,47.9592716 C27.8725312,47.9592716 27.6714762,47.9389268 27.4847795,47.8982364 C27.2980828,47.8575461 27.1197662,47.7917246 26.9498243,47.7007698 C26.7798825,47.609815 26.6123367,47.4949264 26.4471819,47.3561006 C26.2820271,47.2172749 26.1132845,47.0497291 25.9409491,46.8534582 L25.9409491,47.549977 C25.9409491,47.6026351 25.9277848,47.646915 25.9014558,47.6828182 C25.8751268,47.7187215 25.8320435,47.7486404 25.7722049,47.7725758 C25.7123662,47.7965113 25.6321835,47.8132659 25.5316545,47.8228401 C25.4311255,47.8324143 25.3090564,47.8372013 25.1654436,47.8372013 C25.0170437,47.8372013 24.8937778,47.8324143 24.7956424,47.8228401 C24.6975069,47.8132659 24.618521,47.7965113 24.5586823,47.7725758 C24.4988437,47.7486404 24.4569572,47.7187215 24.4330217,47.6828182 C24.4090862,47.646915 24.3971187,47.6026351 24.3971187,47.549977 L24.3971187,38.1074793 C24.3971187,38.0596084 24.4114798,38.0165252 24.4402023,37.9782284 C24.4689249,37.9399316 24.5179919,37.9076192 24.5874048,37.8812902 C24.6568176,37.8549612 24.7489678,37.8346163 24.8638581,37.8202551 C24.9787484,37.8058938 25.1247526,37.7987132 25.3018751,37.7987132 C25.4789976,37.7987132 25.6250018,37.8058938 25.7398921,37.8202551 C25.8547824,37.8346163 25.9469326,37.8549612 26.0163455,37.8812902 C26.0857584,37.9076192 26.1348253,37.9399316 26.1635479,37.9782284 C26.1922705,38.0165252 26.2066316,38.0596084 26.2066316,38.1074793 L26.2066316,41.6475184 C26.3693928,41.4847572 26.5321516,41.3459335 26.6949128,41.2310432 C26.857674,41.1161529 27.0204328,41.0216092 27.1831941,40.9474092 C27.3459553,40.8732093 27.5135011,40.8193553 27.6858365,40.7858456 C27.8581719,40.7523359 28.0400788,40.7355813 28.2315626,40.7355813 C28.705485,40.7355813 29.107595,40.8301251 29.4379045,41.0192153 C29.7682141,41.2083056 30.0374841,41.4632145 30.2457228,41.7839499 C30.4539614,42.1046853 30.6059494,42.4792698 30.7016913,42.9077148 C30.7974332,43.3361598 30.8453034,43.7873368 30.8453034,44.2612592 Z M28.9711651,44.3905101 C28.9711651,44.1176457 28.9508203,43.8543594 28.91013,43.6006434 C28.8694396,43.3469273 28.7988311,43.1219373 28.6983021,42.9256664 C28.5977731,42.7293955 28.4673267,42.5726205 28.306959,42.4553366 C28.1465913,42.3380528 27.9443396,42.2794118 27.7001977,42.2794118 C27.5805204,42.2794118 27.4632383,42.2961663 27.348348,42.329676 C27.2334577,42.3631857 27.1149789,42.42063 26.992908,42.5020106 C26.8708371,42.5833912 26.7451777,42.6887057 26.6159261,42.8179573 C26.4866746,42.9472088 26.3502444,43.1075741 26.2066316,43.2990579 L26.2066316,45.4245175 C26.4603476,45.7500399 26.703289,45.9977684 26.9354631,46.1677102 C27.1676372,46.3376521 27.4105787,46.4226218 27.6642947,46.4226218 C27.8988624,46.4226218 28.0975238,46.362784 28.2602851,46.2431066 C28.4230463,46.1234292 28.5582797,45.967851 28.6659893,45.7763672 C28.773699,45.5848834 28.8514881,45.3670738 28.899359,45.122932 C28.94723,44.8787901 28.9711651,44.634652 28.9711651,44.3905101 Z M34.0347841,47.549977 C34.0347841,47.597848 34.020423,47.6397344 33.9917004,47.6756376 C33.9629779,47.7115409 33.9139109,47.7414597 33.844498,47.7653952 C33.7750851,47.7893307 33.6829349,47.807282 33.5680446,47.8192498 C33.4531544,47.8312175 33.3071502,47.8372013 33.1300276,47.8372013 C32.9529051,47.8372013 32.8069009,47.8312175 32.6920106,47.8192498 C32.5771204,47.807282 32.4849702,47.7893307 32.4155573,47.7653952 C32.3461444,47.7414597 32.2970774,47.7115409 32.2683548,47.6756376 C32.2396323,47.6397344 32.2252712,47.597848 32.2252712,47.549977 L32.2252712,38.1074793 C32.2252712,38.0596084 32.2396323,38.0165252 32.2683548,37.9782284 C32.2970774,37.9399316 32.3461444,37.9076192 32.4155573,37.8812902 C32.4849702,37.8549612 32.5771204,37.8346163 32.6920106,37.8202551 C32.8069009,37.8058938 32.9529051,37.7987132 33.1300276,37.7987132 C33.3071502,37.7987132 33.4531544,37.8058938 33.5680446,37.8202551 C33.6829349,37.8346163 33.7750851,37.8549612 33.844498,37.8812902 C33.9139109,37.9076192 33.9629779,37.9399316 33.9917004,37.9782284 C34.020423,38.0165252 34.0347841,38.0596084 34.0347841,38.1074793 L34.0347841,47.549977 Z M41.8485754,47.549977 C41.8485754,47.597848 41.8366078,47.6397344 41.8126723,47.6756376 C41.7887369,47.7115409 41.7468504,47.7414597 41.6870117,47.7653952 C41.627173,47.7893307 41.5481871,47.807282 41.4500517,47.8192498 C41.3519163,47.8312175 41.2286504,47.8372013 41.0802505,47.8372013 C40.9222763,47.8372013 40.7942235,47.8312175 40.696088,47.8192498 C40.5979526,47.807282 40.5201634,47.7893307 40.4627183,47.7653952 C40.4052732,47.7414597 40.3645835,47.7115409 40.340648,47.6756376 C40.3167125,47.6397344 40.3047449,47.597848 40.3047449,47.549977 L40.3047449,46.8103745 C39.9504999,47.1933421 39.5902764,47.4805635 39.2240636,47.6720473 C38.8578509,47.8635311 38.4784793,47.9592716 38.0859375,47.9592716 C37.6455248,47.9592716 37.2757272,47.8874663 36.9765338,47.7438534 C36.6773403,47.6002406 36.4355957,47.4039726 36.2512925,47.1550437 C36.0669894,46.9061147 35.9353462,46.6176966 35.8563591,46.2897806 C35.7773721,45.9618646 35.7378791,45.5537708 35.7378791,45.0654871 L35.7378791,41.1448759 C35.7378791,41.097005 35.7510434,41.0551185 35.7773725,41.0192153 C35.8037015,40.9833121 35.8515717,40.9533932 35.9209846,40.9294577 C35.9903975,40.9055222 36.0837444,40.8875709 36.2010283,40.8756032 C36.3183121,40.8636354 36.4631195,40.8576517 36.635455,40.8576517 C36.8125775,40.8576517 36.9585817,40.8636354 37.073472,40.8756032 C37.1883622,40.8875709 37.2805124,40.9055222 37.3499253,40.9294577 C37.4193382,40.9533932 37.4684052,40.9833121 37.4971278,41.0192153 C37.5258503,41.0551185 37.5402114,41.097005 37.5402114,41.1448759 L37.5402114,44.7639017 C37.5402114,45.0989983 37.561753,45.355104 37.6048369,45.5322266 C37.6479207,45.7093491 37.7137423,45.8613371 37.8023035,45.9881951 C37.8908648,46.1150531 38.0033598,46.2131871 38.139792,46.2826 C38.2762243,46.3520128 38.4353928,46.3867188 38.6173024,46.3867188 C38.847083,46.3867188 39.0780568,46.3029458 39.3102309,46.1353975 C39.542405,45.9678492 39.7901335,45.723711 40.0534237,45.4029756 L40.0534237,41.1448759 C40.0534237,41.097005 40.066588,41.0551185 40.092917,41.0192153 C40.1192461,40.9833121 40.1671163,40.9533932 40.2365292,40.9294577 C40.3059421,40.9055222 40.3980923,40.8875709 40.5129825,40.8756032 C40.6278728,40.8636354 40.773877,40.8576517 40.9509995,40.8576517 C41.1281221,40.8576517 41.2741263,40.8636354 41.3890165,40.8756032 C41.5039068,40.8875709 41.5948603,40.9055222 41.6618796,40.9294577 C41.7288989,40.9533932 41.7767692,40.9833121 41.8054917,41.0192153 C41.8342143,41.0551185 41.8485754,41.097005 41.8485754,41.1448759 L41.8485754,47.549977 Z M49.5187545,44.1607307 C49.5187545,44.3809371 49.4696875,44.5436959 49.3715521,44.6490119 C49.2734166,44.754328 49.1381832,44.8069853 48.9658478,44.8069853 L45.0667784,44.8069853 C45.0667784,45.0798497 45.0990908,45.3275782 45.1637166,45.5501781 C45.2283424,45.772778 45.3312634,45.9618654 45.4724827,46.117446 C45.613702,46.2730266 45.7956089,46.3915054 46.0182088,46.472886 C46.2408087,46.5542666 46.5076853,46.5949563 46.8188464,46.5949563 C47.1347947,46.5949563 47.4124421,46.572218 47.6517968,46.5267406 C47.8911516,46.4812632 48.0981903,46.4309994 48.2729193,46.3759478 C48.4476483,46.3208962 48.5924557,46.2706325 48.707346,46.2251551 C48.8222363,46.1796777 48.9155832,46.1569393 48.9873896,46.1569393 C49.0304735,46.1569393 49.0663762,46.1653166 49.0950987,46.1820715 C49.1238213,46.1988263 49.1477564,46.2287452 49.1669048,46.271829 C49.1860532,46.3149129 49.1992175,46.3759474 49.2063981,46.4549345 C49.2135788,46.5339216 49.2171691,46.6332523 49.2171691,46.7529297 C49.2171691,46.8582458 49.2147755,46.9480025 49.2099884,47.0222024 C49.2052014,47.0964024 49.1980208,47.1598305 49.1884466,47.2124885 C49.1788724,47.2651466 49.1645114,47.3094265 49.145363,47.3453297 C49.1262146,47.3812329 49.1010827,47.4159389 49.0699666,47.4494485 C49.0388505,47.4829582 48.9538808,47.5284349 48.8150551,47.5858801 C48.6762293,47.6433252 48.4991095,47.6995727 48.2836902,47.7546243 C48.0682709,47.8096759 47.8217392,47.8575461 47.5440877,47.8982364 C47.2664362,47.9389268 46.9696408,47.9592716 46.6536925,47.9592716 C46.0840282,47.9592716 45.584981,47.8874663 45.156536,47.7438534 C44.728091,47.6002406 44.370261,47.382431 44.0830353,47.0904182 C43.7958096,46.7984054 43.5815903,46.4298046 43.440371,45.9846048 C43.2991517,45.5394049 43.2285431,45.0176194 43.2285431,44.4192325 C43.2285431,43.8495682 43.302742,43.33616 43.4511419,42.8789924 C43.5995419,42.4218248 43.8149579,42.034076 44.0973965,41.7157341 C44.3798351,41.3973923 44.7233041,41.1544509 45.1278136,40.9869026 C45.5323231,40.8193542 45.9882871,40.7355813 46.4957191,40.7355813 C47.0318738,40.7355813 47.4902313,40.8145672 47.8708053,40.9725414 C48.2513794,41.1305155 48.5637326,41.3495218 48.8078745,41.6295669 C49.0520163,41.9096119 49.2315297,42.2411133 49.34642,42.6240809 C49.4613103,43.0070485 49.5187545,43.4235195 49.5187545,43.8735064 L49.5187545,44.1607307 Z M47.7666865,43.643727 C47.7810478,43.136295 47.6793236,42.7377753 47.4615107,42.448156 C47.2436979,42.1585368 46.9074095,42.0137293 46.4526355,42.0137293 C46.2228549,42.0137293 46.0229967,42.0568125 45.8530549,42.1429802 C45.683113,42.2291479 45.5418958,42.3452333 45.4293991,42.4912397 C45.3169023,42.6372461 45.2307359,42.8095789 45.1708972,43.0082433 C45.1110585,43.2069078 45.0763526,43.4187336 45.0667784,43.643727 L47.7666865,43.643727 Z\"\n                id=\"blue\"\n                fill=\"#FFFFFF\"\n              ></path>\n            </g>\n          </g>\n        </g>\n      </g>\n    </svg>\n  )\n}\nexport default BlueWallet\n"
  },
  {
    "path": "packages/app/src/Components/Icons/Cashu.tsx",
    "content": "export default function CashuIcon(props: { size?: number }) {\n  return (\n    <svg width={props.size ?? 135} height={props.size ?? 153} viewBox=\"0 0 135 153\">\n      <path\n        d=\"m 18,0 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 V 8 7 6 5 4 3 2 1 0 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 z m 0,9 H 17 16 15 14 13 12 11 10 9 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 V 17 16 15 14 13 12 11 10 Z M 9,18 H 8 7 6 5 4 3 2 1 0 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 H 1 2 3 4 5 6 7 8 9 V 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 Z M 0,53 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 H 8 7 6 V 60 59 58 57 H 5 4 3 V 56 55 54 53 H 2 1 Z m 9,55 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z m 9,18 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z m 9,9 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z m 9,9 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 z m 81,0 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v 1 1 1 1 1 1 1 1 z\"\n        style={{\n          fill: \"#b89563\",\n        }}\n      />\n      <path\n        d=\"m 36,0 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 V 8 7 6 5 4 3 2 1 0 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 z m 45,9 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 V 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 h -1 -1 -1 -1 -1 -1 -1 -1 z m 0,27 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 V 44 43 42 41 40 39 38 37 Z M 63,64 v 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z m 9,8 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z m 9,18 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 z m 36,9 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z m 9,9 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 z\"\n        style={{\n          fill: \"#e2d2b3\",\n        }}\n      />\n      <path\n        d=\"m 18,9 v 1 1 1 1 1 1 1 1 1 H 17 16 15 14 13 12 11 10 9 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h 1 1 1 1 1 1 1 1 1 V 17 16 15 14 13 12 11 10 9 H 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 Z M 9,61 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 z\"\n        style={{\n          fill: \"#c5a77f\",\n        }}\n      />\n      <path\n        d=\"m 36,9 v 1 1 1 1 1 1 1 1 1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h 1 1 1 1 1 1 1 1 1 V 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 z m 9,40 v 1 1 1 1 1 1 h -1 -1 v 1 1 1 h -1 -1 -1 v 1 1 1 h -1 -1 -1 -1 v 1 1 1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 v -1 -1 -1 h -1 -1 -1 v -1 -1 -1 -1 h -1 -1 -1 -1 v -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 z\"\n        style={{\n          fill: \"#dbbf98\",\n        }}\n      />\n      <path\n        d=\"m 0,45 v 1 1 1 1 1 1 1 1 h 1 1 1 v 1 1 1 1 h 1 1 1 v 1 1 1 1 h 1 1 1 1 v 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 h 1 1 1 1 v -1 -1 -1 h 1 1 1 v -1 -1 -1 h 1 1 v -1 -1 -1 -1 -1 -1 h 1 1 1 1 1 1 v 1 1 1 1 1 1 1 1 h 1 1 1 1 v 1 1 1 1 h 1 1 1 v 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 h 1 1 1 1 v -1 -1 -1 -1 h 1 1 1 1 v -1 -1 -1 -1 h 1 1 1 1 V 52 51 50 49 48 47 46 45 H 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 Z m 6,4 h 1 1 1 1 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h 1 1 1 1 v 1 1 1 1 h 1 1 1 1 v 1 1 1 1 h 1 1 1 1 v 1 1 1 1 h -1 -1 -1 -1 v -1 -1 -1 -1 h -1 -1 -1 -1 v 1 1 1 1 H 17 16 15 14 V 60 59 58 57 H 13 12 11 10 V 56 55 54 53 H 9 8 7 6 v -1 -1 -1 z m 8,8 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 -1 v 1 1 1 z m 44,-8 h 1 1 1 1 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h 1 1 1 1 v 1 1 1 1 h 1 1 1 1 v 1 1 1 1 h 1 1 1 1 v 1 1 1 1 h -1 -1 -1 -1 v -1 -1 -1 -1 h -1 -1 -1 -1 v 1 1 1 1 h -1 -1 -1 -1 v -1 -1 -1 -1 h -1 -1 -1 -1 v -1 -1 -1 -1 h -1 -1 -1 -1 v -1 -1 -1 z m 8,8 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 -1 v 1 1 1 z\"\n        style={{\n          fill: \"#000000\",\n        }}\n      />\n      <path\n        d=\"m 6,49 v 1 1 1 1 h 1 1 1 1 V 52 51 50 49 H 9 8 7 Z m 4,4 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m 4,0 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 -1 v 1 1 1 z m 4,0 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m 4,4 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m -4,0 h -1 -1 -1 -1 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 z m 40,-8 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m 4,4 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m 4,0 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 -1 v 1 1 1 z m 4,0 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m 4,4 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 -1 h -1 -1 -1 z m -4,0 h -1 -1 -1 -1 v 1 1 1 1 h 1 1 1 1 v -1 -1 -1 z\"\n        style={{\n          fill: \"#ffffff\",\n        }}\n      />\n      <path\n        d=\"m 99,99 v 1 1 1 1 1 1 1 1 1 h 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 v -1 -1 -1 -1 -1 -1 -1 -1 -1 h -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 z\"\n        style={{\n          fill: \"#f7f8f3\",\n        }}\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Icons/ECash.tsx",
    "content": "export default function ECashIcon(props: { width?: number; height?: number }) {\n  return (\n    <svg viewBox=\"0 0 30 39\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" {...props}>\n      <g id=\"Group 47711\">\n        <path\n          id=\"Rectangle 585\"\n          d=\"M29.3809 2.47055L29.3809 11.7277L26.7913 11.021C23.8493 10.2181 20.727 10.3835 17.8863 11.4929C15.5024 12.4238 12.9113 12.6933 10.3869 12.2728L7.11501 11.7277L7.11501 2.47054L10.3869 3.01557C12.9113 3.43607 15.5024 3.1666 17.8863 2.23566C20.727 1.12632 23.8493 0.960876 26.7913 1.7638L29.3809 2.47055Z\"\n          fill=\"url(#paint0_linear_1976_19241)\"\n        />\n        <path\n          id=\"Rectangle 587\"\n          d=\"M29.3809 27.9803L29.3809 37.2375L26.7913 36.5308C23.8493 35.7278 20.727 35.8933 17.8863 37.0026C15.5024 37.9336 12.9113 38.203 10.3869 37.7825L7.11501 37.2375L7.11501 27.9803L10.3869 28.5253C12.9113 28.9458 15.5024 28.6764 17.8863 27.7454C20.727 26.6361 23.8493 26.4706 26.7913 27.2736L29.3809 27.9803Z\"\n          fill=\"url(#paint1_linear_1976_19241)\"\n        />\n        <path\n          id=\"Rectangle 586\"\n          d=\"M8.494e-08 15.2069L4.89585e-07 24.4641L2.5896 23.7573C5.53159 22.9544 8.6539 23.1198 11.4946 24.2292C13.8784 25.1601 16.4695 25.4296 18.9939 25.0091L22.2658 24.4641L22.2658 15.2069L18.9939 15.7519C16.4695 16.1724 13.8784 15.9029 11.4946 14.972C8.6539 13.8627 5.53159 13.6972 2.5896 14.5001L8.494e-08 15.2069Z\"\n          fill=\"url(#paint2_linear_1976_19241)\"\n        />\n      </g>\n      <defs>\n        <linearGradient\n          id=\"paint0_linear_1976_19241\"\n          x1=\"29.3809\"\n          y1=\"6.7213\"\n          x2=\"7.11501\"\n          y2=\"6.7213\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stopColor=\"white\" />\n          <stop offset=\"1\" stopColor=\"white\" stopOpacity=\"0.5\" />\n        </linearGradient>\n        <linearGradient\n          id=\"paint1_linear_1976_19241\"\n          x1=\"29.3809\"\n          y1=\"32.2311\"\n          x2=\"7.11501\"\n          y2=\"32.2311\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stopColor=\"white\" />\n          <stop offset=\"1\" stopColor=\"white\" stopOpacity=\"0.5\" />\n        </linearGradient>\n        <linearGradient\n          id=\"paint2_linear_1976_19241\"\n          x1=\"2.70746e-07\"\n          y1=\"19.4576\"\n          x2=\"22.2658\"\n          y2=\"19.4576\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stopColor=\"white\" />\n          <stop offset=\"1\" stopColor=\"white\" stopOpacity=\"0.5\" />\n        </linearGradient>\n      </defs>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Icons/Icon.tsx",
    "content": "import { forwardRef, type HTMLProps } from \"react\"\n\nimport IconsSvg from \"@/Components/Icons/icons.svg\"\n\nexport type IconProps = {\n  name: string\n  size?: number\n} & Omit<HTMLProps<SVGSVGElement>, \"src\" | \"href\" | \"width\" | \"height\">\n\nconst Icon = forwardRef<SVGSVGElement, IconProps>(({ name, size, ...props }, ref) => {\n  size ??= 20\n  return (\n    <svg ref={ref} {...props} width={size} height={size}>\n      <use href={`${IconsSvg}#${name}`} />\n    </svg>\n  )\n})\n\nexport default Icon\n"
  },
  {
    "path": "packages/app/src/Components/Icons/NWC.tsx",
    "content": "export default function NWCIcon(props: { width?: number; height?: number }) {\n  return (\n    <svg viewBox=\"0 0 256 256\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" {...props}>\n      <path\n        d=\"M110.605 31.0659C100.371 20.871 83.7516 20.9801 73.5543 31.2111L7.5804 97.4161C-2.61818 107.648 -2.48842 123.976 7.74253 134.172L115.913 242.342C126.146 252.536 142.733 252.451 152.93 242.22L185.082 210.068C175.705 219.445 167.989 212.703 158.845 203.597L140.911 185.664C127.297 191.053 111.385 188.376 100.355 177.367L86.6891 163.701C86.2293 163.245 85.8745 162.769 85.6252 162.172C85.3759 161.574 85.2473 160.933 85.2467 160.286C85.2462 159.638 85.3737 158.997 85.622 158.4C85.8702 157.802 86.2593 157.295 86.7183 156.839L94.4518 149.105L77.6167 132.27C74.9814 129.64 74.5511 125.393 76.9077 122.524C79.6015 119.23 84.4857 119.055 87.4411 122.004L104.504 139.053L116.061 127.496L99.1857 110.663C96.5492 108.032 96.1201 103.786 98.4968 100.897C99.1272 100.13 99.9112 99.5026 100.798 99.0561C101.686 98.6097 102.656 98.3537 103.648 98.3048C104.64 98.2558 105.631 98.4148 106.558 98.7717C107.485 99.1285 108.327 99.6753 109.03 100.377L126.162 117.395L133.422 110.134C133.878 109.675 134.327 109.261 134.925 109.012C135.522 108.763 136.163 108.634 136.811 108.634C137.458 108.633 138.099 108.76 138.697 109.008C139.295 109.256 139.838 109.62 140.295 110.079L153.983 123.74C164.875 134.611 167.723 150.433 162.631 163.945L180.568 181.882C189.712 190.987 197.363 197.787 206.741 188.41L247.312 147.838C237.56 157.59 229.548 150.077 219.911 140.448L110.605 31.0659Z\"\n        fill=\"url(#paint0_linear_4_519)\"\n      />\n      <path\n        d=\"M187.308 13.0273L152.82 47.4873L229.448 124.116C236.783 131.419 243.158 137.239 250.232 134.417C254.321 132.787 257.128 128.351 255.561 124.238C218.894 28.0253 218.879 28.0238 214.015 17.507C209.151 6.99014 195.471 4.76016 187.308 13.0273Z\"\n        fill=\"#897FFF\"\n      />\n      <path\n        d=\"M187.308 13.0273L152.82 47.4873L229.448 124.116C236.783 131.419 243.158 137.239 250.232 134.417C254.321 132.787 257.128 128.351 255.561 124.238C218.894 28.0253 218.879 28.0238 214.015 17.507C209.151 6.99014 195.471 4.76016 187.308 13.0273Z\"\n        fill=\"#897FFF\"\n      />\n      <path\n        d=\"M187.308 13.0273L152.82 47.4873L229.448 124.116C236.783 131.419 243.158 137.239 250.232 134.417C254.321 132.787 257.128 128.351 255.561 124.238C218.894 28.0253 218.879 28.0238 214.015 17.507C209.151 6.99014 195.471 4.76016 187.308 13.0273Z\"\n        fill=\"#897FFF\"\n      />\n      <path\n        d=\"M187.308 13.0273L152.82 47.4873L229.448 124.116C236.783 131.419 243.158 137.239 250.232 134.417C254.321 132.787 257.128 128.351 255.561 124.238C218.894 28.0253 218.879 28.0238 214.015 17.507C209.151 6.99014 195.471 4.76016 187.308 13.0273Z\"\n        fill=\"#897FFF\"\n      />\n      <path\n        d=\"M187.308 13.0273L152.82 47.4873L229.448 124.116C236.783 131.419 243.158 137.239 250.232 134.417C254.321 132.787 257.128 128.351 255.561 124.238C218.894 28.0253 218.879 28.0238 214.015 17.507C209.151 6.99014 195.471 4.76016 187.308 13.0273Z\"\n        fill=\"#897FFF\"\n      />\n      <defs>\n        <linearGradient\n          id=\"paint0_linear_4_519\"\n          x1=\"123.656\"\n          y1=\"10.4403\"\n          x2=\"123.656\"\n          y2=\"249.941\"\n          gradientUnits=\"userSpaceOnUse\"\n        >\n          <stop stopColor=\"#FFCA4A\" />\n          <stop offset=\"1\" stopColor=\"#F7931A\" />\n        </linearGradient>\n      </defs>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Icons/Nostrich.tsx",
    "content": "export default function NostrIcon(props: { width?: number; height?: number }) {\n  return (\n    <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 116.446 84.924\" {...props}>\n      <path\n        fill=\"currentColor\"\n        clipRule=\"evenodd\"\n        d=\"m35.805 39.467c1.512-1.608 5.559-0.682 6.96-2.4-0.595-1.9-4.07-4.608-4.319-6.96-0.112-1.057 0.563-1.379 0.96-2.64 0.243-0.775 0.004-1.643 0.239-2.16 0.681-1.492 2.526-2.548 2.88-4.08-1.356-6.734 4.686-8.103 8.641-10.32 4.301 0.146 9.927-1.066 13.68 0.96 0.113 0.754-0.646 0.634-0.72 1.2 0.339 0.541 1.563 0.197 1.439 1.2-1.327 1.862-4.511-0.112-5.52 1.68 0.646 0.634 1.735 0.824 2.4 1.44v2.64c-0.708 0.172-1.486 0.274-1.921 0.72 1.552 3.67-5.669 2.291-3.359 6 1.339-0.021 4.954-0.144 6.72-1.2 2.784-1.665 2.711-6.367 5.521-8.159 0.691-0.029 1.57 0.131 1.92-0.24 1.151-2.775 3.98-5.438 8.88-5.76 2.746-0.182 8.349-1.87 10.8 0.239 1.465 1.262 0.81 3.268 2.16 4.561 0.988 0.451 2.105 0.774 2.16 2.16 0.267 1.202-1.834 1.31-0.48 2.159-0.962 1.039-1.811 2.19-3.12 2.881-0.113 1.153 1.554 0.526 1.44 1.68-0.802 1.122-1.209 3.907-2.641 3.6-0.806 0.247-0.373-0.746-0.479-1.199-0.89 0.295-1.405 0.67-2.16 0-0.26 0.78-0.709 1.371-1.2 1.92 1.643 1.478 4.003 2.237 5.521 3.84 3.235-1.359 7.077-5.149 10.8-1.92 0.188 0.988-0.368 1.231-0.24 2.16 0.896 0.774 0.978-0.801 1.92-0.721 1.06 0.062 1.265 0.976 2.16 1.2 0.185 0.904-0.293 1.147-0.24 1.92 0.473 0.889 2.352 0.368 2.881 1.2 0.555 2.155-1.012 2.188-0.961 3.84 1.031 0.388 1.998-1.142 3.601-0.96 0.884 1.517 0.381 4.419 2.16 5.04 0.628 3.104-2.561 3.75-4.32 2.4-0.444 0.436-0.312 1.448-0.72 1.92-1.188 0.147-1.536-0.545-2.4-0.721-0.799 1.563 1.617 1.889 0.72 3.601-1.775-0.463-2.337 1.205-3.359 2.16-1.136-0.064-1.352-1.049-2.16-1.44-0.217 0.423-0.884 0.396-0.96 0.96-0.752 0.804 1.801 1.3 0.72 2.4-1.513 2.06-3.329-1.013-5.76 0-0.55-0.57-1.208-1.032-1.44-1.92-2.051 0.131-3.084-0.756-4.319-1.44-3.303-0.538-4.311 1.677-7.44 0.96 0.216 2.23 3.326 2.419 5.28 2.16 2.783 2.896 3.368 7.992 6.72 10.32 0.458-3.125 4.479 6.161 9.12 10.319 3.707-0.149 6.219 0.33 8.16 1.44 0.042 1.242-2.057 0.343-2.64 0.96 1.246 2.751 4.993-0.816 6.96-0.24-0.479 6.364-12.435 7.859-14.881 2.16-6.689-3.79-9.293-11.666-15.119-16.32-2.059-0.502-3.208-1.912-4.801-2.88-5.372 0.134-10.436 0.287-13.92-1.92-2.16 1.263-3.17 4.747-6 5.521-2.923 0.798-5.911-0.139-8.16 1.92-7.446 1.033-14.465 2.494-19.68 5.76-1.237 0.412-2.52-0.162-3.12 0.479 0.48 2.32 1.668 3.934 1.92 6.48-0.519 0.761-0.962 1.598-1.92 1.92 0.095 1.746 2.833 0.848 3.12 2.4-4.069 1.981-6.507-1.59-7.92-3.841 0.508-4.2-0.333-9.392 2.16-11.52 1.205-1.029 2.837-0.545 4.32-1.68 4.366 0.4 8.705-2.869 12.96-3.84 4.858-1.109 9.547-1.108 11.279-5.28-1.414-1.656-3.291-0.841-5.52-1.44-1.111-0.299-1.463-1.133-2.4-1.68-0.562-0.328-1.474-0.334-2.16-0.72-2.196-1.234-3.287-3.257-6.239-3.841-1.489-0.294-2.832-0.085-4.08-0.479-7.656-2.422-10.618-10.302-13.2-18.24-0.314-3.445-0.995-6.524-1.92-9.359-0.827-8.533-7.048-11.673-13.68-14.4-2.024-0.184-3.309 0.372-5.28 0.24-0.977-0.784-2.486-1.034-2.16-3.12 1.78-0.307 3.603-1.558 5.52-0.96 1.04-0.164 1.452-1.567 2.636-2.16 1.045-0.523 3.934-0.583 5.52-1.92 0.24-0.202 4.291-0.067 4.561 0 2.813 0.7 2.876 4.102 5.04 5.76-1.263 4.763 2.796 8.095 3.6 12.24 0.192 0.99-0.095 1.896 0 2.88 0.472 4.913 2.428 11.467 4.8 14.88 0.998 1.438 2.397 2.623 4.078 3.6z\"\n        fillRule=\"evenodd\"\n      ></path>\n    </svg>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Icons/Spinner.tsx",
    "content": "const Spinner = (props: { width?: number; height?: number; className?: string }) => (\n  <svg\n    width={props.width ?? 20}\n    height={props.height ?? 20}\n    viewBox=\"0 0 20 20\"\n    xmlns=\"http://www.w3.org/2000/svg\"\n    stroke=\"currentColor\"\n    {...props}\n  >\n    <g className=\"origin-center animate-spin\">\n      <circle\n        cx=\"10\"\n        cy=\"10\"\n        r=\"7.5\"\n        fill=\"none\"\n        strokeWidth=\"3\"\n        strokeLinecap=\"round\"\n        strokeDasharray=\"30 70\"\n      ></circle>\n    </g>\n  </svg>\n)\n\nexport default Spinner\n"
  },
  {
    "path": "packages/app/src/Components/Icons/Toggle.tsx",
    "content": "import type { IconProps } from \"./Icon\"\n\nexport function ToggleSwitch(props: Omit<IconProps, \"name\">) {\n  const size = props.size || 20\n  return (\n    <svg\n      viewBox=\"0 0 33.015999 19.353487\"\n      fill=\"none\"\n      width={size}\n      height={props.height ?? size}\n      className={props.className}\n      onClick={props.onClick}\n    >\n      <path\n        className=\"fill-neutral-600 transition-[fill] duration-500 [.active_&]:fill-success\"\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"m 10.265361,0.05752611 c 1.126446,-0.06242431 2.251588,-0.05743114046 3.378034,-0.05743114046 0.0077,0 5.70779,0 5.70779,0 1.148521,0 2.273663,-0.0049931695 3.399407,0.05743114046 1.023495,0.05619252 2.020399,0.17605763 3.012887,0.44387929 2.089033,0.5631251 3.913363,1.739307 5.232065,3.4068227 1.310876,1.6569003 2.020399,3.685279 2.020399,5.7678955 0,2.0852294 -0.709523,4.1123014 -2.020399,5.7692404 -1.318702,1.666906 -3.143032,2.843688 -5.232065,3.406775 -0.992488,0.26785 -1.989392,0.387067 -3.012887,0.443869 -1.125744,0.06241 -2.250886,0.0568 -3.377332,0.0568 -0.0078,0 -5.709194,6.78e-4 -5.709194,6.78e-4 -1.147117,-6.78e-4 -2.272259,0.0049 -3.398705,-0.05748 C 9.2425688,19.239206 8.2455645,19.119989 7.253176,18.852139 5.1640828,18.289052 3.3397837,17.11227 2.021091,15.445364 0.71016486,13.788425 0,11.761353 0,9.676801 0,7.5935071 0.71016486,5.5651284 2.021091,3.9082281 3.3397837,2.2407124 5.1640828,1.0645305 7.253176,0.5014054 8.2455645,0.23358374 9.2425688,0.11371863 10.265361,0.05752611 Z\"\n        fill=\"currentColor\"\n      />\n      <path\n        className=\"fill-white transition-transform duration-500 translate-x-0 [.active_&]:translate-x-3 light:fill-black\"\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"m 10.118173,18.367375 c 4.8102,0 8.7097,-3.8995 8.7097,-8.7096999 0,-4.8101905 -3.8995,-8.7096505 -8.7097,-8.7096505 -4.8102196,0 -8.7096796,3.89946 -8.7096796,8.7096505 0,4.8101999 3.89946,8.7096999 8.7096796,8.7096999 z\"\n      />\n    </svg>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/IntlProvider/IntlProvider.tsx",
    "content": "import { type ReactNode, useEffect, useState } from \"react\"\nimport { type MessageFormatElement, IntlProvider as ReactIntlProvider } from \"react-intl\"\n\nimport { DefaultLocale } from \"@/Components/IntlProvider/IntlProviderUtils\"\nimport { useLocale } from \"@/Components/IntlProvider/useLocale\"\nimport enMessages from \"@/translations/en.json\"\n\nconst getMessages = (locale: string) => {\n  const truncatedLocale = locale.toLowerCase().split(/[_-]+/)[0]\n\n  const matchLang = async (lng: string) => {\n    switch (lng) {\n      case \"es-ES\":\n      case \"es\":\n        return (await import(\"@/translations/es_ES.json\")).default\n      case \"zh-CN\":\n      case \"zh-Hans-CN\":\n      case \"zh\":\n        return (await import(\"@/translations/zh_CN.json\")).default\n      case \"zh-TW\":\n        return (await import(\"@/translations/zh_TW.json\")).default\n      case \"ja-JP\":\n      case \"ja\":\n        return (await import(\"@/translations/ja_JP.json\")).default\n      case \"fr-FR\":\n      case \"fr\":\n        return (await import(\"@/translations/fr_FR.json\")).default\n      case \"hu-HU\":\n      case \"hu\":\n        return (await import(\"@/translations/hu_HU.json\")).default\n      case \"id-ID\":\n      case \"id\":\n        return (await import(\"@/translations/id_ID.json\")).default\n      case \"ar-SA\":\n      case \"ar\":\n        return (await import(\"@/translations/ar_SA.json\")).default\n      case \"it-IT\":\n      case \"it\":\n        return (await import(\"@/translations/it_IT.json\")).default\n      case \"de-DE\":\n      case \"de\":\n        return (await import(\"@/translations/de_DE.json\")).default\n      case \"ru-RU\":\n      case \"ru\":\n        return (await import(\"@/translations/ru_RU.json\")).default\n      case \"sv-SE\":\n      case \"sv\":\n        return (await import(\"@/translations/sv_SE.json\")).default\n      case \"hr-HR\":\n      case \"hr\":\n        return (await import(\"@/translations/hr_HR.json\")).default\n      case \"ta-IN\":\n      case \"ta\":\n        return (await import(\"@/translations/ta_IN.json\")).default\n      case \"fa-IR\":\n      case \"fa\":\n        return (await import(\"@/translations/fa_IR.json\")).default\n      case \"th-TH\":\n      case \"th\":\n        return (await import(\"@/translations/th_TH.json\")).default\n      case \"pt-BR\":\n      case \"pt\":\n        return (await import(\"@/translations/pt_BR.json\")).default\n      case \"sw-KE\":\n      case \"sw\":\n        return (await import(\"@/translations/sw_KE.json\")).default\n      case \"nl-NL\":\n      case \"nl\":\n        return (await import(\"@/translations/nl_NL.json\")).default\n      case \"fi-FI\":\n      case \"fi\":\n        return (await import(\"@/translations/fi_FI.json\")).default\n      case \"ko-KR\":\n      case \"ko\":\n        return (await import(\"@/translations/ko_KR.json\")).default\n      case DefaultLocale:\n      case \"en\":\n        return enMessages\n    }\n  }\n\n  return matchLang(locale) ?? matchLang(truncatedLocale) ?? Promise.resolve(enMessages)\n}\nexport function IntlProvider({ children }: { children: ReactNode }) {\n  const { locale } = useLocale()\n  const [messages, setMessages] = useState<Record<string, MessageFormatElement[]>>(\n    enMessages as Record<string, MessageFormatElement[]>,\n  )\n\n  useEffect(() => {\n    getMessages(locale)\n      .then(x => {\n        if (x) {\n          setMessages(x as Record<string, MessageFormatElement[]>)\n        }\n      })\n      .catch(console.error)\n  }, [locale])\n\n  return (\n    <ReactIntlProvider locale={locale} messages={messages}>\n      {children}\n    </ReactIntlProvider>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/IntlProvider/IntlProviderUtils.tsx",
    "content": "export const DefaultLocale = \"en-US\"\n\nexport const getLocale = () => {\n  return (navigator.languages?.[0]) ?? navigator.language ?? DefaultLocale\n}\nexport const getCurrency = () => {\n  const locale = navigator.language || navigator.languages[0]\n  const formatter = new Intl.NumberFormat(locale, {\n    style: \"currency\",\n    currency: \"USD\",\n    currencyDisplay: \"code\",\n  })\n  return formatter.formatToParts(1.2345).find(a => a.type === \"currency\")?.value ?? \"USD\"\n}\nexport const AllLanguageCodes = [\n  \"en\",\n  \"ja\",\n  \"es\",\n  \"hu\",\n  \"zh-CN\",\n  \"zh-TW\",\n  \"fr\",\n  \"ar\",\n  \"it\",\n  \"id\",\n  \"de\",\n  \"ru\",\n  \"sv\",\n  \"hr\",\n  \"ta-IN\",\n  \"fa-IR\",\n  \"th\",\n  \"pt-BR\",\n  \"sw\",\n  \"nl\",\n  \"fi\",\n  \"ko\",\n]\n"
  },
  {
    "path": "packages/app/src/Components/IntlProvider/langStore.tsx",
    "content": "import { ExternalStore } from \"@snort/shared\"\n\nclass LangStore extends ExternalStore<string | null> {\n  setLang(s: string) {\n    localStorage.setItem(\"lang\", s)\n    this.notifyChange()\n  }\n\n  takeSnapshot() {\n    return localStorage.getItem(\"lang\")\n  }\n}\n\nexport const LangOverride = new LangStore()\n"
  },
  {
    "path": "packages/app/src/Components/IntlProvider/useLocale.tsx",
    "content": "import { useSyncExternalStore } from \"react\"\n\nimport { getLocale } from \"@/Components/IntlProvider/IntlProviderUtils\"\nimport { LangOverride } from \"@/Components/IntlProvider/langStore\"\nimport usePreferences from \"@/Hooks/usePreferences\"\n\nexport function useLocale() {\n  const language = usePreferences(s => s.language)\n  const loggedOutLang = useSyncExternalStore(\n    c => LangOverride.hook(c),\n    () => LangOverride.snapshot(),\n  )\n  const locale = language ?? loggedOutLang ?? getLocale()\n  return {\n    locale,\n    lang: locale.toLowerCase().split(/[_-]+/)[0],\n    setOverride: (s: string) => LangOverride.setLang(s),\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Invite.tsx",
    "content": "import { useUserProfile } from \"@snort/system-react\"\nimport Lottie from \"lottie-react\"\nimport { useEffect, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link, useNavigate } from \"react-router-dom\"\n\nimport SnortApi from \"@/External/SnortApi\"\nimport Hugs from \"@/hug.json\"\nimport { getCurrentRefCode, getDisplayName } from \"@/Utils\"\n\nimport Modal from \"./Modal/Modal\"\n\nconst InviteModal = () => {\n  const [pubkey, setPubkey] = useState(\"\")\n  const code = getCurrentRefCode()\n  const navigate = useNavigate()\n  useEffect(() => {\n    if (code) {\n      const api = new SnortApi()\n      api.getRefCodeInfo(code).then(a => setPubkey(a.pubkey))\n    }\n  }, [code])\n  const profile = useUserProfile(pubkey)\n  if (!code) return\n\n  function close() {\n    navigate(\"/\")\n  }\n  return (\n    <Modal id=\"invite-modal\" onClose={close}>\n      <div className=\"flex flex-col gap-4 items-center\">\n        <Lottie animationData={Hugs} />\n        <p className=\"text-3xl font-semibold\">\n          <FormattedMessage\n            defaultMessage=\"{name} invited you to {app}\"\n            id=\"ZlmK/p\"\n            values={{\n              name: <span className=\"text-primary\">{getDisplayName(profile, pubkey)}</span>,\n              app: CONFIG.appNameCapitalized,\n            }}\n          />\n        </p>\n        <Link to=\"/login/sign-up\">\n          <button className=\"primary\">\n            <FormattedMessage defaultMessage=\"Sign Up\" />\n          </button>\n        </Link>\n      </div>\n    </Modal>\n  )\n}\n\nexport default InviteModal\n"
  },
  {
    "path": "packages/app/src/Components/LiveStream/LiveEvent.tsx",
    "content": "import { NostrLink, type TaggedNostrEvent } from \"@snort/system\"\nimport { lazy, Suspense, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport { findTag } from \"@/Utils\"\nimport { extractStreamInfo } from \"@/Utils/stream\"\n\nimport NoteAppHandler from \"../Event/Note/NoteAppHandler\"\nimport ProfileImage from \"../User/ProfileImage\"\nconst LiveKitRoom = lazy(() => import(\"./livekit\"))\n\nexport function LiveEvent({ ev }: { ev: TaggedNostrEvent }) {\n  const service = ev.tags.find(a => a[0] === \"streaming\")?.at(1)\n  function inner() {\n    if (service?.endsWith(\".m3u8\")) {\n      return <LiveStreamEvent ev={ev} />\n    } else if (service?.startsWith(\"wss+livekit://\")) {\n      return (\n        <Suspense>\n          <LiveKitRoom ev={ev} canJoin={true} />\n        </Suspense>\n      )\n    }\n    return <NoteAppHandler ev={ev} />\n  }\n\n  return inner()\n}\n\nfunction LiveStreamEvent({ ev }: { ev: TaggedNostrEvent }) {\n  const { title, status, starts, host } = extractStreamInfo(ev)\n  const [play, setPlay] = useState(false)\n\n  function statusLine() {\n    switch (status) {\n      case \"live\": {\n        return (\n          <div className=\"flex gap-1 items-center\">\n            <Icon name=\"signal-01\" />\n            <b className=\"uppercase\">\n              <FormattedMessage defaultMessage=\"Live\" />\n            </b>\n          </div>\n        )\n      }\n      case \"ended\": {\n        return (\n          <b className=\"uppercase\">\n            <FormattedMessage defaultMessage=\"Ended\" />\n          </b>\n        )\n      }\n      case \"planned\": {\n        return (\n          <b className=\"uppercase\">\n            {new Intl.DateTimeFormat(undefined, { dateStyle: \"full\", timeStyle: \"short\" }).format(\n              new Date(Number(starts) * 1000),\n            )}\n          </b>\n        )\n      }\n    }\n  }\n\n  function cta() {\n    const link = `https://zap.stream/${NostrLink.fromEvent(ev).encode()}`\n    switch (status) {\n      case \"live\": {\n        return (\n          <button className=\"whitespace-nowrap\" onClick={() => setPlay(true)}>\n            <FormattedMessage defaultMessage=\"Watch Stream\" />\n          </button>\n        )\n      }\n      case \"ended\": {\n        if (findTag(ev, \"recording\")) {\n          return (\n            <Link to={link} target=\"_blank\">\n              <button className=\"whitespace-nowrap\">\n                <FormattedMessage defaultMessage=\"Watch Replay\" />\n              </button>\n            </Link>\n          )\n        }\n      }\n    }\n  }\n  if (play) {\n    const link = `https://zap.stream/embed/${NostrLink.fromEvent(ev).encode()}`\n    return (\n      <iframe\n        src={link}\n        width=\"100%\"\n        style={{\n          aspectRatio: \"16/9\",\n        }}\n      />\n    )\n  }\n  return (\n    <div className=\"sm:flex gap-4 rounded-lg px-6 py-4 bg-primary items-center text-white\">\n      <div>\n        <ProfileImage pubkey={host!} showUsername={false} size={50} />\n      </div>\n      <div className=\"flex flex-col gap-2 grow min-w-0\">\n        <div className=\"font-semibold text-3xl text-ellipsis overflow-hidden whitespace-nowrap\">{title}</div>\n        <div>{statusLine()}</div>\n      </div>\n      <div>{cta()}</div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/LiveStream/LiveStreams.tsx",
    "content": "import { type NostrEvent, NostrLink } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport classNames from \"classnames\"\nimport type { CSSProperties } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport useImgProxy from \"@/Hooks/useImgProxy\"\nimport useLiveStreams from \"@/Hooks/useLiveStreams\"\nimport { findTag } from \"@/Utils\"\n\nimport Avatar from \"../User/Avatar\"\nimport { NestsParticipants } from \"./nests-participants\"\nimport { formatShort } from \"@/Utils/Number\"\n\nexport function LiveStreams() {\n  const streams = useLiveStreams()\n  if (streams.length === 0) return null\n\n  return (\n    <div className=\"flex mx-2 gap-4 overflow-x-auto sm-hide-scrollbar\">\n      {streams.map(v => {\n        const k = `${v.kind}:${v.pubkey}:${findTag(v, \"d\")}`\n        const isVideoStream = v.tags.some(a => a[0] === \"streaming\" && a[1].includes(\".m3u8\"))\n        if (isVideoStream) {\n          return <LiveStreamEvent ev={v} key={k} className=\"h-[80px]\" />\n        }\n\n        const isNests = v.tags.some(a => a[0] === \"streaming\" && a[1].startsWith(\"wss+livekit://\"))\n        if (isNests) {\n          return <AudioRoom ev={v} key={k} className=\"h-[80px]\" />\n        }\n      })}\n    </div>\n  )\n}\n\nexport function LiveStreamEvent({ ev, className }: { ev: NostrEvent; className?: string }) {\n  const { proxy } = useImgProxy()\n  const title = findTag(ev, \"title\")\n  const image = findTag(ev, \"image\") ?? findTag(ev, \"thumb\") ?? findTag(ev, \"thumbnail\")\n  const status = findTag(ev, \"status\")\n  const viewers = findTag(ev, \"current_participants\")\n  const host = ev.tags.find(a => a[0] === \"p\" && a[3] === \"host\")?.[1] ?? ev.pubkey\n  const hostProfile = useUserProfile(host)\n\n  const link = NostrLink.fromEvent(ev).encode()\n  const imageProxy = proxy(image ?? \"\")\n\n  return (\n    <Link className={classNames(\"flex gap-2\", className)} to={`https://zap.stream/${link}`} target=\"_blank\">\n      <div className=\"relative aspect-video overflow-hidden light:text-white\">\n        <div\n          className=\"absolute h-full w-full bg-center bg-cover bg-neutral-900 light:bg-neutral-300 rounded-lg \"\n          style={\n            {\n              backgroundImage: `url(${imageProxy})`,\n            } as CSSProperties\n          }\n        ></div>\n        <div className=\"absolute left-0 top-0 w-full\">\n          <div\n            className=\"whitespace-nowrap px-1.5 text-ellipsis overflow-hidden text-xs font-medium bg-black/70 text-center rounded-t-lg\"\n            title={title}\n          >\n            {title}\n          </div>\n        </div>\n        <div className=\"absolute bottom-1 left-1 bg-heart rounded-lg px-2 uppercase font-bold\">{status}</div>\n        <div className=\"absolute right-1 bottom-1\">\n          <Avatar pubkey={host} user={hostProfile} size={25} className=\"outline-2 outline-highlight\" />\n        </div>\n        {viewers && (\n          <div className=\"absolute left-1 bottom-7 rounded-lg px-2 py-1 text-xs bg-neutral-700 font-medium\">\n            <FormattedMessage defaultMessage=\"{n} viewers\" values={{ n: formatShort(Number(viewers)) }} />\n          </div>\n        )}\n      </div>\n    </Link>\n  )\n}\n\nexport function AudioRoom({ ev, className }: { ev: NostrEvent; className?: string }) {\n  const { proxy } = useImgProxy()\n  const title = findTag(ev, \"title\")\n  const image = findTag(ev, \"image\")\n\n  const link = NostrLink.fromEvent(ev).encode()\n  const imageProxy = proxy(image ?? \"\")\n\n  return (\n    <Link className={classNames(\"flex gap-2\", className)} to={`/${link}`}>\n      <div className=\"relative aspect-video\">\n        <div\n          className=\"absolute h-full w-full bg-center bg-cover bg-neutral-900 rounded-lg flex items-end justify-center\"\n          style={\n            {\n              backgroundImage: `url(${imageProxy})`,\n            } as CSSProperties\n          }\n        >\n          <div className=\"flex items-center gap-1\">\n            <NestsParticipants ev={ev} />\n          </div>\n        </div>\n        <div className=\"absolute left-0 top-0 w-full overflow-hidden\">\n          <div\n            className=\"whitespace-nowrap px-1 text-ellipsis overflow-hidden text-xs font-medium opacity-70 text-center\"\n            title={title}\n          >\n            {title}\n          </div>\n        </div>\n      </div>\n    </Link>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/LiveStream/VU.tsx",
    "content": "import { useEffect, useRef } from \"react\"\n\nexport default function VuBar({\n  track,\n  full,\n  width,\n  height,\n  className,\n}: {\n  track?: MediaStreamTrack\n  full?: boolean\n  height?: number\n  width?: number\n  className?: string\n}) {\n  const ref = useRef<HTMLCanvasElement | null>(null)\n\n  useEffect(() => {\n    if (ref && track) {\n      const audioContext = new AudioContext()\n\n      const trackClone = track\n      const mediaStreamSource = audioContext.createMediaStreamSource(new MediaStream([trackClone]))\n      const analyser = audioContext.createAnalyser()\n      const minVU = -60\n      const maxVU = 0\n      const minFreq = 50\n      const maxFreq = 7_000\n      analyser.minDecibels = -100\n      analyser.maxDecibels = 0\n      analyser.smoothingTimeConstant = 0.4\n      analyser.fftSize = 1024\n      mediaStreamSource.connect(analyser)\n\n      const dataArray = new Uint8Array(analyser.frequencyBinCount)\n\n      const filteredAudio = (i: Uint8Array) => {\n        const binFreq = audioContext.sampleRate / 2 / dataArray.length\n        return i.subarray(minFreq / binFreq, maxFreq / binFreq)\n      }\n      const peakVolume = (data: Uint8Array) => {\n        const max = data.reduce((acc, v) => (v > acc ? v : acc), 0)\n        return (maxVU - minVU) * (max / 256) + minVU\n      }\n\n      const canvas = ref.current!\n      const ctx = canvas.getContext(\"2d\")!\n      const t = setInterval(() => {\n        analyser.getByteFrequencyData(dataArray)\n        const data = filteredAudio(dataArray)\n        const vol = peakVolume(data)\n\n        ctx.clearRect(0, 0, canvas.width, canvas.height)\n\n        if (full) {\n          ctx.fillStyle = \"#00FF00\"\n          for (let x = 0; x < data.length; x++) {\n            const bx = data[x]\n            const h = canvas.height / data.length\n            ctx.fillRect(0, x * h, (bx / 255) * canvas.width, h)\n          }\n        }\n\n        const barLen = ((vol - minVU) / (maxVU - minVU)) * canvas.height\n        ctx.fillStyle = \"#fff\"\n        ctx.fillRect(0, canvas.height - barLen, canvas.width, barLen)\n      }, 50)\n\n      return () => {\n        clearInterval(t)\n        audioContext.close()\n      }\n    }\n  }, [track, full])\n\n  return <canvas ref={ref} width={width ?? 200} height={height ?? 10} className={className}></canvas>\n}\n"
  },
  {
    "path": "packages/app/src/Components/LiveStream/livekit.tsx",
    "content": "/* eslint-disable max-lines */\nimport {\n  LiveKitRoom as LiveKitRoomContext,\n  RoomAudioRenderer,\n  useEnsureRoom,\n  useParticipantPermissions,\n  useParticipants,\n} from \"@livekit/components-react\"\nimport { unixNow } from \"@snort/shared\"\nimport {\n  EventKind,\n  type EventPublisher,\n  Nip10,\n  NostrLink,\n  RequestBuilder,\n  type SystemInterface,\n  type TaggedNostrEvent,\n} from \"@snort/system\"\nimport { useRequestBuilder, useUserProfile } from \"@snort/system-react\"\nimport classNames from \"classnames\"\nimport { LocalParticipant, type LocalTrackPublication, type RemoteParticipant, RoomEvent, Track } from \"livekit-client\"\nimport { useCallback, useEffect, useMemo, useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\n\nimport Text from \"@/Components/Text/Text\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport { extractStreamInfo } from \"@/Utils/stream\"\n\nimport AsyncButton from \"../Button/AsyncButton\"\nimport IconButton from \"../Button/IconButton\"\nimport { ProxyImg } from \"../ProxyImg\"\nimport Avatar from \"../User/Avatar\"\nimport DisplayName from \"../User/DisplayName\"\nimport ProfileImage from \"../User/ProfileImage\"\nimport { NestsParticipants } from \"./nests-participants\"\nimport VuBar from \"./VU\"\n\nenum RoomTab {\n  Participants,\n  Chat,\n}\n\nexport default function LiveKitRoom({ ev, canJoin }: { ev: TaggedNostrEvent; canJoin?: boolean }) {\n  const { stream, service, id } = extractStreamInfo(ev)\n  const { publisher, system } = useEventPublisher()\n  const [join, setJoin] = useState(false)\n  const [token, setToken] = useState<string>()\n  const [tab, setTab] = useState(RoomTab.Participants)\n\n  const getToken = useCallback(async () => {\n    if (!service || !publisher) return\n    const url = `${service}/api/v1/nests/${id}`\n    const auth = await publisher.generic(eb => {\n      eb.kind(EventKind.HttpAuthentication)\n      eb.tag([\"url\", url])\n      eb.tag([\"u\", url])\n      eb.tag([\"method\", \"GET\"])\n      return eb\n    })\n    const rsp = await fetch(url, {\n      headers: {\n        authorization: `Nostr ${window.btoa(JSON.stringify(auth))}`,\n      },\n    })\n\n    const text = await rsp.text()\n    if (rsp.ok) {\n      return JSON.parse(text) as { token: string }\n    }\n  }, [service, publisher, id])\n\n  const publishPresence = useCallback(\n    async (pub: EventPublisher, sys: SystemInterface) => {\n      const e = await pub.generic(eb => {\n        const link = NostrLink.fromEvent(ev)\n        return eb\n          .kind(10_312 as EventKind)\n          .tag(Nip10.linkToTag(link))\n          .tag([\"expiration\", (unixNow() + 60).toString()])\n      })\n      await sys.BroadcastEvent(e)\n    },\n    [ev],\n  )\n\n  useEffect(() => {\n    if (join && !token) {\n      getToken()\n        .then(t => setToken(t?.token))\n        .catch(console.error)\n    }\n  }, [join, token, getToken])\n\n  useEffect(() => {\n    if (token && publisher && system) {\n      publishPresence(publisher, system)\n      const t = setInterval(async () => {\n        if (token) {\n          publishPresence(publisher, system)\n        }\n      }, 60_000)\n      return () => clearInterval(t)\n    }\n  }, [token, publisher, system, publishPresence])\n\n  if (!join) {\n    return (\n      <div className=\"px-3 py-2 flex flex-col gap-2\">\n        <RoomHeader ev={ev} />\n        {(canJoin ?? false) && (\n          <AsyncButton onClick={() => setJoin(true)}>\n            <FormattedMessage defaultMessage=\"Join Room\" />\n          </AsyncButton>\n        )}\n      </div>\n    )\n  }\n  return (\n    <LiveKitRoomContext token={token} serverUrl={stream?.replace(\"wss+livekit://\", \"wss://\")} connect={true}>\n      <RoomAudioRenderer volume={1} muted={false} />\n      <RoomBody ev={ev} tab={tab} onSelectTab={setTab} />\n    </LiveKitRoomContext>\n  )\n}\n\nfunction RoomHeader({ ev }: { ev: TaggedNostrEvent }) {\n  const { image, title } = extractStreamInfo(ev)\n  return (\n    <div className=\"relative rounded-lg h-[140px] w-full overflow-hidden\">\n      {image ? (\n        <ProxyImg src={image} className=\"w-full h-full object-cover object-center\" />\n      ) : (\n        <div className=\"absolute bg-neutral-800 w-full h-full\" />\n      )}\n      <div className=\"absolute left-4 top-4 w-full flex justify-between pr-8\">\n        <div className=\"text-2xl\">{title}</div>\n        <div className=\"flex gap-2 items-center\">\n          <NestsParticipants ev={ev} />\n        </div>\n      </div>\n    </div>\n  )\n}\n\nfunction RoomBody({ ev, tab, onSelectTab }: { ev: TaggedNostrEvent; tab: RoomTab; onSelectTab: (t: RoomTab) => void }) {\n  const participants = useParticipants({\n    updateOnlyOn: [\n      RoomEvent.ParticipantConnected,\n      RoomEvent.ParticipantDisconnected,\n      RoomEvent.ParticipantPermissionsChanged,\n      RoomEvent.TrackMuted,\n      RoomEvent.TrackPublished,\n      RoomEvent.TrackUnmuted,\n      RoomEvent.TrackUnmuted,\n    ],\n  })\n  return (\n    <div className=\"px-3 py-2\">\n      <RoomHeader ev={ev} />\n      <MyControls />\n      <div className=\"flex text-center items-center text-xl font-medium mb-2\">\n        <div\n          className={classNames(\"flex-1 py-2 cursor-pointer select-none border-b border-transparent\", {\n            \"!border-highlight\": tab === RoomTab.Participants,\n          })}\n          onClick={() => onSelectTab(RoomTab.Participants)}\n        >\n          <FormattedMessage defaultMessage=\"Participants\" />\n        </div>\n        <div\n          className={classNames(\"flex-1 py-2 cursor-pointer select-none border-b border-transparent\", {\n            \"!border-highlight\": tab === RoomTab.Chat,\n          })}\n          onClick={() => onSelectTab(RoomTab.Chat)}\n        >\n          <FormattedMessage defaultMessage=\"Chat\" />\n        </div>\n      </div>\n      {tab === RoomTab.Participants && (\n        <div className=\"grid grid-cols-4\">\n          {participants.map(a => (\n            <LiveKitUser p={a} key={a.identity} />\n          ))}\n        </div>\n      )}\n      {tab === RoomTab.Chat && (\n        <>\n          <RoomChat ev={ev} />\n          <WriteChatMessage ev={ev} />\n        </>\n      )}\n    </div>\n  )\n}\n\nfunction MyControls() {\n  const room = useEnsureRoom()\n  const p = room.localParticipant\n  const permissions = useParticipantPermissions({\n    participant: p,\n  })\n  useEffect(() => {\n    if (permissions && p instanceof LocalParticipant) {\n      const handler = (lt: LocalTrackPublication) => {\n        lt.mute()\n      }\n      p.on(\"localTrackPublished\", handler)\n      if (permissions.canPublish && p.audioTrackPublications.size === 0) {\n        p.setMicrophoneEnabled(true)\n      }\n      return () => {\n        p.off(\"localTrackPublished\", handler)\n      }\n    }\n  }, [p, permissions])\n  const isMuted = p.getTrackPublication(Track.Source.Microphone)?.isMuted ?? true\n\n  return (\n    <div className=\"flex gap-2 items-center mt-2\">\n      {p.permissions?.canPublish && (\n        <IconButton\n          icon={{ name: !isMuted ? \"mic\" : \"mic-off\", size: 20 }}\n          onClick={async () => {\n            if (isMuted) {\n              await p.setMicrophoneEnabled(true)\n            } else {\n              await p.setMicrophoneEnabled(false)\n            }\n          }}\n        />\n      )}\n      {/*<IconButton icon={{ name: \"hand\", size: 20 }} />*/}\n    </div>\n  )\n}\n\nfunction RoomChat({ ev }: { ev: TaggedNostrEvent }) {\n  const link = NostrLink.fromEvent(ev)\n  const sub = useMemo(() => {\n    const sub = new RequestBuilder(`room-chat:${link.tagKey}`)\n    sub.withOptions({ leaveOpen: true, replaceable: true })\n    sub.withFilter().replyToLink([link]).kinds([EventKind.LiveEventChat]).limit(100)\n    return sub\n  }, [link])\n  const chat = useRequestBuilder(sub)\n\n  return (\n    <div className=\"flex h-[calc(100dvh-370px)] overflow-x-hidden overflow-y-scroll\">\n      <div className=\"flex flex-col gap-1 flex-col-reverse w-full\">\n        {chat\n          .sort((a, b) => b.created_at - a.created_at)\n          .map(e => (\n            <ChatMessage key={e.id} ev={e} />\n          ))}\n      </div>\n    </div>\n  )\n}\n\nfunction ChatMessage({ ev }: { ev: TaggedNostrEvent }) {\n  return (\n    <div className=\"grid grid-cols-[auto_1fr] items-center gap-2\">\n      <ProfileImage pubkey={ev.pubkey} size={20} showFollowDistance={false} className=\"text-highlight\" />\n      <Text id={ev.id} content={ev.content} creator={ev.pubkey} tags={ev.tags} disableMedia={true} />\n    </div>\n  )\n}\n\nfunction WriteChatMessage({ ev }: { ev: TaggedNostrEvent }) {\n  const link = NostrLink.fromEvent(ev)\n  const [chat, setChat] = useState(\"\")\n  const { publisher, system } = useEventPublisher()\n  const { formatMessage } = useIntl()\n\n  async function sendMessage() {\n    if (!publisher || !system || chat.length < 2) return\n    const eChat = await publisher.generic(eb => eb.kind(EventKind.LiveEventChat).tag(link.toEventTag()!).content(chat))\n    await system.BroadcastEvent(eChat)\n    setChat(\"\")\n  }\n\n  return (\n    <div className=\"flex gap-2 mt-2\">\n      <input\n        type=\"text\"\n        value={chat}\n        placeholder={formatMessage({ defaultMessage: \"Write message\" })}\n        onChange={e => setChat(e.target.value)}\n        className=\"grow\"\n        onKeyDown={e => {\n          if (e.key === \"Enter\") {\n            sendMessage()\n          }\n        }}\n      />\n      <IconButton icon={{ name: \"arrow-right\" }} onClick={sendMessage} />\n    </div>\n  )\n}\n\nfunction LiveKitUser({ p }: { p: RemoteParticipant | LocalParticipant }) {\n  const pubkey = p.identity.startsWith(\"guest-\") ? \"anon\" : p.identity\n  const profile = useUserProfile(pubkey)\n  const mic = p.getTrackPublication(Track.Source.Microphone)\n\n  return (\n    <div className=\"flex flex-col gap-2 items-center text-center\">\n      <div className=\"relative w-[45px] h-[45px] flex items-center justify-center rounded-full overflow-hidden\">\n        {mic?.audioTrack?.mediaStreamTrack && (\n          <VuBar track={mic.audioTrack?.mediaStreamTrack} className=\"absolute h-full w-full\" />\n        )}\n        <Avatar pubkey={pubkey} user={profile} size={40} className=\"absolute\" />\n      </div>\n      <div>\n        <DisplayName pubkey={pubkey} user={pubkey === \"anon\" ? { name: \"Anon\" } : profile} />\n        {p.permissions?.canPublish && <div className=\"text-highlight\">Speaker</div>}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/LiveStream/nests-participants.tsx",
    "content": "import { dedupe, unixNow } from \"@snort/shared\"\nimport { type EventKind, NostrLink, RequestBuilder, type TaggedNostrEvent } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nimport { AvatarGroup } from \"../User/AvatarGroup\"\n\nexport function NestsParticipants({ ev }: { ev: TaggedNostrEvent }) {\n  const link = NostrLink.fromEvent(ev)\n  const sub = useMemo(() => {\n    const sub = new RequestBuilder(`livekit-participants:${link.tagKey}`)\n    sub.withOptions({ leaveOpen: true })\n    sub\n      .withFilter()\n      .replyToLink([link])\n      .kinds([10_312 as EventKind])\n      .since(unixNow() - 600)\n    return sub\n  }, [link.tagKey, link])\n\n  const presense = useRequestBuilder(sub)\n  const filteredPresence = presense.filter(ev => ev.created_at > unixNow() - 600)\n  return <AvatarGroup ids={dedupe(filteredPresence.map(a => a.pubkey)).slice(0, 5)} size={32} />\n}\n"
  },
  {
    "path": "packages/app/src/Components/Modal/Modal.tsx",
    "content": "import type React from \"react\"\nimport { type ReactNode, useEffect, useLayoutEffect, useRef } from \"react\"\nimport { createPortal } from \"react-dom\"\n\nexport interface ModalProps {\n  id: string\n  className?: string\n  bodyClassName?: string\n  onClose?: (e: React.MouseEvent | KeyboardEvent) => void\n  onClick?: (e: React.MouseEvent) => void\n  children?: ReactNode\n}\n\nlet scrollbarWidth: number | null = null\n\nconst getScrollbarWidth = () => {\n  if (scrollbarWidth !== null) {\n    return scrollbarWidth\n  }\n\n  const outer = document.createElement(\"div\")\n  outer.style.visibility = \"hidden\"\n  outer.style.width = \"100px\"\n\n  document.body.appendChild(outer)\n\n  const widthNoScroll = outer.offsetWidth\n  outer.style.overflow = \"scroll\"\n\n  const inner = document.createElement(\"div\")\n  inner.style.width = \"100%\"\n  outer.appendChild(inner)\n\n  const widthWithScroll = inner.offsetWidth\n\n  outer.parentNode?.removeChild(outer)\n\n  scrollbarWidth = widthNoScroll - widthWithScroll\n  return scrollbarWidth\n}\n\nexport default function Modal(props: ModalProps) {\n  const onCloseRef = useRef(props.onClose)\n  useLayoutEffect(() => {\n    onCloseRef.current = props.onClose\n  })\n\n  useEffect(() => {\n    document.body.classList.add(\"scroll-lock\")\n    document.body.style.paddingRight = `${getScrollbarWidth()}px`\n\n    const handleKeyDown = (e: KeyboardEvent) => {\n      if (e.key === \"Escape\") {\n        onCloseRef.current?.(e)\n      }\n    }\n    document.addEventListener(\"keydown\", handleKeyDown)\n\n    return () => {\n      document.body.classList.remove(\"scroll-lock\")\n      document.body.style.paddingRight = \"\"\n      document.removeEventListener(\"keydown\", handleKeyDown)\n    }\n  }, [])\n\n  const handleBackdropClick = (e: React.MouseEvent) => {\n    e.stopPropagation()\n    props.onClose?.(e)\n  }\n\n  return createPortal(\n    <div\n      className={\n        props.className === \"hidden\"\n          ? props.className\n          : `w-screen h-screen fixed top-0 left-0 bg-black/80 flex justify-center z-[42] overflow-y-auto ${props.className || \"\"}`\n      }\n      onMouseDown={handleBackdropClick}\n      onClick={e => {\n        e.stopPropagation()\n      }}\n    >\n      <div\n        className={\n          props.bodyClassName || \"layer-1 px-6 py-4 flex flex-col my-auto lg:w-[720px] max-w-full max-h-[80dvh]\"\n        }\n        onMouseDown={e => e.stopPropagation()}\n        onClick={e => {\n          e.stopPropagation()\n          props.onClick?.(e)\n        }}\n      >\n        {props.children}\n      </div>\n    </div>,\n    document.body,\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Nip5Service.tsx",
    "content": "import { mapEventToProfile, type UserMetadata } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport { type ChangeEvent, type ReactElement, useCallback, useEffect, useMemo, useRef, useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport { ProfilesCache } from \"@/Cache\"\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport Copy from \"@/Components/Copy/Copy\"\nimport ZapModal from \"@/Components/ZapModal/ZapModal\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { debounce, unwrap } from \"@/Utils\"\nimport {\n  type CheckRegisterResponse,\n  type HandleAvailability,\n  type HandleRegisterResponse,\n  type ServiceConfig,\n  type ServiceError,\n  type ServiceErrorCode,\n  ServiceProvider,\n} from \"@/Utils/Nip05/ServiceProvider\"\nimport SnortServiceProvider from \"@/Utils/Nip05/SnortServiceProvider\"\nimport { formatShort } from \"@/Utils/Number\"\n\nimport messages from \"./messages\"\n\ntype Nip05ServiceProps = {\n  name: string\n  service: URL | string\n  about: ReactElement\n  link: string\n  supportLink: string\n  helpText?: boolean\n  forSubscription?: string\n  onChange?(h: string): void\n  onSuccess?(h: string): void\n}\n\nexport default function Nip5Service(props: Nip05ServiceProps) {\n  const navigate = useNavigate()\n  const { helpText = true } = props\n  const { formatMessage } = useIntl()\n  const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }))\n  const user = useUserProfile(publicKey)\n  const { publisher, system } = useEventPublisher()\n  const svc = useMemo(() => new ServiceProvider(props.service), [props.service])\n  const [serviceConfig, setServiceConfig] = useState<ServiceConfig>()\n  const [error, setError] = useState<ServiceError>()\n  const [handle, setHandle] = useState<string>(\"\")\n  const [domain, setDomain] = useState<string>(\"\")\n  const checkingRef = useRef(false)\n  const [availabilityResponse, setAvailabilityResponse] = useState<HandleAvailability>()\n  const [registerResponse, setRegisterResponse] = useState<HandleRegisterResponse>()\n  const [showInvoice, setShowInvoice] = useState<boolean>(false)\n  const [registerStatus, setRegisterStatus] = useState<CheckRegisterResponse>()\n\n  const onHandleChange = (e: ChangeEvent<HTMLInputElement>) => {\n    const h = e.target.value.toLowerCase()\n    setHandle(h)\n    if (props.onChange) {\n      props.onChange(`${h}@${domain}`)\n    }\n  }\n\n  const onDomainChange = (e: ChangeEvent<HTMLSelectElement>) => {\n    const d = e.target.value\n    setDomain(d)\n    if (props.onChange) {\n      props.onChange(`${handle}@${d}`)\n    }\n  }\n\n  const domainConfig = useMemo(() => serviceConfig?.domains.find(a => a.name === domain), [domain, serviceConfig])\n\n  useEffect(() => {\n    svc\n      .GetConfig()\n      .then(a => {\n        if (\"error\" in a) {\n          setError(a as ServiceError)\n        } else {\n          const svc = a as ServiceConfig\n          setServiceConfig(svc)\n          const defaultDomain = svc.domains.find(a => a.default)?.name || svc.domains[0].name\n          setDomain(defaultDomain)\n        }\n      })\n      .catch(console.error)\n  }, [svc])\n\n  useEffect(() => {\n    setError(undefined)\n    setAvailabilityResponse(undefined)\n    if (handle && domain) {\n      if (handle.length < (domainConfig?.length[0] ?? 2)) {\n        setAvailabilityResponse({ available: false, why: \"TOO_SHORT\" })\n        return\n      }\n      if (handle.length > (domainConfig?.length[1] ?? 20)) {\n        setAvailabilityResponse({ available: false, why: \"TOO_LONG\" })\n        return\n      }\n      const rx = new RegExp(domainConfig?.regex[0] ?? \"\", domainConfig?.regex[1] ?? \"\")\n      if (!rx.test(handle)) {\n        setAvailabilityResponse({ available: false, why: \"REGEX\" })\n        return\n      }\n      return debounce(500, () => {\n        svc\n          .CheckAvailable(handle, domain)\n          .then(a => {\n            if (\"error\" in a) {\n              setError(a as ServiceError)\n            } else {\n              setAvailabilityResponse(a as HandleAvailability)\n            }\n          })\n          .catch(console.error)\n      })\n    }\n  }, [handle, domain, domainConfig, svc])\n\n  const checkRegistration = useCallback(\n    async (rsp: HandleRegisterResponse) => {\n      const status = await svc.CheckRegistration(rsp.token)\n      if (\"error\" in status) {\n        setError(status)\n        setRegisterResponse(undefined)\n        setShowInvoice(false)\n      } else {\n        const result: CheckRegisterResponse = status\n        if (result.paid) {\n          if (!result.available) {\n            setError({\n              error: \"REGISTERED\",\n            } as ServiceError)\n          } else {\n            setError(undefined)\n          }\n          setShowInvoice(false)\n          setRegisterStatus(status)\n          setRegisterResponse(undefined)\n        }\n      }\n    },\n    [svc],\n  )\n\n  useEffect(() => {\n    if (registerResponse && showInvoice) {\n      const t = setInterval(() => {\n        if (!checkingRef.current) {\n          checkingRef.current = true\n          checkRegistration(registerResponse)\n            .finally(() => {\n              checkingRef.current = false\n            })\n            .catch(console.error)\n        }\n      }, 2_000)\n      return () => clearInterval(t)\n    }\n  }, [registerResponse, showInvoice, checkRegistration])\n\n  function mapError(e: ServiceErrorCode | undefined, t: string | null): string | undefined {\n    if (e === undefined) {\n      return undefined\n    }\n    const whyMap = new Map([\n      [\"TOO_SHORT\", formatMessage(messages.TooShort)],\n      [\"TOO_LONG\", formatMessage(messages.TooLong)],\n      [\"REGEX\", formatMessage(messages.Regex)],\n      [\"REGISTERED\", formatMessage(messages.Registered)],\n      [\"DISALLOWED_null\", formatMessage(messages.Disallowed)],\n      [\"DISALLOWED_later\", formatMessage(messages.DisalledLater)],\n    ])\n    return whyMap.get(e === \"DISALLOWED\" ? `${e}_${t}` : e)\n  }\n\n  async function startBuy(handle: string, domain: string) {\n    if (!publicKey) {\n      return\n    }\n\n    const rsp = await svc.RegisterHandle(handle, domain, publicKey)\n    if (\"error\" in rsp) {\n      setError(rsp)\n    } else {\n      setRegisterResponse(rsp)\n      setShowInvoice(true)\n    }\n  }\n\n  async function claimForSubscription(handle: string, domain: string, sub: string) {\n    if (!publicKey || !publisher) {\n      return\n    }\n\n    const svcEx = new SnortServiceProvider(publisher, props.service)\n    const rsp = await svcEx.registerForSubscription(handle, domain, sub)\n    if (\"error\" in rsp) {\n      setError(rsp)\n    } else {\n      if (props.onSuccess) {\n        const nip05 = `${handle}@${domain}`\n        props.onSuccess(nip05)\n      }\n    }\n  }\n  async function updateProfile(handle: string, domain: string) {\n    if (user && publisher) {\n      const nip05 = `${handle}@${domain}`\n      const newProfile = {\n        ...user,\n        nip05,\n      } as UserMetadata\n      const ev = await publisher.metadata(newProfile)\n      await system.BroadcastEvent(ev)\n      if (props.onSuccess) {\n        props.onSuccess(nip05)\n      }\n      const newMeta = mapEventToProfile(ev)\n      if (newMeta) {\n        ProfilesCache.set(newMeta)\n      }\n      if (helpText) {\n        navigate(\"/settings/profile\")\n      }\n    }\n  }\n\n  return (\n    <>\n      {helpText && <h3>{props.name}</h3>}\n      {helpText && props.about}\n      {helpText && (\n        <p>\n          <FormattedMessage\n            {...messages.FindMore}\n            values={{\n              service: props.name,\n              link: (\n                <a href={props.link} target=\"_blank\" rel=\"noreferrer\">\n                  {props.link}\n                </a>\n              ),\n            }}\n          />\n        </p>\n      )}\n      {error && <b className=\"error\">{error.error}</b>}\n      {!registerStatus && (\n        <div className=\"flex items-center gap-2\">\n          <input\n            type=\"text\"\n            className=\"grow\"\n            placeholder={formatMessage(messages.Handle)}\n            value={handle}\n            onChange={onHandleChange}\n          />\n          @\n          <select value={domain} onChange={onDomainChange}>\n            {serviceConfig?.domains.map(a => (\n              <option key={a.name}>{a.name}</option>\n            ))}\n          </select>\n        </div>\n      )}\n      {availabilityResponse?.available && !registerStatus && (\n        <>\n          {!props.forSubscription && (\n            <div className=\"flex items-center gap-2\">\n              <FormattedMessage\n                {...messages.Sats}\n                values={{ n: formatShort(unwrap(availabilityResponse.quote?.price)) }}\n              />\n              {availabilityResponse.quote?.data.type && <small>({availabilityResponse.quote?.data.type})</small>}\n            </div>\n          )}\n          <AsyncButton\n            onClick={() =>\n              props.forSubscription\n                ? claimForSubscription(handle, domain, props.forSubscription)\n                : startBuy(handle, domain)\n            }\n          >\n            {props.forSubscription ? (\n              <FormattedMessage defaultMessage=\"Claim Now\" />\n            ) : (\n              <FormattedMessage {...messages.BuyNow} />\n            )}\n          </AsyncButton>\n        </>\n      )}\n      {availabilityResponse?.available === false && !registerStatus && (\n        <b className=\"error\">\n          <FormattedMessage {...messages.NotAvailable} />{\" \"}\n          {mapError(availabilityResponse.why, availabilityResponse.reasonTag || null)}\n        </b>\n      )}\n      <ZapModal\n        invoice={registerResponse?.invoice}\n        show={showInvoice}\n        onClose={() => setShowInvoice(false)}\n        title={formatMessage(messages.Buying, { item: `${handle}@${domain}` })}\n      />\n      {registerStatus?.paid && (\n        <>\n          <h4>\n            <FormattedMessage {...messages.OrderPaid} />\n          </h4>\n          <p>\n            <FormattedMessage {...messages.NewNip} />{\" \"}\n            <code>\n              {handle}@{domain}\n            </code>\n          </p>\n          <h3>\n            <FormattedMessage {...messages.AccountSupport} />\n          </h3>\n          <p>\n            <FormattedMessage {...messages.SavePassword} />\n          </p>\n          <Copy text={registerStatus.password} />\n          <p>\n            <FormattedMessage {...messages.GoTo} />{\" \"}\n            <a href={props.supportLink} target=\"_blank\" rel=\"noreferrer\">\n              <FormattedMessage {...messages.AccountPage} />\n            </a>\n          </p>\n          <h4>\n            <FormattedMessage {...messages.ActivateNow} />\n          </h4>\n          <AsyncButton onClick={() => updateProfile(handle, domain)}>\n            <FormattedMessage {...messages.AddToProfile} />\n          </AsyncButton>\n        </>\n      )}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Offline.tsx",
    "content": "import classNames from \"classnames\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\n\nimport AsyncButton from \"./Button/AsyncButton\"\n\nexport function Offline({ onRetry, className }: { onRetry?: () => void | Promise<void>; className?: string }) {\n  return (\n    <div className={classNames(\"flex items-center gap-2\", className)}>\n      <Icon name=\"wifi-off\" className=\"error\" />\n      <div className=\"error\">\n        <FormattedMessage defaultMessage=\"Offline\" />\n      </div>\n      {onRetry && (\n        <AsyncButton onClick={onRetry}>\n          <FormattedMessage defaultMessage=\"Retry\" />\n        </AsyncButton>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/PageSpinner.tsx",
    "content": "import Spinner from \"@/Components/Icons/Spinner\"\n\nexport default function PageSpinner() {\n  return (\n    <div className=\"flex justify-center items-center\">\n      <Spinner width={50} height={50} />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/PinPrompt/PinPrompt.tsx",
    "content": "import { unwrap } from \"@snort/shared\"\nimport { EventPublisher, InvalidPinError, PinEncrypted } from \"@snort/system\"\nimport { type ReactNode, useRef, useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\n\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { createPublisher, LoginStore, sessionNeedsPin } from \"@/Utils/Login\"\nimport { GetPowWorker } from \"@/Utils/wasm\"\n\nimport AsyncButton from \"../Button/AsyncButton\"\nimport Modal from \"../Modal/Modal\"\n\nexport function PinPrompt({\n  onResult,\n  onCancel,\n  subTitle,\n}: {\n  onResult: (v: string) => Promise<void>\n  onCancel: () => void\n  subTitle?: ReactNode\n}) {\n  const [pin, setPin] = useState(\"\")\n  const [error, setError] = useState(\"\")\n  const { formatMessage } = useIntl()\n  const submitButtonRef = useRef<HTMLButtonElement>(null)\n\n  async function submitPin() {\n    if (pin.length < 4) {\n      setError(\n        formatMessage({\n          defaultMessage: \"Pin too short\",\n          id: \"LR1XjT\",\n        }),\n      )\n      return\n    }\n    setError(\"\")\n\n    try {\n      await onResult(pin)\n    } catch (e) {\n      console.error(e)\n      if (e instanceof InvalidPinError) {\n        setError(\n          formatMessage({\n            defaultMessage: \"Incorrect pin\",\n            id: \"qz9fty\",\n          }),\n        )\n      } else if (e instanceof Error) {\n        setError(e.message)\n      }\n    } finally {\n      setPin(\"\")\n    }\n  }\n\n  return (\n    <Modal id=\"pin\" onClose={() => onCancel()}>\n      <form\n        onSubmit={e => {\n          e.preventDefault()\n          if (submitButtonRef.current) {\n            submitButtonRef.current.click()\n          }\n        }}\n      >\n        <div className=\"flex flex-col gap-3\">\n          <h2>\n            <FormattedMessage defaultMessage=\"Enter Pin\" />\n          </h2>\n          {subTitle ? <div>{subTitle}</div> : null}\n          <input\n            type=\"number\"\n            onChange={e => setPin(e.target.value)}\n            value={pin}\n            maxLength={20}\n            minLength={4}\n            className=\"border px-4 py-3 text-[80px] h-[1em] rounded-lg\"\n          />\n          {error && <b className=\"text-error\">{error}</b>}\n          <div className=\"flex gap-2\">\n            <button type=\"button\" onClick={() => onCancel()}>\n              <FormattedMessage defaultMessage=\"Cancel\" />\n            </button>\n            <AsyncButton ref={submitButtonRef} onClick={() => submitPin()} type=\"submit\">\n              <FormattedMessage defaultMessage=\"Submit\" />\n            </AsyncButton>\n          </div>\n        </div>\n      </form>\n    </Modal>\n  )\n}\n\nexport function LoginUnlock() {\n  const login = useLogin()\n  const pow = usePreferences(s => s.pow)\n  const { publisher } = useEventPublisher()\n\n  async function encryptMigration(pin: string) {\n    const k = unwrap(login.privateKey)\n    const newPin = await PinEncrypted.create(k, pin)\n\n    const pub = EventPublisher.privateKey(k)\n    if (pow) {\n      pub.pow(pow, GetPowWorker())\n    }\n    LoginStore.setPublisher(login.id, pub)\n    LoginStore.updateSession({\n      ...login,\n      readonly: false,\n      privateKeyData: newPin,\n      privateKey: undefined,\n    })\n  }\n\n  async function unlockSession(pin: string) {\n    const key = unwrap(login.privateKeyData)\n    await key.unlock(pin)\n    const pub = createPublisher(login)\n    if (pub) {\n      if (pow) {\n        pub.pow(pow, GetPowWorker())\n      }\n      LoginStore.setPublisher(login.id, pub)\n      LoginStore.updateSession({\n        ...login,\n        readonly: false,\n        privateKeyData: key,\n      })\n    }\n  }\n\n  function makeSessionReadonly() {\n    LoginStore.updateSession({\n      ...login,\n      readonly: true,\n    })\n  }\n\n  if (login.publicKey && !publisher && sessionNeedsPin(login) && !login.readonly) {\n    if (login.privateKey !== undefined) {\n      return (\n        <PinPrompt\n          subTitle={\n            <p>\n              <FormattedMessage\n                defaultMessage=\"Enter a pin to encrypt your private key, you must enter this pin every time you open {site}.\"\n                id=\"SLZGPn\"\n                values={{\n                  site: CONFIG.appNameCapitalized,\n                }}\n              />\n            </p>\n          }\n          onResult={encryptMigration}\n          onCancel={() => {\n            // nothing\n          }}\n        />\n      )\n    }\n    return (\n      <PinPrompt\n        subTitle={\n          <p>\n            <FormattedMessage defaultMessage=\"Enter pin to unlock your private key\" />\n          </p>\n        }\n        onResult={unlockSession}\n        onCancel={() => {\n          makeSessionReadonly()\n        }}\n      />\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Progress/Progress.tsx",
    "content": "import type { ReactNode } from \"react\"\nimport { FormattedNumber } from \"react-intl\"\n\nexport default function Progress({ value, status }: { value: number; status?: ReactNode }) {\n  const v = Math.max(0.01, Math.min(1, value))\n  return (\n    <div className=\"relative h-4 rounded overflow-hidden bg-neutral-600\">\n      <div className=\"absolute bg-success h-full\" style={{ width: `${v * 100}%` }}></div>\n      <span className=\"absolute w-full h-full text-center text-sm leading-4\">\n        {status}\n        <FormattedNumber value={v} style=\"percent\" />\n      </span>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/ProxyImg.tsx",
    "content": "import { forwardRef, type HTMLProps, memo, type ReactNode, useEffect, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport useImgProxy from \"@/Hooks/useImgProxy\"\nimport { getUrlHostname } from \"@/Utils\"\n\nexport type ProxyImgProps = HTMLProps<HTMLImageElement> & {\n  size?: number\n  sha256?: string\n  className?: string\n  promptToLoadDirectly?: boolean\n  missingImageElement?: ReactNode\n  bypassProxy?: boolean\n}\n\nconst defaultMissingImageElement = <Icon name=\"x\" className=\"text-warning\" />\n\nconst ProxyImgComponent = forwardRef<HTMLImageElement, ProxyImgProps>(function ProxyImg(\n  { src, size, className, promptToLoadDirectly, missingImageElement, sha256, bypassProxy, ...props }: ProxyImgProps,\n  ref,\n) {\n  const { proxy } = useImgProxy()\n  const [loadFailed, setLoadFailed] = useState(false)\n  const [bypass, setBypass] = useState(CONFIG.media.bypassImgProxyError)\n  const [imgSrc, setImgSrc] = useState<string | undefined>(src ? proxy(src, size, sha256) : undefined)\n\n  useEffect(() => {\n    setLoadFailed(false)\n    if (src) {\n      setImgSrc(proxy(src, size, sha256))\n    }\n  }, [src, size, sha256, proxy])\n\n  if (loadFailed && !bypass && (promptToLoadDirectly ?? true)) {\n    return (\n      <div\n        className=\"text-error\"\n        title={src}\n        onClick={e => {\n          e.stopPropagation()\n          setBypass(true)\n        }}\n      >\n        <FormattedMessage\n          defaultMessage=\"Failed to proxy image from {host}, click here to load directly\"\n          values={{\n            host: getUrlHostname(src),\n          }}\n        />\n      </div>\n    )\n  }\n\n  const handleImageError = (e: React.SyntheticEvent<HTMLImageElement>) => {\n    if (props.onError) {\n      props.onError(e)\n    } else {\n      if (bypass && imgSrc !== src) {\n        setImgSrc(src ?? \"\")\n      } else {\n        setLoadFailed(true)\n      }\n    }\n  }\n\n  if (!imgSrc || loadFailed) {\n    return missingImageElement ?? defaultMissingImageElement\n  }\n\n  return (\n    <img\n      {...props}\n      ref={ref}\n      src={(bypassProxy ?? false) ? src : imgSrc}\n      width={size}\n      height={size}\n      className={className}\n      onError={handleImageError}\n      crossOrigin={props.crossOrigin}\n    />\n  )\n})\n\nconst ProxyImg = memo(ProxyImgComponent)\nProxyImg.displayName = \"ProxyImg\"\n\nexport { ProxyImg }\n"
  },
  {
    "path": "packages/app/src/Components/QrCode.tsx",
    "content": "import QRCodeStyling from \"qr-code-styling\"\nimport { useEffect, useRef } from \"react\"\n\nexport interface QrCodeProps {\n  data?: string\n  link?: string\n  avatar?: string\n  height?: number\n  width?: number\n  className?: string\n}\n\nexport default function QrCode(props: QrCodeProps) {\n  const qrRef = useRef<HTMLDivElement>(null)\n\n  useEffect(() => {\n    if ((props.data?.length ?? 0) > 0 && qrRef.current) {\n      const qr = new QRCodeStyling({\n        width: props.width || 256,\n        height: props.height || 256,\n        data: props.data,\n        margin: 5,\n        type: \"canvas\",\n        image: props.avatar,\n        dotsOptions: {\n          type: \"rounded\",\n        },\n        cornersSquareOptions: {\n          type: \"extra-rounded\",\n        },\n        imageOptions: {\n          crossOrigin: \"anonymous\",\n        },\n      })\n      qrRef.current.innerHTML = \"\"\n      qr.append(qrRef.current)\n      if (props.link) {\n        qrRef.current.onclick = () => {\n          const elm = document.createElement(\"a\")\n          elm.href = props.link ?? \"\"\n          elm.click()\n        }\n      }\n    } else if (qrRef.current) {\n      qrRef.current.innerHTML = \"\"\n    }\n  }, [props.data, props.link, props.avatar, props.height, props.width])\n\n  return <div className={`qr${props.className ?? \"\"}`} ref={qrRef}></div>\n}\n"
  },
  {
    "path": "packages/app/src/Components/ReBroadcaster.tsx",
    "content": "import type { OkResponse, TaggedNostrEvent } from \"@snort/system\"\nimport { SnortContext } from \"@snort/system-react\"\nimport { use, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport Modal from \"@/Components/Modal/Modal\"\nimport useRelays from \"@/Hooks/useRelays\"\n\nexport function ReBroadcaster({ onClose, ev }: { onClose: () => void; ev: TaggedNostrEvent }) {\n  const [selected, setSelected] = useState<Array<string>>()\n  const [replies, setReplies] = useState<Array<OkResponse>>([])\n  const [sending, setSending] = useState(false)\n  const system = use(SnortContext)\n  const relays = useRelays()\n\n  async function sendReBroadcast() {\n    setSending(true)\n    setReplies([])\n    try {\n      if (selected) {\n        await Promise.all(selected.map(r => system.WriteOnceToRelay(r, ev).then(o => setReplies(v => [...v, o]))))\n      } else {\n        const rsp = await system.BroadcastEvent(ev)\n        setReplies(rsp)\n      }\n    } catch (e) {\n      console.error(e)\n    } finally {\n      setSending(false)\n    }\n  }\n\n  return (\n    <Modal id=\"broadcaster\" onClose={onClose}>\n        <div className=\"flex flex-col gap-4\">\n          <div className=\"text-xl font-medium\">\n            <FormattedMessage defaultMessage=\"Broadcast Event\" />\n          </div>\n          {Object.keys(relays)\n            .filter(el => relays[el].write)\n            .map((r, _i, a) => (\n              <div key={r} className=\"flex justify-between\">\n                <div className=\"flex flex-col gap-1\">\n                  <div>{r}</div>\n                  <small>{replies.findLast(a => a.relay === r)?.message}</small>\n                </div>\n                <div>\n                  <input\n                    type=\"checkbox\"\n                    disabled={sending}\n                    checked={!selected || selected.includes(r)}\n                    onChange={e =>\n                      setSelected(\n                        e.target.checked && selected && selected.length === a.length - 1\n                          ? undefined\n                          : a.filter(el => (el === r ? e.target.checked : !selected || selected.includes(el))),\n                      )\n                    }\n                  />\n                </div>\n              </div>\n            ))}\n          <div className=\"flex gap-2\">\n            <button className=\"secondary\" onClick={onClose}>\n              <FormattedMessage defaultMessage=\"Cancel\" />\n            </button>\n            <AsyncButton onClick={sendReBroadcast} disabled={sending}>\n              <FormattedMessage defaultMessage=\"Send\" />\n            </AsyncButton>\n          </div>\n        </div>\n      </Modal>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Relay/Relay.tsx",
    "content": "import { Link } from \"react-router-dom\"\n\nimport useRelayState from \"@/Feed/RelayState\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { getRelayName } from \"@/Utils\"\n\nimport Icon from \"../Icons/Icon\"\nimport RelayPermissions from \"./permissions\"\nimport RelayStatusLabel from \"./status-label\"\nimport RelayUptime from \"./uptime\"\n\nexport interface RelayProps {\n  addr: string\n}\n\nexport default function Relay(props: RelayProps) {\n  const connection = useRelayState(props.addr)\n  const { state } = useLogin(s => ({ v: s.state.version, state: s.state }))\n  if (!connection) return\n  const name = connection.info?.name ?? getRelayName(props.addr)\n  return (\n    <tr>\n      <td className=\"text-ellipsis\" title={props.addr}>\n        <Link to={`/settings/relays/${encodeURIComponent(props.addr)}`}>\n          {name.length > 20 ? <>{name.slice(0, 20)}...</> : name}\n        </Link>\n      </td>\n      <td>\n        <RelayStatusLabel conn={connection} />\n      </td>\n      <td>\n        <RelayPermissions conn={connection} />\n      </td>\n      <td className=\"text-center\">\n        <RelayUptime url={props.addr} />\n      </td>\n      <td>\n        <Icon\n          name=\"trash\"\n          className=\"text-gray-light cursor-pointer\"\n          onClick={async () => {\n            state.removeRelay(props.addr)\n            await state.saveRelays()\n          }}\n        />\n      </td>\n    </tr>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Relay/RelaysMetadata.tsx",
    "content": "import { useState } from \"react\"\n\nimport Nostrich from \"@/assets/img/nostrich.webp\"\n\nexport const RelayFavicon = ({ url, size }: { url: string; size?: number }) => {\n  const cleanUrl = url\n    .replace(/^wss:\\/\\//, \"https://\")\n    .replace(/^ws:\\/\\//, \"http://\")\n    .replace(/\\/$/, \"\")\n  const [faviconUrl, setFaviconUrl] = useState(`${cleanUrl}/favicon.ico`)\n  return (\n    <img\n      className=\"rounded-full object-cover\"\n      src={faviconUrl}\n      onError={() => setFaviconUrl(Nostrich)}\n      alt={`favicon for ${url}`}\n      width={size ?? 20}\n      height={size ?? 20}\n    />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Relay/name.tsx",
    "content": "import useRelayState from \"@/Feed/RelayState\"\nimport { getRelayName } from \"@/Utils\"\nimport { Nip11, type RelayInfoDocument } from \"@snort/system\"\nimport { useEffect, useState } from \"react\"\n\nexport function RelayName({ url }: { url: string }) {\n  const conn = useRelayState(url)\n  const [info, setInfo] = useState<RelayInfoDocument | undefined>(conn?.info)\n\n  useEffect(() => {\n    if (!info) {\n      Nip11.loadRelayDocument(url).then(setInfo).catch(console.error)\n    }\n  }, [info, url])\n\n  return info?.name ?? getRelayName(url)\n}\n"
  },
  {
    "path": "packages/app/src/Components/Relay/paid.tsx",
    "content": "import type { RelayInfoDocument } from \"@snort/system\"\nimport classNames from \"classnames\"\nimport { FormattedMessage } from \"react-intl\"\n\nexport default function RelayPaymentLabel({ info }: { info: RelayInfoDocument }) {\n  const isPaid = info?.limitation?.payment_required ?? false\n  return (\n    <div\n      className={classNames(\"rounded-full px-2 py-1 font-medium\", {\n        \"bg-[var(--pro)] text-black\": isPaid,\n        \"bg-[var(--free)]\": !isPaid,\n      })}\n    >\n      {isPaid && <FormattedMessage defaultMessage=\"Paid\" />}\n      {!isPaid && <FormattedMessage defaultMessage=\"Free\" />}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Relay/permissions.tsx",
    "content": "import type { ConnectionType } from \"@snort/system/dist/connection-pool\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport useLogin from \"@/Hooks/useLogin\"\n\nexport default function RelayPermissions({ conn }: { conn: ConnectionType }) {\n  const { state } = useLogin(s => ({ v: s.state.version, state: s.state }))\n\n  return (\n    <div className=\"flex gap-2 cursor-pointer select-none\">\n      <div\n        className={conn.settings.read ? \"\" : \"text-gray\"}\n        onClick={() =>\n          state.updateRelay(conn.address, {\n            read: !conn.settings.read,\n            write: conn.settings.write,\n          })\n        }\n      >\n        <FormattedMessage defaultMessage=\"Read\" />\n      </div>\n      <div\n        className={conn.settings.write ? \"\" : \"text-gray\"}\n        onClick={() =>\n          state.updateRelay(conn.address, {\n            read: conn.settings.read,\n            write: !conn.settings.write,\n          })\n        }\n      >\n        <FormattedMessage defaultMessage=\"Write\" />\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Relay/software.tsx",
    "content": "import { Link } from \"react-router-dom\"\n\nexport default function RelaySoftware({ software }: { software: string }) {\n  if (software.includes(\"git\")) {\n    const u = new URL(software)\n    return <Link to={software}>{u.pathname.split(\"/\").at(-1)?.replace(\".git\", \"\")}</Link>\n  }\n  return software\n}\n"
  },
  {
    "path": "packages/app/src/Components/Relay/status-label.tsx",
    "content": "import type { ConnectionType } from \"@snort/system/dist/connection-pool\"\nimport classNames from \"classnames\"\nimport { FormattedMessage } from \"react-intl\"\n\nexport default function RelayStatusLabel({ conn }: { conn: ConnectionType }) {\n  return (\n    <div className=\"flex gap-1 items-center\">\n      <div\n        className={classNames(\"rounded-full w-4 h-4\", {\n          \"bg-success\": conn.isOpen,\n          \"bg-error\": !conn.isOpen,\n        })}\n      ></div>\n      {conn.isOpen ? <FormattedMessage defaultMessage=\"Connected\" /> : <FormattedMessage defaultMessage=\"Offline\" />}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Relay/uptime-label.tsx",
    "content": "import classNames from \"classnames\"\nimport { FormattedMessage } from \"react-intl\"\n\nexport default function UptimeLabel({ avgPing }: { avgPing: number }) {\n  const idealPing = 500\n  const badPing = idealPing * 2\n  return (\n    <div\n      className={classNames(\"font-semibold\", {\n        \"text-error\": Number.isNaN(avgPing) || avgPing > badPing,\n        \"text-warning\": avgPing > idealPing && avgPing < badPing,\n        \"text-success\": avgPing < idealPing,\n      })}\n      title={`${avgPing.toFixed(0)} ms`}\n    >\n      {Number.isNaN(avgPing) && <FormattedMessage defaultMessage=\"Dead\" />}\n      {avgPing > badPing && <FormattedMessage defaultMessage=\"Poor\" />}\n      {avgPing > idealPing && avgPing < badPing && <FormattedMessage defaultMessage=\"Good\" />}\n      {avgPing < idealPing && <FormattedMessage defaultMessage=\"Great\" />}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Relay/uptime.tsx",
    "content": "import { sanitizeRelayUrl, unixNow } from \"@snort/shared\"\nimport { type EventKind, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nimport { findTag } from \"@/Utils\"\nimport { Day, MonitorRelays } from \"@/Utils/Const\"\n\nimport UptimeLabel from \"./uptime-label\"\n\nexport default function RelayUptime({ url }: { url: string }) {\n  const sub = useMemo(() => {\n    const u = sanitizeRelayUrl(url)\n    const rb = new RequestBuilder(`uptime`)\n    if (u) {\n      rb.withFilter()\n        .kinds([30_166 as EventKind])\n        .tag(\"d\", [u])\n        .since(unixNow() - Day)\n        .relay(MonitorRelays)\n    }\n    return rb\n  }, [url])\n\n  const data = useRequestBuilder(sub)\n  const myData = data.filter(a => findTag(a, \"d\") === url)\n  const ping = myData.reduce(\n    (acc, v) => {\n      const read = findTag(v, \"rtt-read\")\n      if (read) {\n        acc.n += 1\n        acc.total += Number(read)\n      }\n      return acc\n    },\n    {\n      n: 0,\n      total: 0,\n    },\n  )\n  const avgPing = ping.total / ping.n\n  return <UptimeLabel avgPing={avgPing} />\n}\n"
  },
  {
    "path": "packages/app/src/Components/Review.tsx",
    "content": "import { type EventKind, type NostrLink, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nexport function ReviewSummary({ link }: { link: NostrLink }) {\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(`reviews:${link.id}`)\n    rb.withFilter()\n      .kinds([1986 as EventKind])\n      .replyToLink([link])\n    return rb\n  }, [link.id, link])\n\n  const data = useRequestBuilder(sub)\n  return <pre>{JSON.stringify(data, undefined, 2)}</pre>\n}\n"
  },
  {
    "path": "packages/app/src/Components/RightWidgets/articles.tsx",
    "content": "import { NostrLink } from \"@snort/system\"\nimport { useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport { useCachedArticles } from \"@/Feed/ArticlesFeed\"\nimport { findTag } from \"@/Utils\"\n\nimport IconButton from \"../Button/IconButton\"\nimport { ProxyImg } from \"../ProxyImg\"\nimport ProfilePreview from \"../User/ProfilePreview\"\nimport { BaseWidget } from \"./base\"\n\nexport default function LatestArticlesWidget() {\n  const [idx, setIdx] = useState(0)\n  const articles = useCachedArticles()\n  const selected = articles.at(idx)\n\n  function next(i: number) {\n    setIdx(x => {\n      x += i\n      if (x < 0) {\n        x = articles.length - 1\n      } else if (x > articles.length) {\n        x = 0\n      }\n      return x\n    })\n  }\n\n  if (!selected) return\n  const link = NostrLink.fromEvent(selected)\n  const image = findTag(selected, \"image\")\n  const title = findTag(selected, \"title\")\n  return (\n    <BaseWidget title={<FormattedMessage defaultMessage=\"Latest Articles\" />}>\n      <div className=\"flex flex-col gap-4\">\n        <Link\n          to={`/${link.encode()}`}\n          className=\"relative rounded-lg overflow-hidden w-full aspect-video\"\n          state={selected}\n        >\n          {image ? (\n            <ProxyImg src={image} className=\"absolute w-full h-full object-cover object-center\" />\n          ) : (\n            <div className=\"absolute w-full h-full object-fit bg-neutral-800\"></div>\n          )}\n          <div className=\"absolute bottom-2 left-4 right-4 px-2 py-1 rounded-lg text-lg font-bold text-white bg-black/50\">\n            {title}\n          </div>\n        </Link>\n        <div>\n          <ProfilePreview\n            pubkey={selected.pubkey}\n            profileImageProps={{\n              subHeader: <></>,\n            }}\n            actions={\n              <div className=\"flex gap-2\">\n                <IconButton icon={{ name: \"arrowFront\", className: \"rotate-180\", size: 14 }} onClick={() => next(-1)} />\n                <IconButton icon={{ name: \"arrowFront\", size: 14 }} onClick={() => next(1)} />\n              </div>\n            }\n          />\n        </div>\n      </div>\n    </BaseWidget>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/RightWidgets/base.tsx",
    "content": "import type { ReactNode } from \"react\"\n\nimport Icon from \"../Icons/Icon\"\n\nexport interface BaseWidgetProps {\n  title?: ReactNode\n  icon?: string\n  iconClassName?: string\n  children?: ReactNode\n  contextMenu?: ReactNode\n}\nexport function BaseWidget({ children, title, icon, iconClassName, contextMenu }: BaseWidgetProps) {\n  return (\n    <div className=\"layer-1\">\n      {title && (\n        <div className=\"flex justify-between items-center\">\n          <div className=\"flex gap-2 items-center text-xl font-semibold mb-2\">\n            {icon && (\n              <div className=\"layer-2 rounded-full\">\n                <Icon name={icon} className={iconClassName} />\n              </div>\n            )}\n            {title}\n          </div>\n          {contextMenu}\n        </div>\n      )}\n      {children}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/RightWidgets/index.tsx",
    "content": "export enum RightColumnWidget {\n  TaskList,\n  TrendingNotes,\n  TrendingPeople,\n  TrendingHashtags,\n  LatestArticls,\n  LiveStreams,\n  InviteFriends,\n  AskSnort,\n}\n"
  },
  {
    "path": "packages/app/src/Components/RightWidgets/invite-friends.tsx",
    "content": "import { useCallback } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport SnortApi, { type RefCodeResponse } from \"@/External/SnortApi\"\nimport { useCopy } from \"@/Hooks/useCopy\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\n\nimport AsyncButton from \"../Button/AsyncButton\"\nimport Icon from \"../Icons/Icon\"\nimport { BaseWidget } from \"./base\"\nimport { useCached } from \"@snort/system-react\"\n\nexport default function InviteFriendsWidget() {\n  const { publisher } = useEventPublisher()\n  const loader = useCallback(() => {\n    const api = new SnortApi(undefined, publisher?.signer)\n    return api.getRefCode()\n  }, [publisher])\n  const { data: refCode } = useCached<RefCodeResponse>(\n    publisher ? `ref:${publisher.pubKey}` : undefined,\n    loader,\n    60 * 60 * 24,\n  )\n  const copy = useCopy()\n\n  return (\n    <BaseWidget\n      title={<FormattedMessage defaultMessage=\"Invite Friends\" />}\n      icon=\"heart-solid\"\n      iconClassName=\"text-heart\"\n    >\n      <div className=\"flex flex-col gap-2\">\n        <FormattedMessage defaultMessage=\"Share a personalized invitation with friends!\" />\n        <div>\n          <AsyncButton\n            className=\"secondary\"\n            onClick={() => copy.copy(`https://${window.location.host}?ref=${refCode?.code}`)}\n          >\n            <Icon name={copy.copied ? \"check\" : \"copy\"} />\n            <FormattedMessage defaultMessage=\"Copy link\" />\n          </AsyncButton>\n        </div>\n      </div>\n    </BaseWidget>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/RightWidgets/mini-stream.tsx",
    "content": "import { NostrLink } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\n\nimport useLiveStreams from \"@/Hooks/useLiveStreams\"\nimport { findTag, getDisplayName } from \"@/Utils\"\n\nimport IconButton from \"../Button/IconButton\"\nimport ZapButton from \"../Event/ZapButton\"\nimport { ProxyImg } from \"../ProxyImg\"\nimport Avatar from \"../User/Avatar\"\nimport { BaseWidget } from \"./base\"\n\nexport default function MiniStreamWidget() {\n  const streams = useLiveStreams()\n\n  const ev = streams.at(0)\n  const host = ev?.tags.find(a => a[0] === \"p\" && a.at(3) === \"host\")?.at(1) ?? ev?.pubkey\n  const hostProfile = useUserProfile(host)\n\n  if (!ev) return\n  const link = NostrLink.fromEvent(ev)\n  const image = findTag(ev, \"image\")\n  const title = findTag(ev, \"title\")\n  return (\n    <BaseWidget>\n      <div className=\"flex flex-col gap-4\">\n        <div className=\"rounded-lg relative aspect-video w-full overflow-hidden\">\n          <ProxyImg src={image} className=\"absolute w-full h-full\" />\n          <div className=\"absolute flex items-center justify-center w-full h-full\">\n            <IconButton\n              icon={{\n                name: \"play-square-outline\",\n              }}\n              onClick={() => window.open(`https://zap.stream/${link.encode()}`, \"_blank\")}\n            />\n          </div>\n        </div>\n        <div className=\"flex items-center justify-between\">\n          <div className=\"flex gap-2\">\n            <Avatar pubkey={host ?? \"\"} user={hostProfile} size={48} />\n            <div className=\"flex flex-col\">\n              <div className=\"text-lg text-white f-ellipsis font-semibold\">{title}</div>\n              <div>{getDisplayName(hostProfile, host!)}</div>\n            </div>\n          </div>\n          <div>{host && <ZapButton pubkey={host} event={link} />}</div>\n        </div>\n      </div>\n    </BaseWidget>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/ScrollToTop.tsx",
    "content": "import { useEffect } from \"react\"\nimport { useLocation, useNavigationType } from \"react-router-dom\"\n\nexport default function ScrollToTop() {\n  const { pathname } = useLocation()\n  const navigationType = useNavigationType()\n\n  useEffect(() => {\n    if (navigationType !== \"POP\") {\n      window.scrollTo(0, 0)\n    }\n    // Only scrolls to top on PUSH or REPLACE, not on POP\n  }, [navigationType])\n\n  return null\n}\n"
  },
  {
    "path": "packages/app/src/Components/SearchBox/SearchBox.tsx",
    "content": "import { NostrLink, tryParseNostrLink } from \"@snort/system\"\nimport { type ChangeEvent, useEffect, useMemo, useRef, useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport { useLocation, useNavigate } from \"react-router-dom\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport Spinner from \"@/Components/Icons/Spinner\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport useProfileSearch from \"@/Hooks/useProfileSearch\"\nimport { fetchNip05Pubkey } from \"@snort/shared\"\n\nconst MAX_RESULTS = 3\n\nexport default function SearchBox() {\n  const { formatMessage } = useIntl()\n  const [search, setSearch] = useState(\"\")\n  const [searching, setSearching] = useState(false)\n  const [isFocused, setIsFocused] = useState(false)\n  const navigate = useNavigate()\n  const _location = useLocation()\n  const inputRef = useRef<HTMLInputElement | null>(null)\n\n  const [activeIndex, setActiveIndex] = useState<number>(-1)\n  const resultListRef = useRef<HTMLDivElement | null>(null)\n\n  const searchFn = useProfileSearch()\n  const results = useMemo(() => searchFn(search), [search, searchFn])\n\n  useEffect(() => {\n    const handleGlobalKeyDown = (e: KeyboardEvent) => {\n      if (e.key === \"Escape\") {\n        setSearch(\"\")\n      }\n      if (e.key === \"k\" && (e.metaKey || e.ctrlKey)) {\n        e.preventDefault()\n        inputRef.current?.focus()\n      }\n    }\n\n    document.addEventListener(\"keydown\", handleGlobalKeyDown)\n\n    return () => {\n      document.removeEventListener(\"keydown\", handleGlobalKeyDown)\n    }\n  }, [])\n\n  useEffect(() => {\n    // Close the search on navigation\n    setSearch(\"\")\n    setActiveIndex(-1)\n  }, [])\n\n  const executeSearch = async () => {\n    try {\n      setSearching(true)\n      const link = tryParseNostrLink(search)\n      if (link) {\n        navigate(`/${link.encode()}`)\n        return\n      }\n      if (search.includes(\"@\")) {\n        const [handle, domain] = search.split(\"@\")\n        const pk = await fetchNip05Pubkey(handle, domain)\n        if (pk) {\n          navigate(`/${new NostrLink(CONFIG.profileLinkPrefix, pk).encode()}`)\n          return\n        }\n      }\n      navigate(`/search/${encodeURIComponent(search)}`)\n    } finally {\n      setSearching(false)\n    }\n  }\n\n  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n    const val = e.target.value\n    if (val.match(/nsec1[a-zA-Z0-9]{20,65}/gi)) {\n      e.preventDefault()\n    } else if (val.trim().match(/^(npub|note|nevent|nprofile)1[a-zA-Z0-9]{20,200}$/gi)) {\n      navigate(`/${val.trim()}`)\n      e.preventDefault()\n    } else {\n      setSearch(val)\n    }\n  }\n\n  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n    switch (e.key) {\n      case \"Enter\":\n        if (activeIndex === 0) {\n          navigate(`/search/${encodeURIComponent(search)}`)\n        } else if (activeIndex > 0 && results) {\n          const selectedResult = results[activeIndex - 1]\n          navigate(`/${new NostrLink(CONFIG.profileLinkPrefix, selectedResult.pubkey).encode()}`)\n          inputRef.current?.blur()\n        } else {\n          executeSearch()\n        }\n        break\n      case \"ArrowDown\":\n        e.preventDefault()\n        setActiveIndex(prev => Math.min(prev + 1, Math.min(MAX_RESULTS, results ? results.length : 0)))\n        break\n      case \"ArrowUp\":\n        e.preventDefault()\n        setActiveIndex(prev => Math.max(prev - 1, 0))\n        break\n      default:\n        break\n    }\n  }\n\n  return (\n    <div className=\"flex layer-1 relative\">\n      <input\n        ref={inputRef}\n        type=\"text\"\n        placeholder={formatMessage({ defaultMessage: \"Search\" })}\n        className=\"w-full !border-none !rounded-none leading-10 py-2.5 px-4\"\n        value={search}\n        onChange={handleChange}\n        onKeyDown={handleKeyDown}\n        onFocus={() => setIsFocused(true)}\n        onBlur={() => setTimeout(() => setIsFocused(false), 150)}\n      />\n      {searching ? (\n        <Spinner width={24} height={24} className=\"my-2.5 mx-4\" />\n      ) : (\n        <Icon className=\"my-2.5 mx-4\" name=\"search-outline\" size={24} onClick={() => navigate(\"/search\")} />\n      )}\n      {search && !searching && isFocused && (\n        <div\n          className=\"absolute top-full mt-2 w-full border bg-white dark:bg-black shadow-lg rounded-lg z-10 overflow-hidden\"\n          ref={resultListRef}\n        >\n          <div\n            className=\"cursor-pointer p-2 hover:bg-layer-2\"\n            onMouseEnter={() => setActiveIndex(0)}\n            onClick={() => navigate(`/search/${encodeURIComponent(search)}`, { state: { forceRefresh: true } })}\n          >\n            <FormattedMessage defaultMessage=\"Search notes\" />: <b>{search}</b>\n          </div>\n          {results?.slice(0, MAX_RESULTS).map((result, _idx) => (\n            <ProfileImage pubkey={result.pubkey} showProfileCard={false} className=\"p-2 hover:bg-layer-2\" />\n          ))}\n        </div>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Spotlight/SpotlightMedia.tsx",
    "content": "import { useCallback, useEffect, useMemo, useState } from \"react\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport { ProxyImg } from \"@/Components/ProxyImg\"\nimport useImgProxy from \"@/Hooks/useImgProxy\"\n\ninterface SpotlightMediaProps {\n  media: Array<string>\n  idx: number\n  className?: string\n  onClose: () => void\n  onNext?: () => void\n  onPrev?: () => void\n}\n\nconst videoSuffixes = [\"mp4\", \"webm\", \"ogg\", \"mov\", \"avi\", \"mkv\", \"m3u8\"]\n\nexport function SpotlightMedia(props: SpotlightMediaProps) {\n  const { proxy } = useImgProxy()\n  const [idx, setIdx] = useState(props.idx)\n\n  const media = useMemo(() => {\n    return props.media.at(idx % props.media.length)\n  }, [idx, props])\n\n  const dec = useCallback(() => {\n    if (idx === 0 && props.onPrev) {\n      props.onPrev()\n    } else {\n      setIdx(s => (s - 1 + props.media.length) % props.media.length)\n    }\n  }, [idx, props.onPrev, props.media.length]) // Add dependencies\n\n  const inc = useCallback(() => {\n    if (idx === props.media.length - 1 && props.onNext) {\n      props.onNext()\n    } else {\n      setIdx(s => (s + 1) % props.media.length)\n    }\n  }, [idx, props.onNext, props.media.length]) // Add dependencies\n\n  useEffect(() => {\n    const handleKeyDown = (e: KeyboardEvent) => {\n      switch (e.key) {\n        case \"ArrowLeft\":\n        case \"ArrowUp\": {\n          e.preventDefault()\n          dec()\n          break\n        }\n        case \"ArrowRight\":\n        case \"ArrowDown\": {\n          e.preventDefault()\n          inc()\n          break\n        }\n      }\n    }\n\n    document.addEventListener(\"keydown\", handleKeyDown)\n    return () => document.removeEventListener(\"keydown\", handleKeyDown)\n  }, [dec, inc]) // Now dec and inc are stable\n\n  const isVideo = useMemo(() => {\n    return media && videoSuffixes.some(suffix => media.endsWith(suffix))\n  }, [media])\n\n  const mediaEl = useMemo(() => {\n    if (media && isVideo) {\n      return (\n        <video\n          src={media}\n          poster={proxy(media)}\n          autoPlay={true}\n          loop={true}\n          controls={true}\n          className=\"max-h-screen max-w-full w-full\"\n        />\n      )\n    } else {\n      return <ProxyImg src={media} className=\"max-h-screen max-w-full w-full object-contain\" />\n    }\n  }, [media, isVideo, proxy])\n\n  const onClickBg = (e: React.MouseEvent) => {\n    if (e.target === e.currentTarget) {\n      props.onClose()\n    }\n  }\n\n  const hasMultiple = props.media.length > 1\n  const hasPrev = hasMultiple || props.onPrev\n  const hasNext = hasMultiple || props.onNext\n\n  const arrowClass = \"absolute p-2 top-1/2 cursor-pointer bg-layer-1 md:opacity-20 hover:opacity-90 rounded-full\"\n  return (\n    <div className=\"select-none relative h-screen flex items-center flex-1 justify-center\" onClick={onClickBg}>\n      {mediaEl}\n      <div className=\"absolute flex flex-row items-center gap-4 left-0 top-0 p-4\">\n        <span\n          className=\"p-2 bg-layer-1 rounded-full cursor-pointer opacity-80 hover:opacity-70\"\n          onClick={props.onClose}\n        >\n          <Icon name=\"x-close\" size={24} />\n        </span>\n      </div>\n      <div className=\"absolute flex flex-row items-center gap-4 right-0 top-0 p-4\">\n        {props.media.length > 1 && `${idx + 1}/${props.media.length}`}\n      </div>\n      {hasPrev && (\n        <span\n          className={`left-2 rotate-180 ${arrowClass}`}\n          onClick={e => {\n            e.stopPropagation()\n            dec()\n          }}\n        >\n          <Icon name=\"arrowFront\" size={24} />\n        </span>\n      )}\n      {hasNext && (\n        <span\n          className={`right-2 ${arrowClass}`}\n          onClick={e => {\n            e.stopPropagation()\n            inc()\n          }}\n        >\n          <Icon name=\"arrowFront\" size={24} />\n        </span>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Spotlight/SpotlightThreadModal.tsx",
    "content": "import { NostrLink, type TaggedNostrEvent } from \"@snort/system\"\n\nimport { ThreadElement } from \"@/Components/Event/Thread/Thread\"\nimport Modal from \"@/Components/Modal/Modal\"\nimport { SpotlightMedia } from \"@/Components/Spotlight/SpotlightMedia\"\nimport getEventMedia from \"@/Utils/getEventMedia\"\nimport { ThreadContextWrapper } from \"@/Utils/Thread/ThreadContextWrapper\"\n\ninterface SpotlightThreadModalProps {\n  thread?: NostrLink\n  event?: TaggedNostrEvent\n  className?: string\n  onClose?: () => void\n  onBack?: () => void\n  onNext?: () => void\n  onPrev?: () => void\n}\n\nexport function SpotlightThreadModal(props: SpotlightThreadModalProps) {\n  const onClose = () => props.onClose?.()\n  const onBack = () => props.onBack?.()\n  const onClickBg = (e: React.MouseEvent) => {\n    if (e.target === e.currentTarget) {\n      onClose()\n    }\n  }\n\n  if (!props.thread && !props.event) {\n    throw new Error(\"SpotlightThreadModal requires either thread or event\")\n  }\n\n  const link = props.event ? NostrLink.fromEvent(props.event) : props.thread\n  return (\n    <Modal id=\"spotlight-media-modal\" className={props.className} onClose={onClose} bodyClassName={\"flex flex-1\"}>\n      <ThreadContextWrapper link={link!}>\n        <div className=\"flex flex-row h-screen w-screen\">\n          <div className=\"flex w-full md:w-2/3 items-center justify-center overflow-hidden\" onClick={onClickBg}>\n            <SpotlightFromEvent\n              event={props.event || props.thread}\n              onClose={onClose}\n              onNext={props.onNext}\n              onPrev={props.onPrev}\n            />\n          </div>\n          <div className=\"bg-layer-1 md:flex w-1/3 min-w-[400px] overflow-y-auto\">\n            <ThreadElement onBack={onBack} disableSpotlight={true} />\n          </div>\n        </div>\n      </ThreadContextWrapper>\n    </Modal>\n  )\n}\n\ninterface SpotlightFromEventProps {\n  event: TaggedNostrEvent\n  onClose: () => void\n  onNext?: () => void\n  onPrev?: () => void\n}\n\nfunction SpotlightFromEvent({ event, onClose, onNext, onPrev }: SpotlightFromEventProps) {\n  const media = getEventMedia(event)\n  return (\n    <SpotlightMedia\n      className=\"w-full\"\n      media={media.map(a => a.content)}\n      idx={0}\n      onClose={onClose}\n      onNext={onNext}\n      onPrev={onPrev}\n    />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Spotlight/context.tsx",
    "content": "import { createContext, type ReactNode, useState } from \"react\"\nimport Modal from \"../Modal/Modal\"\nimport { SpotlightMedia } from \"./SpotlightMedia\"\n\ninterface SpotlightContextState {\n  hide: () => void\n  showImages: (i: Array<string>) => void\n  setIndex: (v: number) => void\n}\n\nexport const SpotlightContext = createContext<SpotlightContextState | undefined>(undefined)\n\nexport function SpotlightContextWrapper({ children }: { children: ReactNode }) {\n  const [imageIdx, setImageIdx] = useState(0)\n  const [images, setImages] = useState<Array<string>>()\n\n  return (\n    <SpotlightContext.Provider\n      value={{\n        hide: () => setImages(undefined),\n        showImages: i => {\n          setImages(i)\n          setImageIdx(0)\n        },\n        setIndex: setImageIdx,\n      }}\n    >\n      {images && (\n        <Modal\n          id=\"spotlight\"\n          onClose={e => {\n            e.stopPropagation()\n            setImages(undefined)\n          }}\n          bodyClassName=\"h-screen w-screen flex items-center justify-center\"\n        >\n          <SpotlightMedia media={images} idx={imageIdx} onClose={() => setImages(undefined)} />\n        </Modal>\n      )}\n      {children}\n    </SpotlightContext.Provider>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/SuggestedProfiles.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nimport PageSpinner from \"@/Components/PageSpinner\"\nimport FollowListBase from \"@/Components/User/FollowListBase\"\nimport useDVMLinks from \"@/Hooks/useDvmLinks\"\nimport { NostrPrefix } from \"@snort/shared\"\nimport { NostrLink } from \"@snort/system\"\nimport ProfileImage from \"./User/ProfileImage\"\n\nconst vertexParams = {\n  sort: \"globalPagerank\",\n  limit: \"30\",\n}\nconst relays = [\"wss://relay.vertexlab.io\"]\n\nconst vertexParser = (c: string) => {\n  const rsp = JSON.parse(c) as Array<{ pubkey: string; rank: number }>\n  return Object.values(rsp).map(a => NostrLink.publicKey(a.pubkey))\n}\n\nexport default function SuggestedProfiles() {\n  const { result, links } = useDVMLinks(5313, undefined, undefined, vertexParams, relays, vertexParser)\n  if (!links) return <PageSpinner />\n  return (\n    <div className=\"px-2\">\n      {result && (\n        <div className=\"flex flex-col gap-2\">\n          <h3>\n            <FormattedMessage defaultMessage=\"Suggestions by\" />\n          </h3>\n          <ProfileImage pubkey={result.pubkey} />\n        </div>\n      )}\n      <FollowListBase\n        pubkeys={\n          links?.filter(a => a.type === NostrPrefix.Profile || a.type === NostrPrefix.PublicKey).map(a => a.id) ?? []\n        }\n        profilePreviewProps={{\n          options: {\n            about: true,\n          },\n        }}\n      />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/TabSelectors/TabSelectors.tsx",
    "content": "import classNames from \"classnames\"\nimport type { ReactNode } from \"react\"\n\nimport useHorizontalScroll from \"@/Hooks/useHorizontalScroll\"\n\nexport interface Tab {\n  text: ReactNode\n  value: number\n  disabled?: boolean\n}\n\ninterface TabsProps {\n  tabs: Tab[]\n  tab: Tab\n  className?: string\n  setTab: (t: Tab) => void\n}\n\ninterface TabElementProps extends Omit<TabsProps, \"tabs\"> {\n  t: Tab\n}\n\nexport const TabSelector = ({ t, tab, setTab }: TabElementProps) => {\n  return (\n    <div\n      className={classNames(\n        \"flex gap-2 items-center px-4 py-2 my-1 layer-1-hover rounded-full cursor-pointer font-semibold whitespace-pre\",\n        \"hover:drop-shadow-sm\",\n        {\n          \"bg-layer-3\": tab.value === t.value,\n          disabled: t.disabled,\n        },\n      )}\n      onClick={() => !t.disabled && setTab(t)}\n    >\n      {t.text}\n    </div>\n  )\n}\n\nconst TabSelectors = ({ tabs, tab, className, setTab }: TabsProps) => {\n  const horizontalScroll = useHorizontalScroll()\n  return (\n    <div className={classNames(className, \"flex gap-2 overflow-hidden hide-scrollbar w-full\")} ref={horizontalScroll}>\n      {tabs.map((t, index) => (\n        <TabSelector key={index} tab={tab} setTab={setTab} t={t} />\n      ))}\n    </div>\n  )\n}\n\nexport default TabSelectors\n"
  },
  {
    "path": "packages/app/src/Components/Tasks/BackupKey.tsx",
    "content": "import type { CachedMetadata } from \"@snort/system\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport { BaseUITask } from \"@/Components/Tasks/index\"\nimport type { LoginSession } from \"@/Utils/Login\"\n\nexport class BackupKeyTask extends BaseUITask {\n  id = \"backup-key\"\n  noBaseStyle = true\n\n  check(_: CachedMetadata, session: LoginSession): boolean {\n    return !this.state.muted && session.type === \"private_key\"\n  }\n\n  render() {\n    return (\n      <div className=\"layer-1\">\n        <div className=\"flex flex-col gap-2\">\n          <div className=\"font-semibold text-xl flex gap-2 items-center\">\n            <Icon name=\"key\" size={21} />\n            <FormattedMessage defaultMessage=\"Be sure to back up your keys!\" />\n          </div>\n          <small>\n            <FormattedMessage\n              defaultMessage=\"No keys, no {app}, There is no way to reset it if you don't back up. It only takes a minute.\"\n              values={{\n                app: CONFIG.appNameCapitalized,\n              }}\n            />\n          </small>\n          <div className=\"flex gap-2\">\n            <Link to=\"/settings/keys\">\n              <button>\n                <FormattedMessage defaultMessage=\"Back up now\" />\n              </button>\n            </Link>\n            <button className=\"secondary\" onClick={() => this.mute()}>\n              <FormattedMessage defaultMessage=\"Already backed up\" />\n            </button>\n          </div>\n        </div>\n      </div>\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Tasks/DonateTask.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport { BaseUITask } from \"@/Components/Tasks/index\"\n\nexport class DonateTask extends BaseUITask {\n  id = \"donate\"\n\n  check(): boolean {\n    return !this.state.muted\n  }\n\n  render() {\n    return (\n      <div className=\"flex flex-col gap-2\">\n        <FormattedMessage\n          defaultMessage=\"Thanks for using {site}, please consider donating if you can.\"\n          values={{ site: CONFIG.appNameCapitalized }}\n        />\n        <Link to=\"/about\">\n          <button>\n            <FormattedMessage defaultMessage=\"Donate\" />\n          </button>\n        </Link>\n      </div>\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Tasks/FollowMorePeople.tsx",
    "content": "import type { CachedMetadata } from \"@snort/system\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport { BaseUITask } from \"@/Components/Tasks/index\"\nimport type { LoginSession } from \"@/Utils/Login\"\n\nexport class FollowMorePeopleTask extends BaseUITask {\n  id = \"follow-more-people\"\n\n  check(_meta: CachedMetadata, session: LoginSession): boolean {\n    return !this.state.muted && (session.state.follows?.length ?? 0) < 10\n  }\n\n  render() {\n    return (\n      <p>\n          <FormattedMessage\n            defaultMessage=\"It looks like you dont follow enough people, take a look at {newUsersPage} to discover people to follow!\"\n            values={{\n              newUsersPage: (\n                <Link to={\"/discover\"}>\n                  <FormattedMessage defaultMessage=\"new users page\" />\n                </Link>\n              ),\n            }}\n          />\n        </p>\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Tasks/Nip5Task.tsx",
    "content": "import type { CachedMetadata } from \"@snort/system\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport { BaseUITask } from \"@/Components/Tasks/index\"\n\nexport class Nip5Task extends BaseUITask {\n  id = \"buy-nip5\"\n\n  check(user: CachedMetadata): boolean {\n    return !this.state.muted && !user.nip05\n  }\n\n  render() {\n    return (\n      <p>\n        <FormattedMessage\n          defaultMessage=\"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out {link}\"\n          id=\"ojzbwv\"\n          values={{\n            link: (\n              <Link to=\"/nostr-address\">\n                <FormattedMessage defaultMessage=\"Buy nostr address\" />\n              </Link>\n            ),\n          }}\n        />\n      </p>\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Tasks/NoticeZapPool.tsx",
    "content": "import { FormattedMessage, FormattedNumber } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport { BaseUITask } from \"@/Components/Tasks/index\"\nimport { Wallets } from \"@/Wallet\"\n\nexport class NoticeZapPoolDefault extends BaseUITask {\n  id = \"zap-pool-default\"\n\n  check(): boolean {\n    return !this.state.muted && CONFIG.defaultZapPoolFee !== 0 && !!Wallets.snapshot().wallet?.isReady()\n  }\n\n  render() {\n    return (\n      <p>\n          <FormattedMessage\n            defaultMessage=\"A default Zap Pool split of {n} has been configured for {site} developers, you can disable it at any time in {link}\"\n            id=\"dmsiLv\"\n            values={{\n              site: CONFIG.appNameCapitalized,\n              n: (\n                <FormattedNumber\n                  value={(CONFIG.defaultZapPoolFee ?? 0) / 100}\n                  style=\"percent\"\n                  maximumFractionDigits={2}\n                />\n              ),\n              link: (\n                <Link to=\"/zap-pool\">\n                  <FormattedMessage defaultMessage=\"Zap Pool\" />\n                </Link>\n              ),\n            }}\n          />\n        </p>\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Tasks/PendingChangesTask.tsx",
    "content": "import type { CachedMetadata } from \"@snort/system\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport { BaseUITask } from \"@/Components/Tasks/index\"\nimport type { LoginSession } from \"@/Utils/Login\"\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport useLogin from \"@/Hooks/useLogin\"\n\nexport class PendingChangesTask extends BaseUITask {\n  id = \"pending-changes\"\n\n  check(_meta: CachedMetadata, session: LoginSession): boolean {\n    return !this.state.muted && session.state.pendingChanges > 0\n  }\n\n  render() {\n    return <PendingChangesContent />\n  }\n}\n\nfunction PendingChangesContent() {\n  const session = useLogin()\n\n  const handleSave = async () => {\n    await session.state.saveAll()\n  }\n\n  return (\n    <>\n      <p>\n        <FormattedMessage defaultMessage=\"You have unsaved changes to your profile, contacts, relays, or settings.\" />\n      </p>\n      <AsyncButton onClick={handleSave}>\n        <FormattedMessage defaultMessage=\"Save Changes\" />\n      </AsyncButton>\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Tasks/RenewSubscription.tsx",
    "content": "import type { CachedMetadata } from \"@snort/system\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport { BaseUITask } from \"@/Components/Tasks/index\"\nimport type { LoginSession } from \"@/Utils/Login\"\nimport { getCurrentSubscription } from \"@/Utils/Subscription\"\n\nexport class RenewSubTask extends BaseUITask {\n  id = \"renew-sub\"\n\n  check(_user: CachedMetadata, session: LoginSession): boolean {\n    const sub = getCurrentSubscription(session.subscriptions)\n    return !sub && session.subscriptions.length > 0\n  }\n\n  render() {\n    return (\n      <>\n        <p>\n          <FormattedMessage\n            defaultMessage=\"Your {site_name} subscription is expired\"\n            id=\"jAmfGl\"\n            values={{\n              site_name: CONFIG.appName,\n            }}\n          />\n        </p>\n        <Link to=\"/subscribe/manage\">\n          <FormattedMessage defaultMessage=\"Renew\" />\n        </Link>\n      </>\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Tasks/TaskList.tsx",
    "content": "import { ExternalStore } from \"@snort/shared\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport { Fragment, useSyncExternalStore } from \"react\"\n\nimport CloseButton from \"@/Components/Button/CloseButton\"\nimport type { UITask } from \"@/Components/Tasks/index\"\nimport useLogin from \"@/Hooks/useLogin\"\n\nimport { BackupKeyTask } from \"./BackupKey\"\nimport { DonateTask } from \"./DonateTask\"\nimport { FollowMorePeopleTask } from \"./FollowMorePeople\"\nimport { Nip5Task } from \"./Nip5Task\"\nimport { NoticeZapPoolDefault } from \"./NoticeZapPool\"\nimport { PendingChangesTask } from \"./PendingChangesTask\"\nimport { RenewSubTask } from \"./RenewSubscription\"\nimport { BaseWidget } from \"../RightWidgets/base\"\n\nclass TaskStore extends ExternalStore<Array<UITask>> {\n  #tasks: Array<UITask>\n\n  constructor() {\n    super()\n    const AllTasks: Array<UITask> = [\n      new BackupKeyTask(),\n      new PendingChangesTask(),\n      new FollowMorePeopleTask(),\n      new Nip5Task(),\n    ]\n    if (CONFIG.features.zapPool) {\n      AllTasks.push(new NoticeZapPoolDefault())\n    }\n    if (CONFIG.features.subscriptions) {\n      AllTasks.push(new RenewSubTask())\n    }\n    AllTasks.push(new DonateTask())\n    AllTasks.forEach(a =>\n      a.load(() => {\n        this.notifyChange()\n      }),\n    )\n    this.#tasks = AllTasks\n  }\n\n  takeSnapshot(): UITask[] {\n    return [...this.#tasks]\n  }\n}\n\nconst AllTasks = new TaskStore()\n\nexport function TaskList() {\n  const tasks = useSyncExternalStore(\n    c => AllTasks.hook(c),\n    () => AllTasks.snapshot(),\n  )\n  const session = useLogin()\n  const user = useUserProfile(session.publicKey)\n  const currentTasks = tasks.filter(a => (user ? a.check(user, session) : false)).slice(0, 1)\n  if (currentTasks.length === 0) return\n  return (\n    <div className=\"flex\">\n      {currentTasks.map(a => {\n        if (a.noBaseStyle) {\n          return <Fragment key={a.id}>{a.render()}</Fragment>\n        } else {\n          return (\n            <BaseWidget\n              key={a.id}\n              contextMenu={<CloseButton onClick={() => a.mute()} />}\n              icon=\"lightbulb\"\n              title={<></>}\n            >\n              {a.render()}\n            </BaseWidget>\n          )\n        }\n      })}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Tasks/index.ts",
    "content": "import type { CachedMetadata } from \"@snort/system\"\n\nimport type { LoginSession } from \"@/Utils/Login\"\nimport type { ReactElement } from \"react\"\n\nexport interface UITask {\n  id: string\n  noBaseStyle: boolean\n  /**\n   * Run checks to determine if this Task should be triggered for this user\n   */\n  check(user: CachedMetadata, session: LoginSession): boolean\n  mute(): void\n  load(cb: () => void): void\n  render(): ReactElement\n}\n\nexport interface UITaskState {\n  id: string\n  muted: boolean\n  completed: boolean\n}\n\nexport abstract class BaseUITask implements UITask {\n  #cb?: () => void\n  protected state: UITaskState\n\n  abstract id: string\n  noBaseStyle = false\n  abstract check(user: CachedMetadata, session: LoginSession): boolean\n  abstract render(): ReactElement\n\n  constructor() {\n    this.state = {} as UITaskState\n  }\n\n  mute(): void {\n    this.state.muted = true\n    this.#save()\n  }\n\n  load(cb: () => void) {\n    this.#cb = cb\n    const state = window.localStorage.getItem(`task:${this.id}`)\n    if (state) {\n      this.state = JSON.parse(state)\n    }\n  }\n\n  #save() {\n    window.localStorage.setItem(`task:${this.id}`, JSON.stringify(this.state))\n    this.#cb?.()\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Text/DisableMedia.tsx",
    "content": "const DisableMedia = ({ content }: { content: string }) => (\n  <a\n    href={content}\n    onClick={e => e.stopPropagation()}\n    target=\"_blank\"\n    rel=\"noreferrer\"\n    className=\"text-highlight no-underline hover:underline\"\n  >\n    {content}\n  </a>\n)\n\nexport default DisableMedia\n"
  },
  {
    "path": "packages/app/src/Components/Text/HighlightedText.tsx",
    "content": "const HighlightedText = ({ content, textToHighlight }: { content: string; textToHighlight: string }) => {\n  const textToHighlightArray = textToHighlight.trim().toLowerCase().split(\" \")\n  const re = new RegExp(`(${textToHighlightArray.join(\"|\")})`, \"gi\")\n  const splittedContent = content.split(re)\n\n  const fragments = splittedContent.map((part, index) => {\n    if (textToHighlightArray.includes(part.toLowerCase())) {\n      return (\n        <strong key={index} className=\"text-highlight\">\n          {part}\n        </strong>\n      )\n    } else {\n      return part\n    }\n  })\n\n  return <>{fragments}</>\n}\n\nexport default HighlightedText\n"
  },
  {
    "path": "packages/app/src/Components/Text/Text.tsx",
    "content": "import type { ParsedFragment, } from \"@snort/system\"\nimport classNames from \"classnames\"\nimport type React from \"react\"\nimport { lazy, type ReactNode, Suspense, use } from \"react\"\n\nconst CashuNuts = lazy(async () => await import(\"@/Components/Embed/CashuNuts\"))\nimport Hashtag from \"@/Components/Embed/Hashtag\"\nimport HyperText from \"@/Components/Embed/HyperText\"\nimport Invoice from \"@/Components/Embed/Invoice\"\nimport { baseImageWidth, GRID_GAP, gridConfigMap, ROW_HEIGHT } from \"@/Components/Text/const\"\nimport DisableMedia from \"@/Components/Text/DisableMedia\"\nimport { useTextTransformer } from \"@/Hooks/useTextTransformCache\"\n\nimport RevealMedia, { type RevealMediaProps } from \"../Event/RevealMedia\"\nimport { ProxyImg } from \"../ProxyImg\"\nimport HighlightedText from \"./HighlightedText\"\nimport { SpotlightContext } from \"../Spotlight/context\"\nimport NostrLink from \"../Embed/NostrLink\"\nimport { magnetURIDecode } from \"@/Utils\"\nimport MagnetLink from \"../Embed/MagnetLink\"\nimport BlossomBlob from \"../Embed/BlossomBlob\"\n\nexport interface TextProps {\n  id: string\n  content: string\n  creator: string\n  tags: Array<Array<string>>\n  disableMedia?: boolean\n  disableGallery?: boolean\n  disableLinkPreview?: boolean\n  depth?: number\n  truncate?: number\n  className?: string\n  highlightText?: string\n  onClick?: (e: React.MouseEvent) => void\n}\n\nexport default function Text({\n  id,\n  content,\n  tags,\n  creator,\n  disableMedia,\n  disableGallery,\n  depth,\n  disableLinkPreview,\n  truncate,\n  className,\n  highlightText,\n  onClick,\n}: TextProps) {\n  const spotlight = use(SpotlightContext)\n  const elements = useTextTransformer(id, content, tags)\n\n  const images = elements.filter(a => a.type === \"media\" && a.mimeType?.startsWith(\"image\")).map(a => a.content)\n  const onMediaClick = (e: React.MouseEvent<HTMLImageElement>) => {\n    e.stopPropagation()\n    spotlight?.showImages(images)\n  }\n\n  const textElementClasses = \"whitespace-pre-wrap wrap-break-word\"\n  const renderContent = () => {\n    let lenCtr = 0\n\n    const chunks: Array<ReactNode> = []\n    for (let i = 0; i < elements.length; i++) {\n      const element = elements[i]\n\n      if (truncate) {\n        // If we've exceeded the limit after a link, stop rendering\n        if (lenCtr > truncate) {\n          return chunks\n        }\n\n        // Return truncated text if on truncation boundry\n        if (element.type === \"text\" && lenCtr + element.content.length > truncate) {\n          chunks.push(<span className={textElementClasses}>{element.content.slice(0, truncate - lenCtr)}...</span>)\n          return chunks\n        }\n\n        lenCtr += element.content.length\n      }\n\n      switch (element.type) {\n        case \"media\": {\n          // image element\n          if (element.mimeType?.startsWith(\"image\")) {\n            if (disableMedia ?? false) {\n              chunks.push(<DisableMedia content={element.content} />)\n            } else {\n              const elementsGallery = elements.slice(i)\n              const gal = findGallery(elementsGallery)\n              if (gal && !(disableGallery ?? false)) {\n                chunks.push(\n                  buildGallery(\n                    elementsGallery.filter(a => a.content.trim().length > 0),\n                    onMediaClick,\n                    creator,\n                  ),\n                )\n                // skip to end of galary\n                i += elementsGallery.length\n              } else {\n                chunks.push(\n                  <RevealMedia\n                    src={element.content}\n                    meta={element.data}\n                    size={baseImageWidth}\n                    creator={creator}\n                    onMediaClick={onMediaClick}\n                  />,\n                )\n              }\n            }\n            continue\n          }\n\n          // audo / video element\n          if (element.mimeType?.startsWith(\"audio\") || element.mimeType?.startsWith(\"video\")) {\n            if (disableMedia ?? false) {\n              chunks.push(<DisableMedia content={element.content} />)\n            } else {\n              chunks.push(\n                <RevealMedia\n                  src={element.content}\n                  meta={element.data}\n                  size={baseImageWidth}\n                  creator={creator}\n                  onMediaClick={onMediaClick}\n                />,\n              )\n            }\n            continue\n          }\n\n          // unknown media (link)\n          chunks.push(<HyperText link={element.content} showLinkPreview={!(disableLinkPreview ?? false)} />)\n          break\n        }\n        case \"invoice\": {\n          chunks.push(<Invoice invoice={element.content} />)\n          break\n        }\n        case \"hashtag\": {\n          chunks.push(<Hashtag tag={element.content} />)\n          break\n        }\n        case \"cashu\": {\n          chunks.push(\n            <Suspense>\n              <CashuNuts token={element.content} />\n            </Suspense>,\n          )\n          break\n        }\n        case \"link\": {\n          if (disableMedia ?? false) {\n            chunks.push(<DisableMedia content={element.content} />)\n          } else {\n            chunks.push(<HyperText link={element.content} showLinkPreview={!(disableLinkPreview ?? false)} />)\n          }\n          break\n        }\n        case \"mention\": {\n          chunks.push(<NostrLink link={element.content} depth={depth} />)\n          break\n        }\n        case \"magnet\": {\n          const parsed = magnetURIDecode(element.content)\n          if (parsed) {\n            chunks.push(<MagnetLink magnet={parsed} />)\n          } else {\n            chunks.push(element.content)\n          }\n          break\n        }\n        case \"blossom\": {\n          chunks.push(<BlossomBlob link={element.content} creator={creator} />)\n          break\n        }\n        case \"custom_emoji\": {\n          chunks.push(<ProxyImg src={element.content} size={15} className=\"custom-emoji\" />)\n          break\n        }\n        case \"code_block\": {\n          chunks.push(\n            <pre className=\"bg-layer-2 px-2 py-1 rounded-lg\" lang={element.language}>\n              {element.content}\n            </pre>,\n          )\n          break\n        }\n        case \"inline_code\": {\n          chunks.push(\n            <code className=\"bg-layer-2 px-1.5 py-0.5 rounded-lg\" lang={element.language}>\n              {element.content}\n            </code>,\n          )\n          break\n        }\n        default: {\n          chunks.push(\n            highlightText ? (\n                <HighlightedText content={element.content} textToHighlight={highlightText} />\n              ) : (\n                element.content\n              ),\n          )\n          break\n        }\n      }\n    }\n    return chunks\n  }\n\n  return (\n    <div dir=\"auto\" className={classNames(textElementClasses, className)} onClick={onClick}>\n      {renderContent()}\n    </div>\n  )\n}\n\n/**\n * Only enable gallery if there is multiple images in a row\n */\nfunction findGallery(elements: Array<ParsedFragment>): [number, number] | undefined {\n  // If the current element is of type media and mimeType starts with image,\n  // we verify if the next elements are of the same type and mimeType and push to the galleryImages\n  // Whenever one of the next elements is not longer of the type we are looking for, we break the loop\n\n  const isImage = (a: ParsedFragment) => a.type === \"media\" && a.mimeType?.startsWith(\"image\")\n  const firstImage = elements.findIndex(isImage)\n  if (firstImage === -1) {\n    return\n  }\n\n  // from the first image in the array until the end\n  for (let j = firstImage; j < elements.length; j++) {\n    const nextElement = elements[j]\n\n    // skip over empty space\n    if (nextElement.type === \"text\" && nextElement.content.trim().length === 0) {\n      continue\n    }\n\n    if (!isImage(nextElement)) {\n      return\n    }\n  }\n\n  return [firstImage, elements.length - 1]\n}\n\nfunction buildGallery(\n  elements: Array<ParsedFragment>,\n  onMediaClick: RevealMediaProps[\"onMediaClick\"],\n  creator: string,\n) {\n  if (elements.length === 1) {\n    return (\n      <RevealMedia src={elements[0].content} meta={elements[0].data} creator={creator} onMediaClick={onMediaClick} />\n    )\n  } else {\n    // We build a grid layout to render the grouped images\n    const imagesWithGridConfig = elements.map((gi, index) => {\n      const config = gridConfigMap.get(elements.length)\n      let height = ROW_HEIGHT\n\n      if (config && config[index][1] > 1) {\n        height = config[index][1] * ROW_HEIGHT + GRID_GAP\n      }\n\n      return {\n        content: gi.content,\n        data: gi.data,\n        gridColumn: config ? config[index][0] : 1,\n        gridRow: config ? config[index][1] : 1,\n        height,\n      }\n    })\n    const gallery = (\n      <div className=\"grid grid-cols-4 gap-0.5 place-items-start\">\n        {imagesWithGridConfig.map(img => (\n          <RevealMedia\n            src={img.content}\n            meta={img.data}\n            creator={creator}\n            onMediaClick={onMediaClick}\n            style={{\n              gridColumn: `span ${img.gridColumn}`,\n              gridRow: `span ${img.gridRow}`,\n              height: img.height,\n              objectFit: \"cover\",\n            }}\n          />\n        ))}\n      </div>\n    )\n    return gallery\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/Text/const.ts",
    "content": "export const baseImageWidth = 910\nexport const gridConfigMap = new Map<number, number[][]>([\n  [1, [[4, 3]]],\n  [\n    2,\n    [\n      [2, 2],\n      [2, 2],\n    ],\n  ],\n  [\n    3,\n    [\n      [2, 2],\n      [2, 1],\n      [2, 1],\n    ],\n  ],\n  [\n    4,\n    [\n      [2, 1],\n      [2, 1],\n      [2, 1],\n      [2, 1],\n    ],\n  ],\n  [\n    5,\n    [\n      [2, 1],\n      [2, 1],\n      [2, 1],\n      [1, 1],\n      [1, 1],\n    ],\n  ],\n  [\n    6,\n    [\n      [2, 2],\n      [1, 1],\n      [1, 1],\n      [2, 2],\n      [1, 1],\n      [1, 1],\n    ],\n  ],\n])\nexport const ROW_HEIGHT = 200\nexport const GRID_GAP = 2\n"
  },
  {
    "path": "packages/app/src/Components/Textarea/Textarea.css",
    "content": ".rta__autocomplete {\n  z-index: 99;\n}\n\n.rta__list {\n  border-radius: 1rem;\n  border-color: var(--color-layer-2);\n  overflow: hidden;\n  background: var(--color-layer-1);\n}\n\n.rta__item:not(:last-child) {\n  border: none;\n}\n\n.rta__item {\n  background: none;\n}\n\n.rta__entity {\n  background: none;\n}\n\n.rta__entity--selected {\n  text-decoration: none;\n  background: var(--color-layer-2);\n}\n"
  },
  {
    "path": "packages/app/src/Components/Textarea/Textarea.tsx",
    "content": "import \"@webscopeio/react-textarea-autocomplete/style.css\"\nimport \"./Textarea.css\"\n\nimport { NostrLink } from \"@snort/system\"\nimport ReactTextareaAutocomplete from \"@webscopeio/react-textarea-autocomplete\"\nimport { useIntl } from \"react-intl\"\nimport TextareaAutosize from \"react-textarea-autosize\"\n\nimport Avatar from \"@/Components/User/Avatar\"\nimport type { FuzzySearchResult } from \"@/Db/FuzzySearch\"\nimport useProfileSearch from \"@/Hooks/useProfileSearch\"\nimport searchEmoji from \"@/Utils/emoji-search\"\n\nimport messages from \"../messages\"\nimport DisplayName from \"../User/DisplayName\"\n\nexport interface EmojiItemProps {\n  name: string\n  char: string\n}\n\nconst EmojiItem = ({ entity: { name, char } }: { entity: EmojiItemProps }) => {\n  return (\n    <div className=\"flex flex-row items-center gap-2 !py-3 !px-4\">\n      <div className=\"min-w-4\">{char}</div>\n      <div className=\"font-bold\">{name}</div>\n    </div>\n  )\n}\n\nconst UserItem = (metadata: FuzzySearchResult) => {\n  return (\n    <div key={metadata.pubkey} className=\"flex flex-row items-center gap-2 !py-3 !px-4\">\n      <Avatar pubkey={metadata.pubkey} user={metadata} size={28} />\n      <DisplayName pubkey={metadata.pubkey} user={metadata} />\n    </div>\n  )\n}\n\ninterface TextareaProps {\n  autoFocus: boolean\n  className?: string\n  placeholder?: string\n  onChange(ev: React.ChangeEvent<HTMLTextAreaElement>): void\n  value: string\n  onFocus(): void\n  onKeyDown(ev: React.KeyboardEvent<HTMLTextAreaElement>): void\n  onDragOver?(ev: React.DragEvent<HTMLTextAreaElement>): void\n  onDragLeave?(ev: React.DragEvent<HTMLTextAreaElement>): void\n  onDrop?(ev: React.DragEvent<HTMLTextAreaElement>): void\n}\n\ntype TriggerData = EmojiItemProps | FuzzySearchResult\n\nconst Textarea = (props: TextareaProps) => {\n  const { formatMessage } = useIntl()\n  const userSearch = useProfileSearch()\n\n  const userDataProvider = (token: string) => {\n    return userSearch(token).slice(0, 10)\n  }\n\n  const emojiDataProvider = async (token: string) => {\n    return (await searchEmoji(token)).slice(0, 5).map(({ name, char }) => ({ name, char }))\n  }\n\n  return (\n    // @ts-expect-error 2769\n    <ReactTextareaAutocomplete<TriggerData>\n      dir=\"auto\"\n      {...props}\n      loadingComponent={() => <span>Loading...</span>}\n      placeholder={props.placeholder ?? formatMessage(messages.NotePlaceholder)}\n      textAreaComponent={TextareaAutosize}\n      trigger={{\n        \":\": {\n          dataProvider: emojiDataProvider,\n          component: EmojiItem,\n          output: (item: EmojiItemProps) => item.char,\n        },\n        \"@\": {\n          afterWhitespace: true,\n          dataProvider: userDataProvider,\n          component: (props: { entity: FuzzySearchResult }) => <UserItem {...props.entity} />,\n          output: (item: { pubkey: string }) => `@${NostrLink.profile(item.pubkey).encode()}`,\n        },\n      }}\n    />\n  )\n}\n\nexport default Textarea\n"
  },
  {
    "path": "packages/app/src/Components/Toaster/Toaster.tsx",
    "content": "import { ExternalStore, unixNow } from \"@snort/shared\"\nimport { type ReactNode, useSyncExternalStore } from \"react\"\nimport { createPortal } from \"react-dom\"\nimport { v4 as uuid } from \"uuid\"\n\nimport Icon from \"@/Components/Icons/Icon\"\n\ninterface ToastNotification {\n  element: ReactNode | ((remove: () => void) => ReactNode)\n  expire?: number\n  icon?: string\n  id?: string\n}\n\nclass ToasterSlots extends ExternalStore<Array<ToastNotification>> {\n  #stack: Array<ToastNotification> = []\n\n  push(n: ToastNotification) {\n    n.expire ??= unixNow() + 10\n    n.id ??= uuid()\n    this.#stack.push(n)\n    this.notifyChange()\n  }\n\n  takeSnapshot(): ToastNotification[] {\n    return [...this.#stack]\n  }\n\n  remove(id?: string) {\n    this.#stack = this.#stack.filter(a => a.id !== id)\n    this.notifyChange()\n  }\n}\n\nexport const Toastore = new ToasterSlots()\n\nexport default function Toaster() {\n  const toast = useSyncExternalStore(\n    c => Toastore.hook(c),\n    () => Toastore.snapshot(),\n  )\n\n  return createPortal(\n    <div className=\"fixed bottom-0.5 left-0.5 flex flex-col-reverse z-[9999] gap-1\">\n      {toast.map(a => (\n        <div className=\"px-3 py-2 rounded-lg border gap-2 fade-in\" key={a.id}>\n          {a.icon && <Icon name={a.icon} />}\n          {typeof a.element === \"function\" ? a.element(() => Toastore.remove(a.id)) : a.element}\n        </div>\n      ))}\n    </div>,\n    document.body,\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Trending/ShortNote.tsx",
    "content": "import { NostrLink, type TaggedNostrEvent } from \"@snort/system\"\nimport { Link } from \"react-router-dom\"\n\nimport NoteTime from \"@/Components/Event/Note/NoteTime\"\nimport Text from \"@/Components/Text/Text\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\n\nexport default function TrendingNote({ event }: { event: TaggedNostrEvent }) {\n  // replace newlines with spaces, replace double spaces with single spaces\n  const content = event.content.slice(0, 80).replace(/\\n/g, \" \").replace(/ {2,}/g, \" \")\n  return (\n    <Link\n      to={`/${NostrLink.fromEvent(event).encode(CONFIG.eventLinkPrefix)}`}\n      state={event}\n      className=\"flex flex-col gap-1\"\n    >\n      <div className=\"flex flex-row justify-between\">\n        <ProfileImage pubkey={event.pubkey} size={28} showProfileCard={true} link=\"\" />\n        <NoteTime from={event.created_at * 1000} />\n      </div>\n      <Text\n        id={`${event.id}short`}\n        tags={event.tags}\n        creator={event.pubkey}\n        content={content}\n        truncate={75}\n        disableMedia={true}\n      />\n    </Link>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Trending/TrendingHashtags.tsx",
    "content": "import type { ReactNode } from \"react\"\nimport { Link } from \"react-router-dom\"\n\nimport { useLocale } from \"@/Components/IntlProvider/useLocale\"\nimport PageSpinner from \"@/Components/PageSpinner\"\nimport NostrBandApi from \"@/External/NostrBand\"\nimport { HashTagHeader } from \"@/Pages/HashTagsPage\"\n\nimport { ErrorOrOffline } from \"../ErrorOrOffline\"\nimport { useCached } from \"@snort/system-react\"\nimport { Hour } from \"@/Utils/Const\"\n\nexport default function TrendingHashtags({\n  title,\n  count = Infinity,\n  short,\n}: {\n  title?: ReactNode\n  count?: number\n  short?: boolean\n}) {\n  const { lang } = useLocale()\n  const {\n    data: hashtags,\n    error,\n    loading,\n  } = useCached(\n    \"nostr-band-trending-hashtags\",\n    async () => {\n      const api = new NostrBandApi()\n      return await api.trendingHashtags(lang)\n    },\n    Hour * 2,\n  )\n\n  if (error && !hashtags) return <ErrorOrOffline error={error} onRetry={() => {}} className=\"px-3 py-2\" />\n  if (loading && !hashtags) return <PageSpinner />\n\n  return (\n    <>\n      {title}\n      {hashtags?.hashtags.slice(0, count).map(a => {\n        if (short) {\n          return (\n            <div className=\"py-1 font-bold\" key={a.hashtag}>\n              <Link to={`/t/${a.hashtag}`}>#{a.hashtag}</Link>\n            </div>\n          )\n        } else {\n          return <HashTagHeader key={a.hashtag} tag={a.hashtag} events={a.posts} />\n        }\n      })}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Trending/TrendingPosts.tsx",
    "content": "import classNames from \"classnames\"\nimport { useMemo } from \"react\"\n\nimport { ErrorOrOffline } from \"@/Components/ErrorOrOffline\"\nimport Invoice from \"@/Components/Embed/Invoice\"\nimport Note from \"@/Components/Event/EventComponent\"\nimport PageSpinner from \"@/Components/PageSpinner\"\nimport TrendingNote from \"@/Components/Trending/ShortNote\"\nimport useModeration from \"@/Hooks/useModeration\"\nimport useContentDiscovery from \"@/Hooks/useContentDiscovery\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { findTag } from \"@snort/system\"\n\nexport default function TrendingNotes({ count = Infinity, small = false }: { count?: number; small?: boolean }) {\n  const trendingDvmPubkey = usePreferences(p => p.trendingDvmPubkey)\n\n  const serviceProvider = trendingDvmPubkey || \"0d9ec486275b70f0c4faec277fc4c63b9f14cb1ca1ec029f7d76210e957e5257\"\n  const { data, error } = useContentDiscovery(serviceProvider)\n  const { isEventMuted } = useModeration()\n\n  const options = useMemo(\n    () => ({\n      showFooter: !small,\n      showReactionsLink: !small,\n      showMedia: !small,\n      longFormPreview: !small,\n      truncate: small,\n      showContextMenu: !small,\n    }),\n    [small],\n  )\n\n  function getDVMInvoice(ev: any): { invoice: string; fromTags: boolean } | undefined {\n    // Check bolt11 tag first\n    const bolt11Tag = ev.tags?.find((t: any[]) => t[0] === \"bolt11\")\n    const bolt11 = bolt11Tag?.[1]\n    if (bolt11) return { invoice: bolt11, fromTags: true }\n\n    // NIP-90 kind:7000 may provide BOLT11 as the 3rd element of the \"amount\" tag: [\"amount\", \"<msats>\", \"<bolt11>\"]\n    const amountTag = ev.tags?.find((t: any[]) => t[0] === \"amount\")\n    const amountBolt11 = amountTag?.[2]\n    if (amountBolt11) return { invoice: amountBolt11, fromTags: true }\n\n    // Fallback to content match with broader regex for all bech32 prefixes\n    const contentInvoice = ev.content?.match(/ln(bc|tb|bcrt)[0-9a-zA-Z]+/i)\n    if (contentInvoice?.[0]) return { invoice: contentInvoice[0], fromTags: false }\n\n    return undefined\n  }\n\n  function isDVMPaymentRequired(ev: any): boolean {\n    if (ev.kind !== 7000) return false\n    const status = findTag(ev, \"status\")?.toLowerCase()\n    return status === \"payment-required\"\n  }\n\n  if (error && !data) return <ErrorOrOffline error={error} className=\"px-3 py-2\" />\n\n  const filteredAndLimitedPosts = data ? data.filter(a => !isEventMuted(a)).slice(0, count) : []\n\n  const renderList = () => {\n    if (data.length === 0) return <PageSpinner />\n    return filteredAndLimitedPosts.map((e: any, index) => {\n      // Show invoice for DVM payment-required events in non-small view\n      // Once paid, the DVM processes the request and returns results via NIP-90 responses\n      if (!small && isDVMPaymentRequired(e)) {\n        const invoiceData = getDVMInvoice(e)\n        // Only render extra Invoice component when invoice comes from tags (not content)\n        // to avoid duplicate rendering since Note already renders invoices from content\n        if (invoiceData?.fromTags) {\n          return (\n            <div key={e.id} className=\"flex flex-col gap-4\">\n              <Note key={`note-${e.id}`} data={e} depth={0} options={options} waitUntilInView={index > 5} />\n              <Invoice invoice={invoiceData.invoice} />\n            </div>\n          )\n        }\n      }\n      return small ? (\n        <TrendingNote key={e.id} event={e} />\n      ) : (\n        <Note key={e.id} data={e} depth={0} options={options} waitUntilInView={index > 5} />\n      )\n    })\n  }\n\n  return <div className={classNames(\"flex flex-col\", { \"gap-4 py-4\": small })}>{renderList()}</div>\n}\n"
  },
  {
    "path": "packages/app/src/Components/Trending/TrendingUsers.tsx",
    "content": "import type { ReactNode } from \"react\"\n\nimport PageSpinner from \"@/Components/PageSpinner\"\nimport FollowListBase, { type FollowListBaseProps } from \"@/Components/User/FollowListBase\"\nimport NostrBandApi from \"@/External/NostrBand\"\n\nimport { ErrorOrOffline } from \"../ErrorOrOffline\"\nimport { useCached } from \"@snort/system-react\"\nimport { Hour } from \"@/Utils/Const\"\n\nexport default function TrendingUsers({\n  title,\n  count = Infinity,\n  followListProps,\n}: {\n  title?: ReactNode\n  count?: number\n  followListProps?: Omit<FollowListBaseProps, \"pubkeys\">\n}) {\n  const { data, loading, error } = useCached(\n    \"nostr-band-trending-profiles\",\n    async () => {\n      const api = new NostrBandApi()\n      return await api.trendingProfiles()\n    },\n    Hour * 2,\n  )\n\n  if (error && !data) {\n    return <ErrorOrOffline error={error} onRetry={() => {}} className=\"px-3 py-2\" />\n  }\n\n  if (loading) {\n    return <PageSpinner />\n  }\n\n  return (\n    <FollowListBase\n      pubkeys={data?.profiles.map(a => a.pubkey)?.slice(0, count) ?? []}\n      title={title}\n      showFollowAll={true}\n      className=\"flex flex-col gap-2\"\n      profilePreviewProps={{\n        options: {\n          about: true,\n        },\n      }}\n      {...followListProps}\n    />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/Upload/file-picker.tsx",
    "content": "import classNames from \"classnames\"\nimport { useCallback, useEffect, useState } from \"react\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\n\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useImgProxy from \"@/Hooks/useImgProxy\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { useMediaServerList } from \"@/Hooks/useMediaServerList\"\nimport { type BlobDescriptor, Blossom } from \"@/Utils/Upload/blossom\"\n\nimport AsyncButton from \"../Button/AsyncButton\"\n\nexport function MediaServerFileList({\n  onPicked,\n  cols,\n}: {\n  onPicked: (files: Array<BlobDescriptor>) => void\n  cols?: number\n}) {\n  const { state } = useLogin(s => ({ v: s.state.version, state: s.state }))\n  const { publisher } = useEventPublisher()\n  const [fileList, setFilesList] = useState<Array<BlobDescriptor>>([])\n  const [pickedFiles, setPickedFiles] = useState<Array<string>>([])\n  const servers = useMediaServerList()\n\n  const listFiles = useCallback(async () => {\n    const res = []\n    if (!publisher) return\n    for (const s of servers.servers) {\n      try {\n        const sx = new Blossom(s, publisher)\n        const files = await sx.list(state.pubkey)\n        res.push(...files)\n      } catch (e) {\n        console.error(e)\n      }\n    }\n    setFilesList(res)\n  }, [publisher, servers.servers, state.pubkey])\n\n  function toggleFile(b: BlobDescriptor) {\n    setPickedFiles(a => {\n      if (a.includes(b.sha256)) {\n        return a.filter(a => a !== b.sha256)\n      } else {\n        return [...a, b.sha256]\n      }\n    })\n  }\n\n  useEffect(() => {\n    let cancelled = false\n    listFiles()\n      .then(() => {\n        if (cancelled) setFilesList([])\n      })\n      .catch(console.error)\n    return () => {\n      cancelled = true\n    }\n  }, [listFiles])\n\n  const finalFileList = fileList\n    .sort((a, b) => (b.uploaded ?? 0) - (a.uploaded ?? 0))\n    .reduce(\n      (acc, v) => {\n        acc[v.sha256] ??= []\n        acc[v.sha256].push(v)\n        return acc\n      },\n      {} as Record<string, Array<BlobDescriptor>>,\n    )\n\n  return (\n    <div>\n      <div\n        className={classNames(\"grid gap-4 my-2\", {\n          \"grid-cols-2\": cols === 2 || cols === undefined,\n          \"grid-cols-6\": cols === 6,\n        })}\n      >\n        {Object.entries(finalFileList).map(([k, v]) => (\n          <ServerFile key={k} file={v[0]} onClick={() => toggleFile(v[0])} checked={pickedFiles.includes(k)} />\n        ))}\n      </div>\n      <AsyncButton\n        disabled={pickedFiles.length === 0}\n        onClick={() => onPicked(fileList.filter(a => pickedFiles.includes(a.sha256)))}\n      >\n        <FormattedMessage defaultMessage=\"Select\" />\n      </AsyncButton>\n    </div>\n  )\n}\n\nfunction ServerFile({ file, checked, onClick }: { file: BlobDescriptor; checked: boolean; onClick: () => void }) {\n  const { proxy } = useImgProxy()\n\n  function backgroundImage() {\n    if (file.url && (file.type?.startsWith(\"image/\") || file.type?.startsWith(\"video/\"))) {\n      return `url(${proxy(file.url, 512)})`\n    }\n  }\n\n  return (\n    <div onClick={() => onClick()}>\n      <div\n        className=\"relative bg-layer-2 rounded-lg overflow-hidden aspect-square cursor-pointer hover:outline outline-highlight bg-cover bg-center m-1\"\n        style={{\n          backgroundImage: backgroundImage(),\n        }}\n      >\n        <div className=\"absolute w-full h-full opacity-0 bg-black hover:opacity-80 flex flex-col items-center justify-center gap-4\">\n          <div>\n            {file.size > 1024 * 1024 && (\n              <FormattedMessage\n                defaultMessage=\"{n}MiB\"\n                values={{\n                  n: <FormattedNumber value={file.size / 1024 / 1024} />,\n                }}\n              />\n            )}\n            {file.size < 1024 * 1024 && (\n              <FormattedMessage\n                defaultMessage=\"{n}KiB\"\n                values={{\n                  n: <FormattedNumber value={file.size / 1024} />,\n                }}\n              />\n            )}\n          </div>\n          <div>{file.uploaded && new Date(file.uploaded * 1000).toLocaleString()}</div>\n        </div>\n        <div\n          className={classNames(\"w-4 h-4 border-2 rounded-full right-1 top-1 absolute\", {\n            \"bg-zap\": checked,\n          })}\n        />\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/AnimalName.ts",
    "content": "/* eslint-disable max-lines */\n\nimport { sha256 } from \"@noble/hashes/sha2.js\"\nimport { utf8ToBytes } from \"@noble/hashes/utils.js\"\n\nconst animals = [\n  \"canidae\",\n  \"felidae\",\n  \"cat\",\n  \"cattle\",\n  \"dog\",\n  \"donkey\",\n  \"goat\",\n  \"horse\",\n  \"pig\",\n  \"rabbit\",\n  \"aardvark\",\n  \"aardwolf\",\n  \"albatross\",\n  \"alligator\",\n  \"alpaca\",\n  \"amphibian\",\n  \"anaconda\",\n  \"angelfish\",\n  \"anglerfish\",\n  \"ant\",\n  \"anteater\",\n  \"antelope\",\n  \"antlion\",\n  \"ape\",\n  \"aphid\",\n  \"armadillo\",\n  \"asp\",\n  \"baboon\",\n  \"badger\",\n  \"bandicoot\",\n  \"barnacle\",\n  \"barracuda\",\n  \"basilisk\",\n  \"bass\",\n  \"bat\",\n  \"bear\",\n  \"beaver\",\n  \"bedbug\",\n  \"bee\",\n  \"beetle\",\n  \"bird\",\n  \"bison\",\n  \"blackbird\",\n  \"boa\",\n  \"boar\",\n  \"bobcat\",\n  \"bobolink\",\n  \"bonobo\",\n  \"booby\",\n  \"bovid\",\n  \"bug\",\n  \"butterfly\",\n  \"buzzard\",\n  \"camel\",\n  \"canid\",\n  \"capybara\",\n  \"cardinal\",\n  \"caribou\",\n  \"carp\",\n  \"cat\",\n  \"catshark\",\n  \"caterpillar\",\n  \"catfish\",\n  \"cattle\",\n  \"centipede\",\n  \"cephalopod\",\n  \"chameleon\",\n  \"cheetah\",\n  \"chickadee\",\n  \"chicken\",\n  \"chimpanzee\",\n  \"chinchilla\",\n  \"chipmunk\",\n  \"clam\",\n  \"clownfish\",\n  \"cobra\",\n  \"cockroach\",\n  \"cod\",\n  \"condor\",\n  \"constrictor\",\n  \"coral\",\n  \"cougar\",\n  \"cow\",\n  \"coyote\",\n  \"crab\",\n  \"crane\",\n  \"crawdad\",\n  \"crayfish\",\n  \"cricket\",\n  \"crocodile\",\n  \"crow\",\n  \"cuckoo\",\n  \"cicada\",\n  \"damselfly\",\n  \"deer\",\n  \"dingo\",\n  \"dinosaur\",\n  \"dog\",\n  \"dolphin\",\n  \"donkey\",\n  \"dormouse\",\n  \"dove\",\n  \"dragonfly\",\n  \"dragon\",\n  \"duck\",\n  \"eagle\",\n  \"earthworm\",\n  \"earwig\",\n  \"echidna\",\n  \"eel\",\n  \"egret\",\n  \"elephant\",\n  \"elk\",\n  \"emu\",\n  \"ermine\",\n  \"falcon\",\n  \"ferret\",\n  \"finch\",\n  \"firefly\",\n  \"fish\",\n  \"flamingo\",\n  \"flea\",\n  \"fly\",\n  \"flyingfish\",\n  \"fowl\",\n  \"fox\",\n  \"frog\",\n  \"gamefowl\",\n  \"galliform\",\n  \"gazelle\",\n  \"gecko\",\n  \"gerbil\",\n  \"gibbon\",\n  \"giraffe\",\n  \"goat\",\n  \"goldfish\",\n  \"goose\",\n  \"gopher\",\n  \"gorilla\",\n  \"grasshopper\",\n  \"grouse\",\n  \"guan\",\n  \"guanaco\",\n  \"guineafowl\",\n  \"gull\",\n  \"guppy\",\n  \"haddock\",\n  \"halibut\",\n  \"hamster\",\n  \"hare\",\n  \"harrier\",\n  \"hawk\",\n  \"hedgehog\",\n  \"heron\",\n  \"herring\",\n  \"hippopotamus\",\n  \"hookworm\",\n  \"hornet\",\n  \"horse\",\n  \"hoverfly\",\n  \"hummingbird\",\n  \"hyena\",\n  \"iguana\",\n  \"impala\",\n  \"jackal\",\n  \"jaguar\",\n  \"jay\",\n  \"jellyfish\",\n  \"junglefowl\",\n  \"kangaroo\",\n  \"kingfisher\",\n  \"kite\",\n  \"kiwi\",\n  \"koala\",\n  \"koi\",\n  \"krill\",\n  \"ladybug\",\n  \"lamprey\",\n  \"landfowl\",\n  \"lark\",\n  \"leech\",\n  \"lemming\",\n  \"lemur\",\n  \"leopard\",\n  \"leopon\",\n  \"limpet\",\n  \"lion\",\n  \"lizard\",\n  \"llama\",\n  \"lobster\",\n  \"locust\",\n  \"loon\",\n  \"louse\",\n  \"lungfish\",\n  \"lynx\",\n  \"macaw\",\n  \"mackerel\",\n  \"magpie\",\n  \"mammal\",\n  \"manatee\",\n  \"mandrill\",\n  \"marlin\",\n  \"marmoset\",\n  \"marmot\",\n  \"marsupial\",\n  \"marten\",\n  \"mastodon\",\n  \"meadowlark\",\n  \"meerkat\",\n  \"mink\",\n  \"minnow\",\n  \"mite\",\n  \"mockingbird\",\n  \"mole\",\n  \"mollusk\",\n  \"mongoose\",\n  \"monkey\",\n  \"moose\",\n  \"mosquito\",\n  \"moth\",\n  \"mouse\",\n  \"mule\",\n  \"muskox\",\n  \"narwhal\",\n  \"newt\",\n  \"nightingale\",\n  \"ocelot\",\n  \"octopus\",\n  \"opossum\",\n  \"orangutan\",\n  \"orca\",\n  \"ostrich\",\n  \"otter\",\n  \"owl\",\n  \"ox\",\n  \"panda\",\n  \"panther\",\n  \"parakeet\",\n  \"parrot\",\n  \"parrotfish\",\n  \"partridge\",\n  \"peacock\",\n  \"peafowl\",\n  \"pelican\",\n  \"penguin\",\n  \"perch\",\n  \"pheasant\",\n  \"pig\",\n  \"pigeon\",\n  \"pike\",\n  \"pinniped\",\n  \"piranha\",\n  \"planarian\",\n  \"platypus\",\n  \"pony\",\n  \"porcupine\",\n  \"porpoise\",\n  \"possum\",\n  \"prawn\",\n  \"primate\",\n  \"ptarmigan\",\n  \"puffin\",\n  \"puma\",\n  \"python\",\n  \"quail\",\n  \"quelea\",\n  \"quokka\",\n  \"rabbit\",\n  \"raccoon\",\n  \"rat\",\n  \"rattlesnake\",\n  \"raven\",\n  \"reindeer\",\n  \"reptile\",\n  \"rhinoceros\",\n  \"roadrunner\",\n  \"rodent\",\n  \"rook\",\n  \"rooster\",\n  \"roundworm\",\n  \"sailfish\",\n  \"salamander\",\n  \"salmon\",\n  \"sawfish\",\n  \"scallop\",\n  \"scorpion\",\n  \"seahorse\",\n  \"shark\",\n  \"sheep\",\n  \"shrew\",\n  \"shrimp\",\n  \"silkworm\",\n  \"silverfish\",\n  \"skink\",\n  \"skunk\",\n  \"sloth\",\n  \"slug\",\n  \"smelt\",\n  \"snail\",\n  \"snake\",\n  \"snipe\",\n  \"sole\",\n  \"sparrow\",\n  \"spider\",\n  \"spoonbill\",\n  \"squid\",\n  \"squirrel\",\n  \"starfish\",\n  \"stingray\",\n  \"stoat\",\n  \"stork\",\n  \"sturgeon\",\n  \"swallow\",\n  \"swan\",\n  \"swift\",\n  \"swordfish\",\n  \"swordtail\",\n  \"tahr\",\n  \"takin\",\n  \"tapir\",\n  \"tarantula\",\n  \"tarsier\",\n  \"termite\",\n  \"tern\",\n  \"thrush\",\n  \"tick\",\n  \"tiger\",\n  \"tiglon\",\n  \"toad\",\n  \"tortoise\",\n  \"toucan\",\n  \"trout\",\n  \"tuna\",\n  \"turkey\",\n  \"turtle\",\n  \"tyrannosaurus\",\n  \"urial\",\n  \"vicuna\",\n  \"viper\",\n  \"vole\",\n  \"vulture\",\n  \"wallaby\",\n  \"walrus\",\n  \"wasp\",\n  \"warbler\",\n  \"weasel\",\n  \"whale\",\n  \"whippet\",\n  \"whitefish\",\n  \"wildcat\",\n  \"wildebeest\",\n  \"wildfowl\",\n  \"wolf\",\n  \"wolverine\",\n  \"wombat\",\n  \"woodpecker\",\n  \"worm\",\n  \"wren\",\n  \"xerinae\",\n  \"yak\",\n  \"zebra\",\n  \"alpaca\",\n  \"cat\",\n  \"cattle\",\n  \"chicken\",\n  \"dog\",\n  \"donkey\",\n  \"ferret\",\n  \"gayal\",\n  \"goldfish\",\n  \"guppy\",\n  \"horse\",\n  \"koi\",\n  \"llama\",\n  \"sheep\",\n  \"yak\",\n  \"unicorn\",\n]\n\nconst adjectives = [\n  \"average\",\n  \"big\",\n  \"colossal\",\n  \"fat\",\n  \"giant\",\n  \"gigantic\",\n  \"great\",\n  \"huge\",\n  \"immense\",\n  \"large\",\n  \"little\",\n  \"long\",\n  \"mammoth\",\n  \"massive\",\n  \"miniature\",\n  \"petite\",\n  \"puny\",\n  \"short\",\n  \"small\",\n  \"tall\",\n  \"tiny\",\n  \"boiling\",\n  \"breezy\",\n  \"broken\",\n  \"bumpy\",\n  \"chilly\",\n  \"cold\",\n  \"cool\",\n  \"creepy\",\n  \"crooked\",\n  \"cuddly\",\n  \"curly\",\n  \"damaged\",\n  \"damp\",\n  \"dirty\",\n  \"dry\",\n  \"dusty\",\n  \"filthy\",\n  \"flaky\",\n  \"fluffy\",\n  \"wet\",\n  \"broad\",\n  \"chubby\",\n  \"crooked\",\n  \"curved\",\n  \"deep\",\n  \"flat\",\n  \"high\",\n  \"hollow\",\n  \"low\",\n  \"narrow\",\n  \"round\",\n  \"shallow\",\n  \"skinny\",\n  \"square\",\n  \"steep\",\n  \"straight\",\n  \"wide\",\n  \"ancient\",\n  \"brief\",\n  \"early\",\n  \"fast\",\n  \"late\",\n  \"long\",\n  \"modern\",\n  \"old\",\n  \"quick\",\n  \"rapid\",\n  \"short\",\n  \"slow\",\n  \"swift\",\n  \"young\",\n  \"abundant\",\n  \"empty\",\n  \"few\",\n  \"heavy\",\n  \"light\",\n  \"many\",\n  \"numerous\",\n  \"Sound\",\n  \"cooing\",\n  \"deafening\",\n  \"faint\",\n  \"harsh\",\n  \"hissing\",\n  \"hushed\",\n  \"husky\",\n  \"loud\",\n  \"melodic\",\n  \"moaning\",\n  \"mute\",\n  \"noisy\",\n  \"purring\",\n  \"quiet\",\n  \"raspy\",\n  \"resonant\",\n  \"screeching\",\n  \"shrill\",\n  \"silent\",\n  \"soft\",\n  \"squealing\",\n  \"thundering\",\n  \"voiceless\",\n  \"whispering\",\n  \"bitter\",\n  \"delicious\",\n  \"fresh\",\n  \"juicy\",\n  \"ripe\",\n  \"rotten\",\n  \"salty\",\n  \"sour\",\n  \"spicy\",\n  \"stale\",\n  \"sticky\",\n  \"strong\",\n  \"sweet\",\n  \"tasteless\",\n  \"tasty\",\n  \"thirsty\",\n  \"fluttering\",\n  \"fuzzy\",\n  \"greasy\",\n  \"grubby\",\n  \"hard\",\n  \"hot\",\n  \"icy\",\n  \"loose\",\n  \"melted\",\n  \"plastic\",\n  \"prickly\",\n  \"rainy\",\n  \"rough\",\n  \"scattered\",\n  \"shaggy\",\n  \"shaky\",\n  \"sharp\",\n  \"shivering\",\n  \"silky\",\n  \"slimy\",\n  \"slippery\",\n  \"smooth\",\n  \"soft\",\n  \"solid\",\n  \"steady\",\n  \"sticky\",\n  \"tender\",\n  \"tight\",\n  \"uneven\",\n  \"weak\",\n  \"wet\",\n  \"wooden\",\n  \"afraid\",\n  \"angry\",\n  \"annoyed\",\n  \"anxious\",\n  \"arrogant\",\n  \"ashamed\",\n  \"awful\",\n  \"bad\",\n  \"bewildered\",\n  \"bored\",\n  \"combative\",\n  \"condemned\",\n  \"confused\",\n  \"creepy\",\n  \"cruel\",\n  \"dangerous\",\n  \"defeated\",\n  \"defiant\",\n  \"depressed\",\n  \"disgusted\",\n  \"disturbed\",\n  \"eerie\",\n  \"embarrassed\",\n  \"envious\",\n  \"evil\",\n  \"fierce\",\n  \"foolish\",\n  \"frantic\",\n  \"frightened\",\n  \"grieving\",\n  \"helpless\",\n  \"homeless\",\n  \"hungry\",\n  \"hurt\",\n  \"ill\",\n  \"jealous\",\n  \"lonely\",\n  \"mysterious\",\n  \"naughty\",\n  \"nervous\",\n  \"obnoxious\",\n  \"outrageous\",\n  \"panicky\",\n  \"repulsive\",\n  \"scary\",\n  \"scornful\",\n  \"selfish\",\n  \"sore\",\n  \"tense\",\n  \"terrible\",\n  \"thoughtless\",\n  \"tired\",\n  \"troubled\",\n  \"upset\",\n  \"uptight\",\n  \"weary\",\n  \"wicked\",\n  \"worried\",\n  \"agreeable\",\n  \"amused\",\n  \"brave\",\n  \"calm\",\n  \"charming\",\n  \"cheerful\",\n  \"comfortable\",\n  \"cooperative\",\n  \"courageous\",\n  \"delightful\",\n  \"determined\",\n  \"eager\",\n  \"elated\",\n  \"enchanting\",\n  \"encouraging\",\n  \"energetic\",\n  \"enthusiastic\",\n  \"excited\",\n  \"exuberant\",\n  \"fair\",\n  \"faithful\",\n  \"fantastic\",\n  \"fine\",\n  \"friendly\",\n  \"funny\",\n  \"gentle\",\n  \"glorious\",\n  \"good\",\n  \"happy\",\n  \"healthy\",\n  \"helpful\",\n  \"hilarious\",\n  \"jolly\",\n  \"joyous\",\n  \"kind\",\n  \"lively\",\n  \"lovely\",\n  \"lucky\",\n  \"obedient\",\n  \"perfect\",\n  \"pleasant\",\n  \"proud\",\n  \"relieved\",\n  \"silly\",\n  \"smiling\",\n  \"splendid\",\n  \"successful\",\n  \"thoughtful\",\n  \"victorious\",\n  \"vivacious\",\n  \"witty\",\n  \"wonderful\",\n  \"zealous\",\n  \"zany\",\n  \"other\",\n  \"good\",\n  \"new\",\n  \"old\",\n  \"great\",\n  \"high\",\n  \"small\",\n  \"different\",\n  \"large\",\n  \"local\",\n  \"social\",\n  \"important\",\n  \"long\",\n  \"young\",\n  \"national\",\n  \"british\",\n  \"right\",\n  \"early\",\n  \"possible\",\n  \"big\",\n  \"little\",\n  \"political\",\n  \"able\",\n  \"late\",\n  \"general\",\n  \"full\",\n  \"far\",\n  \"low\",\n  \"public\",\n  \"available\",\n  \"bad\",\n  \"main\",\n  \"sure\",\n  \"clear\",\n  \"major\",\n  \"economic\",\n  \"only\",\n  \"likely\",\n  \"real\",\n  \"black\",\n  \"particular\",\n  \"international\",\n  \"special\",\n  \"difficult\",\n  \"certain\",\n  \"open\",\n  \"whole\",\n  \"white\",\n  \"free\",\n  \"short\",\n  \"easy\",\n  \"strong\",\n  \"european\",\n  \"central\",\n  \"similar\",\n  \"human\",\n  \"common\",\n  \"necessary\",\n  \"single\",\n  \"personal\",\n  \"hard\",\n  \"private\",\n  \"poor\",\n  \"financial\",\n  \"wide\",\n  \"foreign\",\n  \"simple\",\n  \"recent\",\n  \"concerned\",\n  \"american\",\n  \"various\",\n  \"close\",\n  \"fine\",\n  \"english\",\n  \"wrong\",\n  \"present\",\n  \"royal\",\n  \"natural\",\n  \"individual\",\n  \"nice\",\n  \"french\",\n  \"nihilist\",\n  \"solipsist\",\n  \"materialist\",\n  \"surrealist\",\n  \"heroic\",\n  \"awesome\",\n  \"hedonist\",\n  \"absurd\",\n  \"current\",\n  \"modern\",\n  \"labour\",\n  \"legal\",\n  \"happy\",\n  \"final\",\n  \"red\",\n  \"normal\",\n  \"serious\",\n  \"previous\",\n  \"total\",\n  \"prime\",\n  \"significant\",\n  \"industrial\",\n  \"sorry\",\n  \"dead\",\n  \"specific\",\n  \"appropriate\",\n  \"top\",\n  \"soviet\",\n  \"basic\",\n  \"military\",\n  \"original\",\n  \"successful\",\n  \"aware\",\n  \"hon\",\n  \"popular\",\n  \"heavy\",\n  \"professional\",\n  \"direct\",\n  \"dark\",\n  \"cold\",\n  \"ready\",\n  \"green\",\n  \"useful\",\n  \"effective\",\n  \"western\",\n  \"traditional\",\n  \"scottish\",\n  \"german\",\n  \"independent\",\n  \"deep\",\n  \"interesting\",\n  \"considerable\",\n  \"involved\",\n  \"physical\",\n  \"hot\",\n  \"existing\",\n  \"responsible\",\n  \"complete\",\n  \"medical\",\n  \"blue\",\n  \"extra\",\n  \"past\",\n  \"male\",\n  \"interested\",\n  \"fair\",\n  \"essential\",\n  \"beautiful\",\n  \"civil\",\n  \"primary\",\n  \"obvious\",\n  \"future\",\n  \"environmental\",\n  \"positive\",\n  \"senior\",\n  \"nuclear\",\n  \"annual\",\n  \"relevant\",\n  \"huge\",\n  \"rich\",\n  \"commercial\",\n  \"safe\",\n  \"regional\",\n  \"practical\",\n  \"official\",\n  \"separate\",\n  \"key\",\n  \"chief\",\n  \"regular\",\n  \"due\",\n  \"additional\",\n  \"active\",\n  \"powerful\",\n  \"complex\",\n  \"standard\",\n  \"impossible\",\n  \"light\",\n  \"warm\",\n  \"middle\",\n  \"fresh\",\n  \"sexual\",\n  \"front\",\n  \"domestic\",\n  \"actual\",\n  \"united\",\n  \"technical\",\n  \"ordinary\",\n  \"cheap\",\n  \"strange\",\n  \"internal\",\n  \"excellent\",\n  \"quiet\",\n  \"soft\",\n  \"potential\",\n  \"northern\",\n  \"religious\",\n  \"quick\",\n  \"very\",\n  \"famous\",\n  \"cultural\",\n  \"proper\",\n  \"broad\",\n  \"joint\",\n  \"formal\",\n  \"limited\",\n  \"conservative\",\n  \"lovely\",\n  \"usual\",\n  \"ltd\",\n  \"unable\",\n  \"rural\",\n  \"initial\",\n  \"substantial\",\n  \"bright\",\n  \"average\",\n  \"leading\",\n  \"reasonable\",\n  \"immediate\",\n  \"suitable\",\n  \"equal\",\n  \"detailed\",\n  \"working\",\n  \"overall\",\n  \"female\",\n  \"afraid\",\n  \"democratic\",\n  \"growing\",\n  \"sufficient\",\n  \"scientific\",\n  \"eastern\",\n  \"correct\",\n  \"inc\",\n  \"irish\",\n  \"expensive\",\n  \"educational\",\n  \"mental\",\n  \"dangerous\",\n  \"critical\",\n  \"increased\",\n  \"familiar\",\n  \"unlikely\",\n  \"double\",\n  \"perfect\",\n  \"slow\",\n  \"tiny\",\n  \"dry\",\n  \"historical\",\n  \"thin\",\n  \"daily\",\n  \"southern\",\n  \"increasing\",\n  \"wild\",\n  \"alone\",\n  \"urban\",\n  \"empty\",\n  \"married\",\n  \"narrow\",\n  \"liberal\",\n  \"supposed\",\n  \"upper\",\n  \"apparent\",\n  \"tall\",\n  \"busy\",\n  \"bloody\",\n  \"prepared\",\n  \"russian\",\n  \"moral\",\n  \"careful\",\n  \"clean\",\n  \"attractive\",\n  \"japanese\",\n  \"vital\",\n  \"thick\",\n  \"alternative\",\n  \"fast\",\n  \"ancient\",\n  \"elderly\",\n  \"rare\",\n  \"external\",\n  \"capable\",\n  \"brief\",\n  \"wonderful\",\n  \"grand\",\n  \"typical\",\n  \"entire\",\n  \"grey\",\n  \"constant\",\n  \"vast\",\n  \"surprised\",\n  \"ideal\",\n  \"terrible\",\n  \"academic\",\n  \"funny\",\n  \"minor\",\n  \"pleased\",\n  \"severe\",\n  \"ill\",\n  \"corporate\",\n  \"negative\",\n  \"permanent\",\n  \"weak\",\n  \"brown\",\n  \"fundamental\",\n  \"odd\",\n  \"crucial\",\n  \"inner\",\n  \"used\",\n  \"criminal\",\n  \"contemporary\",\n  \"sharp\",\n  \"sick\",\n  \"near\",\n  \"roman\",\n  \"massive\",\n  \"unique\",\n  \"secondary\",\n  \"parliamentary\",\n  \"african\",\n  \"unknown\",\n  \"subsequent\",\n  \"angry\",\n  \"alive\",\n  \"guilty\",\n  \"lucky\",\n  \"enormous\",\n  \"well\",\n  \"yellow\",\n  \"unusual\",\n  \"net\",\n  \"tough\",\n  \"dear\",\n  \"extensive\",\n  \"glad\",\n  \"remaining\",\n  \"agricultural\",\n  \"alright\",\n  \"healthy\",\n  \"italian\",\n  \"principal\",\n  \"tired\",\n  \"efficient\",\n  \"comfortable\",\n  \"chinese\",\n  \"relative\",\n  \"friendly\",\n  \"conventional\",\n  \"willing\",\n  \"sudden\",\n  \"proposed\",\n  \"voluntary\",\n  \"slight\",\n  \"valuable\",\n  \"dramatic\",\n  \"golden\",\n  \"temporary\",\n  \"federal\",\n  \"keen\",\n  \"flat\",\n  \"silent\",\n  \"indian\",\n  \"worried\",\n  \"pale\",\n  \"statutory\",\n  \"welsh\",\n  \"dependent\",\n  \"firm\",\n  \"wet\",\n  \"competitive\",\n  \"armed\",\n  \"radical\",\n  \"outside\",\n  \"acceptable\",\n  \"sensitive\",\n  \"living\",\n  \"pure\",\n  \"global\",\n  \"emotional\",\n  \"sad\",\n  \"secret\",\n  \"rapid\",\n  \"adequate\",\n  \"fixed\",\n  \"sweet\",\n  \"administrative\",\n  \"wooden\",\n  \"remarkable\",\n  \"comprehensive\",\n  \"surprising\",\n  \"solid\",\n  \"rough\",\n  \"mere\",\n  \"mass\",\n  \"brilliant\",\n  \"maximum\",\n  \"absolute\",\n  \"electronic\",\n  \"visual\",\n  \"electric\",\n  \"cool\",\n  \"spanish\",\n  \"literary\",\n  \"continuing\",\n  \"supreme\",\n  \"chemical\",\n  \"genuine\",\n  \"exciting\",\n  \"written\",\n  \"advanced\",\n  \"extreme\",\n  \"classical\",\n  \"fit\",\n  \"favourite\",\n  \"widespread\",\n  \"confident\",\n  \"straight\",\n  \"proud\",\n  \"numerous\",\n  \"opposite\",\n  \"distinct\",\n  \"mad\",\n  \"helpful\",\n  \"given\",\n  \"disabled\",\n  \"consistent\",\n  \"anxious\",\n  \"nervous\",\n  \"awful\",\n  \"stable\",\n  \"constitutional\",\n  \"satisfied\",\n  \"conscious\",\n  \"developing\",\n  \"strategic\",\n  \"holy\",\n  \"smooth\",\n  \"dominant\",\n  \"remote\",\n  \"theoretical\",\n  \"outstanding\",\n  \"pink\",\n  \"pretty\",\n  \"clinical\",\n  \"minimum\",\n  \"honest\",\n  \"impressive\",\n  \"related\",\n  \"residential\",\n  \"extraordinary\",\n  \"plain\",\n  \"visible\",\n  \"accurate\",\n  \"distant\",\n  \"still\",\n  \"greek\",\n  \"complicated\",\n  \"musical\",\n  \"precise\",\n  \"gentle\",\n  \"broken\",\n  \"live\",\n  \"silly\",\n  \"fat\",\n  \"tight\",\n  \"monetary\",\n  \"round\",\n  \"psychological\",\n  \"violent\",\n  \"unemployed\",\n  \"inevitable\",\n  \"junior\",\n  \"sensible\",\n  \"grateful\",\n  \"pleasant\",\n  \"dirty\",\n  \"structural\",\n  \"welcome\",\n  \"deaf\",\n  \"above\",\n  \"continuous\",\n  \"blind\",\n  \"overseas\",\n  \"mean\",\n  \"entitled\",\n  \"delighted\",\n  \"loose\",\n  \"occasional\",\n  \"evident\",\n  \"desperate\",\n  \"fellow\",\n  \"universal\",\n  \"square\",\n  \"steady\",\n  \"classic\",\n  \"equivalent\",\n  \"intellectual\",\n  \"victorian\",\n  \"level\",\n  \"ultimate\",\n  \"creative\",\n  \"lost\",\n  \"medieval\",\n  \"clever\",\n  \"linguistic\",\n  \"convinced\",\n  \"judicial\",\n  \"raw\",\n  \"sophisticated\",\n  \"asleep\",\n  \"vulnerable\",\n  \"illegal\",\n  \"outer\",\n  \"revolutionary\",\n  \"bitter\",\n  \"changing\",\n  \"australian\",\n  \"native\",\n  \"imperial\",\n  \"strict\",\n  \"wise\",\n  \"informal\",\n  \"flexible\",\n  \"collective\",\n  \"frequent\",\n  \"experimental\",\n  \"spiritual\",\n  \"intense\",\n  \"rational\",\n  \"generous\",\n  \"inadequate\",\n  \"prominent\",\n  \"logical\",\n  \"bare\",\n  \"historic\",\n  \"modest\",\n  \"dutch\",\n  \"acute\",\n  \"electrical\",\n  \"valid\",\n  \"weekly\",\n  \"gross\",\n  \"automatic\",\n  \"loud\",\n  \"reliable\",\n  \"mutual\",\n  \"liable\",\n  \"multiple\",\n  \"ruling\",\n  \"curious\",\n  \"sole\",\n  \"managing\",\n  \"pregnant\",\n  \"latin\",\n  \"nearby\",\n  \"exact\",\n  \"underlying\",\n  \"identical\",\n  \"satisfactory\",\n  \"marginal\",\n  \"distinctive\",\n  \"electoral\",\n  \"urgent\",\n  \"presidential\",\n  \"controversial\",\n  \"everyday\",\n  \"encouraging\",\n  \"organic\",\n  \"continued\",\n  \"expected\",\n  \"statistical\",\n  \"desirable\",\n  \"innocent\",\n  \"improved\",\n  \"exclusive\",\n  \"marked\",\n  \"experienced\",\n  \"unexpected\",\n  \"superb\",\n  \"sheer\",\n  \"disappointed\",\n  \"frightened\",\n  \"gastric\",\n  \"romantic\",\n  \"naked\",\n  \"reluctant\",\n  \"magnificent\",\n  \"convenient\",\n  \"established\",\n  \"closed\",\n  \"uncertain\",\n  \"artificial\",\n  \"diplomatic\",\n  \"tremendous\",\n  \"marine\",\n  \"mechanical\",\n  \"retail\",\n  \"institutional\",\n  \"mixed\",\n  \"required\",\n  \"biological\",\n  \"known\",\n  \"functional\",\n  \"straightforward\",\n  \"superior\",\n  \"digital\",\n  \"spectacular\",\n  \"unhappy\",\n  \"confused\",\n  \"unfair\",\n  \"aggressive\",\n  \"spare\",\n  \"painful\",\n  \"abstract\",\n  \"asian\",\n  \"associated\",\n  \"legislative\",\n  \"monthly\",\n  \"intelligent\",\n  \"hungry\",\n  \"explicit\",\n  \"nasty\",\n  \"just\",\n  \"faint\",\n  \"coloured\",\n  \"ridiculous\",\n  \"amazing\",\n  \"comparable\",\n  \"successive\",\n  \"realistic\",\n  \"back\",\n  \"decent\",\n  \"decentralized\",\n  \"bitcoin\",\n  \"cypherpunk\",\n  \"unnecessary\",\n  \"flying\",\n  \"random\",\n  \"influential\",\n  \"dull\",\n  \"genetic\",\n  \"neat\",\n  \"marvellous\",\n  \"crazy\",\n  \"damp\",\n  \"giant\",\n  \"secure\",\n  \"bottom\",\n  \"skilled\",\n  \"subtle\",\n  \"elegant\",\n  \"brave\",\n  \"lesser\",\n  \"parallel\",\n  \"steep\",\n  \"intensive\",\n  \"casual\",\n  \"tropical\",\n  \"lonely\",\n  \"partial\",\n  \"preliminary\",\n  \"concrete\",\n  \"alleged\",\n  \"assistant\",\n  \"vertical\",\n  \"upset\",\n  \"delicate\",\n  \"mild\",\n  \"occupational\",\n  \"excessive\",\n  \"progressive\",\n  \"exceptional\",\n  \"integrated\",\n  \"striking\",\n  \"continental\",\n  \"okay\",\n  \"harsh\",\n  \"combined\",\n  \"fierce\",\n  \"handsome\",\n  \"characteristic\",\n  \"chronic\",\n  \"compulsory\",\n  \"interim\",\n  \"objective\",\n  \"splendid\",\n  \"magic\",\n  \"systematic\",\n  \"obliged\",\n  \"payable\",\n  \"fun\",\n  \"horrible\",\n  \"primitive\",\n  \"fascinating\",\n  \"ideological\",\n  \"metropolitan\",\n  \"surrounding\",\n  \"estimated\",\n  \"peaceful\",\n  \"premier\",\n  \"operational\",\n  \"technological\",\n  \"kind\",\n  \"advisory\",\n  \"hostile\",\n  \"precious\",\n  \"accessible\",\n  \"determined\",\n  \"excited\",\n  \"impressed\",\n  \"provincial\",\n  \"smart\",\n  \"endless\",\n  \"isolated\",\n  \"drunk\",\n  \"geographical\",\n  \"like\",\n  \"dynamic\",\n  \"boring\",\n  \"forthcoming\",\n  \"unfortunate\",\n  \"definite\",\n  \"super\",\n  \"notable\",\n  \"indirect\",\n  \"stiff\",\n  \"wealthy\",\n  \"awkward\",\n  \"lively\",\n  \"neutral\",\n  \"artistic\",\n  \"content\",\n  \"mature\",\n  \"colonial\",\n  \"ambitious\",\n  \"evil\",\n  \"magnetic\",\n  \"verbal\",\n  \"legitimate\",\n  \"sympathetic\",\n  \"empirical\",\n  \"head\",\n  \"shallow\",\n  \"vague\",\n  \"naval\",\n  \"depressed\",\n  \"shared\",\n  \"added\",\n  \"shocked\",\n  \"mid\",\n  \"worthwhile\",\n  \"qualified\",\n  \"missing\",\n  \"blank\",\n  \"absent\",\n  \"favourable\",\n  \"polish\",\n  \"israeli\",\n  \"developed\",\n  \"profound\",\n  \"representative\",\n  \"enthusiastic\",\n  \"dreadful\",\n  \"rigid\",\n  \"reduced\",\n  \"cruel\",\n  \"coastal\",\n  \"peculiar\",\n  \"swiss\",\n  \"crude\",\n  \"extended\",\n  \"selected\",\n  \"eager\",\n  \"canadian\",\n  \"bold\",\n  \"relaxed\",\n  \"corresponding\",\n  \"running\",\n  \"planned\",\n  \"applicable\",\n  \"immense\",\n  \"allied\",\n  \"comparative\",\n  \"uncomfortable\",\n  \"conservation\",\n  \"productive\",\n  \"beneficial\",\n  \"bored\",\n  \"charming\",\n  \"minimal\",\n  \"mobile\",\n  \"turkish\",\n  \"orange\",\n  \"rear\",\n  \"passive\",\n  \"suspicious\",\n  \"overwhelming\",\n  \"fatal\",\n  \"resulting\",\n  \"symbolic\",\n  \"registered\",\n  \"neighbouring\",\n  \"calm\",\n  \"irrelevant\",\n  \"patient\",\n  \"compact\",\n  \"profitable\",\n  \"rival\",\n  \"loyal\",\n  \"moderate\",\n  \"distinguished\",\n  \"interior\",\n  \"noble\",\n  \"insufficient\",\n  \"eligible\",\n  \"mysterious\",\n  \"varying\",\n  \"managerial\",\n  \"molecular\",\n  \"olympic\",\n  \"linear\",\n  \"prospective\",\n  \"printed\",\n  \"parental\",\n  \"diverse\",\n  \"elaborate\",\n  \"furious\",\n  \"fiscal\",\n  \"burning\",\n  \"useless\",\n  \"semantic\",\n  \"embarrassed\",\n  \"inherent\",\n  \"philosophical\",\n  \"deliberate\",\n  \"awake\",\n  \"variable\",\n  \"promising\",\n  \"unpleasant\",\n  \"varied\",\n  \"sacred\",\n  \"selective\",\n  \"inclined\",\n  \"tender\",\n  \"hidden\",\n  \"worthy\",\n  \"intermediate\",\n  \"sound\",\n  \"protective\",\n  \"fortunate\",\n  \"slim\",\n  \"defensive\",\n  \"divine\",\n  \"stuck\",\n  \"driving\",\n  \"invisible\",\n  \"misleading\",\n  \"circular\",\n  \"mathematical\",\n  \"inappropriate\",\n  \"liquid\",\n  \"persistent\",\n  \"solar\",\n  \"doubtful\",\n  \"manual\",\n  \"architectural\",\n  \"intact\",\n  \"incredible\",\n  \"devoted\",\n  \"prior\",\n  \"tragic\",\n  \"respectable\",\n  \"optimistic\",\n  \"convincing\",\n  \"unacceptable\",\n  \"decisive\",\n  \"competent\",\n  \"spatial\",\n  \"respective\",\n  \"binding\",\n  \"relieved\",\n  \"nursing\",\n  \"toxic\",\n  \"select\",\n  \"redundant\",\n  \"integral\",\n  \"then\",\n  \"probable\",\n  \"amateur\",\n  \"fond\",\n  \"passing\",\n  \"specified\",\n  \"territorial\",\n  \"horizontal\",\n  \"inland\",\n  \"cognitive\",\n  \"regulatory\",\n  \"miserable\",\n  \"resident\",\n  \"polite\",\n  \"scared\",\n  \"gothic\",\n  \"civilian\",\n  \"instant\",\n  \"lengthy\",\n  \"adverse\",\n  \"korean\",\n  \"unconscious\",\n  \"anonymous\",\n  \"aesthetic\",\n  \"orthodox\",\n  \"static\",\n  \"unaware\",\n  \"costly\",\n  \"fantastic\",\n  \"foolish\",\n  \"fashionable\",\n  \"causal\",\n  \"compatible\",\n  \"wee\",\n  \"implicit\",\n  \"dual\",\n  \"ok\",\n  \"cheerful\",\n  \"subjective\",\n  \"forward\",\n  \"surviving\",\n  \"exotic\",\n  \"purple\",\n  \"cautious\",\n  \"visiting\",\n  \"aggregate\",\n  \"ethical\",\n  \"teenage\",\n  \"dying\",\n  \"disastrous\",\n  \"delicious\",\n  \"confidential\",\n  \"underground\",\n  \"thorough\",\n  \"grim\",\n  \"autonomous\",\n  \"atomic\",\n  \"frozen\",\n  \"colourful\",\n  \"injured\",\n  \"uniform\",\n  \"ashamed\",\n  \"glorious\",\n  \"wicked\",\n  \"coherent\",\n  \"rising\",\n  \"shy\",\n  \"novel\",\n  \"balanced\",\n  \"delightful\",\n  \"arbitrary\",\n  \"adjacent\",\n  \"worrying\",\n  \"weird\",\n  \"unchanged\",\n  \"rolling\",\n  \"evolutionary\",\n  \"intimate\",\n  \"sporting\",\n  \"disciplinary\",\n  \"formidable\",\n  \"lexical\",\n  \"noisy\",\n  \"gradual\",\n  \"accused\",\n  \"homeless\",\n  \"supporting\",\n  \"coming\",\n  \"renewed\",\n  \"excess\",\n  \"retired\",\n  \"rubber\",\n  \"chosen\",\n  \"outdoor\",\n  \"embarrassing\",\n  \"preferred\",\n  \"bizarre\",\n  \"appalling\",\n  \"agreed\",\n  \"imaginative\",\n  \"governing\",\n  \"accepted\",\n  \"vocational\",\n  \"mighty\",\n  \"puzzled\",\n  \"worldwide\",\n  \"organisational\",\n  \"sunny\",\n  \"eldest\",\n  \"eventual\",\n  \"spontaneous\",\n  \"vivid\",\n  \"rude\",\n  \"faithful\",\n  \"ministerial\",\n  \"innovative\",\n  \"controlled\",\n  \"conceptual\",\n  \"unwilling\",\n  \"civic\",\n  \"meaningful\",\n  \"alive\",\n  \"brainy\",\n  \"breakable\",\n  \"busy\",\n  \"careful\",\n  \"cautious\",\n  \"clever\",\n  \"concerned\",\n  \"crazy\",\n  \"curious\",\n  \"dead\",\n  \"different\",\n  \"difficult\",\n  \"doubtful\",\n  \"easy\",\n  \"famous\",\n  \"fragile\",\n  \"helpful\",\n  \"helpless\",\n  \"important\",\n  \"impossible\",\n  \"innocent\",\n  \"inquisitive\",\n  \"modern\",\n  \"open\",\n  \"outstanding\",\n  \"poor\",\n  \"powerful\",\n  \"puzzled\",\n  \"real\",\n  \"rich\",\n  \"shy\",\n  \"sleepy\",\n  \"super\",\n  \"tame\",\n  \"uninterested\",\n  \"wandering\",\n  \"wild\",\n  \"wrong\",\n  \"adorable\",\n  \"alert\",\n  \"average\",\n  \"beautiful\",\n  \"blonde\",\n  \"bloody\",\n  \"blushing\",\n  \"bright\",\n  \"clean\",\n  \"clear\",\n  \"cloudy\",\n  \"colorful\",\n  \"crowded\",\n  \"cute\",\n  \"dark\",\n  \"drab\",\n  \"distinct\",\n  \"dull\",\n  \"elegant\",\n  \"fancy\",\n  \"filthy\",\n  \"glamorous\",\n  \"gleaming\",\n  \"graceful\",\n  \"grotesque\",\n  \"homely\",\n  \"light\",\n  \"misty\",\n  \"motionless\",\n  \"muddy\",\n  \"plain\",\n  \"poised\",\n  \"quaint\",\n  \"shiny\",\n  \"smoggy\",\n  \"sparkling\",\n  \"spotless\",\n  \"stormy\",\n  \"strange\",\n  \"ugly\",\n  \"unsightly\",\n  \"unusual\",\n  \"bad\",\n  \"better\",\n  \"beautiful\",\n  \"big\",\n  \"black\",\n  \"blue\",\n  \"bright\",\n  \"clumsy\",\n  \"crazy\",\n  \"dizzy\",\n  \"dull\",\n  \"fat\",\n  \"frail\",\n  \"friendly\",\n  \"funny\",\n  \"great\",\n  \"green\",\n  \"gigantic\",\n  \"gorgeous\",\n  \"grumpy\",\n  \"handsome\",\n  \"happy\",\n  \"horrible\",\n  \"itchy\",\n  \"jittery\",\n  \"jolly\",\n  \"kind\",\n  \"long\",\n  \"lazy\",\n  \"magnificent\",\n  \"magenta\",\n  \"many\",\n  \"mighty\",\n  \"mushy\",\n  \"nasty\",\n  \"new\",\n  \"nice\",\n  \"nosy\",\n  \"nutty\",\n  \"nutritious\",\n  \"odd\",\n  \"orange\",\n  \"ordinary\",\n  \"pretty\",\n  \"precious\",\n  \"prickly\",\n  \"purple\",\n  \"quaint\",\n  \"quiet\",\n  \"quick\",\n  \"quickest\",\n  \"rainy\",\n  \"rare\",\n  \"ratty\",\n  \"red\",\n  \"roasted\",\n  \"robust\",\n  \"round\",\n  \"sad\",\n  \"scary\",\n  \"scrawny\",\n  \"short\",\n  \"silly\",\n  \"stingy\",\n  \"strange\",\n  \"striped\",\n  \"spotty\",\n  \"tart\",\n  \"tall\",\n  \"tame\",\n  \"tan\",\n  \"tender\",\n  \"testy\",\n  \"tricky\",\n  \"tough\",\n  \"ugly\",\n  \"ugliest\",\n  \"vast\",\n  \"watery\",\n  \"wasteful\",\n  \"wonderful\",\n  \"yellow\",\n  \"yummy\",\n  \"zany\",\n]\n\nfunction capitalize(s: string) {\n  return s.charAt(0).toUpperCase() + s.slice(1)\n}\n\n/**\n * deterministically create adjective + animal names\n */\nexport default function (seed: string) {\n  if (!seed) {\n    throw new Error(\"No seed provided\")\n  }\n  const hash = sha256(utf8ToBytes(seed)) // Uint8Array\n  const adjective = adjectives[hash[0] % adjectives.length]\n  const animal = animals[hash[1] % animals.length]\n  return `${capitalize(adjective)} ${capitalize(animal)}`\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/Avatar.tsx",
    "content": "import type { UserMetadata } from \"@snort/system\"\nimport classNames from \"classnames\"\nimport { forwardRef, type HTMLProps, type ReactNode, useMemo } from \"react\"\n\nimport { ProxyImg } from \"@/Components/ProxyImg\"\nimport { defaultAvatar, getDisplayName } from \"@/Utils\"\n\ninterface AvatarProps {\n  pubkey: string\n  user?: UserMetadata\n  onClick?: () => void\n  size?: number\n  image?: string\n  imageOverlay?: ReactNode\n  icons?: ReactNode\n  showTitle?: boolean\n  className?: string\n}\n\nconst Avatar = forwardRef<\n  HTMLDivElement,\n  AvatarProps & Omit<HTMLProps<HTMLDivElement>, \"onClick\" | \"style\" | \"className\">\n>(\n  (\n    { pubkey, user, size = 48, onClick, image, imageOverlay, icons, className, showTitle = true, children, ...others },\n    ref,\n  ) => {\n    const defaultImg = defaultAvatar(pubkey)\n    const url = useMemo(() => {\n      if ((image?.length ?? 0) > 0) return image\n      if ((user?.picture?.length ?? 0) > 0) return user?.picture\n      return defaultImg\n    }, [user, image, defaultImg])\n\n    size ??= 120\n\n    const domain = user?.nip05?.split(\"@\")[1]\n    return (\n      <div\n        ref={ref}\n        onClick={onClick}\n        style={{\n          width: `${size}px`,\n          height: `${size}px`,\n        }}\n        className={classNames(\n          \"relative rounded-full aspect-square flex items-center justify-center gap-2 bg-neutral-600 z-1\",\n          className,\n        )}\n        data-domain={domain?.toLowerCase()}\n        title={showTitle ? getDisplayName(user, \"\") : undefined}\n        {...others}\n      >\n        <ProxyImg\n          className=\"absolute rounded-full w-full h-full object-cover\"\n          src={url}\n          bypassProxy={url === defaultImg}\n          size={size}\n          alt={getDisplayName(user, \"\")}\n          promptToLoadDirectly={false}\n        />\n        {icons && (\n          <div\n            className=\"absolute flex items-center justify-center w-full h-full origin-center\"\n            style={{\n              transform: \"rotate(-135deg) translateY(50%)\",\n            }}\n          >\n            <div\n              style={{\n                transform: \"rotate(135deg)\",\n              }}\n            >\n              {icons}\n            </div>\n          </div>\n        )}\n        {imageOverlay && (\n          <div className=\"absolute rounded-full bg-black/40 w-full h-full flex items-center justify-center\">\n            {imageOverlay}\n          </div>\n        )}\n        {children}\n      </div>\n    )\n  },\n)\nexport default Avatar\n"
  },
  {
    "path": "packages/app/src/Components/User/AvatarEditor.tsx",
    "content": "import { useState } from \"react\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport Spinner from \"@/Components/Icons/Spinner\"\nimport { openFile, unwrap } from \"@/Utils\"\nimport useFileUpload from \"@/Utils/Upload\"\nimport classNames from \"classnames\"\n\ninterface AvatarEditorProps {\n  picture?: string\n  className?: string\n  onPictureChange?: (newPicture: string) => void\n  privKey?: string\n}\n\nexport default function AvatarEditor({ picture, onPictureChange, privKey, className }: AvatarEditorProps) {\n  const uploader = useFileUpload(privKey)\n  const [error, setError] = useState(\"\")\n  const [loading, setLoading] = useState(false)\n\n  async function uploadFile() {\n    setError(\"\")\n    setLoading(true)\n    try {\n      const f = await openFile()\n      if (f && uploader) {\n        const rsp = await uploader.upload(f)\n        onPictureChange?.(unwrap(rsp.url))\n      }\n    } catch (e) {\n      if (e instanceof Error) {\n        setError(`Upload failed: ${e.message}`)\n      } else {\n        setError(`Upload failed`)\n      }\n    }\n    setLoading(false)\n  }\n\n  return (\n    <>\n      <div className=\"flex justify-center items-center\">\n        <div\n          style={{ backgroundImage: `url(${picture})`, backgroundSize: \"cover\", backgroundPosition: \"center\" }}\n          className={classNames(\"layer-2 w-40 h-40 rounded-full\", className)}\n        >\n          <div\n            className={`flex items-center justify-center w-full h-full cursor-pointer rounded-full ${picture ? \"opacity-20 hover:opacity-90\" : \"\"}`}\n            onClick={() => uploadFile().catch(console.error)}\n          >\n            <div className=\"light:bg-neutral-200 p-4 rounded-full\">\n              {loading ? <Spinner /> : <Icon name={picture ? \"edit\" : \"camera-plus\"} />}\n            </div>\n          </div>\n        </div>\n      </div>\n      {error && <b className=\"text-error\">{error}</b>}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/AvatarGroup.tsx",
    "content": "import ProfileImage, { type ProfileImageProps } from \"@/Components/User/ProfileImage\"\n\nexport function AvatarGroup({ ids, ...props }: { ids: string[] } & Omit<ProfileImageProps, \"pubkey\">) {\n  // set defaults\n  props.showUsername ??= false\n  props.link ??= \"\"\n  props.size ??= 24\n  props.showFollowDistance ??= false\n  props.showProfileCard ??= false\n\n  return (\n    <div className=\"flex items-center\">\n      {ids.map((a, index) => (\n        <div className={`inline-block ${index > 0 ? \"-ml-2\" : \"\"}`} key={a}>\n          <ProfileImage pubkey={a} {...props} />\n        </div>\n      ))}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/BadgeList.tsx",
    "content": "import type { TaggedNostrEvent } from \"@snort/system\"\nimport { useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport Modal from \"@/Components/Modal/Modal\"\nimport { ProxyImg } from \"@/Components/ProxyImg\"\nimport Username from \"@/Components/User/Username\"\nimport { findTag } from \"@/Utils\"\nimport useProfileBadges from \"@/Feed/BadgesFeed\"\n\ninterface BadgeInfo {\n  id: string\n  pubkey: string\n  name?: string\n  description?: string\n  thumb?: string\n  image?: string\n}\n\nexport default function BadgeList({ badges }: { badges: TaggedNostrEvent[] }) {\n  const [badgeModal, setShowModal] = useState<BadgeInfo>()\n  const badgeMetadata = badges.map(b => {\n    const thumb = findTag(b, \"thumb\")\n    const image = findTag(b, \"image\")\n    const name = findTag(b, \"name\")\n    const description = findTag(b, \"description\")\n    return {\n      id: b.id,\n      pubkey: b.pubkey,\n      name,\n      description,\n      thumb: (thumb?.length ?? 0 > 0) ? thumb : image,\n      image,\n    } as BadgeInfo\n  })\n  if (badgeMetadata.length === 0) return\n  return (\n    <>\n      <div className=\"flex items-center gap-1 flex-wrap\">\n        {badgeMetadata.map(v => (\n          <ProxyImg\n            alt={v.name}\n            key={v.id}\n            className=\"w-8 h-8 object-contain cursor-pointer\"\n            size={64}\n            src={v.thumb}\n            promptToLoadDirectly={false}\n            onClick={() => setShowModal(v)}\n            missingImageElement={\n              <div\n                className=\"w-8 h-8 layer-1 flex items-center justify-center cursor-pointer\"\n                onClick={() => setShowModal(v)}\n              >\n                ?\n              </div>\n            }\n          />\n        ))}\n      </div>\n      {badgeModal && (\n        <Modal id=\"badges-info\" onClose={() => setShowModal(undefined)}>\n          <div className=\"flex flex-col gap-2\">\n            <h2>\n              <FormattedMessage defaultMessage=\"Badge Info\" />\n            </h2>\n            <ProxyImg src={badgeModal.image} size={128} alt={badgeModal.name} />\n            <h3>{badgeModal.name}</h3>\n            <p>{badgeModal.description}</p>\n            <div>\n              <FormattedMessage\n                defaultMessage=\"By: {author}\"\n                values={{ author: <Username pubkey={badgeModal.pubkey} onLinkVisit={() => setShowModal(undefined)} /> }}\n              />\n            </div>\n          </div>\n        </Modal>\n      )}\n    </>\n  )\n}\n\nexport function ProfileBadges({ pubkey }: { pubkey: string }) {\n  const badges = useProfileBadges(pubkey)\n  return <BadgeList badges={badges} />\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/Bookmarks.tsx",
    "content": "import type { TaggedNostrEvent } from \"@snort/system\"\nimport { type ChangeEvent, use, useMemo, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport Note from \"@/Components/Event/EventComponent\"\nimport useLogin from \"@/Hooks/useLogin\"\n\nimport messages from \"../messages\"\nimport { SnortContext } from \"@snort/system-react\"\n\ninterface BookmarksProps {\n  pubkey: string\n  bookmarks: readonly TaggedNostrEvent[]\n}\n\nconst Bookmarks = ({ pubkey, bookmarks }: BookmarksProps) => {\n  const [onlyPubkey, setOnlyPubkey] = useState<string | \"all\">(\"all\")\n  const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }))\n\n  const system = use(SnortContext)\n  const ps = useMemo(() => {\n    return [...new Set(bookmarks.map(ev => ev.pubkey))]\n  }, [bookmarks])\n  const options = useMemo(\n    () => ({ showTime: false, showBookmarked: true, canUnbookmark: publicKey === pubkey, longFormPreview: true }),\n    [publicKey, pubkey],\n  )\n\n  function renderOption(p: string) {\n    const profile = system.config.profiles.getFromCache(p)\n    return profile ? <option value={p}>{profile?.display_name || profile?.name}</option> : null\n  }\n\n  return (\n    <>\n      <div className=\"flex-end px-3 py-2\">\n        <select\n          disabled={ps.length <= 1}\n          value={onlyPubkey}\n          onChange={(e: ChangeEvent<HTMLSelectElement>) => setOnlyPubkey(e.target.value)}\n        >\n          <option value=\"all\">\n            <FormattedMessage {...messages.All} />\n          </option>\n          {ps.map(renderOption)}\n        </select>\n      </div>\n      {bookmarks\n        .filter(b => (onlyPubkey === \"all\" ? true : b.pubkey === onlyPubkey))\n        .map(n => {\n          return <Note key={n.id} data={n} options={options} />\n        })}\n    </>\n  )\n}\n\nexport default Bookmarks\n"
  },
  {
    "path": "packages/app/src/Components/User/Debug.tsx",
    "content": "import { useUserProfile } from \"@snort/system-react\"\n\nimport { UserRelays } from \"@/Cache\"\nimport useWoT from \"@/Hooks/useWoT\"\nimport { getRelayName } from \"@/Utils\"\n\nexport function UserDebug({ pubkey }: { pubkey: string }) {\n  const profile = useUserProfile(pubkey)\n  const relays = UserRelays.getFromCache(pubkey)\n  const wot = useWoT()\n\n  return (\n    <div className=\"text-xs\">\n      <div className=\"flex flex-col overflow-wrap\">\n        <div className=\"flex justify-between gap-1\">\n          <div>WoT Distance:</div>\n          <div>{wot.followDistance(pubkey)}</div>\n        </div>\n        {Object.entries(profile ?? {}).map(([k, v]) => {\n          let vv = <div>{v}</div>\n\n          if (k === \"loaded\") vv = <div>{new Date(Number(v)).toISOString()}</div>\n          if (k === \"created\") vv = <div>{new Date(Number(v) * 1000).toISOString()}</div>\n          if (k === \"npub\" || k === \"pubkey\") return\n          return (\n            <div key={`${pubkey}-${k}`} className=\"flex justify-between gap-1\">\n              <div>{k}</div>\n              {vv}\n            </div>\n          )\n        })}\n      </div>\n      <hr />\n      <div className=\"flex flex-col\">\n        <div>Relays Updated: {new Date(1000 * (relays?.created ?? 0)).toISOString()}</div>\n        {relays?.relays.map(a => (\n          <div className=\"flex hover:bg-neutral-800\" key={a.url}>\n            <div className=\"grow\">{getRelayName(a.url)}</div>\n            <div>{a.settings.read && <>R</>}</div>\n            <div>{a.settings.write && <>W</>}</div>\n          </div>\n        ))}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/DisplayName.tsx",
    "content": "import type { UserMetadata } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport classNames from \"classnames\"\nimport { useMemo, useRef } from \"react\"\n\nimport { getDisplayNameOrPlaceHolder } from \"@/Utils\"\n\ninterface DisplayNameProps {\n  pubkey: string\n  user?: UserMetadata | undefined\n  className?: string\n}\n\nconst DisplayName = ({ pubkey, user, className }: DisplayNameProps) => {\n  const ref = useRef<HTMLSpanElement>(null)\n  const profile = useUserProfile(user ? undefined : pubkey, ref) ?? user\n  const [name, isPlaceHolder] = useMemo(() => getDisplayNameOrPlaceHolder(profile, pubkey), [profile, pubkey])\n\n  return (\n    <span ref={ref} className={classNames(className, { \"text-gray-light\": isPlaceHolder })}>\n      {name}\n    </span>\n  )\n}\n\nexport default DisplayName\n"
  },
  {
    "path": "packages/app/src/Components/User/FollowButton.tsx",
    "content": "import classNames from \"classnames\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport useFollowsControls from \"@/Hooks/useFollowControls\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { parseId } from \"@/Utils\"\n\nimport messages from \"../messages\"\n\nexport interface FollowButtonProps {\n  pubkey: string\n  className?: string\n}\nexport default function FollowButton(props: FollowButtonProps) {\n  const pubkey = parseId(props.pubkey)\n  const readonly = useLogin(s => s.readonly)\n  const control = useFollowsControls()\n  const isFollowing = control.isFollowing(pubkey)\n\n  return (\n    <AsyncButton\n      className={classNames(props.className, \"secondary\")}\n      disabled={readonly}\n      onClick={async e => {\n        e.stopPropagation()\n        await (isFollowing ? control.removeFollow([pubkey]) : control.addFollow([pubkey]))\n      }}\n    >\n      {isFollowing ? <FormattedMessage {...messages.Unfollow} /> : <FormattedMessage {...messages.Follow} />}\n    </AsyncButton>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/FollowDistanceIndicator.tsx",
    "content": "import classNames from \"classnames\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport useWoT from \"@/Hooks/useWoT\"\n\ninterface FollowDistanceIndicatorProps {\n  pubkey: string\n  className?: string\n}\n\nexport default function FollowDistanceIndicator({ pubkey, className }: FollowDistanceIndicatorProps) {\n  const wot = useWoT()\n  const followDistance = wot.followDistance(pubkey)\n  let followDistanceColor = \"\"\n  let title = \"\"\n\n  if (followDistance === 0) {\n    title = \"You\"\n    followDistanceColor = \"text-success\"\n  } else if (followDistance <= 1) {\n    followDistanceColor = \"text-success\"\n    title = \"Following\"\n  } else if (followDistance === 2) {\n    const followedByFriendsCount = wot.followedByCount(pubkey)\n    if (followedByFriendsCount > 10) {\n      followDistanceColor = \"text-zap\"\n    }\n    title = `Followed by ${followedByFriendsCount} friends`\n  } else if (followDistance > 2) {\n    return null\n  }\n\n  return (\n    <div\n      className={classNames(\"w-4 h-4 bg-layer-1 rounded-full flex items-center justify-center\", className)}\n      title={title}\n    >\n      <Icon name=\"check\" className={followDistanceColor} size={10} />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/FollowListBase.tsx",
    "content": "import classNames from \"classnames\"\nimport { type ReactNode, useMemo, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport ProfilePreview, { type ProfilePreviewProps } from \"@/Components/User/ProfilePreview\"\nimport useFollowsControls from \"@/Hooks/useFollowControls\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport useWoT from \"@/Hooks/useWoT\"\n\nimport AsyncButton from \"../Button/AsyncButton\"\n\nexport interface FollowListBaseProps {\n  pubkeys: string[]\n  title?: ReactNode\n  showFollowAll?: boolean\n  className?: string\n  actions?: ReactNode\n  profilePreviewProps?: Omit<ProfilePreviewProps, \"pubkey\">\n  pageSize?: number\n}\n\nexport default function FollowListBase({\n  pubkeys,\n  title,\n  showFollowAll,\n  className,\n  actions,\n  profilePreviewProps,\n  pageSize = 50,\n}: FollowListBaseProps) {\n  const control = useFollowsControls()\n  const readonly = useLogin(s => s.readonly)\n  const wot = useWoT()\n  const [currentPage, setCurrentPage] = useState(1)\n\n  const sortedPubkeys = useMemo(() => wot.sortPubkeys(pubkeys), [pubkeys, wot])\n\n  const totalPages = Math.ceil(sortedPubkeys.length / pageSize)\n  const startIndex = (currentPage - 1) * pageSize\n  const endIndex = startIndex + pageSize\n  const currentPagePubkeys = sortedPubkeys.slice(startIndex, endIndex)\n\n  async function followAll() {\n    await control.addFollow(pubkeys)\n  }\n\n  const goToPage = (page: number) => {\n    setCurrentPage(Math.max(1, Math.min(page, totalPages)))\n  }\n\n  return (\n    <>\n      <div className={classNames(\"flex flex-col gap-2\", className)}>\n        {(showFollowAll ?? true) && (\n          <div className=\"flex items-center\">\n            <div className=\"grow font-bold text-xl\">{title}</div>\n            {actions}\n            <AsyncButton className=\"transparent\" type=\"button\" onClick={() => followAll()} disabled={readonly}>\n              <FormattedMessage defaultMessage=\"Follow All\" />\n            </AsyncButton>\n          </div>\n        )}\n        {currentPagePubkeys.map(a => (\n          <ProfilePreview pubkey={a} key={a} {...profilePreviewProps} />\n        ))}\n      </div>\n      {totalPages > 1 && (\n        <div className=\"flex items-center justify-center gap-2 mt-4 mb-10\">\n          <button onClick={() => goToPage(currentPage - 1)} disabled={currentPage === 1}>\n            <FormattedMessage defaultMessage=\"Previous\" />\n          </button>\n          <span className=\"text-sm\">\n            <FormattedMessage\n              defaultMessage=\"Page {current} of {total} ({count} items)\"\n              values={{ current: currentPage, total: totalPages, count: sortedPubkeys.length }}\n            />\n          </span>\n          <button onClick={() => goToPage(currentPage + 1)} disabled={currentPage === totalPages}>\n            <FormattedMessage defaultMessage=\"Next\" />\n          </button>\n        </div>\n      )}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/FollowedBy.tsx",
    "content": "import { Fragment, useMemo } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport { AvatarGroup } from \"@/Components/User/AvatarGroup\"\nimport DisplayName from \"@/Components/User/DisplayName\"\nimport { ProfileLink } from \"@/Components/User/ProfileLink\"\nimport useWoT from \"@/Hooks/useWoT\"\nimport type { ProfileImageProps } from \"./ProfileImage\"\n\nconst MAX_FOLLOWED_BY_FRIENDS = 3\n\nexport default function FollowedBy({ pubkey, ...props }: { pubkey: string } & Omit<ProfileImageProps, \"pubkey\">) {\n  const wot = useWoT()\n  const followDistance = wot.followDistance(pubkey)\n  const { followedByFriendsArray, totalFollowedByFriends } = useMemo(() => {\n    const followedByFriends = wot.followedBy(pubkey)\n    return {\n      followedByFriendsArray: Array.from(followedByFriends).slice(0, MAX_FOLLOWED_BY_FRIENDS),\n      totalFollowedByFriends: followedByFriends.size,\n    }\n  }, [pubkey, wot.followedBy])\n\n  const renderFollowedByFriendsLinks = () => {\n    return followedByFriendsArray.map((a, index) => (\n      <Fragment key={a}>\n        <ProfileLink pubkey={a} className=\"link inline\">\n          <DisplayName user={undefined} pubkey={a} />\n        </ProfileLink>\n        {index < followedByFriendsArray.length - 1 && \",\"}{\" \"}\n      </Fragment>\n    ))\n  }\n\n  return (\n    <div className=\"flex items-center gap-2\">\n      <AvatarGroup ids={followedByFriendsArray} {...props} />\n      {totalFollowedByFriends > 0 && (\n        <div className=\"text-gray-light\">\n          <span className=\"mr-1\">\n            <FormattedMessage defaultMessage=\"Followed by\" />\n          </span>\n          {renderFollowedByFriendsLinks()}\n          {totalFollowedByFriends > MAX_FOLLOWED_BY_FRIENDS && (\n            <span>\n              <FormattedMessage\n                defaultMessage=\"and {count} others you follow\"\n                id=\"CYkOCI\"\n                values={{ count: totalFollowedByFriends - MAX_FOLLOWED_BY_FRIENDS }}\n              />\n            </span>\n          )}\n        </div>\n      )}\n      {followDistance > 3 && (\n        <div className=\"text-gray-light\">\n          <FormattedMessage defaultMessage=\"Not followed by anyone you follow\" />\n        </div>\n      )}\n      {followDistance === 3 && ( // TODO \"followed by friends of {n} friends\"\n        <div className=\"text-gray-light\">\n          <FormattedMessage defaultMessage=\"Followed by friends of friends\" />\n        </div>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/Following.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport useFollowsControls from \"@/Hooks/useFollowControls\"\n\nexport function FollowingMark({ pubkey }: { pubkey: string }) {\n  const { isFollowing } = useFollowsControls()\n  const doesFollow = isFollowing(pubkey)\n  if (!doesFollow) return\n\n  return (\n    <span className=\"flex gap-1 px-1 py-0.5 text-sm layer-1\">\n      <Icon name=\"check\" className=\"text-success\" size={12} />\n      <FormattedMessage defaultMessage=\"following\" />\n    </span>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/FollowsYou.tsx",
    "content": "import { useIntl } from \"react-intl\"\n\nimport messages from \"../messages\"\n\nexport interface FollowsYouProps {\n  followsMe: boolean\n}\n\nexport default function FollowsYou({ followsMe }: FollowsYouProps) {\n  const { formatMessage } = useIntl()\n  return followsMe ? (\n    <span className=\"layer-1 text-xs font-normal px-1.5 py-1 leading-none\">{formatMessage(messages.FollowsYou)}</span>\n  ) : null\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/MuteButton.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nimport useModeration from \"@/Hooks/useModeration\"\n\nimport AsyncButton from \"../Button/AsyncButton\"\n\ninterface MuteButtonProps {\n  pubkey: string\n}\n\nconst MuteButton = ({ pubkey }: MuteButtonProps) => {\n  const { mute, unmute, isMuted } = useModeration()\n  return isMuted(pubkey) ? (\n    <AsyncButton className=\"secondary\" type=\"button\" onClick={() => unmute(pubkey)}>\n      <FormattedMessage defaultMessage=\"Unmute\" />\n    </AsyncButton>\n  ) : (\n    <AsyncButton type=\"button\" onClick={() => mute(pubkey)}>\n      <FormattedMessage defaultMessage=\"Mute\" />\n    </AsyncButton>\n  )\n}\n\nexport default MuteButton\n"
  },
  {
    "path": "packages/app/src/Components/User/MutedList.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nimport MuteButton from \"@/Components/User/MuteButton\"\nimport ProfilePreview from \"@/Components/User/ProfilePreview\"\nimport useModeration from \"@/Hooks/useModeration\"\n\nimport messages from \"../messages\"\n\nexport interface MutedListProps {\n  pubkeys: Array<string>\n}\n\nexport default function MutedList() {\n  const { muteList } = useModeration()\n\n  return (\n    <div className=\"px-3 py-2\">\n      <div className=\"flex justify-between\">\n        <div className=\"bold\">\n          <FormattedMessage {...messages.MuteCount} values={{ n: muteList?.length }} />\n        </div>\n      </div>\n      {muteList?.map(a => {\n        const tag = a.toEventTag()\n        switch (tag?.at(0)) {\n          case \"p\": {\n            return (\n              <ProfilePreview\n                actions={<MuteButton pubkey={tag[1]} />}\n                pubkey={tag[1]}\n                options={{ about: false }}\n                key={tag[1]}\n              />\n            )\n          }\n        }\n        return undefined\n      })}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/Nip05.tsx",
    "content": "import { fetchNip05PubkeyWithThrow } from \"@snort/shared\"\nimport { useCached, useUserProfile } from \"@snort/system-react\"\nimport classNames from \"classnames\"\nimport { useCallback, useRef } from \"react\"\nimport { useInView } from \"react-intersection-observer\"\nimport { Day } from \"@/Utils/Const\"\nimport Icon from \"../Icons/Icon\"\n\nexport interface Nip05Params {\n  className?: string\n  nip05?: string\n  pubkey?: string\n  /**\n   * Force the handle as verified, for display purposes\n   */\n  forceVerified?: boolean\n\n  /**\n   * Show verification badges\n   */\n  showBadges?: boolean\n}\n\nexport default function Nip05({ nip05, pubkey, forceVerified, showBadges, className }: Nip05Params) {\n  const { inView, ref: inViewRef } = useInView({ triggerOnce: true })\n  const spanRef = useRef<HTMLSpanElement>(null)\n  const profile = useUserProfile(pubkey && !nip05 ? pubkey : undefined, spanRef)\n  const toSplit = nip05 ?? profile?.nip05\n\n  const [name, domain] = toSplit ? toSplit.toLocaleLowerCase().split(\"@\") : []\n  const isDefaultUser = name === \"_\"\n  const loader = useCallback(async () => {\n    return await fetchNip05PubkeyWithThrow(name, domain)\n  }, [name, domain])\n  const { data, error } = useCached(toSplit && inView && pubkey ? `nip5:${toSplit}` : undefined, loader, Day)\n\n  const canVerify = pubkey !== undefined\n  const isVerified = (forceVerified ?? false) || (data === pubkey && canVerify)\n  const isSpecialDomain =\n    domain?.toLowerCase() === \"snort.social\" || domain?.toLowerCase() === CONFIG.nip05Domain.toLowerCase()\n\n  const setRefs = useCallback(\n    (el: HTMLSpanElement | null) => {\n      spanRef.current = el\n      inViewRef(el)\n    },\n    [inViewRef],\n  )\n\n  return (\n    <span\n      className={classNames(\n        \"inline-flex items-center text-neutral-400 font-normal\",\n        { \"opacity-50\": !isVerified },\n        className,\n      )}\n      ref={setRefs}\n      title={error?.message}\n    >\n      {!isDefaultUser && <span className=\"nick\">{`${name}@`}</span>}\n      <span className={`${isSpecialDomain && isVerified ? \"text-snort-gradient\" : \"text-neutral-400\"}`}>{domain}</span>\n      {(showBadges ?? false) && !isVerified && (\n        <Icon\n          size={13}\n          name={isVerified ? \"check\" : \"x\"}\n          className={classNames(\"ml-0.5\", isVerified ? \"text-success\" : \"text-error\")}\n        />\n      )}\n    </span>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/NoteToSelf.tsx",
    "content": "import classNames from \"classnames\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\n\nimport messages from \"../messages\"\n\nexport interface NoteToSelfProps {\n  className?: string\n}\n\nfunction NoteLabel() {\n  return (\n    <div className=\"font-bold flex items-center gap-1\">\n      <FormattedMessage {...messages.NoteToSelf} /> <Icon name=\"badge\" size={15} />\n    </div>\n  )\n}\n\nexport default function NoteToSelf({ className }: NoteToSelfProps) {\n  return (\n    <div className={classNames(\"flex items-center\", className)}>\n      <div className=\"mr-2\">\n        <div className=\"w-12 h-12 flex items-center justify-center cursor-pointer\">\n          <Icon name=\"book-closed\" size={20} />\n        </div>\n      </div>\n      <NoteLabel />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/ProfileCard.tsx",
    "content": "import type { UserMetadata } from \"@snort/system\"\n\nimport Text from \"@/Components/Text/Text\"\nimport FollowedBy from \"@/Components/User/FollowedBy\"\n\nimport useLogin from \"../../Hooks/useLogin\"\nimport { UserDebug } from \"./Debug\"\nimport FollowButton from \"./FollowButton\"\nimport ProfileImage from \"./ProfileImage\"\nimport { UserWebsiteLink } from \"./UserWebsiteLink\"\n\nexport function ProfileCard({ pubkey, user }: { pubkey: string; user?: UserMetadata }) {\n  const { publicKey: myPublicKey } = useLogin(s => ({ publicKey: s.publicKey }))\n  const debug = Boolean(localStorage.getItem(\"debug\"))\n\n  return (\n    <div className=\"w-[360px] layer-2 overflow-hidden\">\n      <div className=\"flex flex-col gap-2 text-white px-3 py-2 light:text-black\">\n        <div className=\"flex justify-between\">\n          <ProfileImage pubkey={pubkey} profile={user} showProfileCard={false} link=\"\" showNip05={false} />\n          <div className=\"flex gap-2\">\n            {/*<button type=\"button\" onClick={() => {\n                        LoginStore.loginWithPubkey(pubkey, LoginSessionType.PublicKey, undefined, undefined, undefined, true);\n                    }}>\n                        <FormattedMessage defaultMessage=\"Stalk\" />\n                    </button>*/}\n            {myPublicKey !== pubkey && <FollowButton pubkey={pubkey} />}\n          </div>\n        </div>\n        <Text\n          id={`profile-card-${pubkey}`}\n          content={user?.about ?? \"\"}\n          creator={pubkey}\n          tags={[]}\n          disableMedia={true}\n          disableLinkPreview={true}\n          truncate={250}\n        />\n        <UserWebsiteLink user={user} />\n        {myPublicKey && (\n          <FollowedBy\n            pubkey={pubkey}\n            showUsername={false}\n            link=\"\"\n            showFollowDistance={false}\n            showProfileCard={false}\n            size={24}\n          />\n        )}\n        {debug && <UserDebug pubkey={pubkey} />}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/ProfileCardWrapper.tsx",
    "content": "import type { UserMetadata } from \"@snort/system\"\nimport type { ReactNode } from \"react\"\nimport * as HoverCard from \"@radix-ui/react-hover-card\"\n\nimport { ProfileCard } from \"./ProfileCard\"\n\ninterface ProfileCardWrapperProps {\n  pubkey: string\n  user?: UserMetadata\n  children: ReactNode\n}\n\nexport function ProfileCardWrapper({ pubkey, user, children }: ProfileCardWrapperProps) {\n  return (\n    <HoverCard.Root openDelay={100} closeDelay={300}>\n      <HoverCard.Trigger asChild>{children}</HoverCard.Trigger>\n      <HoverCard.Portal>\n        <HoverCard.Content className=\"z-[9999]\" sideOffset={5}>\n          <ProfileCard pubkey={pubkey} user={user} />\n        </HoverCard.Content>\n      </HoverCard.Portal>\n    </HoverCard.Root>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/ProfileImage.tsx",
    "content": "import type { UserMetadata } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport classNames from \"classnames\"\nimport type React from \"react\"\nimport { type ReactNode, useRef } from \"react\"\n\nimport Avatar from \"@/Components/User/Avatar\"\nimport FollowDistanceIndicator from \"@/Components/User/FollowDistanceIndicator\"\n\nimport DisplayName from \"./DisplayName\"\nimport Nip05 from \"./Nip05\"\nimport { ProfileCardWrapper } from \"./ProfileCardWrapper\"\nimport { ProfileLink } from \"./ProfileLink\"\n\nexport interface ProfileImageProps {\n  pubkey: string\n  subHeader?: ReactNode\n  showUsername?: boolean\n  className?: string\n  link?: string\n  defaultNip?: string\n  verifyNip?: boolean\n  overrideUsername?: ReactNode\n  profile?: UserMetadata\n  size?: number\n  onClick?: (e: React.MouseEvent) => void\n  imageOverlay?: ReactNode\n  showFollowDistance?: boolean\n  icons?: ReactNode\n  showProfileCard?: boolean\n  displayNameClassName?: string\n  showNip05?: boolean\n}\n\nexport default function ProfileImage({\n  pubkey,\n  subHeader,\n  showUsername = true,\n  className,\n  link,\n  overrideUsername,\n  profile,\n  size,\n  imageOverlay,\n  onClick,\n  showFollowDistance = true,\n  icons,\n  showProfileCard = false,\n  displayNameClassName,\n  showNip05 = true,\n}: ProfileImageProps) {\n  const ref = useRef<HTMLDivElement>(null)\n  const user = useUserProfile(profile ? \"\" : pubkey, ref) ?? profile\n\n  function handleClick(e: React.MouseEvent) {\n    if (link === \"\") {\n      e.preventDefault()\n      onClick?.(e)\n    }\n  }\n\n  function inner() {\n    const avatar = (\n      <Avatar\n        pubkey={pubkey}\n        user={user}\n        size={size}\n        imageOverlay={imageOverlay}\n        showTitle={!showProfileCard}\n        icons={\n          showFollowDistance || icons ? (\n            <>\n              {icons}\n              {showFollowDistance && <FollowDistanceIndicator pubkey={pubkey} />}\n            </>\n          ) : undefined\n        }\n      ></Avatar>\n    )\n\n    return (\n      <>\n        {showProfileCard ? (\n          <ProfileCardWrapper pubkey={pubkey} user={user}>\n            {avatar}\n          </ProfileCardWrapper>\n        ) : (\n          avatar\n        )}\n        {showUsername && (\n          <div className={displayNameClassName}>\n            <div className=\"font-medium\">\n              {overrideUsername ? overrideUsername : <DisplayName pubkey={pubkey} user={user} />}\n              {user?.nip05 && CONFIG.showNip05 && showNip05 && (\n                <>\n                  &nbsp;\n                  <Nip05 nip05={user?.nip05} pubkey={pubkey} showBadges={true} className=\"text-xs\" />\n                </>\n              )}\n            </div>\n            {subHeader}\n          </div>\n        )}\n      </>\n    )\n  }\n\n  const classNamesOverInner = classNames(\n    \"min-w-0 z-2\",\n    {\n      \"flex gap-2 items-center\": showUsername,\n    },\n    className,\n  )\n\n  const content =\n    link === \"\" ? (\n      <div ref={ref} className={classNamesOverInner} onClick={handleClick}>\n        {inner()}\n      </div>\n    ) : (\n      <div ref={ref} className=\"contents\">\n        <ProfileLink\n          pubkey={pubkey}\n          user={user}\n          explicitLink={link}\n          className={classNamesOverInner}\n          onClick={handleClick}\n        >\n          {inner()}\n        </ProfileLink>\n      </div>\n    )\n\n  return content\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/ProfileLink.tsx",
    "content": "import type { CachedMetadata, UserMetadata } from \"@snort/system\"\nimport type { ReactNode } from \"react\"\nimport { Link, type LinkProps } from \"react-router-dom\"\n\nimport { useProfileLink } from \"@/Hooks/useProfileLink\"\n\nexport function ProfileLink({\n  pubkey,\n  user,\n  explicitLink,\n  children,\n  ...others\n}: {\n  pubkey: string\n  user?: UserMetadata | CachedMetadata\n  explicitLink?: string\n  children?: ReactNode\n} & Omit<LinkProps, \"to\">) {\n  const link = useProfileLink(pubkey, user)\n  return (\n    <Link {...others} to={explicitLink ?? link} state={user}>\n      {children}\n    </Link>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/ProfilePreview.tsx",
    "content": "import type { UserMetadata } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport classNames from \"classnames\"\nimport { forwardRef, type ReactNode, useRef } from \"react\"\n\nimport FollowButton from \"@/Components/User/FollowButton\"\nimport ProfileImage, { type ProfileImageProps } from \"@/Components/User/ProfileImage\"\n\nexport interface ProfilePreviewProps {\n  pubkey: string\n  options?: {\n    about?: boolean\n  }\n  profile?: UserMetadata\n  actions?: ReactNode\n  className?: string\n  onClick?: (e: React.MouseEvent<HTMLDivElement>) => void\n  profileImageProps?: Omit<ProfileImageProps, \"pubkey\" | \"profile\">\n}\nconst ProfilePreview = forwardRef<HTMLDivElement, ProfilePreviewProps>(function ProfilePreview(\n  props: ProfilePreviewProps,\n  ref,\n) {\n  const pubkey = props.pubkey\n  const innerRef = useRef<HTMLDivElement>(null)\n  const user = useUserProfile(pubkey, innerRef)\n  const options = {\n    about: true,\n    ...props.options,\n  }\n\n  function handleClick(e: React.MouseEvent<HTMLDivElement>) {\n    if (props.onClick) {\n      e.stopPropagation()\n      e.preventDefault()\n      props.onClick(e)\n    }\n  }\n\n  return (\n    <div\n        className={classNames(\"flex items-center justify-between\", props.className)}\n        ref={el => {\n          innerRef.current = el\n          if (typeof ref === \"function\") ref(el)\n          else if (ref) ref.current = el\n        }}\n        onClick={handleClick}\n      >\n        <ProfileImage\n          pubkey={pubkey}\n          profile={props.profile}\n          className=\"overflow-hidden\"\n          subHeader={\n            options.about && (\n              <div className=\"text-sm text-neutral-400 whitespace-nowrap text-ellipsis overflow-hidden\">\n                {user?.about}\n              </div>\n            )\n          }\n          {...props.profileImageProps}\n        />\n        {props.actions ?? (\n          <div className=\"whitespace-nowrap\">\n            <FollowButton pubkey={pubkey} />\n          </div>\n        )}\n      </div>\n  )\n})\n\nexport default ProfilePreview\n"
  },
  {
    "path": "packages/app/src/Components/User/UserWebsiteLink.tsx",
    "content": "import type { CachedMetadata, UserMetadata } from \"@snort/system\"\n\nimport Icon from \"@/Components/Icons/Icon\"\n\nexport function UserWebsiteLink({ user }: { user?: CachedMetadata | UserMetadata }) {\n  const website_url =\n    user?.website && !user.website.startsWith(\"http\") ? `https://${user.website}` : user?.website || \"\"\n\n  function tryFormatWebsite(url: string) {\n    try {\n      const u = new URL(url)\n      return `${u.hostname}${u.pathname !== \"/\" ? u.pathname : \"\"}`\n    } catch {\n      // ignore\n    }\n    return url\n  }\n\n  if (user?.website) {\n    return (\n      <div className=\"flex items-center gap-2\">\n        <Icon name=\"link-02\" size={16} />\n        <a\n          href={website_url}\n          target=\"_blank\"\n          rel=\"noreferrer\"\n          className=\"text-ellipsis overflow-hidden hover:underline cursor-pointer\"\n        >\n          {tryFormatWebsite(user.website)}\n        </a>\n      </div>\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/User/Username.tsx",
    "content": "import { useUserProfile } from \"@snort/system-react\"\nimport { useRef } from \"react\"\n\nimport DisplayName from \"./DisplayName\"\nimport { ProfileLink } from \"./ProfileLink\"\n\nexport default function Username({ pubkey, onLinkVisit }: { pubkey: string; onLinkVisit?(): void }) {\n  const ref = useRef<HTMLSpanElement>(null)\n  const user = useUserProfile(pubkey, ref)\n\n  return (\n    <span ref={ref}>\n      <ProfileLink pubkey={pubkey} onClick={onLinkVisit} user={user}>\n        <DisplayName pubkey={pubkey} user={user} />\n      </ProfileLink>\n    </span>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/WarningNotice/WarningNotice.tsx",
    "content": "import Icon from \"@/Components/Icons/Icon\"\n\nexport function WarningNotice({ children, onClick }: { children: React.ReactNode; onClick?: () => void }) {\n  return (\n    <div\n      className=\"text-warning border px-4 py-2 rounded-lg flex gap-2 items-center font-bold\"\n      onClick={e => {\n        e.stopPropagation()\n        onClick?.()\n      }}\n    >\n      <Icon name=\"alert-circle\" size={26} />\n      <div>{children}</div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/ZapModal/SuccessAction.tsx",
    "content": "import type { LNURLSuccessAction } from \"@snort/shared\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\n\nexport function SuccessAction({ success }: { success: LNURLSuccessAction }) {\n  return (\n    <div className=\"flex items-center\">\n      <p className=\"flex gap-3\">\n        <Icon name=\"check\" className=\"success\" />\n        {success?.description ?? <FormattedMessage defaultMessage=\"Paid\" />}\n      </p>\n      {success.url && (\n        <p>\n          <a href={success.url} rel=\"noreferrer\" target=\"_blank\">\n            {success.url}\n          </a>\n        </p>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/ZapModal/ZapModal.tsx",
    "content": "import type { LNURLSuccessAction } from \"@snort/shared\"\nimport { Zapper, type ZapTarget, type ZapTargetResult } from \"@snort/wallet\"\nimport { type ReactNode, useEffect, useState } from \"react\"\n\nimport CloseButton from \"@/Components/Button/CloseButton\"\nimport Modal from \"@/Components/Modal/Modal\"\nimport { SuccessAction } from \"@/Components/ZapModal/SuccessAction\"\nimport { type SendSatsInputSelection, ZapModalInput } from \"@/Components/ZapModal/ZapModalInput\"\nimport { ZapModalInvoice } from \"@/Components/ZapModal/ZapModalInvoice\"\nimport { ZapModalTitle } from \"@/Components/ZapModal/ZapModalTitle\"\nimport { ZapType } from \"@/Components/ZapModal/ZapType\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport { debounce } from \"@/Utils\"\nimport { useWallet } from \"@/Wallet\"\n\nexport interface SendSatsProps {\n  onClose?: () => void\n  targets?: Array<ZapTarget>\n  show?: boolean\n  invoice?: string // shortcut to invoice qr tab\n  title?: ReactNode\n  notice?: string\n  allocatePool?: boolean\n}\n\nexport default function ZapModal(props: SendSatsProps) {\n  const onClose = props.onClose || (() => undefined)\n\n  const [zapper, setZapper] = useState<Zapper>()\n  const [invoice, setInvoice] = useState<Array<ZapTargetResult>>()\n  const [error, setError] = useState<string>()\n  const [success, setSuccess] = useState<LNURLSuccessAction>()\n  const [amount, setAmount] = useState<SendSatsInputSelection>()\n\n  const { publisher, system } = useEventPublisher()\n  const walletState = useWallet()\n  const wallet = walletState.wallet\n\n  useEffect(() => {\n    if (props.show) {\n      const invoiceTarget = {\n        target: {\n          type: \"lnurl\",\n          value: \"\",\n          weight: 1,\n        },\n        pr: props.invoice,\n        paid: false,\n        sent: 0,\n        fee: 0,\n      } as ZapTargetResult\n\n      setError(undefined)\n      setInvoice(props.invoice ? [invoiceTarget] : undefined)\n      setSuccess(undefined)\n    }\n  }, [props.show, props.invoice])\n\n  useEffect(() => {\n    if (success && !success.url) {\n      // Fire onClose when success is set with no URL action\n      return debounce(1_000, () => {\n        onClose()\n      })\n    }\n  }, [success, onClose])\n\n  useEffect(() => {\n    if (props.targets && props.show) {\n      try {\n        const zapper = new Zapper(system, publisher)\n        zapper.load(props.targets).then(() => {\n          setZapper(zapper)\n        })\n      } catch (e) {\n        console.error(e)\n        if (e instanceof Error) {\n          setError(e.message)\n        }\n      }\n    }\n  }, [props.targets, props.show, system, publisher])\n\n  if (!(props.show ?? false)) return null\n  return (\n    <Modal id=\"send-sats\" onClose={onClose}>\n      <div className=\"flex flex-col gap-2\">\n        <div className=\"flex gap-2\">\n          <div className=\"flex items-center grow gap-2\">\n            {props.title || <ZapModalTitle amount={amount} targets={props.targets} zapper={zapper} />}\n          </div>\n          <CloseButton onClick={onClose} />\n        </div>\n        {zapper && !invoice && (\n          <ZapModalInput\n            zapper={zapper}\n            onChange={v => setAmount(v)}\n            onNextStage={async p => {\n              const targetsWithComments = (props.targets ?? []).map(v => {\n                if (p.comment) {\n                  v.memo = p.comment\n                }\n                if (p.type === ZapType.AnonZap && v.zap) {\n                  v.zap = {\n                    ...v.zap,\n                    anon: true,\n                  }\n                } else if (p.type === ZapType.NonZap) {\n                  v.zap = undefined\n                }\n                return v\n              })\n              if (targetsWithComments.length > 0) {\n                const sends = await zapper.send(wallet, targetsWithComments, p.amount)\n                if (sends[0].error) {\n                  setError(sends[0].error.message)\n                } else if (sends.every(a => a.paid)) {\n                  setSuccess({})\n                } else {\n                  setInvoice(sends)\n                }\n              }\n            }}\n          />\n        )}\n        {error && <p className=\"error\">{error}</p>}\n        {invoice && !success && (\n          <ZapModalInvoice\n            invoice={invoice}\n            wallet={wallet}\n            notice={props.notice}\n            onInvoicePaid={() => {\n              setSuccess({})\n            }}\n          />\n        )}\n        {success && <SuccessAction success={success} />}\n      </div>\n    </Modal>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/ZapModal/ZapModalInput.tsx",
    "content": "import type { Zapper } from \"@snort/wallet\"\nimport { useEffect, useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport messages from \"@/Components/messages\"\nimport { ZapType } from \"@/Components/ZapModal/ZapType\"\nimport { ZapTypeSelector } from \"@/Components/ZapModal/ZapTypeSelector\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { formatShort } from \"@/Utils/Number\"\nimport classNames from \"classnames\"\n\nexport interface SendSatsInputSelection {\n  amount: number\n  comment?: string\n  type: ZapType\n}\n\nexport function ZapModalInput(props: {\n  zapper: Zapper\n  onChange?: (v: SendSatsInputSelection) => void\n  onNextStage: (v: SendSatsInputSelection) => Promise<void>\n}) {\n  const defaultZapAmount = usePreferences(s => s.defaultZapAmount)\n  const readonly = useLogin(s => s.readonly)\n  const { formatMessage } = useIntl()\n  const amounts: Record<string, string> = {\n    [defaultZapAmount.toString()]: \"\",\n    \"1000\": \"👍\",\n    \"5000\": \"💜\",\n    \"10000\": \"😍\",\n    \"20000\": \"🤩\",\n    \"50000\": \"🔥\",\n    \"100000\": \"🚀\",\n    \"1000000\": \"🤯\",\n  }\n  const [comment, setComment] = useState<string>()\n  const [amount, setAmount] = useState<number>(defaultZapAmount)\n  const [customAmount, setCustomAmount] = useState<number>(defaultZapAmount)\n  const [zapType, setZapType] = useState(readonly ? ZapType.AnonZap : ZapType.PublicZap)\n\n  function getValue() {\n    return {\n      amount,\n      comment,\n      type: zapType,\n    } as SendSatsInputSelection\n  }\n\n  useEffect(() => {\n    if (props.onChange) {\n      props.onChange(getValue())\n    }\n  }, [getValue, props.onChange])\n\n  function renderAmounts() {\n    const min = props.zapper.minAmount() / 1000\n    const max = props.zapper.maxAmount() / 1000\n    const filteredAmounts = Object.entries(amounts).filter(([k]) => Number(k) >= min && Number(k) <= max)\n\n    return (\n      <div className=\"grid grid-cols-4 gap-2\">\n        {filteredAmounts.map(([k, v]) => {\n          return (\n            <span\n              className={classNames(\"text-center font-medium py-1 cursor-pointer layer-2-hover rounded-full\", {\n                \"opacity-30\": amount !== Number(k),\n              })}\n              key={k}\n              onClick={() => setAmount(Number(k))}\n            >\n              {v}&nbsp;\n              {k === \"1000\" ? \"1K\" : formatShort(Number(k))}\n            </span>\n          )\n        })}\n      </div>\n    )\n  }\n\n  function custom() {\n    const min = props.zapper.minAmount() / 1000\n    const max = props.zapper.maxAmount() / 1000\n\n    return (\n      <div className=\"flex gap-2\">\n        <input\n          type=\"number\"\n          min={min}\n          max={max}\n          className=\"grow\"\n          placeholder={formatMessage(messages.Custom)}\n          value={customAmount}\n          onChange={e => setCustomAmount(parseInt(e.target.value, 10))}\n        />\n        <button\n          className=\"secondary\"\n          type=\"button\"\n          disabled={!customAmount}\n          onClick={() => setAmount(customAmount ?? 0)}\n        >\n          <FormattedMessage {...messages.Confirm} />\n        </button>\n      </div>\n    )\n  }\n\n  return (\n    <div className=\"flex flex-col gap-4\">\n      <div className=\"flex flex-col gap-2\">\n        <div className=\"font-medium\">\n          <FormattedMessage defaultMessage=\"Zap amount:\" />\n        </div>\n        {renderAmounts()}\n        {custom()}\n        {props.zapper.maxComment() > 0 && (\n          <input\n              type=\"text\"\n              placeholder={formatMessage(messages.Comment)}\n              className=\"grow\"\n              maxLength={props.zapper.maxComment()}\n              onChange={e => setComment(e.target.value)}\n            />\n        )}\n      </div>\n      <ZapTypeSelector zapType={zapType} setZapType={setZapType} />\n      {(amount ?? 0) > 0 && (\n        <AsyncButton onClick={() => props.onNextStage(getValue())}>\n          <Icon name=\"zap\" />\n          <FormattedMessage defaultMessage=\"Zap {n} sats\" values={{ n: formatShort(amount) }} />\n        </AsyncButton>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/ZapModal/ZapModalInvoice.tsx",
    "content": "import type { LNWallet, ZapTargetResult } from \"@snort/wallet\"\nimport type { ReactNode } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport Copy from \"@/Components/Copy/Copy\"\nimport QrCode from \"@/Components/QrCode\"\nimport AsyncButton from \"../Button/AsyncButton\"\n\nexport function ZapModalInvoice(props: {\n  invoice: Array<ZapTargetResult>\n  wallet?: LNWallet\n  notice?: ReactNode\n  onInvoicePaid: () => void\n}) {\n  return (\n    <div className=\"flex flex-col items-center gap-2 txt-center\">\n      {props.notice && <b className=\"error\">{props.notice}</b>}\n      {props.invoice.map(v => (\n        <>\n          <QrCode data={v.pr} link={`lightning:${v.pr}`} />\n          <Copy text={v.pr} maxSize={26} className=\"items-center\" />\n          <a href={`lightning:${v.pr}`}>\n            <AsyncButton>\n              <FormattedMessage defaultMessage=\"Open Wallet\" />\n            </AsyncButton>\n          </a>\n        </>\n      ))}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/ZapModal/ZapModalTitle.tsx",
    "content": "import type { Zapper, ZapTarget } from \"@snort/wallet\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport type { SendSatsInputSelection } from \"@/Components/ZapModal/ZapModalInput\"\nimport { formatShort } from \"@/Utils/Number\"\n\nexport function ZapModalTitle({\n  targets,\n  zapper,\n  amount,\n}: {\n  targets?: Array<ZapTarget>\n  zapper?: Zapper\n  amount?: SendSatsInputSelection\n}) {\n  if (!targets) {\n    return (\n      <div className=\"text-lg font-medium\">\n          {zapper?.canZap() ? (\n            <FormattedMessage defaultMessage=\"Send zap\" />\n          ) : (\n            <FormattedMessage defaultMessage=\"Send sats\" />\n          )}\n        </div>\n    )\n  }\n  if (targets.length === 1 && targets[0].name) {\n    const t = targets[0]\n    const values = {\n      name: t.name,\n    }\n    return (\n      <ProfileImage\n        pubkey={t.zap?.pubkey ?? \"\"}\n        overrideUsername={\n          <div className=\"text-lg font-medium\">\n            {zapper?.canZap() ? (\n              <FormattedMessage defaultMessage=\"Zap {name}\" values={values} />\n            ) : (\n              <FormattedMessage defaultMessage=\"Send sats to {name}\" values={values} />\n            )}\n          </div>\n        }\n        link=\"\"\n      />\n    )\n  }\n  if (targets.length > 1) {\n    const total = targets.reduce((acc, v) => (acc += v.weight), 0)\n\n    return (\n      <div className=\"flex flex-col gap-3\">\n        <div className=\"text-lg font-medium\">\n          {zapper?.canZap() ? (\n            <FormattedMessage defaultMessage=\"Send zap splits to\" />\n          ) : (\n            <FormattedMessage defaultMessage=\"Send sats splits to\" />\n          )}\n        </div>\n        <div className=\"flex gap-1 f-wrap\">\n          {targets.map(v => (\n            <ProfileImage\n              key={v.value}\n              pubkey={v.value}\n              showUsername={false}\n              showFollowDistance={false}\n              imageOverlay={formatShort(Math.floor((amount?.amount ?? 0) * (v.weight / total)))}\n            />\n          ))}\n        </div>\n      </div>\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/ZapModal/ZapType.tsx",
    "content": "export enum ZapType {\n  PublicZap = 1,\n  AnonZap = 2,\n  PrivateZap = 3,\n  NonZap = 4,\n}\n"
  },
  {
    "path": "packages/app/src/Components/ZapModal/ZapTypeSelector.tsx",
    "content": "import type React from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport { ZapType } from \"@/Components/ZapModal/ZapType\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport AsyncButton from \"../Button/AsyncButton\"\n\nexport function ZapTypeSelector({ zapType, setZapType }: { zapType: ZapType; setZapType: (t: ZapType) => void }) {\n  const { readonly } = useLogin(s => ({ readonly: s.readonly }))\n  const makeTab = (t: ZapType, n: React.ReactNode) => (\n    <AsyncButton className={zapType === t ? \"!bg-neutral-400\" : \"\"} onClick={() => setZapType(t)}>\n      {n}\n    </AsyncButton>\n  )\n  return (\n    <div className=\"flex flex-col gap-2\">\n      <div className=\"font-medium\">\n        <FormattedMessage defaultMessage=\"Zap Type:\" />\n      </div>\n      <div className=\"flex gap-2\">\n        {!readonly && makeTab(ZapType.PublicZap, <FormattedMessage defaultMessage=\"Public\" />)}\n        {/*makeTab(ZapType.PrivateZap, \"Private\")*/}\n        {makeTab(ZapType.AnonZap, <FormattedMessage defaultMessage=\"Anon\" />)}\n        {makeTab(ZapType.NonZap, <FormattedMessage defaultMessage=\"Non-Zap\" />)}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/flyout.tsx",
    "content": "import classNames from \"classnames\"\nimport type { CSSProperties, ReactNode } from \"react\"\nimport { createPortal } from \"react-dom\"\n\nimport IconButton from \"@/Components/Button/IconButton\"\n\nexport default function Flyout({\n  show,\n  children,\n  title,\n  actions,\n  onClose,\n  side,\n  width,\n}: {\n  show: boolean\n  title?: ReactNode\n  actions?: ReactNode\n  children?: ReactNode\n  onClose: () => void\n  side: \"left\" | \"right\"\n  width?: string\n}) {\n  const styles = {\n    \"--flyout-w\": width ?? \"400px\",\n    transition: \"all 0.2s ease-in-out\",\n    width: \"var(--flyout-w)\",\n    transform:\n      side === \"right\"\n        ? `translate(${show ? \"0\" : \"var(--flyout-w)\"},0)`\n        : `translate(${show ? \"0\" : \"calc(-1 * var(--flyout-w))\"},0)`,\n  } as CSSProperties\n\n  return createPortal(\n    <div\n      className={classNames(\"absolute top-0 overflow-hidden z-50\", {\n        \"pointer-events-none\": !show,\n        \"right-0\": side === \"right\",\n        \"left-0\": side === \"left\",\n      })}\n    >\n      <div className=\"layer-1 h-[100vh] top-0 overflow-hidden\" style={styles}>\n        <div className=\"flex justify-between items-center\">\n          {title}\n          <div className=\"flex gap-2 items-center\">\n            {actions}\n            <IconButton icon={{ name: \"x\" }} onClick={onClose} />\n          </div>\n        </div>\n        {children}\n      </div>\n    </div>,\n    document.body,\n  ) as React.ReactNode\n}\n"
  },
  {
    "path": "packages/app/src/Components/json.tsx",
    "content": "export default function JsonBlock({ obj }: { obj: object }) {\n  return (\n    <div className=\"layer-2 p-3 overflow-auto text-[10px] font-mono whitespace-pre\">\n      {JSON.stringify(obj, undefined, 2)}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Components/kind-name.tsx",
    "content": "/* eslint-disable max-lines */\nimport { FormattedMessage } from \"react-intl\"\n\n// Take the markdown kinds table and find-replace with following regex:\n// FIND: ^\\|\\s+`([`\\d\\-]+)`\\s+\\| ([\\w \\-\\(\\)\\/]+)[\\s]*\\|.*$\n// REPLACE: case $1:\\n\\treturn <FormattedMessage defaultMessage=\"$2\" />;\n\nexport default function KindName({ kind }: { kind: number }) {\n  switch (kind) {\n    case 0:\n      return <FormattedMessage defaultMessage=\"User Metadata\" />\n    case 1:\n      return <FormattedMessage defaultMessage=\"Short Text Note\" />\n    case 2:\n      return <FormattedMessage defaultMessage=\"Recommend Relay\" />\n    case 3:\n      return <FormattedMessage defaultMessage=\"Follows\" />\n    case 4:\n      return <FormattedMessage defaultMessage=\"Encrypted Direct Messages\" />\n    case 5:\n      return <FormattedMessage defaultMessage=\"Event Deletion Request\" />\n    case 6:\n      return <FormattedMessage defaultMessage=\"Repost\" />\n    case 7:\n      return <FormattedMessage defaultMessage=\"Reaction\" />\n    case 8:\n      return <FormattedMessage defaultMessage=\"Badge Award\" />\n    case 9:\n      return <FormattedMessage defaultMessage=\"Chat Message\" />\n    case 10:\n      return <FormattedMessage defaultMessage=\"Group Chat Threaded Reply\" />\n    case 11:\n      return <FormattedMessage defaultMessage=\"Thread\" />\n    case 12:\n      return <FormattedMessage defaultMessage=\"Group Thread Reply\" />\n    case 13:\n      return <FormattedMessage defaultMessage=\"Seal\" />\n    case 14:\n      return <FormattedMessage defaultMessage=\"Direct Message\" />\n    case 15:\n      return <FormattedMessage defaultMessage=\"File Message\" />\n    case 16:\n      return <FormattedMessage defaultMessage=\"Generic Repost\" />\n    case 17:\n      return <FormattedMessage defaultMessage=\"Reaction to a website\" />\n    case 20:\n      return <FormattedMessage defaultMessage=\"Picture\" />\n    case 21:\n      return <FormattedMessage defaultMessage=\"Video Event\" />\n    case 22:\n      return <FormattedMessage defaultMessage=\"Short-form Portrait Video Event\" />\n    case 30:\n      return <FormattedMessage defaultMessage=\"internal reference\" />\n    case 31:\n      return <FormattedMessage defaultMessage=\"external web reference\" />\n    case 32:\n      return <FormattedMessage defaultMessage=\"hardcopy reference\" />\n    case 33:\n      return <FormattedMessage defaultMessage=\"prompt reference\" />\n    case 40:\n      return <FormattedMessage defaultMessage=\"Channel Creation\" />\n    case 41:\n      return <FormattedMessage defaultMessage=\"Channel Metadata\" />\n    case 42:\n      return <FormattedMessage defaultMessage=\"Channel Message\" />\n    case 43:\n      return <FormattedMessage defaultMessage=\"Channel Hide Message\" />\n    case 44:\n      return <FormattedMessage defaultMessage=\"Channel Mute User\" />\n    case 62:\n      return <FormattedMessage defaultMessage=\"Request to Vanish\" />\n    case 64:\n      return <FormattedMessage defaultMessage=\"Chess (PGN)\" />\n    case 818:\n      return <FormattedMessage defaultMessage=\"Merge Requests\" />\n    case 1018:\n      return <FormattedMessage defaultMessage=\"Poll Response\" />\n    case 1021:\n      return <FormattedMessage defaultMessage=\"Bid\" />\n    case 1022:\n      return <FormattedMessage defaultMessage=\"Bid confirmation\" />\n    case 1040:\n      return <FormattedMessage defaultMessage=\"OpenTimestamps\" />\n    case 1059:\n      return <FormattedMessage defaultMessage=\"Gift Wrap\" />\n    case 1063:\n      return <FormattedMessage defaultMessage=\"File Metadata\" />\n    case 1068:\n      return <FormattedMessage defaultMessage=\"Poll\" />\n    case 1111:\n      return <FormattedMessage defaultMessage=\"Comment\" />\n    case 1311:\n      return <FormattedMessage defaultMessage=\"Live Chat Message\" />\n    case 1337:\n      return <FormattedMessage defaultMessage=\"Code Snippet\" />\n    case 1617:\n      return <FormattedMessage defaultMessage=\"Patches\" />\n    case 1621:\n      return <FormattedMessage defaultMessage=\"Issues\" />\n    case 1622:\n      return <FormattedMessage defaultMessage=\"Git Replies (deprecated)\" />\n    case 1971:\n      return <FormattedMessage defaultMessage=\"Problem Tracker\" />\n    case 1984:\n      return <FormattedMessage defaultMessage=\"Reporting\" />\n    case 1985:\n      return <FormattedMessage defaultMessage=\"Label\" />\n    case 1986:\n      return <FormattedMessage defaultMessage=\"Relay reviews\" />\n    case 1987:\n      return <FormattedMessage defaultMessage=\"AI Embeddings / Vector lists\" />\n    case 2003:\n      return <FormattedMessage defaultMessage=\"Torrent\" />\n    case 2004:\n      return <FormattedMessage defaultMessage=\"Torrent Comment\" />\n    case 2022:\n      return <FormattedMessage defaultMessage=\"Coinjoin Pool\" />\n    case 4550:\n      return <FormattedMessage defaultMessage=\"Community Post Approval\" />\n    case 7000:\n      return <FormattedMessage defaultMessage=\"Job Feedback\" />\n    case 7374:\n      return <FormattedMessage defaultMessage=\"Reserved Cashu Wallet Tokens\" />\n    case 7375:\n      return <FormattedMessage defaultMessage=\"Cashu Wallet Tokens\" />\n    case 7376:\n      return <FormattedMessage defaultMessage=\"Cashu Wallet History\" />\n    case 9041:\n      return <FormattedMessage defaultMessage=\"Zap Goal\" />\n    case 9321:\n      return <FormattedMessage defaultMessage=\"Nutzap\" />\n    case 9467:\n      return <FormattedMessage defaultMessage=\"Tidal login\" />\n    case 9734:\n      return <FormattedMessage defaultMessage=\"Zap Request\" />\n    case 9735:\n      return <FormattedMessage defaultMessage=\"Zap\" />\n    case 9802:\n      return <FormattedMessage defaultMessage=\"Highlights\" />\n    case 10000:\n      return <FormattedMessage defaultMessage=\"Mute list\" />\n    case 10001:\n      return <FormattedMessage defaultMessage=\"Pin list\" />\n    case 10002:\n      return <FormattedMessage defaultMessage=\"Relay List Metadata\" />\n    case 10003:\n      return <FormattedMessage defaultMessage=\"Bookmark list\" />\n    case 10004:\n      return <FormattedMessage defaultMessage=\"Communities list\" />\n    case 10005:\n      return <FormattedMessage defaultMessage=\"Public chats list\" />\n    case 10006:\n      return <FormattedMessage defaultMessage=\"Blocked relays list\" />\n    case 10007:\n      return <FormattedMessage defaultMessage=\"Search relays list\" />\n    case 10009:\n      return <FormattedMessage defaultMessage=\"User groups\" />\n    case 10013:\n      return <FormattedMessage defaultMessage=\"Private event relay list\" />\n    case 10015:\n      return <FormattedMessage defaultMessage=\"Interests list\" />\n    case 10019:\n      return <FormattedMessage defaultMessage=\"Nutzap Mint Recommendation\" />\n    case 10030:\n      return <FormattedMessage defaultMessage=\"User emoji list\" />\n    case 10050:\n      return <FormattedMessage defaultMessage=\"Relay list to receive DMs\" />\n    case 10063:\n      return <FormattedMessage defaultMessage=\"User server list\" />\n    case 10096:\n      return <FormattedMessage defaultMessage=\"File storage server list\" />\n    case 10166:\n      return <FormattedMessage defaultMessage=\"Relay Monitor Announcement\" />\n    case 13194:\n      return <FormattedMessage defaultMessage=\"Wallet Info\" />\n    case 17375:\n      return <FormattedMessage defaultMessage=\"Cashu Wallet Event\" />\n    case 21000:\n      return <FormattedMessage defaultMessage=\"Lightning Pub RPC\" />\n    case 22242:\n      return <FormattedMessage defaultMessage=\"Client Authentication\" />\n    case 23194:\n      return <FormattedMessage defaultMessage=\"Wallet Request\" />\n    case 23195:\n      return <FormattedMessage defaultMessage=\"Wallet Response\" />\n    case 24133:\n      return <FormattedMessage defaultMessage=\"Nostr Connect\" />\n    case 24242:\n      return <FormattedMessage defaultMessage=\"Blobs stored on mediaservers\" />\n    case 27235:\n      return <FormattedMessage defaultMessage=\"HTTP Auth\" />\n    case 30000:\n      return <FormattedMessage defaultMessage=\"Follow sets\" />\n    case 30001:\n      return <FormattedMessage defaultMessage=\"Generic lists\" />\n    case 30002:\n      return <FormattedMessage defaultMessage=\"Relay sets\" />\n    case 30003:\n      return <FormattedMessage defaultMessage=\"Bookmark sets\" />\n    case 30004:\n      return <FormattedMessage defaultMessage=\"Curation sets\" />\n    case 30005:\n      return <FormattedMessage defaultMessage=\"Video sets\" />\n    case 30007:\n      return <FormattedMessage defaultMessage=\"Kind mute sets\" />\n    case 30008:\n      return <FormattedMessage defaultMessage=\"Profile Badges\" />\n    case 30009:\n      return <FormattedMessage defaultMessage=\"Badge Definition\" />\n    case 30015:\n      return <FormattedMessage defaultMessage=\"Interest sets\" />\n    case 30017:\n      return <FormattedMessage defaultMessage=\"Create or update a stall\" />\n    case 30018:\n      return <FormattedMessage defaultMessage=\"Create or update a product\" />\n    case 30019:\n      return <FormattedMessage defaultMessage=\"Marketplace UI/UX\" />\n    case 30020:\n      return <FormattedMessage defaultMessage=\"Product sold as an auction\" />\n    case 30023:\n      return <FormattedMessage defaultMessage=\"Long-form Content\" />\n    case 30024:\n      return <FormattedMessage defaultMessage=\"Draft Long-form Content\" />\n    case 30030:\n      return <FormattedMessage defaultMessage=\"Emoji sets\" />\n    case 30040:\n      return <FormattedMessage defaultMessage=\"Curated Publication Index\" />\n    case 30041:\n      return <FormattedMessage defaultMessage=\"Curated Publication Content\" />\n    case 30063:\n      return <FormattedMessage defaultMessage=\"Release artifact sets\" />\n    case 30078:\n      return <FormattedMessage defaultMessage=\"Application-specific Data\" />\n    case 30166:\n      return <FormattedMessage defaultMessage=\"Relay Discovery\" />\n    case 30267:\n      return <FormattedMessage defaultMessage=\"App curation sets\" />\n    case 30311:\n      return <FormattedMessage defaultMessage=\"Live Event\" />\n    case 30315:\n      return <FormattedMessage defaultMessage=\"User Statuses\" />\n    case 30388:\n      return <FormattedMessage defaultMessage=\"Slide Set\" />\n    case 30402:\n      return <FormattedMessage defaultMessage=\"Classified Listing\" />\n    case 30403:\n      return <FormattedMessage defaultMessage=\"Draft Classified Listing\" />\n    case 30617:\n      return <FormattedMessage defaultMessage=\"Repository announcements\" />\n    case 30618:\n      return <FormattedMessage defaultMessage=\"Repository state announcements\" />\n    case 30818:\n      return <FormattedMessage defaultMessage=\"Wiki article\" />\n    case 30819:\n      return <FormattedMessage defaultMessage=\"Redirects\" />\n    case 31234:\n      return <FormattedMessage defaultMessage=\"Draft Event\" />\n    case 31388:\n      return <FormattedMessage defaultMessage=\"Link Set\" />\n    case 31890:\n      return <FormattedMessage defaultMessage=\"Feed\" />\n    case 31922:\n      return <FormattedMessage defaultMessage=\"Date-Based Calendar Event\" />\n    case 31923:\n      return <FormattedMessage defaultMessage=\"Time-Based Calendar Event\" />\n    case 31924:\n      return <FormattedMessage defaultMessage=\"Calendar\" />\n    case 31925:\n      return <FormattedMessage defaultMessage=\"Calendar Event RSVP\" />\n    case 31989:\n      return <FormattedMessage defaultMessage=\"Handler recommendation\" />\n    case 31990:\n      return <FormattedMessage defaultMessage=\"Handler information\" />\n    case 32267:\n      return <FormattedMessage defaultMessage=\"Software Application\" />\n    case 34550:\n      return <FormattedMessage defaultMessage=\"Community Definition\" />\n    case 38383:\n      return <FormattedMessage defaultMessage=\"Peer-to-peer Order events\" />\n    case 39089:\n      return <FormattedMessage defaultMessage=\"Starter Pack\" />\n    case 39701:\n      return <FormattedMessage defaultMessage=\"Web bookmarks\" />\n    default:\n      return kind\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/messages.ts",
    "content": "import { defineMessages } from \"react-intl\"\n\nexport default defineMessages({\n  Cancel: { defaultMessage: \"Cancel\", id: \"47FYwb\" },\n  Reply: { defaultMessage: \"Reply\", id: \"9HU8vw\" },\n  Send: { defaultMessage: \"Send\", id: \"9WRlF4\" },\n  NotePlaceholder: { defaultMessage: \"What's on your mind?\", id: \"flnGvv\" },\n  Back: { defaultMessage: \"Back\", id: \"cyR7Kh\" },\n  Block: { defaultMessage: \"Block\", id: \"Up5U7K\" },\n  Unblock: { defaultMessage: \"Unblock\", id: \"nDejmx\" },\n  MuteCount: { defaultMessage: \"{n} muted\", id: \"VlJkSk\" },\n  Mute: { defaultMessage: \"Mute\", id: \"x82IOl\" },\n  MutedAuthor: { defaultMessage: \"This author has been muted\", id: \"ASRK0S\" },\n  Others: { defaultMessage: ` & {n} {n, plural, =1 {other} other {others}}`, id: \"egib+2\" },\n  Show: { defaultMessage: \"Show\", id: \"K7AkdL\" },\n  Delete: { defaultMessage: \"Delete\", id: \"K3r6DQ\" },\n  Deleted: { defaultMessage: \"Deleted\", id: \"KQvWvD\" },\n  Unmute: { defaultMessage: \"Unmute\", id: \"W9355R\" },\n  MuteAll: { defaultMessage: \"Mute all\", id: \"cWx9t8\" },\n  BlockCount: { defaultMessage: \"{n} blocked\", id: \"nwZXeh\" },\n  JustNow: { defaultMessage: \"Just now\", id: \"bxv59V\" },\n  Follow: { defaultMessage: \"Follow\", id: \"ieGrWo\" },\n  FollowAll: { defaultMessage: \"Follow all\", id: \"mKAr6h\" },\n  Unfollow: { defaultMessage: \"Unfollow\", id: \"izWS4J\" },\n  FollowerCount: { defaultMessage: \"{n} followers\", id: \"o7e+nJ\" },\n  FollowingCount: { defaultMessage: \"Follows {n}\", id: \"9SvQep\" },\n  FollowsYou: { defaultMessage: \"follows you\", id: \"FmXUJg\" },\n  Invoice: { defaultMessage: \"Lightning Invoice\", id: \"9wO4wJ\" },\n  PayInvoice: { defaultMessage: \"Pay Invoice\", id: \"lvlPhZ\" },\n  Expired: { defaultMessage: \"Expired\", id: \"RahCRH\" },\n  Pay: { defaultMessage: \"Pay\", id: \"lD3+8a\" },\n  Loading: { defaultMessage: \"Loading...\", id: \"gjBiyj\" },\n  Logout: { defaultMessage: \"Logout\", id: \"C81/uG\" },\n  ShowMore: { defaultMessage: \"Show more\", id: \"aWpBzj\" },\n  TranslateTo: { defaultMessage: \"Translate to {lang}\", id: \"Ebl/B2\" },\n  TranslatedFrom: { defaultMessage: \"Translated from {lang}\", id: \"Cu/K85\" },\n  TranslationFailed: { defaultMessage: \"Translation failed\", id: \"qmJ8kD\" },\n  UnknownEventKind: { defaultMessage: \"Unknown event kind: {kind}\", id: \"KahimY\" },\n  ConfirmDeletion: { defaultMessage: `Are you sure you want to delete {id}`, id: \"RhDAoS\" },\n  ConfirmRepost: { defaultMessage: `Are you sure you want to repost: {id}`, id: \"+D82kt\" },\n  Reactions: { defaultMessage: \"Reactions\", id: \"XgWvGA\" },\n  ReactionsCount: { defaultMessage: \"Reactions ({n})\", id: \"iCqGww\" },\n  Share: { defaultMessage: \"Share\", id: \"OKhRC6\" },\n  CopyID: { defaultMessage: \"Copy ID\", id: \"wtLjP6\" },\n  CopyJSON: { defaultMessage: \"Copy Event JSON\", id: \"P61BTu\" },\n  Dislike: { defaultMessage: \"{n} Dislike\", id: \"GspYR7\" },\n  DislikeAction: { defaultMessage: \"Dislike\", id: \"4OB335\" },\n  Sats: { defaultMessage: `{n} {n, plural, =1 {sat} other {sats}}`, id: \"jA3OE/\" },\n  Zapped: { defaultMessage: \"zapped\", id: \"B6+XJy\" },\n  OthersZapped: { defaultMessage: `{n, plural, =0 {} =1 {zapped} other {zapped}}`, id: \"mKhgP9\" },\n  Likes: { defaultMessage: \"Likes ({n})\", id: \"6ewQqw\" },\n  Zaps: { defaultMessage: \"Zaps ({n})\", id: \"JHEHCk\" },\n  Dislikes: { defaultMessage: \"Dislikes ({n})\", id: \"2k0Cv+\" },\n  Reposts: { defaultMessage: \"Reposts ({n})\", id: \"8/vBbP\" },\n  NoteToSelf: { defaultMessage: \"Note to Self\", id: \"4rYCjn\" },\n  Read: { defaultMessage: \"Read\", id: \"filwqD\" },\n  Write: { defaultMessage: \"Write\", id: \"k2veDA\" },\n  Seconds: { defaultMessage: \"{n} secs\", id: \"0yO7wF\" },\n  Milliseconds: { defaultMessage: \"{n} ms\", id: \"/n5KSF\" },\n  ShowLatest: { defaultMessage: \"Show latest {n} notes\", id: \"DZzCem\" },\n  LNURLFail: { defaultMessage: \"Failed to load LNURL service\", id: \"zonsdq\" },\n  InvalidLNURL: { defaultMessage: \"Invalid LNURL\", id: \"0jOEtS\" },\n  InvoiceFail: { defaultMessage: \"Failed to load invoice\", id: \"CHTbO3\" },\n  Custom: { defaultMessage: \"Custom\", id: \"Sjo1P4\" },\n  Confirm: { defaultMessage: \"Confirm\", id: \"N2IrpM\" },\n  Comment: { defaultMessage: \"Comment\", id: \"LgbKvU\" },\n  SendZap: { defaultMessage: \"Send zap\", id: \"5ykRmX\" },\n  ShowReplies: { defaultMessage: \"Show replies\", id: \"hicxcO\" },\n  TooShort: { defaultMessage: \"name too short\", id: \"B4C47Y\" },\n  TooLong: { defaultMessage: \"name too long\", id: \"8g2vyB\" },\n  Regex: { defaultMessage: \"name has disallowed characters\", id: \"0mch2Y\" },\n  Registered: { defaultMessage: \"name is registered\", id: \"cuV2gK\" },\n  Disallowed: { defaultMessage: \"name is blocked\", id: \"wih7iJ\" },\n  DisalledLater: { defaultMessage: \"name will be available later\", id: \"HFls6j\" },\n  BuyNow: { defaultMessage: \"Buy Now\", id: \"lCILNz\" },\n  NotAvailable: { defaultMessage: \"Not available:\", id: \"MI2jkA\" },\n  Buying: { defaultMessage: \"Buying {item}\", id: \"MzRYWH\" },\n  OrderPaid: { defaultMessage: \"Order Paid!\", id: \"H6/kLh\" },\n  NewNip: { defaultMessage: \"Your new NIP-05 handle is:\", id: \"4L2vUY\" },\n  ActivateNow: { defaultMessage: \"Activate Now\", id: \"ZKORll\" },\n  AddToProfile: { defaultMessage: \"Add to Profile\", id: \"qkvYUb\" },\n  AccountPage: { defaultMessage: \"account page\", id: \"lgg1KN\" },\n  AccountSupport: { defaultMessage: \"Account Support\", id: \"/JE/X+\" },\n  GoTo: { defaultMessage: \"Go to\", id: \"xIoGG9\" },\n  FindMore: { defaultMessage: \"Find out more info about {service} at {link}\", id: \"wqyN/i\" },\n  SavePassword: {\n    defaultMessage: \"Please make sure to save the following password in order to manage your handle in the future\",\n    id: \"+vIQlC\",\n  },\n  Handle: { defaultMessage: \"Handle\", id: \"iNWbVV\" },\n  Pin: { defaultMessage: \"Pin\", id: \"puLNUJ\" },\n  Pinned: { defaultMessage: \"Pinned\", id: \"fWZYP5\" },\n  Bookmark: { defaultMessage: \"Bookmark\", id: \"Rs4kCE\" },\n  Bookmarks: { defaultMessage: \"Bookmarks\", id: \"nGBrvw\" },\n  BookmarksCount: { defaultMessage: \"Bookmarks ({n})\", id: \"GL8aXW\" },\n  Bookmarked: { defaultMessage: \"Saved\", id: \"fsB/4p\" },\n  All: { defaultMessage: \"All\", id: \"zQvVDJ\" },\n  ConfirmUnbookmark: { defaultMessage: \"Are you sure you want to remove this note from bookmarks?\", id: \"1Mo59U\" },\n  ConfirmUnpin: { defaultMessage: \"Are you sure you want to unpin this note?\", id: \"IEwZvs\" },\n  ReactionsLink: { defaultMessage: \"{n} Reactions\", id: \"jzgQ2z\" },\n  ReBroadcast: { defaultMessage: \"Broadcast Again\", id: \"c3g2hL\" },\n  IrisUserNameLengthError: { defaultMessage: \"Name must be between 8 and 15 characters\", id: \"LhLvRx\" },\n  IrisUserNameFormatError: { defaultMessage: \"Username must only contain lowercase letters and numbers\", id: \"RSr2uB\" },\n  InvalidNip05Address: { defaultMessage: \"Invalid Nostr Address\", id: \"P2o+ZZ\" },\n  ErrorValidatingNip05Address: { defaultMessage: \"Cannot verify Nostr Address\", id: \"LmdPXO\" },\n  UserNameLengthError: { defaultMessage: \"Name must be less than {limit} characters\", id: \"u9NoC1\" },\n  AboutLengthError: { defaultMessage: \"About must be less than {limit} characters\", id: \"DrZqav\" },\n  InvalidLud16: { defaultMessage: \"Invalid Lightning Address\", id: \"GqQeu/\" },\n})\n"
  },
  {
    "path": "packages/app/src/Components/nip.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nexport default function NipDescription({ nip }: { nip: number }) {\n  switch (nip) {\n    case 1:\n      return <FormattedMessage defaultMessage=\"Basic protocol flow description\" />\n    case 2:\n      return <FormattedMessage defaultMessage=\"Follow List\" />\n    case 3:\n      return <FormattedMessage defaultMessage=\"OpenTimestamps Attestations for Events\" />\n    case 4:\n      return <FormattedMessage defaultMessage=\"Encrypted Direct Message\" />\n    case 5:\n      return <FormattedMessage defaultMessage=\"Mapping Nostr keys to DNS-based internet identifiers\" />\n    case 6:\n      return <FormattedMessage defaultMessage=\"Basic key derivation from mnemonic seed phrase\" />\n    case 7:\n      return <FormattedMessage defaultMessage=\"window.nostr capability for web browsers\" />\n    case 8:\n      return <FormattedMessage defaultMessage=\"Handling Mentions\" />\n    case 9:\n      return <FormattedMessage defaultMessage=\"Event Deletion Request\" />\n    case 10:\n      return <FormattedMessage defaultMessage=\"Conventions for clients' use of e and p tags in text events\" />\n    case 11:\n      return <FormattedMessage defaultMessage=\"Relay Information Document\" />\n    case 13:\n      return <FormattedMessage defaultMessage=\"Proof of Work\" />\n    case 14:\n      return <FormattedMessage defaultMessage=\"Subject tag in text events\" />\n    case 15:\n      return <FormattedMessage defaultMessage=\"Nostr Marketplace (for resilient marketplaces)\" />\n    case 17:\n      return <FormattedMessage defaultMessage=\"Private Direct Messages\" />\n    case 18:\n      return <FormattedMessage defaultMessage=\"Reposts\" />\n    case 19:\n      return <FormattedMessage defaultMessage=\"bech32-encoded entities\" />\n    case 21:\n      return <FormattedMessage defaultMessage=\"nostr: URI scheme\" />\n    case 23:\n      return <FormattedMessage defaultMessage=\"Long-form Content\" />\n    case 24:\n      return <FormattedMessage defaultMessage=\"Extra metadata fields and tags\" />\n    case 25:\n      return <FormattedMessage defaultMessage=\"Reactions\" />\n    case 26:\n      return <FormattedMessage defaultMessage=\"Delegated Event Signing\" />\n    case 27:\n      return <FormattedMessage defaultMessage=\"Text Note References\" />\n    case 28:\n      return <FormattedMessage defaultMessage=\"Public Chat\" />\n    case 29:\n      return <FormattedMessage defaultMessage=\"Relay-based Groups\" />\n    case 30:\n      return <FormattedMessage defaultMessage=\"Custom Emoji\" />\n    case 31:\n      return <FormattedMessage defaultMessage=\"Dealing with Unknown Events\" />\n    case 32:\n      return <FormattedMessage defaultMessage=\"Labeling\" />\n    case 34:\n      return <FormattedMessage defaultMessage=\"git stuff\" />\n    case 35:\n      return <FormattedMessage defaultMessage=\"Torrents\" />\n    case 36:\n      return <FormattedMessage defaultMessage=\"Sensitive Content\" />\n    case 38:\n      return <FormattedMessage defaultMessage=\"User Statuses\" />\n    case 39:\n      return <FormattedMessage defaultMessage=\"External Identities in Profiles\" />\n    case 40:\n      return <FormattedMessage defaultMessage=\"Expiration Timestamp\" />\n    case 42:\n      return <FormattedMessage defaultMessage=\"Authentication of clients to relays\" />\n    case 44:\n      return <FormattedMessage defaultMessage=\"Versioned Encryption\" />\n    case 45:\n      return <FormattedMessage defaultMessage=\"Counting results\" />\n    case 46:\n      return <FormattedMessage defaultMessage=\"Nostr Connect\" />\n    case 47:\n      return <FormattedMessage defaultMessage=\"Wallet Connect\" />\n    case 48:\n      return <FormattedMessage defaultMessage=\"Proxy Tags\" />\n    case 49:\n      return <FormattedMessage defaultMessage=\"Private Key Encryption\" />\n    case 50:\n      return <FormattedMessage defaultMessage=\"Search Capability\" />\n    case 51:\n      return <FormattedMessage defaultMessage=\"Lists\" />\n    case 52:\n      return <FormattedMessage defaultMessage=\"Calendar Events\" />\n    case 53:\n      return <FormattedMessage defaultMessage=\"Live Activities\" />\n    case 54:\n      return <FormattedMessage defaultMessage=\"Wiki\" />\n    case 55:\n      return <FormattedMessage defaultMessage=\"Android Signer Application\" />\n    case 56:\n      return <FormattedMessage defaultMessage=\"Reporting\" />\n    case 57:\n      return <FormattedMessage defaultMessage=\"Lightning Zaps\" />\n    case 58:\n      return <FormattedMessage defaultMessage=\"Badges\" />\n    case 59:\n      return <FormattedMessage defaultMessage=\"Gift Wrap\" />\n    case 64:\n      return <FormattedMessage defaultMessage=\"Chess (PGN)\" />\n    case 65:\n      return <FormattedMessage defaultMessage=\"Relay List Metadata\" />\n    case 70:\n      return <FormattedMessage defaultMessage=\"Protected Events\" />\n    case 71:\n      return <FormattedMessage defaultMessage=\"Video Events\" />\n    case 72:\n      return <FormattedMessage defaultMessage=\"Moderated Communities\" />\n    case 73:\n      return <FormattedMessage defaultMessage=\"External Content IDs\" />\n    case 75:\n      return <FormattedMessage defaultMessage=\"Zap Goals\" />\n    case 78:\n      return <FormattedMessage defaultMessage=\"Application-specific data\" />\n    case 84:\n      return <FormattedMessage defaultMessage=\"Highlights\" />\n    case 89:\n      return <FormattedMessage defaultMessage=\"Recommended Application Handlers\" />\n    case 90:\n      return <FormattedMessage defaultMessage=\"Data Vending Machines\" />\n    case 92:\n      return <FormattedMessage defaultMessage=\"Media Attachments\" />\n    case 94:\n      return <FormattedMessage defaultMessage=\"File Metadata\" />\n    case 96:\n      return <FormattedMessage defaultMessage=\"HTTP File Storage Integration\" />\n    case 98:\n      return <FormattedMessage defaultMessage=\"HTTP Auth\" />\n    case 99:\n      return <FormattedMessage defaultMessage=\"Classified Listings\" />\n    default:\n      return (\n        <FormattedMessage\n          defaultMessage=\"Unknown NIP-{x}\"\n          values={{\n            x: nip.toString().padStart(2, \"0\"),\n          }}\n        />\n      )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Components/zap-amount.tsx",
    "content": "import { formatShort } from \"@/Utils/Number\"\n\nimport Icon from \"./Icons/Icon\"\n\nexport default function ZapAmount({ n }: { n: number }) {\n  return (\n    <div className=\"flex gap-2 items-center text-xl font-bold\">\n      <Icon name=\"zap-solid\" size={20} className=\"text-zap\" />\n      <span>{formatShort(n)}</span>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Db/FuzzySearch.ts",
    "content": "import type { CachedMetadata, NostrEvent } from \"@snort/system\"\nimport Fuse from \"fuse.js\"\n\nexport type FuzzySearchResult = {\n  pubkey: string\n  name?: string\n  display_name?: string\n  nip05?: string\n}\n\nconst fuzzySearch = new Fuse<FuzzySearchResult>([], {\n  keys: [\"name\", \"display_name\", { name: \"nip05\", weight: 0.5 }],\n  threshold: 0.3,\n  // sortFn here?\n})\n\nconst profileTimestamps = new Map<string, number>() // is this somewhere in cache?\n\nexport const addEventToFuzzySearch = (ev: NostrEvent) => {\n  if (ev.kind !== 0) {\n    return\n  }\n  queueMicrotask(() => {\n    const existing = profileTimestamps.get(ev.pubkey)\n    if (existing) {\n      if (existing > ev.created_at) {\n        return\n      }\n      // for some reason we get duplicates even though this should be removing existing profile on update\n      fuzzySearch.remove(doc => doc.pubkey === ev.pubkey)\n    }\n    profileTimestamps.set(ev.pubkey, ev.created_at)\n    try {\n      const data = JSON.parse(ev.content)\n      if (ev.pubkey && (data.name || data.display_name || data.nip05)) {\n        data.pubkey = ev.pubkey\n        fuzzySearch.add(data)\n      }\n    } catch (e) {\n      console.error(e)\n    }\n  })\n}\n\nexport const addCachedMetadataToFuzzySearch = (profile: CachedMetadata) => {\n  const existing = profileTimestamps.get(profile.pubkey)\n  if (existing) {\n    if (existing > profile.created) {\n      return\n    }\n    fuzzySearch.remove(doc => doc.pubkey === profile.pubkey)\n  }\n  profileTimestamps.set(profile.pubkey, profile.created)\n  if (profile.pubkey && (profile.name || profile.display_name || profile.nip05)) {\n    fuzzySearch.add(profile)\n  }\n}\n\nexport default fuzzySearch\n"
  },
  {
    "path": "packages/app/src/External/NostrBand.ts",
    "content": "import type { NostrEvent } from \"@snort/system\"\nimport { JsonApi } from \"./base\"\n\nexport interface TrendingProfile {\n  pubkey: string\n  new_follower_count: number\n  profile?: NostrEvent\n  relays?: Array<string>\n}\n\nexport interface TrendingProfilesResponse {\n  profiles: Array<TrendingProfile>\n}\n\nexport interface TrendingHashtagsResponse {\n  hashtags: Array<{ hashtag: string; posts: number }>\n}\n\nexport default class NostrBandApi extends JsonApi {\n  url = \"https://api.nostr.band\"\n  readonly #supportedLangs = [\"en\", \"de\", \"ja\", \"zh\", \"th\", \"pt\", \"es\", \"fr\"]\n\n  async trendingProfiles() {\n    return await this.getJson<TrendingProfilesResponse>(\"/v0/trending/profiles\")\n  }\n\n  // trendingNotesUrl(lang?: string) {\n  //   return `${this.url}/v0/trending/notes${lang && this.#supportedLangs.includes(lang) ? `?lang=${lang}` : \"\"}`;\n  // }\n\n  // suggestedFollowsUrl(pubkey: string) {\n  //   return `${this.url}/v0/suggested/profiles/${pubkey}`;\n  // }\n\n  async trendingHashtags(lang?: string) {\n    return await this.getJson<TrendingHashtagsResponse>(\n      `/v0/trending/hashtags${lang && this.#supportedLangs.includes(lang) ? `?lang=${lang}` : \"\"}`,\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/External/NostrServices.ts",
    "content": "import { JsonApi } from \"./base\"\n\nexport interface LinkPreviewData {\n  title?: string\n  description?: string\n  image?: string\n  og_tags?: Array<[name: string, value: string]>\n}\n\n/**\n * API client for https://nostr-rs-api.v0l.io\n */\nexport class NostrServices extends JsonApi {\n  readonly url: string\n  constructor(url?: string) {\n    super()\n    this.url = url ?? \"https://nostr-rs-api.v0l.io\"\n  }\n\n  linkPreview(url: string) {\n    return this.getJson<LinkPreviewData>(`/preview?url=${encodeURIComponent(url)}`)\n  }\n}\n"
  },
  {
    "path": "packages/app/src/External/SnortApi.ts",
    "content": "import { EventPublisher, type EventSigner } from \"@snort/system\"\n\nimport { ApiHost } from \"@/Utils/Const\"\nimport type { SubscriptionType } from \"@/Utils/Subscription\"\nimport { JsonApi } from \"./base\"\n\nexport interface RevenueToday {\n  donations: number\n  nip5: number\n}\n\nexport interface RevenueSplit {\n  pubKey: string\n  split: number\n}\n\nexport interface InvoiceResponse {\n  pr: string\n}\n\nexport interface Subscription {\n  id: string\n  type: SubscriptionType\n  created: number\n  expires: number\n  state: \"new\" | \"expired\" | \"paid\"\n  handle?: string\n}\n\nexport enum SubscriptionErrorCode {\n  InternalError = 1,\n  SubscriptionActive = 2,\n  Duplicate = 3,\n}\n\nexport class SubscriptionError extends Error {\n  code: SubscriptionErrorCode\n\n  constructor(msg: string, code: SubscriptionErrorCode) {\n    super(msg)\n    this.code = code\n  }\n}\n\nexport interface PushNotifications {\n  endpoint: string\n  p256dh: string\n  auth: string\n  scope: string\n}\n\nexport interface TranslationRequest {\n  text: Array<string>\n  target_lang: string\n}\n\nexport interface TranslationResponse {\n  translations: Array<{\n    detected_source_language: string\n    text: string\n  }>\n}\n\nexport interface RelayDistance {\n  url: string\n  distance: number\n  users: number\n  country?: string\n  city?: string\n  is_paid?: boolean\n  description?: string\n}\n\nexport interface RefCodeResponse {\n  code: string\n  pubkey: string\n  revShare?: number\n  leaderState?: \"pending\" | \"approved\"\n}\n\n/**\n * API client wrapper for https://api.snort.social/swagger\n */\nexport default class SnortApi extends JsonApi {\n  readonly url: string\n  readonly signer?: EventSigner\n\n  constructor(url?: string, signer?: EventSigner | EventPublisher) {\n    super()\n    this.url = new URL(url ?? ApiHost).toString()\n    this.signer = signer instanceof EventPublisher ? signer.signer : signer\n  }\n\n  revenueSplits() {\n    return this.getJson<Array<RevenueSplit>>(\"api/v1/revenue/splits\")\n  }\n\n  revenueToday() {\n    return this.getJson<RevenueToday>(\"api/v1/revenue/today\")\n  }\n\n  createSubscription(type: number, refCode?: string) {\n    if (!this.signer) {\n      throw new Error(\"No signer set\")\n    }\n    return this.getJsonAuthd<InvoiceResponse>(`api/v1/subscription?type=${type}&refCode=${refCode}`, this.signer, \"PUT\")\n  }\n\n  renewSubscription(id: string, months = 1) {\n    if (!this.signer) {\n      throw new Error(\"No signer set\")\n    }\n    return this.getJsonAuthd<InvoiceResponse>(`api/v1/subscription/${id}/renew?months=${months}`, this.signer, \"GET\")\n  }\n\n  listSubscriptions() {\n    if (!this.signer) {\n      throw new Error(\"No signer set\")\n    }\n    return this.getJsonAuthd<Array<Subscription>>(\"api/v1/subscription\", this.signer)\n  }\n\n  onChainDonation() {\n    return this.getJson<{ address: string }>(\"p/on-chain\")\n  }\n\n  getPushNotificationInfo() {\n    return this.getJson<{ publicKey: string }>(\"api/v1/notifications/info\")\n  }\n\n  registerPushNotifications(sub: PushNotifications) {\n    if (!this.signer) {\n      throw new Error(\"No signer set\")\n    }\n    return this.getJsonAuthd<void>(\"api/v1/notifications/register\", this.signer, \"POST\", sub)\n  }\n\n  translate(tx: TranslationRequest) {\n    return this.getJson<TranslationResponse | object>(\"api/v1/translate\", \"POST\", tx)\n  }\n\n  closeRelays(lat: number, lon: number, count = 5) {\n    return this.getJson<Array<RelayDistance>>(`api/v1/relays?count=${count}`, \"POST\", { lat, lon })\n  }\n\n  getRefCode() {\n    if (!this.signer) {\n      throw new Error(\"No signer set\")\n    }\n    return this.getJsonAuthd<RefCodeResponse>(\"api/v1/referral\", this.signer, \"GET\")\n  }\n\n  getRefCodeInfo(code: string) {\n    return this.getJson<RefCodeResponse>(`api/v1/referral/${code}`, \"GET\")\n  }\n\n  applyForLeader() {\n    if (!this.signer) {\n      throw new Error(\"No signer set\")\n    }\n    return this.getJsonAuthd<RefCodeResponse>(\"api/v1/referral/leader-apply\", this.signer, \"POST\")\n  }\n}\n"
  },
  {
    "path": "packages/app/src/External/base.ts",
    "content": "import { throwIfOffline, unwrap } from \"@snort/shared\"\nimport { EventBuilder, EventKind, type EventSigner } from \"@snort/system\"\n\nexport abstract class JsonApi {\n  abstract url: string\n  protected async getJsonAuthd<T>(\n    path: string,\n    signer: EventSigner,\n    method?: \"GET\" | string,\n    body?: object,\n    headers?: { [key: string]: string },\n  ): Promise<T> {\n    const auth = await new EventBuilder()\n      .kind(EventKind.HttpAuthentication)\n      .tag([\"url\", `${this.url}${path}`])\n      .tag([\"method\", method ?? \"GET\"])\n      .buildAndSign(signer)\n\n    return this.getJson<T>(path, method, body, {\n      ...headers,\n      authorization: `Nostr ${window.btoa(JSON.stringify(auth))}`,\n    })\n  }\n\n  protected async getJson<T>(\n    path: string,\n    method?: \"GET\" | string,\n    body?: object,\n    headers?: { [key: string]: string },\n  ): Promise<T> {\n    throwIfOffline()\n    const rsp = await fetch(`${this.url}${path}`, {\n      method: method,\n      body: body ? JSON.stringify(body) : undefined,\n      headers: {\n        accept: \"application/json\",\n        ...(body ? { \"content-type\": \"application/json\" } : {}),\n        ...headers,\n      },\n    })\n\n    if (rsp.ok) {\n      const text = (await rsp.text()) as string | null\n      if ((text?.length ?? 0) > 0) {\n        const obj = JSON.parse(unwrap(text))\n        if (\"error\" in obj) {\n          throw new Error(obj.error, obj.code)\n        }\n        return obj as T\n      } else {\n        return {} as T\n      }\n    } else {\n      throw new Error(\"Invalid response\")\n    }\n  }\n}\n"
  },
  {
    "path": "packages/app/src/External/index.ts",
    "content": "export * from \"./NostrBand\"\nexport * from \"./NostrServices\"\n"
  },
  {
    "path": "packages/app/src/Feed/ArticlesFeed.ts",
    "content": "import { EventKind, RequestBuilder } from \"@snort/system\"\nimport { SnortContext, useCached, useRequestBuilder } from \"@snort/system-react\"\nimport { useCallback, use, useMemo } from \"react\"\n\nimport useFollowsControls from \"@/Hooks/useFollowControls\"\nimport { Hour } from \"@/Utils/Const\"\n\nexport function useArticles(limit = 10) {\n  const { followList } = useFollowsControls()\n\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(\"articles\")\n    if (followList.length > 0) {\n      rb.withFilter().kinds([EventKind.LongFormTextNote]).authors(followList).limit(limit)\n    }\n    return rb\n  }, [followList, limit])\n\n  return useRequestBuilder(sub)\n}\n\nexport function useCachedArticles(limit = 10) {\n  const { followList } = useFollowsControls()\n  const system = use(SnortContext)\n\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(\"articles\")\n    if (followList.length > 0) {\n      rb.withFilter().kinds([EventKind.LongFormTextNote]).authors(followList).limit(limit)\n    }\n    return rb\n  }, [followList, limit])\n\n  const loader = useCallback(async () => {\n    return await system.Fetch(sub)\n  }, [sub, system])\n\n  const { data } = useCached(\"articles\", loader, Hour * 6)\n  return data ?? []\n}\n"
  },
  {
    "path": "packages/app/src/Feed/BadgesFeed.ts",
    "content": "import { EventKind, NostrLink, } from \"@snort/system\"\nimport { useEventFeed, useEventsFeed, } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nimport { NostrPrefix, removeUndefined } from \"@snort/shared\"\n\ntype BadgeAwards = {\n  pubkeys: string[]\n  ds: string[]\n}\n\nexport default function useProfileBadges(pubkey: string) {\n  const profileBadgesLink = new NostrLink(NostrPrefix.Address, \"profile_badges\", EventKind.ProfileBadges, pubkey)\n  const profileBadges = useEventFeed(profileBadgesLink)\n  const links = NostrLink.fromTags(profileBadges?.tags ?? [])\n  const linkedEvents = useEventsFeed(`badges:${pubkey}`, links)\n\n  // filter badge award events to selected profile badges\n  const validBadgeAwards = useMemo(() => {\n    const selectedBadges = links.filter(a => a.type === NostrPrefix.Address && a.kind === EventKind.Badge)\n    const wasAwardedByAuthorBadges = selectedBadges.filter(a => {\n      const awardEvent = linkedEvents.find(\n        b =>\n          b.kind === EventKind.BadgeAward &&\n          b.pubkey === a.author! &&\n          b.tags.some(c => c[0] === \"p\" && c[1] === pubkey),\n      )\n      return awardEvent !== undefined\n    })\n    return wasAwardedByAuthorBadges\n  }, [links, linkedEvents, pubkey])\n  return removeUndefined(validBadgeAwards.map(a => linkedEvents.find(b => a.matchesEvent(b))))\n}\n"
  },
  {
    "path": "packages/app/src/Feed/FollowersFeed.ts",
    "content": "import { EventKind, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nimport useWoT from \"@/Hooks/useWoT\"\n\nexport default function useFollowersFeed(pubkey?: string) {\n  const wot = useWoT()\n  const sub = useMemo(() => {\n    const b = new RequestBuilder(`followers`)\n    if (pubkey) {\n      b.withFilter().kinds([EventKind.ContactList]).tag(\"p\", [pubkey])\n    }\n    return b\n  }, [pubkey])\n\n  const followersFeed = useRequestBuilder(sub)\n\n  const followers = useMemo(() => {\n    const contactLists = followersFeed?.filter(\n      a => a.kind === EventKind.ContactList && a.tags.some(b => b[0] === \"p\" && b[1] === pubkey),\n    )\n    return wot.sortEvents(contactLists)\n  }, [followersFeed, pubkey, wot.sortEvents])\n\n  return followers\n}\n"
  },
  {
    "path": "packages/app/src/Feed/FollowsFeed.ts",
    "content": "import { EventKind, RequestBuilder, type TaggedNostrEvent } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nexport default function useFollowsFeed(pubkey?: string) {\n  const sub = useMemo(() => {\n    const b = new RequestBuilder(`follows:for`)\n    if (pubkey) {\n      b.withFilter().kinds([EventKind.ContactList]).authors([pubkey])\n    }\n    return b\n  }, [pubkey])\n\n  const contactFeed = useRequestBuilder(sub)\n  return useMemo(() => {\n    return getFollowing(contactFeed ?? [], pubkey)\n  }, [contactFeed, pubkey])\n}\n\nexport function getFollowing(notes: readonly TaggedNostrEvent[], pubkey?: string) {\n  const contactLists = notes.filter(a => a.kind === EventKind.ContactList && a.pubkey === pubkey)\n  const pTags = contactLists?.map(a => a.tags.filter(b => b[0] === \"p\").map(c => c[1]))\n  return [...new Set(pTags?.flat())]\n}\n"
  },
  {
    "path": "packages/app/src/Feed/HashtagsFeed.ts",
    "content": "import { removeUndefined, unixNow } from \"@snort/shared\"\nimport { EventKind, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nimport useLogin from \"@/Hooks/useLogin\"\nimport { Hour } from \"@/Utils/Const\"\n\nexport default function useHashtagsFeed() {\n  const { hashtags } = useLogin(s => ({ hashtags: s.state.getList(EventKind.InterestsList) }))\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(\"hashtags-feed\")\n    rb.withFilter()\n      .kinds([EventKind.TextNote, EventKind.LiveEvent, EventKind.LongFormTextNote, EventKind.Polls])\n      .tag(\"t\", removeUndefined(hashtags.map(a => a.toEventTag()?.[1])))\n      .since(unixNow() - Hour * 6)\n    return rb\n  }, [hashtags])\n\n  return {\n    data: useRequestBuilder(sub),\n    hashtags,\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Feed/LoginFeed.ts",
    "content": "import { bech32ToHex, unixNowMs } from \"@snort/shared\"\nimport { EventKind, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useEffect, useMemo } from \"react\"\n\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { System } from \"@/system\"\nimport { unwrap } from \"@/Utils\"\nimport { SnortPubKey } from \"@/Utils/Const\"\nimport { addSubscription } from \"@/Utils/Login\"\nimport type { SubscriptionEvent } from \"@/Utils/Subscription\"\n\n/**\n * Managed loading data for the current logged in user\n */\nexport default function useLoginFeed() {\n  const login = useLogin()\n  const { publicKey: pubKey } = login\n  const checkSigs = usePreferences(s => s.checkSigs)\n  const { publisher, system } = useEventPublisher()\n\n  useEffect(() => {\n    system.checkSigs = checkSigs\n  }, [system, checkSigs])\n\n  useEffect(() => {\n    if (pubKey) {\n      const start = unixNowMs()\n      system.config.socialGraphInstance.setRoot(pubKey)\n      console.debug(\n        `Social graph loaded in ${(unixNowMs() - start).toFixed(2)}ms`,\n        System.config.socialGraphInstance.size(),\n      )\n    }\n  }, [pubKey, system.config.socialGraphInstance.setRoot])\n\n  useEffect(() => {\n    login.state.init(publisher?.signer, system).catch(console.error)\n  }, [login, publisher, system])\n\n  const subLogin = useMemo(() => {\n    const b = new RequestBuilder(`login:sub`)\n    b.withOptions({\n      leaveOpen: true,\n    })\n    if (CONFIG.features.subscriptions && !login.readonly) {\n      if (pubKey) {\n        b.withFilter()\n          .relay(\"wss://relay.snort.social/\")\n          .kinds([EventKind.SnortSubscriptions])\n          .authors([bech32ToHex(SnortPubKey)])\n          .tag(\"p\", [pubKey])\n          .limit(10)\n      }\n    }\n    return b\n  }, [pubKey, login])\n\n  const loginFeed = useRequestBuilder(subLogin)\n\n  // update relays and follow lists\n  useEffect(() => {\n    if (loginFeed && publisher) {\n      const subs = loginFeed.filter(\n        a => a.kind === EventKind.SnortSubscriptions && a.pubkey === bech32ToHex(SnortPubKey),\n      )\n      Promise.all(\n        subs.map(async a => {\n          const dx = await publisher.decryptDm(a)\n          if (dx) {\n            const ex = JSON.parse(dx)\n            return {\n              id: a.id,\n              ...ex,\n            } as SubscriptionEvent\n          }\n        }),\n      ).then(a => addSubscription(login, ...a.filter(a => a !== undefined).map(unwrap)))\n    }\n  }, [login, loginFeed, publisher])\n\n  useEffect(() => {\n    system.profileLoader.TrackKeys(login.state.follows ?? []) // always track follows profiles\n  }, [system, login.state.follows])\n}\n"
  },
  {
    "path": "packages/app/src/Feed/RelayState.ts",
    "content": "import { SnortContext } from \"@snort/system-react\"\nimport { use } from \"react\"\n\nexport default function useRelayState(addr: string) {\n  const system = use(SnortContext)\n  const c = system.pool.getConnection(addr)\n  return c\n}\n"
  },
  {
    "path": "packages/app/src/Feed/RelaysFeed.tsx",
    "content": "import { EventKind, parseRelayTags, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nexport default function useRelaysFeed(pubkey?: string) {\n  const sub = useMemo(() => {\n    const b = new RequestBuilder(`relays:${pubkey ?? \"\"}`)\n    if (pubkey) {\n      b.withFilter().authors([pubkey]).kinds([EventKind.Relays])\n    }\n    return b\n  }, [pubkey])\n\n  const relays = useRequestBuilder(sub)\n  return parseRelayTags(relays[0]?.tags.filter(a => a[0] === \"r\") ?? [])\n}\n"
  },
  {
    "path": "packages/app/src/Feed/StatusFeed.ts",
    "content": "import { unixNow } from \"@snort/shared\"\nimport { type EventKind, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nimport { findTag } from \"@/Utils\"\n\nexport function useStatusFeed(id?: string, leaveOpen = false) {\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(`statud:${id}`)\n    rb.withOptions({ leaveOpen })\n    if (id) {\n      rb.withFilter()\n        .kinds([30315 as EventKind])\n        .authors([id])\n    }\n    return rb\n  }, [id, leaveOpen])\n\n  const status = useRequestBuilder(sub)\n\n  const statusFiltered = status.filter(a => {\n    const exp = Number(findTag(a, \"expiration\"))\n    return Number.isNaN(exp) || exp >= unixNow()\n  })\n  const general = statusFiltered?.find(a => findTag(a, \"d\") === \"general\")\n  const music = statusFiltered?.find(a => findTag(a, \"d\") === \"music\")\n\n  return {\n    general,\n    music,\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Feed/TimelineFeed.ts",
    "content": "import { unixNow } from \"@snort/shared\"\nimport { EventKind, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilderAdvanced } from \"@snort/system-react\"\nimport { useCallback, useMemo, useSyncExternalStore } from \"react\"\n\nimport useModeration from \"@/Hooks/useModeration\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport useTimelineWindow from \"@/Hooks/useTimelineWindow\"\nimport { SearchRelays } from \"@/Utils/Const\"\n\nexport interface TimelineFeedOptions {\n  method: \"TIME_RANGE\" | \"LIMIT_UNTIL\"\n  window?: number\n  now?: number\n}\n\nexport interface TimelineSubject {\n  type: \"pubkey\" | \"hashtag\" | \"global\" | \"ptag\" | \"post_keyword\" | \"profile_keyword\"\n  discriminator: string\n  items: string[]\n  relay?: Array<string>\n  extra?: (rb: RequestBuilder) => void\n  kinds?: EventKind[]\n}\n\nexport type TimelineFeed = ReturnType<typeof useTimelineFeed>\n\nexport default function useTimelineFeed(subject: TimelineSubject, options: TimelineFeedOptions) {\n  const { now, since, until, older, setUntil } = useTimelineWindow({\n    window: options.window,\n    now: options.now ?? unixNow(),\n  })\n  const _autoShowLatest = usePreferences(s => s.autoShowLatest)\n  const { isEventMuted } = useModeration()\n\n  const createBuilder = useCallback(() => {\n    const kinds =\n      subject.kinds ??\n      (subject.type === \"profile_keyword\"\n        ? [EventKind.SetMetadata]\n        : [EventKind.TextNote, EventKind.Repost, EventKind.Polls])\n\n    const b = new RequestBuilder(`timeline:${subject.type}:${subject.discriminator}`)\n    const f = b.withFilter().kinds(kinds)\n\n    if (subject.relay) {\n      subject.relay.forEach(r => f.relay(r))\n    }\n    switch (subject.type) {\n      case \"pubkey\": {\n        f.authors(subject.items)\n        break\n      }\n      case \"hashtag\": {\n        f.tag(\"t\", subject.items)\n        break\n      }\n      case \"ptag\": {\n        f.tag(\"p\", subject.items)\n        break\n      }\n      case \"profile_keyword\": {\n        f.search(subject.items[0])\n        SearchRelays.forEach(r => f.relay(r))\n        break\n      }\n      case \"post_keyword\": {\n        f.search(subject.items[0])\n        SearchRelays.forEach(r => f.relay(r))\n        break\n      }\n    }\n    subject.extra?.(b)\n    return b\n  }, [subject])\n\n  const sub = useMemo(() => {\n    const rb = createBuilder()\n    for (const filter of rb.filterBuilders) {\n      if (options.method === \"LIMIT_UNTIL\") {\n        filter.until(until).limit(50)\n      } else {\n        filter.since(since).until(until)\n        if (since === undefined) {\n          filter.limit(50)\n        }\n      }\n    }\n    return rb\n  }, [until, since, options.method, createBuilder])\n\n  const mainQuery = useRequestBuilderAdvanced(sub)\n  const main = useSyncExternalStore(\n    h => {\n      mainQuery.uncancel()\n      mainQuery.on(\"event\", h)\n      mainQuery.start()\n      return () => {\n        mainQuery.flush()\n        mainQuery.cancel()\n        mainQuery.off(\"event\", h)\n      }\n    },\n    () => mainQuery?.snapshot,\n  )\n\n  const subRealtime = useMemo(() => {\n    const rb = createBuilder()\n    rb.id = `${rb.id}:latest`\n    rb.withOptions({\n      leaveOpen: true,\n    })\n    for (const filter of rb.filterBuilders) {\n      filter.limit(1).since(now)\n    }\n    return rb\n  }, [createBuilder, now])\n\n  const latestQuery = useRequestBuilderAdvanced(subRealtime)\n  const latest = useSyncExternalStore(\n    h => {\n      latestQuery.uncancel()\n      latestQuery.on(\"event\", h)\n      latestQuery.start()\n      return () => {\n        latestQuery.flush()\n        latestQuery.cancel()\n        latestQuery.off(\"event\", h)\n      }\n    },\n    () => latestQuery?.snapshot,\n  )\n\n  return {\n    main: main?.filter(a => !isEventMuted(a)),\n    latest: latest?.filter(a => !isEventMuted(a)),\n    loadMore: () => {\n      if (main) {\n        console.debug(\"Timeline load more!\")\n        if (options.method === \"LIMIT_UNTIL\") {\n          const oldest = main.reduce((acc, v) => (acc = v.created_at < acc ? v.created_at : acc), unixNow())\n          setUntil(oldest)\n        } else {\n          older()\n        }\n      }\n    },\n    showLatest: () => {\n      if (latest) {\n        mainQuery?.feed.add(latest)\n        latestQuery?.feed.clear()\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Feed/WorkerRelayView.ts",
    "content": "import { EventKind, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nimport useLogin from \"@/Hooks/useLogin\"\n\nexport function useNotificationsView() {\n  const publicKey = useLogin(s => s.publicKey)\n  const kinds = [EventKind.TextNote, EventKind.Reaction, EventKind.Repost, EventKind.ZapReceipt]\n  const req = useMemo(() => {\n    const rb = new RequestBuilder(\"notifications\")\n    rb.withOptions({\n      leaveOpen: true,\n    })\n    if (publicKey) {\n      rb.withFilter().kinds(kinds).tag(\"p\", [publicKey]).limit(100)\n    }\n    return rb\n  }, [publicKey, kinds])\n  return useRequestBuilder(req)\n}\n"
  },
  {
    "path": "packages/app/src/Feed/ZapsFeed.ts",
    "content": "import { EventKind, type NostrLink, parseZap, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nexport default function useZapsFeed(link?: NostrLink) {\n  const sub = useMemo(() => {\n    const b = new RequestBuilder(`zaps:${link?.encode()}`)\n    if (link) {\n      b.withFilter().kinds([EventKind.ZapReceipt]).replyToLink([link])\n    }\n    return b\n  }, [link])\n\n  const zapsFeed = useRequestBuilder(sub)\n\n  const zaps = useMemo(() => {\n    if (zapsFeed) {\n      const parsedZaps = zapsFeed.map(a => parseZap(a)).filter(z => z.valid)\n      return parsedZaps.sort((a, b) => b.amount - a.amount)\n    }\n    return []\n  }, [zapsFeed])\n\n  return zaps\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useAiAgent.ts",
    "content": "import { useRef, useCallback, useEffect } from \"react\"\nimport {\n  Agent,\n  Runner,\n  tool,\n  setTracingDisabled,\n  OpenAIChatCompletionsModel,\n  type ModelProvider,\n  RunItemStreamEvent,\n  type RunToolCallItem,\n  type RunToolCallOutputItem,\n  type Session,\n  MemorySession,\n} from \"@openai/agents\"\nimport OpenAI from \"openai\"\nimport { z } from \"zod\"\nimport { RequestBuilder, type UserMetadata, NostrLink, tryParseNostrLink } from \"@snort/system\"\nimport { SnortSystemPrompt } from \"@/Agent/system-prompt\"\nimport useEventPublisher from \"./useEventPublisher\"\nimport useProfileSearch from \"./useProfileSearch\"\nimport usePreferences from \"./usePreferences\"\nimport { hexToBech32, NostrPrefix } from \"@snort/shared\"\n\nclass CustomModelProvider implements ModelProvider {\n  private client: OpenAI\n  private modelName: string\n\n  constructor(apiUrl: string, apiKey: string | undefined, modelName: string) {\n    this.client = new OpenAI({\n      apiKey: apiKey || \"not-needed\",\n      baseURL: apiUrl,\n      dangerouslyAllowBrowser: true,\n    })\n    this.modelName = modelName\n  }\n\n  async getModel(modelName?: string) {\n    return new OpenAIChatCompletionsModel(this.client, modelName || this.modelName)\n  }\n\n  async listModels(): Promise<Array<{ id: string }>> {\n    try {\n      const response = await this.client.models.list()\n      return response.data\n    } catch (error) {\n      console.error(\"Error listing models:\", error)\n      return []\n    }\n  }\n}\n\nconst AI_CONFIG = {\n  apiUrl: \"https://or.v0l.io/v1\",\n  model: \"code\",\n  apiKey: \"sk-215c78cfd59ec07b-a1f9a1-59a9fe61\",\n}\n\nexport interface ModelInfo {\n  id: string\n  name: string\n}\n\nexport type AiStreamEvent =\n  | { type: \"done\" }\n  | { type: \"error\"; error: Error | string }\n  | { type: \"text\"; content: string }\n  | { type: \"thinking\"; content: string }\n  | { type: \"tool_call\"; name: string; args: object | undefined }\n  | { type: \"tool_result\"; name: string; result: object | string | undefined }\n\nexport interface ChatHistoryItem {\n  role: \"user\" | \"assistant\"\n  content: string\n}\n\ninterface AgentInstance {\n  provider: CustomModelProvider\n  agent: Agent\n  runner: Runner\n  session: Session\n}\n\nexport function useAiAgent() {\n  const agentRef = useRef<AgentInstance | null>(null)\n  const { publisher, system } = useEventPublisher()\n  const search = useProfileSearch()\n  const agentConfig = usePreferences(s => ({\n    url: s.agentUrl,\n    key: s.agentKey,\n    model: s.agentModel,\n  }))\n  const memoryRef = useRef(new MemorySession())\n\n  useEffect(() => {\n    // reset agent on config change\n    agentRef.current = null\n  }, [agentConfig, agentRef])\n\n  const getOrCreate = useCallback(() => {\n    if (agentRef.current) return agentRef.current\n\n    setTracingDisabled(true)\n\n    const apiUrl = agentConfig.url || AI_CONFIG.apiUrl\n    const apiKey = agentConfig.key || AI_CONFIG.apiKey\n    const modelName = agentConfig.model || AI_CONFIG.model\n    const modelProvider = new CustomModelProvider(apiUrl, apiKey, modelName)\n    const runner = new Runner({ modelProvider })\n\n    const tools = [\n      tool({\n        name: \"create_event\",\n        description: \"Create a new Nostr event\",\n        parameters: z\n          .object({\n            content: z.string().describe(\"The content of the event\"),\n            kind: z.number().describe(\"The event kind number\"),\n            tags: z\n              .array(z.array(z.string()))\n              .optional()\n              .describe(\"Nostr tags, for referencing other events / users, optional\"),\n            created_at: z.number().optional().describe(\"Created timestamp as unix seconds, optional\"),\n          })\n          .describe(\"Unsigned nostr event\"),\n        execute: async input => {\n          try {\n            const es = await publisher?.generic(eb => {\n              for (const [k, v] of Object.entries(input)) {\n                switch (k) {\n                  case \"created_at\": {\n                    if (typeof v === \"number\") {\n                      eb.createdAt(v)\n                      break\n                    } else {\n                      throw \"Created at must be a number\"\n                    }\n                  }\n                  case \"kind\": {\n                    if (typeof v === \"number\") {\n                      eb.kind(v)\n                      break\n                    } else {\n                      throw \"Kind must be a number\"\n                    }\n                  }\n                  case \"content\": {\n                    if (typeof v === \"string\") {\n                      eb.content(v)\n                      break\n                    } else {\n                      throw \"Content must be a string\"\n                    }\n                  }\n                  case \"tags\": {\n                    if (Array.isArray(v)) {\n                      if (v.length === 0) break\n                      if ((v as Array<never>).every(b => Array.isArray(b))) {\n                        for (const t of v as Array<Array<string>>) {\n                          eb.tag(t)\n                        }\n                      }\n                    } else {\n                      throw \"Tags must be 2d array of strings, each entry must have at least 2 items (k,v)\"\n                    }\n                  }\n                }\n              }\n              return eb\n            })\n            return JSON.stringify(es)\n          } catch (error) {\n            return `Error creating post: ${error instanceof Error ? error.message : String(error)}`\n          }\n        },\n      }),\n      tool({\n        name: \"search_username\",\n        description:\n          \"Search for users by name or NIP-05 using fuzzy matching. Returns matching profiles with their pubkeys, display names, and NIP-05 addresses. Use this when you need to find a user's profile before following them or mentioning them.\",\n        parameters: z.object({\n          query: z.string().describe(\"Search query - user name, display name, or NIP-05 address\"),\n        }),\n        execute: async input => {\n          try {\n            const results = search(input.query)\n            if (!results || results.length === 0) {\n              return \"No users found\"\n            }\n            const formatted = results.slice(0, 10).map(p => ({\n              name: p.display_name || p.name || \"Unknown\",\n              nip05: p.nip05 || \"no nip05\",\n              pubkey: p.pubkey,\n              npub: hexToBech32(\"npub\", p.pubkey),\n            }))\n            return JSON.stringify(formatted)\n          } catch (error) {\n            return `Error searching users: ${error instanceof Error ? error.message : String(error)}`\n          }\n        },\n      }),\n      tool({\n        name: \"update_profile\",\n        description: \"Update user profile information\",\n        parameters: z.object({\n          displayName: z.string().nullable().describe(\"Display name\"),\n          bio: z.string().nullable().describe(\"Bio/note\"),\n          avatarUrl: z.string().nullable().describe(\"Profile image URL\"),\n          bannerUrl: z.string().nullable().describe(\"Banner image URL\"),\n          website: z.string().nullable().describe(\"Website URL\"),\n        }),\n        execute: async input => {\n          if (!publisher) return JSON.stringify({ error: \"Not logged in, cannot update profile\" })\n          try {\n            const profile: UserMetadata = {}\n            if (input.displayName) profile.display_name = input.displayName\n            if (input.bio) profile.about = input.bio\n            if (input.avatarUrl) profile.picture = input.avatarUrl\n            if (input.bannerUrl) profile.banner = input.bannerUrl\n            if (input.website) profile.website = input.website\n            const event = await publisher.metadata(profile)\n            return JSON.stringify(event)\n          } catch (error) {\n            return `Error updating profile: ${error instanceof Error ? error.message : String(error)}`\n          }\n        },\n      }),\n      tool({\n        name: \"query_nostr\",\n        description:\n          \"Query the local relay for Nostr events using REQ filters. IMPORTANT: authors must be 64-char hex pubkeys, NOT npub/nip05. Use 'search_username' for names. For fetching a specific event by nevent/naddr link, use 'prepare_event_filter' first to get the correct filter with relay hints.\",\n        parameters: z.object({\n          filters: z\n            .array(z.record(z.string(), z.any()))\n            .describe(\n              \"Array of Nostr REQ filter objects. Each filter can have: authors (64-char hex only), kinds, ids, #e, #p, #t, #a, search, since, until, and relays (array of URLs). IMPORTANT: If you have a nevent/naddr link, first call 'prepare_event_filter' to get a properly formatted filter with relay hints.\",\n            ),\n          timeout: z\n            .union([z.number(), z.string()])\n            .nullable()\n            .optional()\n            .describe(\"Optional: timeout in ms (default 10000)\"),\n        }),\n        execute: async input => {\n          try {\n            if (!input.filters || !Array.isArray(input.filters) || input.filters.length === 0) {\n              return \"Error: filters must be a non-empty array of filter objects\"\n            }\n\n            const req = new RequestBuilder(`ai-query-${Date.now()}`)\n            let timeout = (input.timeout as number | string) || 10000\n            if (typeof timeout === \"string\" && !isNaN(parseInt(timeout, 10))) {\n              timeout = parseInt(timeout, 10)\n            }\n            req.withOptions({ timeout: typeof timeout === \"string\" ? parseInt(timeout, 10) : timeout })\n\n            // Build filters - relays should be inside the filter object, not as a separate parameter\n            for (const f of input.filters) {\n              req.withBareFilter(f)\n            }\n\n            const events = await system.Fetch(req)\n            const count = events ? events.length : 0\n\n            if (count === 0) {\n              return JSON.stringify({\n                type: \"query\",\n                filters: input.filters,\n                count: 0,\n                note: \"No events found matching your query (either no events exist or relays timed out)\",\n              })\n            }\n            return JSON.stringify(events)\n          } catch (error) {\n            return `Error querying Nostr: ${error instanceof Error ? error.message : String(error)}`\n          }\n        },\n      }),\n      tool({\n        name: \"prepare_event_filter\",\n        description:\n          \"Take a nevent or naddr link and return the properly formatted filter object with relay hints. Use this before calling 'query_nostr' when you have a specific event link. Returns a filter object ready to be passed to query_nostr.\",\n        parameters: z.object({\n          link: z.string().describe(\"nevent or naddr link (e.g., 'nevent1...' or 'naddr1...')\"),\n        }),\n        execute: async input => {\n          try {\n            const link = tryParseNostrLink(input.link)\n            if (!link) {\n              return `Failed to parse link: ${input.link}`\n            }\n\n            const filter: Record<string, any> = {}\n\n            if (link.type === \"nevent\" || link.type === \"note\") {\n              filter.ids = [link.id]\n            } else if (link.type === \"naddr\") {\n              filter[\"#a\"] = [`${link.kind}:${link.author}:${link.id}`]\n            } else {\n              return `Unsupported link type: ${link.type}`\n            }\n\n            // Add relay hint if available (included in filter object)\n            if (link.relays && link.relays.length > 0) {\n              filter.relays = link.relays\n            }\n\n            // Add author hint if available\n            if (link.author) {\n              if (link.type === \"nevent\" || link.type === \"naddr\") {\n                filter.authors = [link.author]\n              }\n            }\n\n            // Add kind hint if available\n            if (link.kind) {\n              filter.kinds = [link.kind]\n            }\n\n            return JSON.stringify({\n              filter,\n              note: \"Pass the 'filter' object above directly to query_nostr's filters parameter\",\n            })\n          } catch (error) {\n            return `Error preparing filter: ${error instanceof Error ? error.message : String(error)}`\n          }\n        },\n      }),\n      tool({\n        name: \"update_preferences\",\n        description: \"Update application preferences\",\n        parameters: z.object({\n          theme: z.enum([\"light\", \"dark\", \"auto\"]).nullable().describe(\"Theme preference\"),\n          language: z.string().nullable().describe(\"Language preference\"),\n          notificationsEnabled: z.boolean().nullable().describe(\"Enable/disable notifications\"),\n          showNsfw: z.boolean().nullable().describe(\"Show NSFW content\"),\n        }),\n        execute: async () => JSON.stringify({ type: \"preferences\", note: \"not yet implemented\" }),\n      }),\n      tool({\n        name: \"decode_nostr_link\",\n        description:\n          \"Decode a Nostr link string (npub, nprofile, nevent, naddr, note, nsec) into its component parts. Returns the type, id, kind (if applicable), author, relays, and scope.\",\n        parameters: z.object({\n          linkString: z\n            .string()\n            .describe(\"Nostr link string to decode (e.g., 'npub1...', 'nprofile1...', 'nevent1...', 'naddr1...')\"),\n        }),\n        execute: async input => {\n          try {\n            const link = tryParseNostrLink(input.linkString)\n            if (!link) {\n              return `Failed to parse NostrLink: ${input.linkString}`\n            }\n            return JSON.stringify({\n              type: link.type,\n              id: link.id,\n              kind: link.kind,\n              author: link.author,\n              relays: link.relays,\n              scope: link.scope,\n            })\n          } catch (error) {\n            return `Error decoding NostrLink: ${error instanceof Error ? error.message : String(error)}`\n          }\n        },\n      }),\n      tool({\n        name: \"encode_nostr_link\",\n        description:\n          \"Encode a Nostr link into its bech32 representation (npub, nprofile, nevent, naddr, note, nsec). Requires linkType and linkId at minimum.\",\n        parameters: z.object({\n          linkType: z.enum([\"npub\", \"nprofile\", \"nevent\", \"naddr\", \"note\", \"nsec\"]).describe(\"Type of link to encode\"),\n          linkId: z.string().describe(\"ID (hex for events/profiles, string for others)\"),\n          linkKind: z.number().optional().describe(\"Kind number (required for naddr)\"),\n          linkAuthor: z.string().optional().describe(\"Author pubkey hex (for nprofile/nevent/naddr)\"),\n          linkRelays: z.array(z.string()).optional().describe(\"Relay URLs (optional)\"),\n        }),\n        execute: async input => {\n          try {\n            // Map linkType to NostrPrefix\n            let prefix: NostrPrefix\n            switch (input.linkType) {\n              case \"npub\":\n                prefix = NostrPrefix.PublicKey\n                break\n              case \"nprofile\":\n                prefix = NostrPrefix.Profile\n                break\n              case \"nevent\":\n                prefix = NostrPrefix.Event\n                break\n              case \"naddr\":\n                prefix = NostrPrefix.Address\n                break\n              case \"note\":\n                prefix = NostrPrefix.Note\n                break\n              case \"nsec\":\n                prefix = NostrPrefix.PrivateKey\n                break\n              default:\n                return `Invalid linkType: ${input.linkType}`\n            }\n            const link = new NostrLink(prefix, input.linkId, input.linkKind, input.linkAuthor, input.linkRelays)\n            return JSON.stringify({ encoded: link.encode() })\n          } catch (error) {\n            return `Error encoding NostrLink: ${error instanceof Error ? error.message : String(error)}`\n          }\n        },\n      }),\n    ]\n\n    let systemPrompt = SnortSystemPrompt\n    if (publisher?.pubKey) {\n      systemPrompt += `\\nThe currently logged in user pubkey is ${publisher.pubKey}`\n    }\n    const agent = new Agent({\n      name: \"Snort AI Assistant\",\n      instructions: systemPrompt,\n      tools,\n    })\n    const newAgent = {\n      provider: modelProvider,\n      agent,\n      runner,\n      session: memoryRef.current,\n    }\n    agentRef.current = newAgent\n\n    return newAgent\n  }, [publisher, system, agentConfig, memoryRef])\n\n  const runStream = useCallback(\n    async function* (message: string): AsyncGenerator<AiStreamEvent> {\n      const { agent, runner, session } = getOrCreate()\n\n      const stream = await runner.run(agent, message, { stream: true, session: session } as const)\n\n      for await (const event of stream) {\n        if (event.type === \"raw_model_stream_event\") {\n          const data = (event as unknown as { data: Record<string, unknown> }).data\n          if (!data) continue\n\n          if (data.type === \"output_text_delta\" && typeof data.delta === \"string\") {\n            yield { type: \"text\", content: data.delta }\n          } else if (data.type === \"model\") {\n            const chunk = data.event as {\n              choices?: Array<{ delta?: { content?: string; reasoning?: string; reasoning_content?: string } }>\n            }\n            const delta = chunk?.choices?.[0]?.delta\n            const reasoning = delta?.reasoning || delta?.reasoning_content\n            if (reasoning) {\n              yield { type: \"thinking\", content: reasoning }\n            }\n          }\n        } else if (event instanceof RunItemStreamEvent) {\n          console.debug(\"RAW AGENT MSG:\", event)\n          switch (event.name) {\n            case \"tool_called\": {\n              const toolCall = event.item as RunToolCallItem\n              if (\"name\" in toolCall.rawItem && \"arguments\" in toolCall.rawItem) {\n                let args = {}\n                try {\n                  args = JSON.parse(toolCall.rawItem.arguments as string)\n                } catch {}\n                yield { type: \"tool_call\", name: toolCall.rawItem.name, args }\n              } else {\n                debugger\n              }\n              break\n            }\n            case \"tool_output\": {\n              const toolOutput = event.item as RunToolCallOutputItem\n              let result: object | string | undefined\n              if (toolOutput.output) {\n                if (typeof toolOutput.output === \"string\") {\n                  try {\n                    result = JSON.parse(toolOutput.output)\n                  } catch {\n                    result = toolOutput.output\n                  }\n                } else {\n                  result = toolOutput.output\n                }\n              }\n              yield {\n                type: \"tool_result\",\n                name: \"name\" in event.item.rawItem ? (event.item.rawItem.name as string) : event.item.rawItem.id!,\n                result: result,\n              }\n              break\n            }\n            default: {\n              console.warn(\"Unhandeled event item\", event)\n            }\n          }\n        }\n      }\n      yield {\n        type: \"done\",\n      }\n    },\n    [getOrCreate],\n  )\n\n  return {\n    runStream,\n    models: useCallback(async () => {\n      const { provider } = getOrCreate()\n      return await provider.listModels()\n    }, [getOrCreate]),\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useAppHandler.ts",
    "content": "import {\n  type EventKind,\n  mapEventToProfile,\n  type NostrEvent,\n  NostrLink,\n  RequestBuilder,\n  type TaggedNostrEvent,\n  type UserMetadata,\n} from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\nimport useWoT from \"./useWoT\"\n\nexport interface AppHandler {\n  event: TaggedNostrEvent\n  metadata?: UserMetadata\n  reccomendations: Array<NostrEvent>\n}\n\nexport default function useAppHandler(kind: EventKind | undefined): Array<AppHandler> {\n  const wot = useWoT()\n\n  const sub = useMemo(() => {\n    if (!kind) return new RequestBuilder(\"empty\")\n    const sub = new RequestBuilder(`app-handler:${kind}`)\n    sub\n      .withFilter()\n      .kinds([31990 as EventKind])\n      .tag(\"k\", [kind.toString()])\n    return sub\n  }, [kind])\n\n  const dataApps = useRequestBuilder(sub)\n\n  const reccomendsSub = useMemo(() => {\n    if (!kind || dataApps.length === 0) return new RequestBuilder(\"empty-reccomends\")\n    const reccomendsSub = new RequestBuilder(`app-handler:${kind}:reccomends`)\n    reccomendsSub\n      .withFilter()\n      .kinds([31989 as EventKind])\n      .replyToLink(dataApps.map(a => NostrLink.fromEvent(a)))\n    return reccomendsSub\n  }, [kind, dataApps.length, dataApps.map])\n\n  const dataRecommends = useRequestBuilder(reccomendsSub)\n\n  const apps = useMemo(() => {\n    if (!kind) return []\n    return dataApps.map(a => {\n      const meta = a.content.startsWith(\"{\") && a.content.endsWith(\"}\") ? mapEventToProfile(a) : undefined\n      const link = NostrLink.fromEvent(a)\n      return {\n        event: a,\n        metadata: meta,\n        reccomendations: wot.sortEvents(dataRecommends.filter(a => link.isReplyToThis(a))),\n      } as AppHandler\n    })\n  }, [wot, dataApps.map, dataRecommends.filter, kind])\n\n  return apps.sort((a, b) => (a.reccomendations.length > b.reccomendations.length ? -1 : 1))\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useBlindSpot.ts",
    "content": "import { useMemo } from \"react\"\nimport useFollowsControls from \"./useFollowControls\"\nimport { EventExt, EventKind, NostrLink, RequestBuilder, type TaggedNostrEvent } from \"@snort/system\"\nimport { useEventsFeed, useRequestBuilder } from \"@snort/system-react\"\nimport { dedupe } from \"@snort/shared\"\n\nexport function useBlindSpot(count = 10) {\n  const { followList, pubkey } = useFollowsControls()\n  const rbReactions = useMemo(() => {\n    const rb = new RequestBuilder(\"follows-reactions\")\n    if (followList.length > 0) {\n      rb.withFilter().authors(followList).kinds([EventKind.Reaction, EventKind.Repost]).limit(50)\n      rb.withFilter().tag(\"P\", followList).kinds([EventKind.ZapReceipt]).limit(50)\n    }\n    return rb\n  }, [followList])\n\n  const reactions = useRequestBuilder(rbReactions)\n\n  // compute the list of targets (target) => Reaction Events\n  const targets = useMemo(() => {\n    const res = reactions\n      .map(a => ({ links: NostrLink.replyTags(a.tags), event: a }))\n      .reduce(\n        (acc, v) => {\n          for (const link of v.links) {\n            acc[link.tagKey] ??= {\n              link,\n              events: [],\n            }\n            acc[link.tagKey].events.push(v.event)\n          }\n          return acc\n        },\n        {} as Record<string, { link: NostrLink; events: Array<TaggedNostrEvent> }>,\n      )\n\n    // filter events which we also reacted to\n    // filter targets which have more than 1 pubkey reacting to it\n    return Object.values(res).filter(\n      a => dedupe(a.events.map(c => EventExt.getRootPubKey(c))).length > 1 && !a.events.some(b => b.pubkey === pubkey),\n    )\n  }, [reactions, pubkey])\n\n  // select the top N reactions\n  const topNReactions = useMemo(() => {\n    return targets\n      .sort((a, b) => (b.events.length < a.events.length ? -1 : 1))\n      .slice(0, count)\n      .map(a => a.link)\n  }, [targets, count])\n\n  return useEventsFeed(\"follows-reactions-events\", topNReactions)\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useBlossomServers.ts",
    "content": "import { sha256 } from \"@snort/shared\"\nimport { RequestBuilder, EventKind, NostrLink } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nexport default function useBlossomServers(authors?: Array<string> | Array<NostrLink>) {\n  const subServerLists = useMemo(() => {\n    const rb = new RequestBuilder(`blossom-lists:${sha256(authors?.join(\",\") ?? \"\")}`)\n    if (authors && authors.length > 0) {\n      const authorIds =\n        authors[0] instanceof NostrLink ? authors.map(a => (a as NostrLink).id) : (authors as Array<string>)\n      rb.withFilter().authors(authorIds).kinds([EventKind.BlossomServerList])\n    }\n    return rb\n  }, [authors])\n\n  const data = useRequestBuilder(subServerLists)\n\n  return Object.fromEntries(\n    data.map(a => {\n      return [a.pubkey, a.tags.filter(a => a[0] === \"server\").map(a => a[1])]\n    }),\n  ) as Record<string, Array<string>>\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useCloseRelays.ts",
    "content": "import { unixNow } from \"@snort/shared\"\nimport { type EventKind, type NostrEvent, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport Geohash from \"latlon-geohash\"\nimport { useMemo } from \"react\"\n\nimport { calculateDistance, findTag, getCountry } from \"@/Utils\"\nimport { Day, MonitorRelays } from \"@/Utils/Const\"\n\ninterface RelayDistance {\n  distance: number\n  event: NostrEvent\n  addr: string\n}\n\nexport function useCloseRelays() {\n  const country = getCountry()\n\n  const sub = useMemo(() => {\n    const geoHash = Geohash.encode(country.lat, country.lon)\n    const geoHashes = []\n    for (let x = 2; x < geoHash.length; x++) {\n      geoHashes.push(geoHash.substring(0, x))\n    }\n    const rb = new RequestBuilder(`close-relays:${country}`)\n    rb.withFilter()\n      .kinds([30_166 as EventKind])\n      .tag(\"g\", geoHashes)\n      .since(unixNow() - Day)\n      .relay(MonitorRelays)\n    return rb\n  }, [country])\n\n  const data = useRequestBuilder(sub)\n\n  const distRelays = data\n    .map(a => {\n      const lowestDistance = a.tags\n        .filter(a => a[0] === \"g\" && a[1].length > 5)\n        .map(a => {\n          const g = Geohash.decode(a[1])\n          return calculateDistance(g.lat, g.lon, country.lat, country.lon)\n        })\n        .reduce((acc, v) => (v < acc ? v : acc), Number.MAX_VALUE)\n      return {\n        distance: lowestDistance,\n        event: a,\n        addr: findTag(a, \"d\") ?? \"\",\n      } as RelayDistance\n    })\n    .sort((a, b) => (b.distance < a.distance ? 1 : -1))\n    .reduce((acc, v) => {\n      const u = new URL(v.addr)\n      if (!acc.has(u.hostname)) {\n        acc.set(u.hostname, {\n          ...v,\n          addr: `${u.protocol}//${u.host}/`,\n        })\n      }\n      if (acc.get(u.hostname)?.distance > v.distance) {\n        acc.set(u.hostname, v)\n      }\n      return acc\n    }, new Map<string, RelayDistance>())\n\n  return [...distRelays.values()]\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useCommunityLeaders.tsx",
    "content": "import { unwrap } from \"@snort/shared\"\nimport { EventKind, parseNostrLink } from \"@snort/system\"\nimport { useEffect, useSyncExternalStore } from \"react\"\n\nimport { LeadersStore } from \"@/Cache/CommunityLeadersStore\"\n\nimport { useLinkList } from \"./useLists\"\n\nexport function useCommunityLeaders() {\n  const link =\n    CONFIG.features.communityLeaders && CONFIG.communityLeaders\n      ? parseNostrLink(unwrap(CONFIG.communityLeaders).list)\n      : undefined\n\n  const list = useLinkList(\"leaders\", rb => {\n    if (link) {\n      rb.withFilter().kinds([EventKind.FollowSet]).link(link)\n    }\n  })\n\n  useEffect(() => {\n    LeadersStore.setLeaders(list.map(a => a.id))\n  }, [list])\n}\n\nexport function useCommunityLeader(pubkey?: string) {\n  const store = useSyncExternalStore(\n    c => LeadersStore.hook(c),\n    () => LeadersStore.snapshot(),\n  )\n\n  return pubkey && store.includes(pubkey)\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useContentDiscovery.ts",
    "content": "import { RequestBuilder } from \"@snort/system\"\nimport { useMemo } from \"react\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport useDVMLinks from \"./useDvmLinks\"\n\nexport default function useContentDiscovery(serviceProvider: string, relays?: Array<string>) {\n  const { req, links, error } = useDVMLinks(5300, serviceProvider, undefined, undefined, relays)\n\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(`content-discovery:${req.id}`)\n    if (links) {\n      const f = rb.withFilter()\n      links.forEach(p => f.link(p))\n    }\n    return rb\n  }, [req, links])\n\n  const data = useRequestBuilder(sub)\n  return {\n    req,\n    data,\n    links,\n    error,\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useCopy.ts",
    "content": "import { useEffect, useRef, useState } from \"react\"\n\nexport const useCopy = (timeout = 2000) => {\n  const [error, setError] = useState(false)\n  const [copied, setCopied] = useState(false)\n  const timerRef = useRef<ReturnType<typeof setTimeout>>(null)\n\n  useEffect(() => {\n    return () => {\n      if (timerRef.current) clearTimeout(timerRef.current)\n    }\n  }, [])\n\n  const copy = async (text: string) => {\n    setError(false)\n    try {\n      if (navigator.clipboard && window.isSecureContext) {\n        await navigator.clipboard.writeText(text)\n      } else {\n        const textArea = document.createElement(\"textarea\")\n        textArea.value = text\n        textArea.style.position = \"absolute\"\n        textArea.style.opacity = \"0\"\n        document.body.appendChild(textArea)\n        textArea.select()\n        await document.execCommand(\"copy\")\n        textArea.remove()\n      }\n      setCopied(true)\n    } catch (_error) {\n      setError(true)\n    }\n\n    if (timerRef.current) clearTimeout(timerRef.current)\n    timerRef.current = setTimeout(() => setCopied(false), timeout)\n  }\n\n  return { error, copied, copy }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useDiscoverMediaServers.ts",
    "content": "import { removeUndefined, sanitizeRelayUrl } from \"@snort/shared\"\nimport { EventKind, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\n/**\n * Find popular blossom servers based on blossom server list events\n */\nexport default function useDiscoverMediaServers() {\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(\"media-servers-all\")\n    rb.withFilter().kinds([EventKind.BlossomServerList]).limit(100)\n    return rb\n  }, [])\n\n  const data = useRequestBuilder(sub)\n\n  return data.reduce(\n    (acc, v) => {\n      const servers = removeUndefined(v.tags.filter(a => a[0] === \"server\").map(a => sanitizeRelayUrl(a[1])))\n      for (const server of servers) {\n        acc[server] ??= 0\n        acc[server]++\n      }\n      return acc\n    },\n    {} as Record<string, number>,\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useDvmLinks.ts",
    "content": "import { type DVMJobInput, DVMJobRequest, NostrLink, PrivateKeySigner, type TaggedNostrEvent } from \"@snort/system\"\nimport { useEffect, useMemo, useState } from \"react\"\nimport useEventPublisher from \"./useEventPublisher\"\n\n// Session-scoped ephemeral signer for anonymous DVM requests\nlet ephemeralSigner: PrivateKeySigner | undefined\nfunction getEphemeralSigner() {\n  if (!ephemeralSigner) {\n    ephemeralSigner = PrivateKeySigner.random()\n  }\n  return ephemeralSigner\n}\n\n/**\n * Request a DVM to return a list of links\n */\nexport default function useDVMLinks(\n  kind: number,\n  provider?: string,\n  inputs?: Array<DVMJobInput>,\n  params?: Record<string, string>,\n  relays?: Array<string>,\n  parser?: (c: string) => Array<NostrLink>,\n) {\n  const cacheKey = `${provider ? `${provider}:` : \"\"}${kind}${relays ? `:${relays.join(\",\")}` : \"\"}`\n  const { publisher, system } = useEventPublisher()\n  const [result, setResult] = useState<TaggedNostrEvent>()\n  const [error, setError] = useState<Error>()\n\n  // Use ephemeral signer for logged-out users\n  const signer = useMemo(() => publisher?.signer ?? getEphemeralSigner(), [publisher])\n\n  const req = useMemo(() => {\n    const job = new DVMJobRequest(kind)\n    if (provider) {\n      job.setServiceProvider(provider)\n    }\n    if (params) {\n      for (const [k, v] of Object.entries(params)) {\n        job.setParam(k, v)\n      }\n    }\n    if (inputs) {\n      for (const i of inputs) {\n        job.addInput(i)\n      }\n    }\n    relays?.forEach(r => job.addRelay(r))\n    return job\n  }, [kind, provider, inputs, params, relays])\n\n  useEffect(() => {\n    if (!system) {\n      return\n    }\n    const k = `dvm-links:${cacheKey}`\n    const cached = window.sessionStorage.getItem(k)\n    if (cached) {\n      try {\n        const jCached = JSON.parse(cached) as TaggedNostrEvent | undefined\n        if (jCached && \"content\" in jCached) {\n          setResult(jCached)\n          return\n        } else {\n          window.sessionStorage.removeItem(k)\n        }\n      } catch {\n        window.sessionStorage.removeItem(k)\n      }\n    }\n    setResult(undefined)\n\n    req.on(\"result\", e => {\n      setResult(e)\n      window.sessionStorage.setItem(k, JSON.stringify(e))\n    })\n    req.on(\"error\", e => {\n      setError(new Error(e))\n    })\n    req.request(signer, system, relays)\n    return () => {\n      req.abort(system)\n    }\n  }, [req, signer, system, cacheKey, relays])\n\n  const links = useMemo(() => {\n    if (!result) return\n    if (parser) {\n      return parser(result.content)\n    } else {\n      return NostrLink.fromTags(JSON.parse(result.content) as Array<Array<string>>)\n    }\n  }, [result, parser])\n\n  return { result, req, links, error }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useEventPublisher.tsx",
    "content": "import { SnortContext } from \"@snort/system-react\"\nimport { use } from \"react\"\n\nimport useLogin from \"@/Hooks/useLogin\"\nimport { createPublisher, LoginStore, sessionNeedsPin } from \"@/Utils/Login\"\n\nexport default function useEventPublisher() {\n  const login = useLogin()\n  const system = use(SnortContext)\n\n  let existing = LoginStore.getPublisher(login.id)\n\n  if (login.publicKey && !existing && !sessionNeedsPin(login)) {\n    existing = createPublisher(login)\n    if (existing) {\n      LoginStore.setPublisher(login.id, existing)\n    }\n  }\n  return {\n    publisher: existing,\n    system,\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useFollowControls.ts",
    "content": "import { NostrLink } from \"@snort/system\"\nimport { useMemo } from \"react\"\n\nimport useLogin from \"./useLogin\"\n\n/**\n * Simple hook for adding / removing follows\n */\nexport default function useFollowsControls() {\n  const { state, v } = useLogin(s => ({ v: s.state.version, state: s.state }))\n\n  return useMemo(() => {\n    const follows = state.follows\n    return {\n      isFollowing: (pk: string) => {\n        return follows?.includes(pk)\n      },\n      addFollow: async (pk: Array<string>) => {\n        for (const p of pk) {\n          state.follow(NostrLink.publicKey(p))\n        }\n        await state.saveContacts()\n        // TODO: update WOT\n      },\n      removeFollow: async (pk: Array<string>) => {\n        for (const p of pk) {\n          state.unfollow(NostrLink.publicKey(p))\n        }\n        await state.saveContacts()\n        // TODO: update WOT\n      },\n      setFollows: async (pk: Array<string>) => {\n        state.replaceFollows(pk.map(a => NostrLink.publicKey(a)))\n        await state.saveContacts()\n      },\n      followList: follows ?? [],\n      pubkey: state.pubkey,\n    }\n  }, [state.follow, state.follows, state.pubkey, state.replaceFollows, state.saveContacts, state.unfollow])\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useHistoryState.tsx",
    "content": "import { useCallback, useEffect, useRef, useState } from \"react\"\n\nfunction useHistoryState<T>(initialValue: T, key: string) {\n  const currentHistoryState = globalThis.history.state ? globalThis.history.state[key] : undefined\n  const myInitialValue = currentHistoryState === undefined ? initialValue : currentHistoryState\n  const [state, setState] = useState(myInitialValue)\n\n  const latestValue = useRef(state)\n\n  const setHistoryState = useCallback((value: T) => {\n    const newHistoryState = { ...globalThis.history.state, [keyRef.current]: value }\n    globalThis.history.replaceState(newHistoryState, \"\")\n    latestValue.current = value\n  }, [])\n\n  useEffect(() => {\n    if (state !== latestValue.current) {\n      setHistoryState(state)\n      const newHistoryState = { ...globalThis.history.state, [key]: state }\n      globalThis.history.replaceState(newHistoryState, \"\")\n      latestValue.current = state\n    }\n\n    // Cleanup logic\n    return () => {\n      if (state !== latestValue.current) {\n        const newHistoryState = { ...globalThis.history.state, [key]: state }\n        globalThis.history.replaceState(newHistoryState, \"\") // Save the final state\n      }\n    }\n  }, [state, key, setHistoryState])\n\n  const keyRef = useRef(key)\n  useEffect(() => {\n    keyRef.current = key\n  })\n\n  useEffect(() => {\n    const handler = (event: PopStateEvent) => {\n      if (event.state && keyRef.current in event.state) {\n        setState(event.state[keyRef.current])\n      }\n    }\n    window.addEventListener(\"popstate\", handler)\n    return () => {\n      window.removeEventListener(\"popstate\", handler)\n    }\n  }, [])\n\n  return [state, setState]\n}\n\nexport default useHistoryState\n"
  },
  {
    "path": "packages/app/src/Hooks/useHorizontalScroll.tsx",
    "content": "import { useEffect, useRef } from \"react\"\n\nfunction useHorizontalScroll() {\n  const elRef = useRef<HTMLDivElement>(null)\n  useEffect(() => {\n    const el = elRef.current\n    if (el) {\n      const onWheel = (ev: WheelEvent) => {\n        if (ev.deltaY === 0) return\n        ev.preventDefault()\n        el.scrollTo({ left: el.scrollLeft + ev.deltaY, behavior: \"smooth\" })\n      }\n      el.addEventListener(\"wheel\", onWheel)\n      return () => el.removeEventListener(\"wheel\", onWheel)\n    }\n  }, [])\n  return elRef\n}\n\nexport default useHorizontalScroll\n"
  },
  {
    "path": "packages/app/src/Hooks/useHovering.ts",
    "content": "import { useCallback, useEffect, useRef, useState } from \"react\"\n\ninterface HoveringProps {\n  enterTimeout?: number\n  leaveTimeout?: number\n}\n\nexport default function useHovering<T extends HTMLElement>(props?: HoveringProps) {\n  const [isHovering, setIsHovering] = useState(false)\n  const [position, setPosition] = useState<{ top: number; left: number } | null>(null)\n  const elmRef = useRef<T>(null)\n  const hoverTimeoutRef = useRef<ReturnType<typeof setTimeout>>(null)\n\n  const updatePosition = useCallback(() => {\n    if (elmRef.current) {\n      const rect = elmRef.current.getBoundingClientRect()\n      setPosition({\n        top: rect.bottom + window.scrollY,\n        left: rect.left + window.scrollX,\n      })\n    }\n  }, [])\n\n  const isHoveringRef = useRef(false)\n\n  const handleMouseEnter = useCallback(() => {\n    if (hoverTimeoutRef.current || isHoveringRef.current) return\n    hoverTimeoutRef.current = setTimeout(() => {\n      isHoveringRef.current = true\n      setIsHovering(true)\n      updatePosition()\n      hoverTimeoutRef.current = null\n    }, props?.enterTimeout ?? 100)\n  }, [props?.enterTimeout, updatePosition])\n\n  const handleMouseLeave = useCallback(() => {\n    if (hoverTimeoutRef.current || !isHoveringRef.current) return\n    hoverTimeoutRef.current = setTimeout(() => {\n      isHoveringRef.current = false\n      setIsHovering(false)\n      hoverTimeoutRef.current = null\n    }, props?.leaveTimeout ?? 500)\n  }, [props?.leaveTimeout])\n\n  useEffect(() => {\n    const el = elmRef.current\n    if (el) {\n      el.addEventListener(\"mouseenter\", handleMouseEnter)\n      el.addEventListener(\"mouseleave\", handleMouseLeave)\n      return () => {\n        el.removeEventListener(\"mouseenter\", handleMouseEnter)\n        el.removeEventListener(\"mouseleave\", handleMouseLeave)\n        if (hoverTimeoutRef.current) {\n          clearTimeout(hoverTimeoutRef.current)\n          hoverTimeoutRef.current = null\n        }\n      }\n    }\n  }, [handleMouseEnter, handleMouseLeave])\n\n  return { isHovering, elmRef, position }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useImgProxy.ts",
    "content": "import { useMemo } from \"react\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { proxyImg } from \"@snort/shared\"\n\nexport default function useImgProxy() {\n  const imgProxyConfig = usePreferences(s => s.imgProxyConfig)\n\n  const proxy = useMemo(\n    () => (url: string, resize?: number, sha256?: string) => proxyImg(url, imgProxyConfig, resize, sha256),\n    [imgProxyConfig],\n  )\n\n  return {\n    proxy,\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useKeyboardShortcut.ts",
    "content": "import { useCallback, useEffect, useLayoutEffect, useRef } from \"react\"\n\nexport default function useKeyboardShortcut(key: string, callback: (event: KeyboardEvent) => void, node = null) {\n  // implement the callback ref pattern\n  const callbackRef = useRef(callback)\n  useLayoutEffect(() => {\n    callbackRef.current = callback\n  })\n\n  // handle what happens on key press\n  const handleKeyPress = useCallback(\n    (event: KeyboardEvent) => {\n      // check if one of the key is part of the ones we want\n      if (event.key === key) {\n        callbackRef.current(event)\n      }\n    },\n    [key],\n  )\n\n  useEffect(() => {\n    // target is either the provided node or the document\n    const targetNode = node ?? document\n    // attach the event listener\n    targetNode?.addEventListener(\"keydown\", handleKeyPress)\n\n    // remove the event listener\n    return () => targetNode?.removeEventListener(\"keydown\", handleKeyPress)\n  }, [handleKeyPress, node])\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useLists.tsx",
    "content": "import { EventKind, NostrLink, RequestBuilder } from \"@snort/system\"\nimport { useEventsFeed, useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nconst PinListKinds = [EventKind.PinList]\nconst BookmarksListKinds = [EventKind.BookmarksList]\nconst InterestsListKinds = [EventKind.InterestsList]\n\n/**\n * Use a link event containing e/a/p/t tags\n */\nexport function useLinkList(id: string, kinds: Array<EventKind>, pubkey: string | undefined) {\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(id)\n    if (pubkey) {\n      rb.withFilter().kinds(kinds).authors([pubkey])\n    }\n    return rb\n  }, [id, kinds, pubkey])\n\n  const listStore = useRequestBuilder(sub)\n  return useMemo(() => {\n    if (listStore && listStore.length > 0) {\n      return listStore.flatMap(e => NostrLink.fromTags(e.tags))\n    }\n    return []\n  }, [listStore])\n}\n\nexport function useLinkListEvents(id: string, kinds: Array<EventKind>, pubkey: string | undefined) {\n  const links = useLinkList(id, kinds, pubkey)\n  return useEventsFeed(`${id}:events`, links)\n}\n\nexport function usePinList(pubkey: string | undefined) {\n  return useLinkListEvents(`list:pins:${pubkey?.slice(0, 12)}`, PinListKinds, pubkey)\n}\n\nexport function useBookmarkList(pubkey: string | undefined) {\n  return useLinkListEvents(`list:bookmark:${pubkey?.slice(0, 12)}`, BookmarksListKinds, pubkey)\n}\n\nexport function useInterestsList(pubkey: string | undefined) {\n  return useLinkList(`list:interest:${pubkey?.slice(0, 12)}`, InterestsListKinds, pubkey)\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useLiveStreams.ts",
    "content": "import { unixNow } from \"@snort/shared\"\nimport { EventKind, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nimport { findTag } from \"@/Utils\"\nimport { Hour } from \"@/Utils/Const\"\n\nexport default function useLiveStreams() {\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(\"streams\")\n    rb.withFilter()\n      .kinds([EventKind.LiveEvent])\n      .since(unixNow() - 4 * Hour)\n    return rb\n  }, [])\n\n  return useRequestBuilder(sub)\n    .filter(a => {\n      return findTag(a, \"status\") === \"live\"\n    })\n    .sort((a, b) => {\n      const sA = Number(findTag(a, \"starts\"))\n      const sB = Number(findTag(b, \"starts\"))\n      return sA > sB ? -1 : 1\n    })\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useLoading.tsx",
    "content": "import { useState } from \"react\"\n\nexport default function useLoading<T>(fn: ((e: React.MouseEvent) => Promise<T> | T) | undefined, disabled?: boolean) {\n  const [loading, setLoading] = useState<boolean>(false)\n\n  async function handle(e: React.MouseEvent) {\n    e.preventDefault()\n    if (loading || disabled) return\n    setLoading(true)\n    try {\n      if (typeof fn === \"function\") {\n        await fn(e)\n      }\n    } catch (e) {\n      console.error(e)\n    } finally {\n      setLoading(false)\n    }\n  }\n\n  return { handle, loading }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useLogin.tsx",
    "content": "import { useSyncExternalStoreWithSelector } from \"use-sync-external-store/with-selector\"\n\nimport { type LoginSession, LoginStore } from \"@/Utils/Login\"\n\nexport default function useLogin<T = LoginSession>(selector?: (v: LoginSession) => T) {\n  const defaultSelector = (v: LoginSession) => v as unknown as T\n\n  return useSyncExternalStoreWithSelector<LoginSession, T>(\n    s => LoginStore.hook(s),\n    () => LoginStore.snapshot(),\n    undefined,\n    selector || defaultSelector,\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useLoginHandler.tsx",
    "content": "import { bech32ToHex, fetchNostrAddress, NostrPrefix, unwrap } from \"@snort/shared\"\nimport { type KeyStorage, Nip46Signer, tryParseNostrLink } from \"@snort/system\"\n\nimport { EmailRegex, MnemonicRegex } from \"@/Utils/Const\"\nimport { LoginSessionType, LoginStore } from \"@/Utils/Login\"\nimport { entropyToPrivateKey, generateBip39Entropy } from \"@/Utils/nip6\"\n\nexport default function useLoginHandler() {\n  async function doLogin(key: string, pin: (key: string) => Promise<KeyStorage>) {\n    // private key logins\n    if (key.startsWith(\"nsec\")) {\n      const hexKey = bech32ToHex(key)\n      if (hexKey.length === 64) {\n        LoginStore.loginWithPrivateKey(await pin(hexKey))\n        return\n      } else {\n        throw new Error(\"INVALID PRIVATE KEY\")\n      }\n    } else if (key.match(MnemonicRegex)?.length === 24) {\n      const entropy = generateBip39Entropy(key)\n      const privKey = await entropyToPrivateKey(entropy)\n      LoginStore.loginWithPrivateKey(await pin(privKey))\n      return\n    } else if (key.length === 64) {\n      LoginStore.loginWithPrivateKey(await pin(key))\n      return\n    }\n\n    // public key logins\n    if (key.startsWith(\"npub\") || key.startsWith(\"nprofile\")) {\n      const link = tryParseNostrLink(key, NostrPrefix.PublicKey)\n      if (!link) {\n        throw new Error(\"Invalid public key\")\n      }\n      LoginStore.loginWithPubkey(link.id, LoginSessionType.PublicKey)\n    } else if (key.match(EmailRegex)) {\n      const [name, domain] = key.split(\"@\")\n      const json = await fetchNostrAddress(name, domain)\n      if (!json) {\n        throw new Error(\"Invalid nostr address\")\n      }\n      const match = Object.keys(json.names).find(n => {\n        return n.toLowerCase() === name.toLowerCase()\n      })\n      if (!match) {\n        throw new Error(\"Invalid nostr address\")\n      }\n      const pubkey = json.names[match]\n\n      if (json.nip46) {\n        const bunkerRelays = json.nip46[json.names._]\n        const nip46 = new Nip46Signer(`bunker://${pubkey}?relay=${encodeURIComponent(bunkerRelays[0])}`)\n        nip46.on(\"oauth\", url => {\n          window.open(url, CONFIG.appNameCapitalized, \"width=600,height=800,popup=yes\")\n        })\n        await nip46.init()\n\n        const loginPubkey = await nip46.getPubKey()\n        LoginStore.loginWithPubkey(\n          loginPubkey,\n          LoginSessionType.Nip46,\n          undefined,\n          nip46.relays,\n          await pin(unwrap(nip46.privateKey)),\n        )\n        nip46.close()\n      } else {\n        LoginStore.loginWithPubkey(pubkey, LoginSessionType.PublicKey)\n      }\n    } else if (key.startsWith(\"bunker://\")) {\n      const nip46 = new Nip46Signer(key)\n      nip46.on(\"oauth\", url => {\n        window.open(url, CONFIG.appNameCapitalized, \"width=600,height=800,popup=yes\")\n      })\n      await nip46.init()\n\n      const loginPubkey = await nip46.getPubKey()\n      LoginStore.loginWithPubkey(\n        loginPubkey,\n        LoginSessionType.Nip46,\n        undefined,\n        nip46.relays,\n        await pin(unwrap(nip46.privateKey)),\n      )\n      nip46.close()\n    } else {\n      throw new Error(\"INVALID PRIVATE KEY\")\n    }\n  }\n\n  return {\n    doLogin,\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useLoginRelays.tsx",
    "content": "import type { RelaySettings, SystemInterface } from \"@snort/system\"\nimport { useEffect } from \"react\"\n\nimport useEventPublisher from \"./useEventPublisher\"\nimport useRelays from \"./useRelays\"\n\nexport function useLoginRelays() {\n  const relays = useRelays()\n  const { system } = useEventPublisher()\n\n  useEffect(() => {\n    if (relays) {\n      updateRelayConnections(system, relays).catch(console.error)\n    }\n  }, [relays, system])\n}\n\nexport async function updateRelayConnections(system: SystemInterface, relays: Record<string, RelaySettings>) {\n  if (import.meta.env.VITE_SINGLE_RELAY) {\n    system.ConnectToRelay(import.meta.env.VITE_SINGLE_RELAY, { read: true, write: true })\n  } else {\n    for (const [k, v] of Object.entries(relays)) {\n      // note: don't awit this, causes race condition with sending requests to relays\n      system.ConnectToRelay(k, v)\n    }\n    for (const [k, v] of system.pool) {\n      if (!relays[k] && !v.ephemeral) {\n        system.DisconnectRelay(k)\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useMediaServerList.ts",
    "content": "import { removeUndefined, sanitizeRelayUrl } from \"@snort/shared\"\nimport { EventKind, UnknownTag } from \"@snort/system\"\nimport { useMemo } from \"react\"\n\nimport useEventPublisher from \"./useEventPublisher\"\nimport useLogin from \"./useLogin\"\n\nexport const DefaultMediaServers = [\n  new UnknownTag([\"server\", \"https://nostr.download/\"]),\n  new UnknownTag([\"server\", \"https://blossom.band/\"]),\n  new UnknownTag([\"server\", \"https://nostrcheck.me/\"]),\n  new UnknownTag([\"server\", \"https://blossom.primal.net/\"]),\n]\n\nexport function useMediaServerList() {\n  const { publisher } = useEventPublisher()\n  const { state } = useLogin(s => ({ v: s.state.version, state: s.state }))\n\n  let servers = state?.getList(EventKind.BlossomServerList) ?? []\n  if (servers.length === 0) {\n    servers = DefaultMediaServers\n  }\n\n  return useMemo(\n    () => ({\n      servers: removeUndefined(servers.map(a => a.toEventTag()))\n        .filter(a => a[0] === \"server\")\n        .map(a => a[1]),\n      addServer: async (s: string) => {\n        if (!publisher) return\n\n        const u = sanitizeRelayUrl(s)\n        if (!u) return\n        state?.addToList(EventKind.BlossomServerList, new UnknownTag([\"server\", u]), true)\n      },\n      removeServer: async (s: string) => {\n        const u = sanitizeRelayUrl(s)\n        if (!u) return\n        state?.removeFromList(EventKind.BlossomServerList, new UnknownTag([\"server\", u]), true)\n      },\n    }),\n    [servers, publisher, state?.addToList, state?.removeFromList],\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useModeration.tsx",
    "content": "import { dedupe } from \"@snort/shared\"\nimport {\n  EventKind,\n  type NostrEvent,\n  NostrLink,\n  type TaggedNostrEvent,\n  type ToNostrEventTag,\n  UnknownTag,\n} from \"@snort/system\"\n\nimport useLogin from \"@/Hooks/useLogin\"\n\nimport useWoT from \"./useWoT\"\n\nexport class MutedWordTag implements ToNostrEventTag {\n  constructor(readonly word: string) {}\n  equals(other: ToNostrEventTag): boolean {\n    return other instanceof MutedWordTag && other.word === this.word\n  }\n\n  toEventTag(): string[] | undefined {\n    return [\"word\", this.word.toLowerCase()]\n  }\n}\n\nexport default function useModeration() {\n  const { state } = useLogin(s => ({ v: s.state.version, state: s.state }))\n  const wot = useWoT()\n\n  function isMuted(pubkey: string) {\n    const link = NostrLink.publicKey(pubkey)\n    const distance = wot.followDistance(pubkey)\n    return state.muted.some(a => a.equals(link)) || (state.appdata?.preferences.muteWithWoT && distance > 2)\n  }\n\n  async function unmute(id: string) {\n    const link = NostrLink.publicKey(id)\n    state.unmute(link)\n    await state.saveList(EventKind.MuteList)\n  }\n\n  async function mute(id: string) {\n    const link = NostrLink.publicKey(id)\n    state.mute(link)\n    await state.saveList(EventKind.MuteList)\n  }\n\n  async function muteAll(ids: string[]) {\n    const links = dedupe(ids).map(a => NostrLink.publicKey(a))\n    for (const link of links) {\n      state.mute(link)\n    }\n    await state.saveList(EventKind.MuteList)\n  }\n\n  function isMutedWord(word: string) {\n    const words = getMutedWords()\n    return words.includes(word)\n  }\n\n  async function addMutedWord(word: string | Array<string>) {\n    const words = Array.isArray(word) ? word : [word]\n    for (const w of words) {\n      state.addToList(EventKind.MuteList, new MutedWordTag(w.toLowerCase()))\n    }\n    await state.saveList(EventKind.MuteList)\n  }\n\n  async function removeMutedWord(word: string) {\n    state.removeFromList(EventKind.MuteList, new MutedWordTag(word.toLowerCase()))\n    await state.saveList(EventKind.MuteList)\n  }\n\n  function isEventMuted(ev: TaggedNostrEvent | NostrEvent) {\n    return isMuted(ev.pubkey) || false\n  }\n\n  function getMutedWords() {\n    return state\n      .getList(EventKind.MuteList)\n      .filter(a => a instanceof UnknownTag && a.value[0] === \"word\")\n      .map(a => (a as UnknownTag).value[1])\n  }\n\n  return {\n    muteList: state.muted,\n    mute,\n    muteAll,\n    unmute,\n    isMuted,\n    isMutedWord,\n    isEventMuted,\n    addMutedWord,\n    removeMutedWord,\n    getMutedWords,\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/usePageDimensions.tsx",
    "content": "import { useEffect, useRef, useState } from \"react\"\n\nexport default function usePageDimensions() {\n  const ref = useRef<HTMLDivElement | null>(document.querySelector(\"#root\"))\n  const [dimensions, setDimensions] = useState({\n    width: ref.current?.clientWidth ?? 0,\n    height: ref.current?.clientHeight ?? 0,\n  })\n\n  useEffect(() => {\n    if (ref.current && \"ResizeObserver\" in window) {\n      const observer = new ResizeObserver(entries => {\n        if (entries[0].target === ref.current) {\n          const { width, height } = entries[0].contentRect\n          setDimensions({ width, height })\n        }\n      })\n\n      observer.observe(ref.current)\n\n      return () => observer.disconnect()\n    }\n  }, [])\n\n  return dimensions\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/usePreferences.ts",
    "content": "import { DefaultPreferences, saveAppData, updateAppData, type UserPreferences } from \"@/Utils/Login\"\n\nimport useLogin from \"./useLogin\"\n\nexport default function usePreferences<T = UserPreferences>(selector?: (v: UserPreferences) => T): T {\n  const defaultSelector = (v: UserPreferences) => v as unknown as T\n  return useLogin(s => {\n    const pref = s.state.appdata?.preferences ?? {\n      ...DefaultPreferences,\n      ...CONFIG.defaultPreferences,\n    }\n\n    return (selector || defaultSelector)(pref)\n  })\n}\n\nexport function useAllPreferences() {\n  const { id, pref } = useLogin(s => {\n    const pref = s.state.appdata?.preferences ?? {\n      ...DefaultPreferences,\n      ...CONFIG.defaultPreferences,\n    }\n\n    return {\n      id: s.id,\n      pref: pref,\n    }\n  })\n  return {\n    preferences: pref,\n    update: (data: UserPreferences) => {\n      updateAppData(id, d => {\n        return { ...d, preferences: data }\n      })\n    },\n    save: async () => {\n      await saveAppData(id)\n    },\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useProfileLink.ts",
    "content": "import { type CachedMetadata, NostrLink, type UserMetadata } from \"@snort/system\"\nimport { SnortContext } from \"@snort/system-react\"\nimport { use } from \"react\"\n\nimport { randomSample } from \"@/Utils\"\n\nexport function useProfileLink(pubkey?: string, user?: UserMetadata | CachedMetadata) {\n  const system = use(SnortContext)\n  if (!pubkey) return \"#\"\n  const relays = system.config.relays\n    .getFromCache(pubkey)\n    ?.relays?.filter(a => a.settings.write)\n    ?.map(a => a.url)\n\n  if (\n    user?.nip05?.endsWith(`@${CONFIG.nip05Domain}`) &&\n    (!(\"isNostrAddressValid\" in user) || user.isNostrAddressValid)\n  ) {\n    const [username] = user.nip05.split(\"@\")\n    return `/${username}`\n  }\n  const link = NostrLink.profile(pubkey, relays ? randomSample(relays, 3) : undefined)\n  return `/${link.encode(CONFIG.profileLinkPrefix)}`\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useProfileSearch.tsx",
    "content": "import fuzzySearch from \"@/Db/FuzzySearch\"\n\nimport useWoT, { type WoT } from \"./useWoT\"\n\nexport default function useProfileSearch() {\n  const wot = useWoT()\n  return (search: string | undefined) => userSearch(wot, search)\n}\n\nfunction userSearch(wot: WoT, search: string | undefined) {\n  const searchString = search?.trim() ?? \"\"\n  const fuseResults = (searchString?.length ?? 0) > 0 ? fuzzySearch.search(searchString) : []\n\n  const followDistanceNormalizationFactor = 3\n  const seenIds = new Set()\n\n  const combinedResults = fuseResults\n    .map(result => {\n      const fuseScore = result.score === undefined ? 1 : result.score\n\n      const followDistance = wot.followDistance(result.item.pubkey) / followDistanceNormalizationFactor\n\n      const startsWithSearchString = [result.item.name, result.item.display_name, result.item.nip05].some(\n        field => field?.toLowerCase?.().startsWith(searchString.toLowerCase()),\n      )\n\n      const boostFactor = startsWithSearchString ? 0.25 : 1\n\n      const weightForFuseScore = 0.8\n      const weightForFollowDistance = 0.2\n\n      const combinedScore = (fuseScore * weightForFuseScore + followDistance * weightForFollowDistance) * boostFactor\n\n      return { ...result, combinedScore }\n    })\n    // Sort by combined score, lower is better\n    .sort((a, b) => a.combinedScore - b.combinedScore)\n    .filter(r => {\n      // for some reason we get duplicates even though fuzzySearch should be removing existing profile on update\n      if (seenIds.has(r.item.pubkey)) {\n        return false\n      }\n      seenIds.add(r.item.pubkey)\n      return true\n    })\n\n  return combinedResults.map(r => r.item)\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useRates.tsx",
    "content": "import { bech32ToHex, removeUndefined, unixNow } from \"@snort/shared\"\nimport { type EventKind, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\n\nimport { getNewest } from \"@/Utils\"\nimport { SnortPubkey } from \"@/Utils/Const\"\n\nexport function useRates(symbol: string, leaveOpen = true) {\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(`rates:${symbol}`)\n    rb.withOptions({\n      leaveOpen,\n    })\n    rb.withFilter()\n      .kinds([1009 as EventKind])\n      .authors([bech32ToHex(SnortPubkey)])\n      .tag(\"d\", [symbol])\n      .limit(1)\n    return rb\n  }, [symbol, leaveOpen])\n\n  const feed = useRequestBuilder(sub)\n  const ev = getNewest(feed)\n\n  const tag = ev?.tags.find(a => a[0] === \"d\" && a[1] === symbol)\n  if (!tag) return undefined\n  return {\n    time: ev?.created_at,\n    ask: Number(tag[2]),\n    bid: Number(tag[3]),\n    low: Number(tag[4]),\n    high: Number(tag[5]),\n  }\n}\n\nexport function useRateHistory(symbol: string, size: number, leaveOpen = false) {\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(`rates:${symbol}:history:${size}`)\n    rb.withOptions({ leaveOpen })\n    rb.withFilter()\n      .kinds([1009 as EventKind])\n      .authors([bech32ToHex(SnortPubkey)])\n      .tag(\"d\", [symbol])\n      .since(unixNow() - size)\n    return rb\n  }, [symbol, size, leaveOpen])\n\n  const feed = useRequestBuilder(sub)\n\n  return removeUndefined(\n    feed.map(a => {\n      const tag = a.tags.find(a => a[0] === \"d\" && a[1] === symbol)\n      if (!tag) return undefined\n      return {\n        time: a?.created_at,\n        ask: Number(tag[2]),\n        bid: Number(tag[3]),\n        low: Number(tag[4]),\n        high: Number(tag[5]),\n      }\n    }),\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useRelays.tsx",
    "content": "import useLogin from \"./useLogin\"\n\nexport default function useRelays() {\n  const relays = useLogin(s => s.state.relays)\n  return relays ? Object.fromEntries(relays.map(a => [a.url, a.settings])) : CONFIG.defaultRelays\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useTextTransformCache.tsx",
    "content": "import { type ParsedFragment, transformText } from \"@snort/system\"\nimport { LRUCache } from \"typescript-lru-cache\"\n\nconst TextCache = new LRUCache<string, Array<ParsedFragment>>({\n  maxSize: 1000,\n})\n\nexport function transformTextCached(id: string, content: string, tags: Array<Array<string>>): Array<ParsedFragment> {\n  if (content.length > 0) {\n    const cached = TextCache.get(id)\n    if (cached) return cached\n    const newCache = transformText(content, tags)\n    TextCache.set(id, newCache)\n    return newCache\n  }\n  return []\n}\n\nexport function useTextTransformer(id: string, content: string, tags: Array<Array<string>>) {\n  return transformTextCached(id, content, tags)\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useTheme.tsx",
    "content": "import { useEffect } from \"react\"\n\nimport usePreferences from \"./usePreferences\"\n\nexport function useTheme() {\n  const theme = usePreferences(s => s.theme)\n\n  useEffect(() => {\n    const osTheme = window.matchMedia(\"(prefers-color-scheme: light)\")\n    setTheme(theme === \"system\" && osTheme.matches ? \"light\" : theme === \"light\" ? \"light\" : \"dark\")\n\n    const handler = (e: MediaQueryListEvent) => {\n      if (theme === \"system\") {\n        setTheme(e.matches ? \"light\" : \"dark\")\n      }\n    }\n    osTheme.addEventListener(\"change\", handler)\n    return () => {\n      osTheme.removeEventListener(\"change\", handler)\n    }\n  }, [theme])\n}\n\nexport function setTheme(theme: \"light\" | \"dark\") {\n  const elm = document.documentElement\n  if (theme === \"light\" && !elm.classList.contains(\"light\")) {\n    elm.classList.add(\"light\")\n    elm.classList.remove(\"dark\")\n  } else if (theme === \"dark\" && !elm.classList.contains(\"dark\")) {\n    elm.classList.add(\"dark\")\n    elm.classList.remove(\"light\")\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useTimelineChunks.ts",
    "content": "import { useState } from \"react\"\n\nexport interface WindowChunk {\n  since: number\n  until: number\n}\n\nexport default function useTimelineChunks(opt: { window?: number; firstChunkSize?: number; now: number }) {\n  const windowSize = opt.window ?? 60 * 60 * 2\n  const [windows, setWindows] = useState(1)\n\n  let offset = opt.now\n  const chunks: Array<WindowChunk> = []\n  for (let x = 0; x < windows; x++) {\n    // offset from now going backwards in time\n    const size = x === 0 && opt.firstChunkSize ? opt.firstChunkSize : windowSize\n    chunks.push({\n      since: offset - size,\n      until: offset,\n    })\n    offset -= size\n  }\n\n  return {\n    now: opt.now,\n    chunks,\n    showMore: () => {\n      setWindows(s => s + 1)\n    },\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useTimelineWindow.tsx",
    "content": "import { useState } from \"react\"\n\nexport default function useTimelineWindow(opt: { window?: number; now: number }) {\n  const window = opt.window ?? 60 * 60 * 2\n  const [until, setUntil] = useState(opt.now)\n  const [since, setSince] = useState(opt.now - window)\n\n  return {\n    now: opt.now,\n    since,\n    until,\n    setUntil,\n    older: () => {\n      setUntil(s => s - window)\n      setSince(s => s - window)\n    },\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useTraceTimeline.tsx",
    "content": "import { useEffect, useState } from \"react\"\n\nconst TRACE_TIMELINE_KEY = \"trace-timeline-open\"\n\n/**\n * Hook to manage trace timeline overlay state with localStorage persistence\n */\nexport function useTraceTimeline() {\n  const [isOpen, setIsOpen] = useState(() => {\n    if (typeof localStorage === \"undefined\") return false\n    return localStorage.getItem(TRACE_TIMELINE_KEY) === \"true\"\n  })\n\n  useEffect(() => {\n    if (typeof localStorage === \"undefined\") return\n    localStorage.setItem(TRACE_TIMELINE_KEY, isOpen.toString())\n  }, [isOpen])\n\n  const toggle = () => setIsOpen(prev => !prev)\n  const open = () => setIsOpen(true)\n  const close = () => setIsOpen(false)\n\n  return { isOpen, toggle, open, close }\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useWindowSize.ts",
    "content": "import { useEffect, useState } from \"react\"\n\nexport default function useWindowSize() {\n  const [dims, setDims] = useState({\n    width: window.innerWidth,\n    height: window.innerHeight,\n  })\n\n  useEffect(() => {\n    const handler = () => {\n      setDims({\n        width: window.innerWidth,\n        height: window.innerHeight,\n      })\n    }\n    window.addEventListener(\"resize\", handler)\n    return () => window.removeEventListener(\"resize\", handler)\n  }, [])\n  return dims\n}\n"
  },
  {
    "path": "packages/app/src/Hooks/useWoT.ts",
    "content": "import type { SystemInterface, TaggedNostrEvent } from \"@snort/system\"\nimport { SnortContext } from \"@snort/system-react\"\nimport { use, useMemo } from \"react\"\n\nexport interface WoT {\n  sortEvents: (events: Array<TaggedNostrEvent>) => Array<TaggedNostrEvent>\n  sortPubkeys: (events: Array<string>) => Array<string>\n  followDistance: (pk: string) => number\n  followedByCount: (pk: string) => number\n  followedBy: (pk: string) => Set<string>\n}\n\nfunction wotOnSystem(system: SystemInterface) {\n  const sgi = system.config.socialGraphInstance\n  return {\n    sortEvents: (events: Array<TaggedNostrEvent>) =>\n      events.sort((a, b) => sgi.getFollowDistance(a.pubkey) - sgi.getFollowDistance(b.pubkey)),\n    sortPubkeys: (events: Array<string>) => events.sort((a, b) => sgi.getFollowDistance(a) - sgi.getFollowDistance(b)),\n    followDistance: (pk: string) => sgi.getFollowDistance(pk),\n    followedByCount: (pk: string) => sgi.followedByFriendsCount(pk),\n    followedBy: (pk: string) => sgi.followedByFriends(pk),\n    instance: sgi,\n  }\n}\n\nexport default function useWoT() {\n  const system = use(SnortContext)\n  return useMemo<WoT>(() => wotOnSystem(system), [system])\n}\n"
  },
  {
    "path": "packages/app/src/Pages/About.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nimport Changelog from \"@/../CHANGELOG.md?raw\"\nimport { Markdown } from \"@/Components/Event/Markdown\"\n\nexport function AboutPage() {\n  const version = document.querySelector(\"meta[name='application-name']\")?.getAttribute(\"content\")\n  return (\n    <div className=\"px-3 py-2\">\n      <h1>\n        <FormattedMessage defaultMessage=\"About\" />\n      </h1>\n      Version: <b>{version?.split(\":\")?.at(1) ?? \"unknown version\"}</b>\n      <Markdown content={Changelog} tags={[]} />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Agent/AgentPage.tsx",
    "content": "import { useState, useRef, useCallback, useEffect, useSyncExternalStore, use } from \"react\"\nimport { type AiStreamEvent, useAiAgent } from \"@/Hooks/useAiAgent\"\nimport { Markdown } from \"@/Components/Event/Markdown\"\nimport { FixedPage } from \"../FixedPage\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport Spinner from \"@/Components/Icons/Spinner\"\nimport { ExternalStore, unixNow } from \"@snort/shared\"\nimport { AvatarGroup } from \"@/Components/User/AvatarGroup\"\nimport { useLocation } from \"react-router-dom\"\nimport { Note } from \"@/Components/Event/Note/Note\"\nimport type { NostrEvent, TaggedNostrEvent } from \"@snort/system\"\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport { SnortContext } from \"@snort/system-react\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { setPreference } from \"@/Utils/Login\"\nimport Icon from \"@/Components/Icons/Icon\"\n\ninterface ChatMessage {\n  id: string\n  created: number\n  role: \"user\" | \"assistant\"\n  segments: Array<AiStreamEvent>\n  thinkingExpanded?: boolean\n  done: boolean\n}\n\nclass MessageStore extends ExternalStore<Array<ChatMessage>> {\n  private messages: Array<ChatMessage> = []\n\n  addMessage(msg: ChatMessage) {\n    this.messages.push(msg)\n    this.notifyChange()\n  }\n\n  addStreamChunk(msgId: string, event: AiStreamEvent) {\n    // Convertes the streamed raw chunks into single accumilated chunks for better UX\n    const acc = this.messages.find(a => a.id === msgId)\n    if (!acc) {\n      console.warn(\"AGENT: Dropping new segment, agent message not found: \", event)\n      return\n    }\n    if (event.type === \"done\") {\n      acc.done = true\n      this.notifyChange()\n      return\n    }\n    if (acc.segments.length > 0 && acc.segments[acc.segments.length - 1].type === event.type) {\n      const lastSeg = acc.segments[acc.segments.length - 1]\n      if (\"content\" in lastSeg && \"content\" in event) {\n        lastSeg.content += event.content\n      } else {\n        // Skip empty new segments (like '\\n\\n' at the start)\n        if (\"content\" in event && event.content.trim().length > 0) {\n          acc.segments.push(event)\n        }\n      }\n    } else {\n      acc.segments.push(event)\n    }\n    this.notifyChange()\n  }\n\n  updateMessage(msgId: string, fnUpdate: (old: ChatMessage) => void) {\n    const old = this.messages.find(a => a.id === msgId)\n    if (old) {\n      fnUpdate(old)\n      this.notifyChange()\n    }\n  }\n\n  takeSnapshot(p?: any): ChatMessage[] {\n    return [...this.messages]\n  }\n}\n\nexport default function AgentPage() {\n  const [input, setInput] = useState(\"\")\n  const [isLoading, setIsLoading] = useState(false)\n  const [error, setError] = useState<string | null>(null)\n  const [models, setModels] = useState<Array<{ id: string }>>([])\n  const messagesRef = useRef(new MessageStore())\n  const scrollRef = useRef<HTMLDivElement>(null)\n  const { formatMessage } = useIntl()\n  const { state } = useLocation()\n  const { runStream, models: listModels } = useAiAgent()\n  const system = use(SnortContext)\n  const { agentModel } = usePreferences(s => ({\n    agentModel: s.agentModel,\n  }))\n\n  const messages = useSyncExternalStore(\n    c => messagesRef.current.hook(c),\n    () => messagesRef.current.snapshot(),\n  )\n\n  // Fetch models when agent URL changes\n  useEffect(() => {\n    listModels().then(setModels)\n  }, [])\n\n  // biome-ignore lint/correctness/useExhaustiveDependencies: scroll to bottom when messages change\n  useEffect(() => {\n    if (scrollRef.current) {\n      const t = requestAnimationFrame(() => {\n        if (scrollRef.current) {\n          scrollRef.current.scrollTop = scrollRef.current.scrollHeight\n        }\n      })\n      return () => {\n        cancelAnimationFrame(t)\n      }\n    }\n  }, [messages, scrollRef])\n\n  const sendChat = useCallback(\n    async (e: string) => {\n      const trimmed = e.trim()\n      if (!trimmed || isLoading) return\n\n      setError(null)\n      setInput(\"\")\n\n      const userMsg: ChatMessage = {\n        id: `user-${Date.now()}`,\n        role: \"user\",\n        created: unixNow(),\n        segments: [{ type: \"text\", content: trimmed }],\n        done: true,\n      }\n\n      const assistantId = `assistant-${Date.now()}`\n      const assistantMsg: ChatMessage = {\n        id: assistantId,\n        created: userMsg.created + 1,\n        role: \"assistant\",\n        segments: [],\n        thinkingExpanded: false,\n        done: false,\n      }\n      messagesRef.current.addMessage(userMsg)\n      messagesRef.current.addMessage(assistantMsg)\n      setIsLoading(true)\n\n      try {\n        const stream = runStream(trimmed)\n        for await (const event of stream) {\n          messagesRef.current.addStreamChunk(assistantId, event)\n        }\n      } catch (err) {\n        console.error(\"AI stream error:\", err)\n        messagesRef.current.updateMessage(assistantId, c => {\n          c.segments = [{ type: \"error\", error: err as Error | string }]\n          c.done = true\n        })\n      } finally {\n        setIsLoading(false)\n      }\n    },\n    [input, runStream, messagesRef],\n  )\n\n  useEffect(() => {\n    if (\n      messagesRef.current.snapshot().length === 0 &&\n      state?.initialMessage &&\n      typeof state.initialMessage === \"string\"\n    ) {\n      sendChat(state.initialMessage)\n    }\n  }, [state, messagesRef, sendChat])\n\n  const renderSegments = (msg: ChatMessage) => {\n    return msg.segments.map((seg, i) => {\n      if (seg.type === \"thinking\") {\n        return (\n          <div className=\"text-xs text-gray-400 italic border-l-2 border-gray-500 pl-2 mb-2\">\n            <span\n              onClick={() => {\n                messagesRef.current.updateMessage(msg.id, o => {\n                  o.thinkingExpanded = !o.thinkingExpanded\n                })\n              }}\n              className={`cursor-pointer hover:text-gray-300 transition-colors${msg.done ? \"\" : \" animate-pulse\"}`}\n            >\n              <span className=\"font-semibold\">Thinking:</span> {msg.thinkingExpanded ? \"▼\" : \"▶\"}\n            </span>\n            {msg.thinkingExpanded && <Markdown key={`${msg.id}-thinking-${i}`} content={seg.content} />}\n          </div>\n        )\n      }\n      if (seg.type === \"text\") {\n        return <Markdown key={`${msg.id}-text-${i}`} content={seg.content} />\n      }\n      if (seg.type === \"error\") {\n        return (\n          <span className=\"text-error font-bold flex gap-2 items-center\">\n            <Icon name=\"x\" />\n            {seg.error instanceof Error ? seg.error.message : seg.error}\n          </span>\n        )\n      }\n      if (seg.type === \"tool_call\") {\n        const argsStr =\n          typeof seg.args === \"object\" && seg.args !== null ? JSON.stringify(seg.args, null, 2) : String(seg.args)\n        return (\n          <div key={`tool-call-${i}`} className=\"text-xs text-gray-400 block mt-1\">\n            → {seg.name}\n            <pre className=\"text-[10px] bg-layer-3 p-2 rounded overflow-auto max-h-64\">{argsStr}</pre>\n          </div>\n        )\n      }\n      if (seg.type === \"tool_result\") {\n        switch (seg.name) {\n          case \"query_nostr\": {\n            if (Array.isArray(seg.result)) {\n              return (\n                <div key={`tool-result-${i}`} className=\"text-xs text-gray-300 block\">\n                  <div className=\"mb-1 text-green-400\">\n                    <FormattedMessage defaultMessage=\"Found {n} events!\" values={{ n: seg.result.length }} />\n                  </div>\n                  <pre className=\"text-[10px] bg-layer-3 p-2 rounded overflow-auto max-h-64\">\n                    {JSON.stringify(seg.result, null, 2)}\n                  </pre>\n                </div>\n              )\n            }\n            if (typeof seg.result === \"string\" && seg.result.startsWith(\"Error\")) {\n              return (\n                <div key={`tool-result-${i}`} className=\"text-xs text-red-400 block\">\n                  {seg.result}\n                </div>\n              )\n            }\n            // Handle JSON string result (like from prepare_event_filter)\n            if (typeof seg.result === \"string\") {\n              try {\n                const parsed = JSON.parse(seg.result)\n                return (\n                  <div key={`tool-result-${i}`} className=\"text-xs text-gray-300 block\">\n                    {parsed.note && <div className=\"mb-1\">{parsed.note}</div>}\n                    <pre className=\"text-[10px] bg-layer-3 p-2 rounded overflow-auto max-h-64\">\n                      {JSON.stringify(parsed, null, 2)}\n                    </pre>\n                  </div>\n                )\n              } catch {\n                return (\n                  <div key={`tool-result-${i}`} className=\"text-xs text-gray-300 block\">\n                    {seg.result}\n                  </div>\n                )\n              }\n            }\n          }\n          case \"prepare_event_filter\": {\n            if (typeof seg.result === \"string\" && !seg.result.startsWith(\"Error\")) {\n              try {\n                const parsed = JSON.parse(seg.result)\n                return (\n                  <div key={`tool-result-${i}`} className=\"text-xs text-gray-300 block\">\n                    {parsed.note && <div className=\"mb-1\">{parsed.note}</div>}\n                    <pre className=\"text-[10px] bg-layer-3 p-2 rounded overflow-auto max-h-64\">\n                      {JSON.stringify(parsed, null, 2)}\n                    </pre>\n                  </div>\n                )\n              } catch {\n                return (\n                  <div key={`tool-result-${i}`} className=\"text-xs text-gray-300 block\">\n                    {seg.result}\n                  </div>\n                )\n              }\n            }\n            if (typeof seg.result === \"string\" && seg.result.startsWith(\"Error\")) {\n              return (\n                <div key={`tool-result-${i}`} className=\"text-xs text-red-400 block\">\n                  {seg.result}\n                </div>\n              )\n            }\n          }\n          case \"search_username\": {\n            if (Array.isArray(seg.result)) {\n              const results = seg.result as Array<{ pubkey: string }>\n              return (\n                <span key={`tool-result-${i}`} className=\"text-xs text-gray-300 block\">\n                  <FormattedMessage defaultMessage=\"Results:\" />\n                  <AvatarGroup ids={[...results].reverse().map(a => a.pubkey)} />\n                </span>\n              )\n            }\n            break\n          }\n          case \"create_event\": {\n            return (\n              <div key={`tool-result-${i}`} className=\"p-2 bg-neutral-900 rounded-lg\">\n                <Note data={seg.result as TaggedNostrEvent} />\n                <AsyncButton\n                  onClick={async () => {\n                    await system.BroadcastEvent(seg.result as NostrEvent)\n                  }}\n                >\n                  <FormattedMessage defaultMessage=\"Post Event\" />\n                </AsyncButton>\n              </div>\n            )\n          }\n          default:\n            break\n        }\n\n        // Default fallback for other tool results\n        let resultDisplay: React.ReactNode = String(seg.result ?? \"\")\n        if (typeof seg.result === \"string\") {\n          try {\n            const parsed = JSON.parse(seg.result)\n            resultDisplay = (\n              <pre className=\"text-[10px] bg-layer-3 p-2 rounded overflow-auto max-h-64\">\n                {JSON.stringify(parsed, null, 2)}\n              </pre>\n            )\n          } catch {\n            // Not JSON, display as-is\n            resultDisplay = seg.result\n          }\n        } else if (typeof seg.result === \"object\" && seg.result !== null) {\n          resultDisplay = (\n            <pre className=\"text-[10px] bg-layer-3 p-2 rounded overflow-auto max-h-64\">\n              {JSON.stringify(seg.result, null, 2)}\n            </pre>\n          )\n        }\n\n        return (\n          <span key={`tool-result-${i}`} className=\"text-xs text-gray-300 block\">\n            ← {seg.name}: {resultDisplay}\n          </span>\n        )\n      }\n      return null\n    })\n  }\n\n  return (\n    <FixedPage className=\"flex flex-col\">\n      <div className=\"px-4 border-b border-gray-700\">\n        <div className=\"flex items-center py-2\">\n          <div className=\"text-lg font-semibold flex-1\">\n            <FormattedMessage defaultMessage=\"Agent\" />\n          </div>\n          {/* Model Selector */}\n          {models.length > 1 && (\n            <div className=\"flex items-center gap-2 flex-1\">\n              <label className=\"text-xs text-gray-500 block mb-1\">\n                <FormattedMessage defaultMessage=\"Model\" />\n              </label>\n              <select\n                value={agentModel || \"\"}\n                onChange={e => {\n                  setPreference({ agentModel: e.target.value })\n                }}\n                className=\"w-full bg-layer-2 text-white rounded px-2 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-primary\"\n              >\n                {models.map(m => (\n                  <option key={m.id} value={m.id}>\n                    {m.id}\n                  </option>\n                ))}\n              </select>\n            </div>\n          )}\n        </div>\n        <p className=\"text-sm text-gray-400\">\n          <FormattedMessage\n            defaultMessage=\"Ask me anything about Nostr or {appName}\"\n            values={{ appName: CONFIG.appNameCapitalized }}\n          />\n        </p>\n      </div>\n\n      {messages.length === 0 && (\n        <div className=\"text-center text-gray-500 mt-8\">\n          <p className=\"text-lg mb-2\">\n            <FormattedMessage defaultMessage=\"👋 Welcome to AI Chat!\" />\n          </p>\n          <p>\n            <FormattedMessage\n              defaultMessage=\"Ask me to post, reply, search, or help you navigate {appName}\"\n              values={{ appName: CONFIG.appNameCapitalized }}\n            />\n          </p>\n        </div>\n      )}\n      <div ref={scrollRef} className=\"overflow-y-auto p-4 space-y-4 flex-1\">\n        <div className=\"flex flex-col gap-2\">\n          {messages\n            .sort((a, b) => a.created - b.created)\n            .map(msg => {\n              return (\n                <div key={msg.id} className={`flex ${msg.role === \"user\" ? \"justify-end\" : \"justify-start\"}`}>\n                  <div\n                    className={`max-w-[90%] rounded-lg p-3 ${\n                      msg.role === \"user\" ? \"bg-primary text-white\" : \"bg-layer-2 text-gray-100\"\n                    }`}\n                  >\n                    <div className=\"overflow-auto\">\n                      {renderSegments(msg)}\n                      {!msg.done && msg.role === \"assistant\" && <Spinner height={14} />}\n                    </div>\n                  </div>\n                </div>\n              )\n            })}\n\n          {error && (\n            <div className=\"text-center text-red-400 p-2\">\n              <p>{error}</p>\n            </div>\n          )}\n        </div>\n      </div>\n\n      <form\n        onSubmit={e => {\n          e.preventDefault()\n          sendChat(input)\n        }}\n        className=\"p-4 border-t border-gray-700\"\n      >\n        <div className=\"flex gap-2\">\n          <input\n            type=\"text\"\n            value={input}\n            onChange={e => setInput(e.target.value)}\n            placeholder={formatMessage({ defaultMessage: \"Ask me anything...\" })}\n            className=\"flex-1 bg-layer-2 text-white rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-primary\"\n            disabled={isLoading}\n          />\n          <button\n            type=\"submit\"\n            disabled={isLoading || !input.trim()}\n            className=\"bg-primary text-white px-4 py-2 rounded-lg hover:bg-primary/80 disabled:opacity-50\"\n          >\n            {isLoading ? \"...\" : <FormattedMessage defaultMessage=\"Send\" />}\n          </button>\n        </div>\n      </form>\n    </FixedPage>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/CacheDebug.tsx",
    "content": "import type { NostrEvent, TaggedNostrEvent } from \"@snort/system\"\nimport { SnortContext } from \"@snort/system-react\"\nimport { use, useState } from \"react\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\n\nexport function DebugPage() {\n  const system = use(SnortContext)\n  const [filter, setFilter] = useState(\"\")\n  const [event, setEvent] = useState(\"\")\n  const [results, setResult] = useState<Array<TaggedNostrEvent>>([])\n\n  async function search() {\n    if (filter && system.cacheRelay) {\n      const r = await system.cacheRelay.query([\"REQ\", \"test\", JSON.parse(filter)])\n      setResult(r.map(a => ({ ...a, relays: [] })))\n    }\n  }\n\n  async function insert() {\n    if (event && system.cacheRelay) {\n      const r = await system.cacheRelay.event(JSON.parse(event) as NostrEvent)\n      setResult([\n        {\n          content: JSON.stringify(r),\n        } as unknown as TaggedNostrEvent,\n      ])\n    }\n  }\n\n  async function removeEvents() {\n    if (filter && system.cacheRelay) {\n      const r = await system.cacheRelay.delete([\"REQ\", \"delete-events\", JSON.parse(filter)])\n      setResult(r.map(a => ({ id: a }) as TaggedNostrEvent))\n    }\n  }\n  return (\n    <div className=\"flex flex-col gap-2\">\n      <h3>Cache Query</h3>\n      <textarea value={filter} onChange={e => setFilter(e.target.value)} placeholder=\"nostr filter\" />\n      <AsyncButton onClick={() => search()}>Query</AsyncButton>\n      <AsyncButton onClick={() => removeEvents()} className=\"!bg-red-500\">\n        Delete\n      </AsyncButton>\n\n      <h3>Manual Insert</h3>\n      <textarea value={event} onChange={e => setEvent(e.target.value)} placeholder=\"nostr event\" />\n      <AsyncButton onClick={() => insert()}>Insert</AsyncButton>\n      <div className=\"p-4 overflow-hidden\">\n        <h4>Results: {results.length}</h4>\n        {results?.map(a => (\n          <pre key={a.id} className=\"text-mono text-xs text-pretty\">\n            {JSON.stringify(a, undefined, 2)}\n          </pre>\n        ))}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/ComponentDebug.tsx",
    "content": "import { EventBuilder, EventExt, type NostrEvent, NostrLink } from \"@snort/system\"\nimport { NostrPrefix, bech32ToHex, sha256, unixNow } from \"@snort/shared\"\nimport { useState } from \"react\"\n\nimport { KieranPubKey } from \"@/Utils/Const\"\n\n// Button Components\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport BackButton from \"@/Components/Button/BackButton\"\nimport CloseButton from \"@/Components/Button/CloseButton\"\nimport IconButton from \"@/Components/Button/IconButton\"\nimport LogoutButton from \"@/Components/Button/LogoutButton\"\nimport NavLink from \"@/Components/Button/NavLink\"\n\n// Icon Components\nimport Icon from \"@/Components/Icons/Icon\"\nimport Spinner from \"@/Components/Icons/Spinner\"\nimport Alby from \"@/Components/Icons/Alby\"\nimport Cashu from \"@/Components/Icons/Cashu\"\nimport Nostrich from \"@/Components/Icons/Nostrich\"\nimport BlueWallet from \"@/Components/Icons/BlueWallet\"\nimport ECash from \"@/Components/Icons/ECash\"\nimport NWC from \"@/Components/Icons/NWC\"\nimport { ToggleSwitch } from \"@/Components/Icons/Toggle\"\n\n// Text Components\nimport Text from \"@/Components/Text/Text\"\nimport HighlightedText from \"@/Components/Text/HighlightedText\"\n\n// User Components\nimport Avatar from \"@/Components/User/Avatar\"\nimport Username from \"@/Components/User/Username\"\nimport DisplayName from \"@/Components/User/DisplayName\"\nimport FollowButton from \"@/Components/User/FollowButton\"\nimport FollowsYou from \"@/Components/User/FollowsYou\"\nimport Nip05 from \"@/Components/User/Nip05\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport { ProfileLink } from \"@/Components/User/ProfileLink\"\nimport { AvatarGroup } from \"@/Components/User/AvatarGroup\"\nimport MuteButton from \"@/Components/User/MuteButton\"\nimport FollowDistanceIndicator from \"@/Components/User/FollowDistanceIndicator\"\n\n// Embed Components\nimport Hashtag from \"@/Components/Embed/Hashtag\"\nimport Mention from \"@/Components/Embed/Mention\"\nimport Invoice from \"@/Components/Embed/Invoice\"\nimport MagnetLink from \"@/Components/Embed/MagnetLink\"\n\n// Event Components\nimport Note from \"@/Components/Event/EventComponent\"\nimport NoteTime from \"@/Components/Event/Note/NoteTime\"\nimport ZapButton from \"@/Components/Event/ZapButton\"\nimport { ClientTag } from \"@/Components/Event/Note/ClientTag\"\nimport Poll from \"@/Components/Event/Poll\"\nimport { LongFormText } from \"@/Components/Event/LongFormText\"\nimport { ZapGoal } from \"@/Components/Event/ZapGoal\"\nimport { ZapsSummary } from \"@/Components/Event/ZapsSummary\"\nimport NoteHeader from \"@/Components/Event/Note/NoteHeader\"\n\n// Other Components\nimport Copy from \"@/Components/Copy/Copy\"\nimport { ProxyImg } from \"@/Components/ProxyImg\"\nimport QrCode from \"@/Components/QrCode\"\nimport Collapsed, { CollapsedSection } from \"@/Components/Collapsed\"\nimport Modal from \"@/Components/Modal/Modal\"\nimport { WarningNotice } from \"@/Components/WarningNotice/WarningNotice\"\nimport Progress from \"@/Components/Progress/Progress\"\nimport TabSelectors, { type Tab } from \"@/Components/TabSelectors/TabSelectors\"\nimport PageSpinner from \"@/Components/PageSpinner\"\nimport Toaster, { Toastore } from \"@/Components/Toaster/Toaster\"\nimport { Markdown } from \"@/Components/Event/Markdown\"\n\n// Feed Components\nimport LoadMore from \"@/Components/Feed/LoadMore\"\n\n// Embed - Music & Video\nimport SpotifyEmbed from \"@/Components/Embed/SpotifyEmbed\"\nimport YoutubeEmbed from \"@/Components/Embed/YoutubeEmbed\"\nimport TwitchEmbed from \"@/Components/Embed/TwitchEmbed\"\nimport AppleMusicEmbed from \"@/Components/Embed/AppleMusicEmbed\"\nimport TidalEmbed from \"@/Components/Embed/TidalEmbed\"\nimport SoundCloudEmbed from \"@/Components/Embed/SoundCloudEmded\"\nimport WavlakeEmbed from \"@/Components/Embed/WavlakeEmbed\"\nimport MixCloudEmbed from \"@/Components/Embed/MixCloudEmbed\"\nimport NostrNestsEmbed from \"@/Components/Embed/NostrNestsEmbed\"\nimport CashuNuts from \"@/Components/Embed/CashuNuts\"\n\n// More User Components\nimport NoteToSelf from \"@/Components/User/NoteToSelf\"\nimport BadgeList from \"@/Components/User/BadgeList\"\nimport { UserWebsiteLink } from \"@/Components/User/UserWebsiteLink\"\nimport FollowedBy from \"@/Components/User/FollowedBy\"\n\n// Relay Components\nimport PaidRelayLabel from \"@/Components/Relay/paid\"\nimport UptimeLabel from \"@/Components/Relay/uptime-label\"\n\n// Trending Components\nimport TrendingHashtags from \"@/Components/Trending/TrendingHashtags\"\nimport TrendingUsers from \"@/Components/Trending/TrendingUsers\"\nimport TrendingPosts from \"@/Components/Trending/TrendingPosts\"\n\n// Other Components\nimport KindName from \"@/Components/kind-name\"\nimport SuggestedProfiles from \"@/Components/SuggestedProfiles\"\nimport ZapAmountLabel from \"@/Components/zap-amount\"\n\nimport { magnetURIDecode } from \"@/Utils\"\nimport { LiveEvent } from \"@/Components/LiveStream/LiveEvent\"\nimport { setTheme } from \"@/Hooks/useTheme\"\nimport { NoteProvider } from \"@/Components/Event/Note/NoteContext\"\n\n// Sample data - Using Kieran's pubkey for examples\nconst SAMPLE_HEX_PUBKEY = bech32ToHex(KieranPubKey)\n// Additional sample pubkeys from DeveloperAccounts\nconst SAMPLE_PUBKEY_2 = \"4523be58d395b1b196a9b8c82b038b6895cb02b683d0c253a955068dba1facd0\" // Martti\nconst SAMPLE_PUBKEY_3 = \"7fa56f5d6962ab1e3cd424e758c3002b8665f7b0d8dcee9fe9e288d7751ac194\" // verbiricha\n\nconst SAMPLE_INVOICE =\n  \"lnbc210n1p50yk0qpp5kdtjslgczmphsugxskskhf4l6090gjqs3v26zk38gk3yfqc2h5jqdqcv4uxzmtsd3jjq6twwehkjcm9cqzzsxqyz5vqsp5c0pv9plkvx5e9ddcm6rkvycvt4mc2540awcl4kyzl0khhkqn9tgs9qxpqysgqw5h7plfn0m26vxggs0jhakcnm45k3044q5wv5yrx8yeljtqdnmr439pzr397uqxef4eljm76ek0m2z9nm3kjustf7zkpxm78t8z2p5cqkds20e\"\nconst SAMPLE_YOUTUBE_URL = \"https://www.youtube.com/watch?v=dQw4w9WgXcQ\"\nconst SAMPLE_SPOTIFY_URL = \"https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT\"\nconst SAMPLE_APPLE_MUSIC_URL = \"https://music.apple.com/us/album/example\"\nconst SAMPLE_TIDAL_URL = \"https://tidal.com/browse/track/111398735\"\nconst SAMPLE_SOUNDCLOUD_URL = \"https://soundcloud.com/djgrooveteck/sidepiece-walking-on-a-dream-vip\"\nconst SAMPLE_WAVLAKE_URL = \"https://wavlake.com/track/1079f9b0-e60a-4eba-87c4-c380aa795786\"\nconst SAMPLE_MIXCLOUD_URL = \"https://www.mixcloud.com/johndigweed/transitions-with-john-digweed-and-adam-freeland\"\nconst SAMPLE_NOSTR_NESTS_URL = \"https://nostrnests.com/example\"\nconst SAMPLE_CASHU_TOKEN =\n  \"cashuAeyJ0b2tlbiI6W3sibWludCI6Imh0dHBzOi8vbWludC5taW5pYml0cy5jYXNoL0JpdGNvaW4iLCJwcm9vZnMiOlt7ImFtb3VudCI6MTYsIkMiOiIwMjFlODY2YzMzNjYzNzQzMjMyMWYwNjRjYzQ3NTdlMTRjZmE0NDJlYjhlMTVmMjUwN2ExNmJhOGMyOGFmMDg0NWEiLCJpZCI6IjltbGZkNXZDemdHbCIsInNlY3JldCI6ImFlZjhhYmJkYzQzOTI4NWM3MDI1YzI3YzU5NjE1Y2Q1YjM0ODU0YjJmNmJlMzFlMDdlNzQ5YzQ5OWU0NzQ1MjIifSx7ImFtb3VudCI6NCwiQyI6IjAzOTMwYzFmNjg5NDY1ZTQwMWVmODU0YTg5MzdmYzJmMWIyNTRhOGYxNWIxZmU2ZmMyNDc2ODZmYTQyM2E4NmQ4ZCIsImlkIjoiOW1sZmQ1dkN6Z0dsIiwic2VjcmV0IjoiZGY3YmM1ZGFiNGM1YzUzZmQwNjgwNDRjMGYxM2NkNzA2MmNhYTBhOGY4NDA3ZDU4NGFkZTg0ZWQ1NTBhMTdkNSJ9LHsiYW1vdW50Ijo0LCJDIjoiMDI1ZWFhODE2ZGY3ZWZlYmY2MTZjYTM3NTg0ODIxMmE3OWFmZmEzNjY0NzA1ZGNhY2I3Y2FkMDY0ODgyYTU2NmRmIiwiaWQiOiI5bWxmZDV2Q3pnR2wiLCJzZWNyZXQiOiJiZTAwNGY5ZjYxOTk1NzY3NDliN2Q4YmQzMDJhYTZiYjlmYzJjOTFlYTAyZmVmZDk5MDZjOWE4MmJiY2E5ZDg0In0seyJhbW91bnQiOjEsIkMiOiIwMmRiZjg0YmYzNjg1ZTQ2MDUxMTM0MjMzNzJkZmE5MGY4OGE2YmU1ODEzOWIzMmM5MTc4MmY2ZWFjMWFkMmEzZjUiLCJpZCI6IjltbGZkNXZDemdHbCIsInNlY3JldCI6IjczMmNiYTVjYzFkNTQwOTdhMzM3NWJlNDg2NGM2OTUxNDZlNTZiOTJlOWU3MjU3ZmZiMWZjY2NhN2ZjZjA0N2YifV19XX0\"\n\n// Sample events for complex components\nconst SAMPLE_POLL_EVENT = {\n  id: \"\",\n  pubkey: SAMPLE_HEX_PUBKEY,\n  created_at: unixNow(),\n  kind: 6969,\n  tags: [\n    [\"poll_option\", \"0\", \"Option A\"],\n    [\"poll_option\", \"1\", \"Option B\"],\n    [\"poll_option\", \"2\", \"Option C\"],\n  ],\n  content: \"What's your favorite?\",\n  sig: \"\",\n} as NostrEvent\nSAMPLE_POLL_EVENT.id = EventExt.createId(SAMPLE_POLL_EVENT)\n\nconst SAMPLE_LONG_FORM_EVENT = {\n  id: \"\",\n  pubkey: SAMPLE_HEX_PUBKEY,\n  created_at: unixNow(),\n  kind: 30023,\n  tags: [\n    [\"d\", \"example\"],\n    [\"title\", \"Component Debug Guide\"],\n    [\"summary\", \"A comprehensive guide to debugging components\"],\n    [\"t\", \"development\"],\n  ],\n  content:\n    \"# Introduction\\n\\nThis is a sample long-form article to demonstrate the LongFormText component. It includes **markdown** formatting, _italic text_, and more.\\n\\n## Features\\n\\n- Read time calculation\\n- Text-to-speech\\n- Truncation support\",\n  sig: \"\",\n} as NostrEvent\nSAMPLE_LONG_FORM_EVENT.id = EventExt.createId(SAMPLE_LONG_FORM_EVENT)\n\nconst SAMPLE_ZAP_GOAL_EVENT = {\n  id: \"\",\n  pubkey: SAMPLE_HEX_PUBKEY,\n  created_at: unixNow(),\n  kind: 9041,\n  tags: [[\"amount\", \"100000\"]],\n  content: \"Help support development!\",\n  sig: \"\",\n} as NostrEvent\nSAMPLE_ZAP_GOAL_EVENT.id = EventExt.createId(SAMPLE_ZAP_GOAL_EVENT)\n\n// Sample text note (kind 1)\nconst SAMPLE_TEXT_NOTE = {\n  id: \"\",\n  pubkey: SAMPLE_HEX_PUBKEY,\n  created_at: unixNow(),\n  kind: 1,\n  tags: [],\n  content:\n    \"This is a sample text note (kind 1) with some content. It can include #hashtags and links like https://snort.social\",\n  sig: \"\",\n} as NostrEvent\nSAMPLE_TEXT_NOTE.id = EventExt.createId(SAMPLE_TEXT_NOTE)\n\n// Sample note with gallery (1 image)\nconst SAMPLE_GALLERY_1_NOTE = {\n  id: \"\",\n  pubkey: SAMPLE_HEX_PUBKEY,\n  created_at: unixNow(),\n  kind: 1,\n  tags: [],\n  content: \"Single image gallery\\n\\nhttps://picsum.photos/800/600.jpg\",\n  sig: \"\",\n} as NostrEvent\nSAMPLE_GALLERY_1_NOTE.id = EventExt.createId(SAMPLE_GALLERY_1_NOTE)\n\n// Sample note with gallery (2 images)\nconst SAMPLE_GALLERY_2_NOTE = {\n  id: \"\",\n  pubkey: SAMPLE_HEX_PUBKEY,\n  created_at: unixNow(),\n  kind: 1,\n  tags: [],\n  content: \"Two images side by side\\n\\nhttps://picsum.photos/400/400.jpg\\nhttps://picsum.photos/400/400.jpg\",\n  sig: \"\",\n} as NostrEvent\nSAMPLE_GALLERY_2_NOTE.id = EventExt.createId(SAMPLE_GALLERY_2_NOTE)\n\n// Sample note with gallery (3 images)\nconst SAMPLE_GALLERY_3_NOTE = {\n  id: \"\",\n  pubkey: SAMPLE_HEX_PUBKEY,\n  created_at: unixNow(),\n  kind: 1,\n  tags: [],\n  content:\n    \"Three images - one big, two small\\n\\nhttps://picsum.photos/500/500.jpg\\nhttps://picsum.photos/300/300.jpg\\nhttps://picsum.photos/300/300.jpg\",\n  sig: \"\",\n} as NostrEvent\nSAMPLE_GALLERY_3_NOTE.id = EventExt.createId(SAMPLE_GALLERY_3_NOTE)\n\n// Sample note with gallery (4 images)\nconst SAMPLE_GALLERY_4_NOTE = {\n  id: \"\",\n  pubkey: SAMPLE_HEX_PUBKEY,\n  created_at: unixNow(),\n  kind: 1,\n  tags: [],\n  content:\n    \"Four images in a grid\\n\\nhttps://picsum.photos/400/300.jpg\\nhttps://picsum.photos/400/300.jpg\\nhttps://picsum.photos/400/300.jpg\\nhttps://picsum.photos/400/300.jpg\",\n  sig: \"\",\n} as NostrEvent\nSAMPLE_GALLERY_4_NOTE.id = EventExt.createId(SAMPLE_GALLERY_4_NOTE)\n\n// Sample note with gallery (5 images)\nconst SAMPLE_GALLERY_5_NOTE = {\n  id: \"\",\n  pubkey: SAMPLE_HEX_PUBKEY,\n  created_at: unixNow(),\n  kind: 1,\n  tags: [],\n  content:\n    \"Five images mixed layout\\n\\nhttps://picsum.photos/450/300.jpg\\nhttps://picsum.photos/450/300.jpg\\nhttps://picsum.photos/450/300.jpg\\nhttps://picsum.photos/250/300.jpg\\nhttps://picsum.photos/250/300.jpg\",\n  sig: \"\",\n} as NostrEvent\nSAMPLE_GALLERY_5_NOTE.id = EventExt.createId(SAMPLE_GALLERY_5_NOTE)\n\n// Sample note with gallery (6 images)\nconst SAMPLE_GALLERY_6_NOTE = {\n  id: \"\",\n  pubkey: SAMPLE_HEX_PUBKEY,\n  created_at: unixNow(),\n  kind: 1,\n  tags: [],\n  content:\n    \"Six images complex layout\\n\\nhttps://picsum.photos/500/500.jpg\\nhttps://picsum.photos/250/250.jpg\\nhttps://picsum.photos/250/250.jpg\\nhttps://picsum.photos/500/500.jpg\\nhttps://picsum.photos/250/250.jpg\\nhttps://picsum.photos/250/250.jpg\",\n  sig: \"\",\n} as NostrEvent\nSAMPLE_GALLERY_6_NOTE.id = EventExt.createId(SAMPLE_GALLERY_6_NOTE)\n\n// Sample repost (kind 6)\nconst SAMPLE_REPOST = {\n  id: \"\",\n  pubkey: SAMPLE_HEX_PUBKEY,\n  created_at: unixNow(),\n  kind: 6,\n  tags: [\n    [\"e\", SAMPLE_TEXT_NOTE.id, \"\", \"mention\"],\n    [\"p\", SAMPLE_PUBKEY_2],\n  ],\n  content: JSON.stringify(SAMPLE_TEXT_NOTE),\n  sig: \"\",\n} as NostrEvent\nSAMPLE_REPOST.id = EventExt.createId(SAMPLE_REPOST)\n\n// Sample reply (kind 1 with reply tags)\nconst SAMPLE_REPLY = {\n  id: \"\",\n  pubkey: SAMPLE_HEX_PUBKEY,\n  created_at: unixNow(),\n  kind: 1,\n  tags: [\n    [\"e\", SAMPLE_TEXT_NOTE.id, \"\", \"reply\"],\n    [\"p\", SAMPLE_HEX_PUBKEY],\n  ],\n  content: \"This is a reply to another note!\",\n  sig: \"\",\n} as NostrEvent\nSAMPLE_REPLY.id = EventExt.createId(SAMPLE_REPLY)\n\nconst SAMPLE_LIVE_STREAM_EVENT = {\n  kind: 30311,\n  id: \"316e22791b576ef66a6f0325cbd2a81c5242dc096ba09e9e6a264cdabdf07cfa\",\n  pubkey: \"cf45a6ba1363ad7ed213a078e710d24115ae721c9b47bd1ebf4458eaefb4c2a5\",\n  created_at: 1760717551,\n  tags: [\n    [\"d\", \"537a365c-f1ec-44ac-af10-22d14a7319fb\"],\n    [\"status\", \"live\"],\n    [\"starts\", \"1739464332\"],\n    [\"title\", \"NoGood Radio\"],\n    [\n      \"summary\",\n      \"NoGood Radio is a 24/7 pirate radio station running on scrap parts and broadcasting from a basement somewhere.\",\n    ],\n    [\"image\", \"https://blossom.nogood.studio/6d5bb489e87c2f2db2a0fa61fd2bfca9f6d4f50e05b7caf1784644886c0e4ff6\"],\n    [\"thumb\", \"https://api-core.zap.stream/537a365c-f1ec-44ac-af10-22d14a7319fb/thumb.webp?n=1760717527\"],\n    [\"goal\", \"854bac46f638e93f9cdb6aa0f415cbcfb8041e5383571aa5c538ba354145e584\"],\n    [\"t\", \"Radio\"],\n    [\"t\", \"24/7\"],\n    [\"t\", \"internal:music\"],\n    [\"current_participants\", \"7\"],\n    [\n      \"alt\",\n      \"Watch live on https://zap.stream/naddr1qqjr2vehvyenvdtr94nrzetr956rgctr94skvvfs95eryep3x3snwve389nxyq3qeaz6dwsnvwkha5sn5puwwyxjgy26uusundrm684lg3vw4ma5c2jsxpqqqpmxwrqz3al\",\n    ],\n    [\"p\", \"55f04590674f3648f4cdc9dc8ce32da2a282074cd0b020596ee033d12d385185\", \"\", \"host\"],\n    [\"service\", \"https://api-core.zap.stream/api/v1\"],\n    [\"streaming\", \"https://api-core.zap.stream/537a365c-f1ec-44ac-af10-22d14a7319fb/hls/live.m3u8\"],\n  ],\n  content: \"\",\n  sig: \"6674b3d183da4c6208908f0e1118dee5682f5f635fd3b21141563a5986635d2f687d532686f4cf55bb2256cde561f3bb8c660a9d805c95d13443c8bf7bb2b75f\",\n}\n\nconst ExampleMagnetLink =\n  \"magnet:?xt=urn:btih:9065a82c1bb9e8e69ad14044ee4a4aba35cb17ea&dn=nostr.band%20snapshot&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337%2Fannounce&tr=udp%3A%2F%2Fopen.demonii.com%3A1337%2Fannounce&tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce&tr=udp%3A%2F%2Fexplodie.org%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker-udp.gbitt.info%3A80%2Fannounce&tr=https%3A%2F%2Ftracker.tamersunion.org%3A443%2Fannounce&tr=udp%3A%2F%2Ftracker2.dler.org%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker1.bt.moack.co.kr%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.theoks.net%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.ccp.ovh%3A6969%2Fannounce\"\n\nconst TextExample = `Hello Nostr! This is a test message with #nostr and https://example.com \nhttps://github.com/v0l/snort\nblossom:ba9037d243fc6fbf23ae6b6af36cd5235fddc59fbea5cc7c0f590966fba102db.jpg?xs=nostr.download&xs=example.com&as=63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed&as=266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5&sz=324265\n${ExampleMagnetLink}\nnostr:${NostrLink.fromEvent(SAMPLE_LIVE_STREAM_EVENT).encode()}\n${SAMPLE_CASHU_TOKEN}\n${SAMPLE_INVOICE}\n`\n\nexport default function ComponentDebugPage() {\n  const [showModal, setShowModal] = useState(false)\n  const [selectedTab, setSelectedTab] = useState<Tab>({ value: 0, text: \"Tab 1\" })\n  const [collapsed, setCollapsed] = useState(true)\n  const [toggleState, setToggleState] = useState(false)\n  const [isLightMode, setIsLightMode] = useState(false)\n\n  const tabs: Tab[] = [\n    { value: 0, text: \"Tab 1\" },\n    { value: 1, text: \"Tab 2\" },\n    { value: 2, text: \"Tab 3\" },\n    { value: 3, text: \"Disabled\", disabled: true },\n  ]\n\n  const sampleNostrLink = new NostrLink(NostrPrefix.Profile, SAMPLE_HEX_PUBKEY)\n\n  const toggleTheme = () => {\n    setIsLightMode(!isLightMode)\n    setTheme(!isLightMode ? \"light\" : \"dark\")\n  }\n\n  return (\n    <div className=\"max-w-[720px] mx-auto\">\n      <div className=\"flex justify-between items-center mb-8\">\n        <h1 className=\"text-3xl font-bold\">Component Debug Page</h1>\n        <div className=\"flex items-center gap-3\">\n          <span className=\"text-sm\">Dark</span>\n          <ToggleSwitch size={32} onClick={toggleTheme} className={isLightMode ? \"active\" : \"\"} />\n          <span className=\"text-sm\">Light</span>\n        </div>\n      </div>\n\n      {/* Buttons Section */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">Buttons</h2>\n        <div className=\"space-y-4\">\n          <div className=\"flex justify-between gap-4 flex-wrap\">\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">AsyncButton</span>\n              <AsyncButton onClick={async () => new Promise(resolve => setTimeout(resolve, 1000))}>\n                Click Me (Async)\n              </AsyncButton>\n            </div>\n\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">AsyncButton (Disabled)</span>\n              <AsyncButton disabled onClick={async () => {}}>\n                Disabled\n              </AsyncButton>\n            </div>\n\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">BackButton</span>\n              <BackButton />\n            </div>\n\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">CloseButton</span>\n              <CloseButton />\n            </div>\n\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">IconButton</span>\n              <IconButton icon={{ name: \"heart\" }} />\n            </div>\n\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">NavLink</span>\n              <NavLink to=\"/\">Home</NavLink>\n            </div>\n\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">LogoutButton</span>\n              <LogoutButton />\n            </div>\n          </div>\n        </div>\n      </section>\n\n      {/* Icons Section */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">Icons</h2>\n        <div className=\"flex items-center gap-6 flex-wrap\">\n          <div className=\"flex flex-col items-center gap-2\">\n            <Icon name=\"heart\" size={24} />\n            <span className=\"text-sm \">heart</span>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <Icon name=\"repost\" size={24} />\n            <span className=\"text-sm \">repost</span>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <Icon name=\"reply\" size={24} />\n            <span className=\"text-sm \">reply</span>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <Icon name=\"zap-filled\" size={24} />\n            <span className=\"text-sm \">zap</span>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <Icon name=\"bookmark\" size={24} />\n            <span className=\"text-sm \">bookmark</span>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <Icon name=\"dots\" size={24} />\n            <span className=\"text-sm \">dots</span>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <Spinner />\n            <span className=\"text-sm \">spinner</span>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <Alby size={24} />\n            <span className=\"text-sm \">alby</span>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <Cashu size={24} />\n            <span className=\"text-sm \">cashu</span>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <Nostrich height={24} width={24} />\n            <span className=\"text-sm \">nostrich</span>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <BlueWallet width={24} height={24} />\n            <span className=\"text-sm \">bluewallet</span>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <ECash width={24} height={24} />\n            <span className=\"text-sm \">ecash</span>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <NWC width={24} height={24} />\n            <span className=\"text-sm \">nwc</span>\n          </div>\n          <div className=\"flex flex-col items-center gap-2\">\n            <ToggleSwitch\n              size={24}\n              onClick={() => setToggleState(!toggleState)}\n              className={toggleState ? \"active\" : \"\"}\n            />\n            <span className=\"text-sm \">toggle</span>\n          </div>\n        </div>\n      </section>\n\n      {/* User Components Section */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">User Components</h2>\n        <div className=\"space-y-6\">\n          <div className=\"flex justify-between\">\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">Avatar (size: 48)</span>\n              <Avatar pubkey={SAMPLE_HEX_PUBKEY} size={48} />\n            </div>\n\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">ProfileImage</span>\n              <ProfileImage pubkey={SAMPLE_HEX_PUBKEY} />\n            </div>\n\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">AvatarGroup</span>\n              <AvatarGroup ids={[SAMPLE_HEX_PUBKEY, SAMPLE_PUBKEY_2, SAMPLE_PUBKEY_3]} size={30} />\n            </div>\n          </div>\n\n          <div className=\"space-y-2\">\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-sm  w-48\">Username:</span>\n              <Username pubkey={SAMPLE_HEX_PUBKEY} />\n            </div>\n\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-sm  w-48\">DisplayName:</span>\n              <DisplayName pubkey={SAMPLE_HEX_PUBKEY} />\n            </div>\n\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-sm  w-48\">ProfileLink:</span>\n              <ProfileLink pubkey={SAMPLE_HEX_PUBKEY}>View Profile</ProfileLink>\n            </div>\n\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-sm  w-48\">Nip05:</span>\n              <Nip05 nip05=\"user@domain.com\" pubkey={SAMPLE_HEX_PUBKEY} />\n            </div>\n\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-sm  w-48\">FollowButton:</span>\n              <FollowButton pubkey={SAMPLE_HEX_PUBKEY} />\n            </div>\n\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-sm  w-48\">MuteButton:</span>\n              <MuteButton pubkey={SAMPLE_HEX_PUBKEY} />\n            </div>\n\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-sm  w-48\">FollowsYou (true):</span>\n              <FollowsYou followsMe={true} />\n            </div>\n\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-sm  w-48\">FollowsYou (false):</span>\n              <FollowsYou followsMe={false} />\n            </div>\n\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-sm  w-48\">FollowDistanceIndicator:</span>\n              <FollowDistanceIndicator pubkey={SAMPLE_HEX_PUBKEY} />\n            </div>\n\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-sm  w-48\">BadgeList:</span>\n              <BadgeList badges={[]} />\n            </div>\n\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-sm  w-48\">UserWebsiteLink:</span>\n              <UserWebsiteLink user={{ website: \"https://snort.social\" } as any} />\n            </div>\n\n            <div className=\"flex items-center gap-2\">\n              <span className=\"text-sm  w-48\">FollowedBy:</span>\n              <FollowedBy pubkey={SAMPLE_HEX_PUBKEY} />\n            </div>\n          </div>\n        </div>\n      </section>\n\n      {/* Text Components Section */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">Text Components</h2>\n        <div className=\"space-y-4\">\n          <div>\n            <span className=\"mb-2\">Text with content:</span>\n            <div className=\"layer-1\">\n              <Text id={sha256(TextExample)} depth={0} content={TextExample} tags={[]} creator={SAMPLE_HEX_PUBKEY} />\n            </div>\n          </div>\n\n          <div>\n            <span className=\"mb-2\">HighlightedText:</span>\n            <div className=\"bg-neutral-800 light:bg-neutral-200 p-4 rounded\">\n              <HighlightedText\n                content=\"This is some highlighted text to demonstrate the component\"\n                textToHighlight=\"highlighted text\"\n              />\n            </div>\n          </div>\n        </div>\n      </section>\n\n      {/* Embed Components Section */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">Embed Components</h2>\n        <div className=\"space-y-6\">\n          <div>\n            <h3 className=\"text-lg font-semibold mb-3\">Basic Embeds</h3>\n            <div className=\"flex gap-4 flex-wrap justify-between\">\n              <div className=\"flex flex-col gap-2\">\n                <span className=\"text-sm \">Hashtag:</span>\n                <Hashtag tag=\"nostr\" />\n              </div>\n\n              <div className=\"flex flex-col gap-2\">\n                <span className=\"text-sm \">Hashtag (bitcoin):</span>\n                <Hashtag tag=\"bitcoin\" />\n              </div>\n\n              <div className=\"flex flex-col gap-2\">\n                <span className=\"text-sm \">Mention:</span>\n                <Mention link={sampleNostrLink} />\n              </div>\n            </div>\n\n            <div className=\"flex-1\">\n              <span className=\"text-sm mb-4\">Invoice:</span>\n              <Invoice invoice={SAMPLE_INVOICE} />\n            </div>\n\n            <div className=\"flex-1\">\n              <span className=\"text-sm mb-4\">MagnetLink:</span>\n              <MagnetLink magnet={magnetURIDecode(ExampleMagnetLink)!} />\n            </div>\n\n            <div className=\"flex-1\">\n              <span className=\"text-sm mb-4\">CashuNuts:</span>\n              <CashuNuts token={SAMPLE_CASHU_TOKEN} />\n            </div>\n          </div>\n\n          <div>\n            <h3 className=\"text-lg font-semibold mb-3\">Media Embeds</h3>\n            <div className=\"space-y-4\">\n              <div>\n                <span className=\"mb-2\">YoutubeEmbed:</span>\n                <YoutubeEmbed link={SAMPLE_YOUTUBE_URL} />\n              </div>\n\n              <div>\n                <span className=\"mb-2\">SpotifyEmbed:</span>\n                <SpotifyEmbed link={SAMPLE_SPOTIFY_URL} />\n              </div>\n\n              <div>\n                <span className=\"mb-2\">AppleMusicEmbed:</span>\n                <AppleMusicEmbed link={SAMPLE_APPLE_MUSIC_URL} />\n              </div>\n\n              <div>\n                <span className=\"mb-2\">TwitchEmbed:</span>\n                <TwitchEmbed link={\"https://twitch.tv/asmongold247\"} />\n              </div>\n\n              <div>\n                <span className=\"mb-2\">TidalEmbed:</span>\n                <TidalEmbed link={SAMPLE_TIDAL_URL} />\n              </div>\n\n              <div>\n                <span className=\"mb-2\">SoundCloudEmbed:</span>\n                <SoundCloudEmbed link={SAMPLE_SOUNDCLOUD_URL} />\n              </div>\n\n              <div>\n                <span className=\"mb-2\">WavlakeEmbed:</span>\n                <WavlakeEmbed link={SAMPLE_WAVLAKE_URL} />\n              </div>\n\n              <div>\n                <span className=\"mb-2\">MixCloudEmbed:</span>\n                <MixCloudEmbed link={SAMPLE_MIXCLOUD_URL} />\n              </div>\n\n              <div>\n                <span className=\"mb-2\">NostrNestsEmbed:</span>\n                <NostrNestsEmbed link={SAMPLE_NOSTR_NESTS_URL} />\n              </div>\n            </div>\n          </div>\n        </div>\n      </section>\n\n      {/* Event Components Section */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">Event Components</h2>\n        <div className=\"space-y-4\">\n          <div className=\"flex justify-between\">\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">NoteTime (relative):</span>\n              <NoteTime from={(unixNow() - 3600) * 1000} />\n            </div>\n\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">NoteTime (2 days ago):</span>\n              <NoteTime from={(unixNow() - 172800) * 1000} />\n            </div>\n\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">ZapButton:</span>\n              <ZapButton pubkey={SAMPLE_HEX_PUBKEY} />\n            </div>\n\n            <div className=\"flex flex-col gap-2\">\n              <span className=\"text-sm \">ClientTag:</span>\n              <ClientTag\n                ev={\n                  {\n                    tags: [EventBuilder.ClientTag],\n                  } as any\n                }\n              />\n            </div>\n          </div>\n\n          <div>\n            <span className=\"mb-2\">KindName (various event kinds):</span>\n            <div className=\"flex justify-between\">\n              {[1, 6, 7, 9735, 30023].map(k => (\n                <div>\n                  {k}: <KindName kind={k} />\n                </div>\n              ))}\n            </div>\n          </div>\n\n          <div>\n            <span className=\"mb-2\">NoteHeader:</span>\n            <div className=\"w-full\">\n              <NoteProvider ev={SAMPLE_POLL_EVENT}>\n                <NoteHeader options={{ showTime: true, showContextMenu: true }} />\n              </NoteProvider>\n            </div>\n          </div>\n\n          <div>\n            <span className=\"mb-2\">NoteReaction:</span>\n            <div className=\"flex gap-2\">\n              <span className=\"text-2xl\">🚀</span>\n              <span className=\"text-2xl\">❤️</span>\n              <span className=\"text-2xl\">🔥</span>\n              <span className=\"text-2xl\">👍</span>\n            </div>\n          </div>\n\n          <div>\n            <span className=\"mb-2\">ZapAmountLabel:</span>\n            <ZapAmountLabel n={21000} />\n          </div>\n\n          <div>\n            <span className=\"mb-2\">ZapsSummary:</span>\n            <ZapsSummary zaps={[]} onClick={() => {}} />\n          </div>\n        </div>\n\n        <div className=\"space-y-4\">\n          <h3 className=\"text-lg font-semibold\">Complex Event Components</h3>\n\n          <div>\n            <span className=\"mb-2\">Poll (Interactive voting):</span>\n            <div className=\"max-w-2xl border rounded p-4\">\n              <Poll ev={SAMPLE_POLL_EVENT} zaps={[]} />\n            </div>\n          </div>\n\n          <div>\n            <span className=\"mb-2\">ZapGoal (Fundraising goal):</span>\n            <div className=\"max-w-2xl\">\n              <ZapGoal ev={SAMPLE_ZAP_GOAL_EVENT} />\n            </div>\n          </div>\n\n          <div>\n            <span className=\"mb-2\">LongFormText (Article preview):</span>\n            <div className=\"max-w-2xl border rounded\">\n              <LongFormText ev={SAMPLE_LONG_FORM_EVENT} isPreview={false} truncate={true} />\n            </div>\n          </div>\n        </div>\n      </section>\n\n      {/* Note Component with Different Event Types */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">Note Component (Different Event Types)</h2>\n        <div className=\"space-y-6\">\n          <div>\n            <h3 className=\"text-lg font-semibold mb-2\">Text Note (Kind 1)</h3>\n            <Note data={SAMPLE_TEXT_NOTE} />\n          </div>\n\n          <div>\n            <h3 className=\"text-lg font-semibold mb-2\">Note with Image Gallery - 1 Image</h3>\n            <Note data={SAMPLE_GALLERY_1_NOTE} />\n          </div>\n\n          <div>\n            <h3 className=\"text-lg font-semibold mb-2\">Note with Image Gallery - 2 Images (Side by Side)</h3>\n            <Note data={SAMPLE_GALLERY_2_NOTE} />\n          </div>\n\n          <div>\n            <h3 className=\"text-lg font-semibold mb-2\">Note with Image Gallery - 3 Images (1 Big + 2 Small)</h3>\n            <Note data={SAMPLE_GALLERY_3_NOTE} />\n          </div>\n\n          <div>\n            <h3 className=\"text-lg font-semibold mb-2\">Note with Image Gallery - 4 Images (Grid)</h3>\n            <Note data={SAMPLE_GALLERY_4_NOTE} />\n          </div>\n\n          <div>\n            <h3 className=\"text-lg font-semibold mb-2\">Note with Image Gallery - 5 Images (Mixed Layout)</h3>\n            <Note data={SAMPLE_GALLERY_5_NOTE} />\n          </div>\n\n          <div>\n            <h3 className=\"text-lg font-semibold mb-2\">Note with Image Gallery - 6 Images (Complex Layout)</h3>\n            <Note data={SAMPLE_GALLERY_6_NOTE} />\n          </div>\n\n          <div>\n            <h3 className=\"text-lg font-semibold mb-2\">Reply Note (Kind 1 with reply tags)</h3>\n            <Note data={SAMPLE_REPLY} />\n          </div>\n\n          <div>\n            <h3 className=\"text-lg font-semibold mb-2\">Repost (Kind 6)</h3>\n            <Note data={SAMPLE_REPOST} />\n          </div>\n\n          <div>\n            <h3 className=\"text-lg font-semibold mb-2\">Poll (Kind 6969)</h3>\n            <Note data={SAMPLE_POLL_EVENT} />\n          </div>\n\n          <div>\n            <h3 className=\"text-lg font-semibold mb-2\">Long Form Article (Kind 30023)</h3>\n            <Note data={SAMPLE_LONG_FORM_EVENT} />\n          </div>\n\n          <div>\n            <h3 className=\"text-lg font-semibold mb-2\">Zap Goal (Kind 9041)</h3>\n            <Note data={SAMPLE_ZAP_GOAL_EVENT} />\n          </div>\n\n          <div>\n            <h3 className=\"text-lg font-semibold mb-2\">Live Stream (Kind 30311)</h3>\n            <Note data={SAMPLE_LIVE_STREAM_EVENT as any} />\n          </div>\n        </div>\n      </section>\n\n      {/* Utility Components Section */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">Utility Components</h2>\n        <div className=\"space-y-4\">\n          <div>\n            <span className=\"mb-2\">Copy:</span>\n            <Copy text=\"Sample text to copy\" />\n          </div>\n\n          <div>\n            <span className=\"mb-2\">QrCode:</span>\n            <QrCode data=\"https://example.com\" />\n          </div>\n\n          <div>\n            <span className=\"mb-2\">ProxyImg:</span>\n            <ProxyImg src=\"https://picsum.photos/200\" size={200} />\n          </div>\n\n          <div>\n            <span className=\"mb-2\">Progress (65%):</span>\n            <Progress value={0.65} />\n          </div>\n\n          <div>\n            <span className=\"mb-2\">Progress (100%):</span>\n            <Progress value={1.0} />\n          </div>\n\n          <div>\n            <span className=\"mb-2\">Collapsed:</span>\n            <Collapsed text=\"Click to expand\" collapsed={collapsed} setCollapsed={setCollapsed}>\n              <div className=\"p-4 bg-neutral-800 rounded\">This is the expanded content that was hidden before!</div>\n            </Collapsed>\n          </div>\n\n          <div>\n            <span className=\"mb-2\">CollapsedSection:</span>\n            <CollapsedSection title=\"Expandable Section\" startClosed={true}>\n              <div className=\"p-4 bg-neutral-800 rounded mt-2\">This is content inside a collapsible section.</div>\n            </CollapsedSection>\n          </div>\n\n          <div>\n            <span className=\"mb-2\">WarningNotice:</span>\n            <WarningNotice>This is a warning message</WarningNotice>\n          </div>\n\n          <div>\n            <span className=\"mb-2\">TabSelectors:</span>\n            <TabSelectors tabs={tabs} tab={selectedTab} setTab={setSelectedTab} />\n          </div>\n\n          <div>\n            <span className=\"mb-2\">SearchBox (no props needed):</span>\n            <div className=\"text-sm text-gray-400\">SearchBox is a self-contained component with its own state</div>\n          </div>\n\n          <div>\n            <span className=\"mb-2\">PageSpinner:</span>\n            <div className=\"h-20 relative\">\n              <PageSpinner />\n            </div>\n          </div>\n\n          <div>\n            <span className=\"mb-2\">LoadMore:</span>\n            <LoadMore onLoadMore={() => console.log(\"Load more clicked\")} shouldLoadMore={true} />\n          </div>\n        </div>\n      </section>\n\n      {/* Specialized Components Section */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">Specialized Components</h2>\n        <div className=\"space-y-4\">\n          <div>\n            <span className=\"mb-2 text-lg\">NoteToSelf:</span>\n            <NoteToSelf />\n          </div>\n\n          <div>\n            <span className=\"mb-2 text-xl\">TrendingHashtags:</span>\n            <TrendingHashtags count={1} />\n          </div>\n\n          <div>\n            <span className=\"mb-2 text-xl\">TrendingUsers:</span>\n            <TrendingUsers count={1} />\n          </div>\n\n          <div>\n            <span className=\"mb-2 text-xl\">TrendingPosts:</span>\n            <TrendingPosts count={1} small={true} />\n          </div>\n\n          <div>\n            <span className=\"mb-2 text-xl\">SuggestedProfiles:</span>\n            <SuggestedProfiles />\n          </div>\n\n          <div>\n            <span className=\"mb-2 text-xl\">PaidRelayLabel:</span>\n            <div className=\"flex gap-2\">\n              <PaidRelayLabel info={{ limitation: { payment_required: true } } as any} />\n              <PaidRelayLabel info={{ limitation: { payment_required: false } } as any} />\n            </div>\n          </div>\n\n          <div>\n            <span className=\"mb-2 text-xl\">UptimeLabel:</span>\n            <UptimeLabel avgPing={95.5} />\n          </div>\n\n          <div>\n            <span className=\"mb-2 text-xl\">LiveStream Components:</span>\n            <div className=\"text-sm\">\n              <LiveEvent ev={SAMPLE_LIVE_STREAM_EVENT} />\n            </div>\n          </div>\n        </div>\n      </section>\n\n      {/* Modal Section */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">Modal</h2>\n        <div>\n          <AsyncButton onClick={async () => setShowModal(true)}>Open Modal</AsyncButton>\n          {showModal && (\n            <Modal id=\"debug-modal\" onClose={() => setShowModal(false)}>\n              <div className=\"p-6\">\n                <h3 className=\"text-xl font-bold mb-4\">Sample Modal</h3>\n                <p className=\"mb-4\">This is a modal dialog component</p>\n                <AsyncButton onClick={async () => setShowModal(false)}>Close</AsyncButton>\n              </div>\n            </Modal>\n          )}\n        </div>\n      </section>\n\n      {/* States Section */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">Component States</h2>\n        <div className=\"space-y-4\">\n          <div className=\"bg-neutral-800 p-4 rounded\">\n            <h3>Button States</h3>\n            <div className=\"flex items-center gap-4 flex-wrap\">\n              <AsyncButton onClick={async () => {}}>Normal</AsyncButton>\n              <AsyncButton disabled onClick={async () => {}}>\n                Disabled\n              </AsyncButton>\n              <AsyncButton onClick={async () => new Promise(resolve => setTimeout(resolve, 50000))}>\n                Long Task\n              </AsyncButton>\n            </div>\n          </div>\n        </div>\n      </section>\n\n      {/* Toaster */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">Toaster</h2>\n        <div className=\"flex items-center gap-4 flex-wrap\">\n          <AsyncButton\n            onClick={async () => {\n              Toastore.push({ element: <div className=\"text-xl\">Example Notification</div> })\n            }}\n          >\n            Example Notification\n          </AsyncButton>\n        </div>\n        <Toaster />\n      </section>\n\n      {/* Markdown Section */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">Markdown</h2>\n        <div className=\"space-y-6\">\n          <div className=\"light:bg-neutral-200 bg-neutral-800 p-6 rounded-lg border\">\n            <h3 className=\"text-lg font-semibold mb-4\">Complete Markdown Example</h3>\n            <Markdown\n              content={`# Heading 1\nThis is a comprehensive markdown example demonstrating all supported markdown features.\n\n## Heading 2\n### Heading 3\n#### Heading 4\n##### Heading 5\n###### Heading 6\n\n---\n\n## Text Formatting\n\nThis is **bold text** using double asterisks.\n\nThis is *italic text* using single asterisks or _underscores_.\n\nThis is ***bold and italic*** using triple asterisks.\n\nThis is ~~strikethrough text~~ using double tildes.\n\nThis is \\`inline code\\` using backticks.\n\n---\n\n## Links\n\nHere's a regular link: [Snort Social](https://snort.social)\n\nHere's a link with title: [Nostr Protocol](https://nostr.com \"Nostr Homepage\")\n\nAutolinked URL: https://github.com/nostr-protocol/nips\n\n---\n\n## Lists\n\n### Unordered Lists\n\n- First item\n- Second item\n- Third item\n  - Nested item 1\n  - Nested item 2\n    - Deeply nested item\n- Fourth item\n\n### Ordered Lists\n\n1. First item\n2. Second item\n3. Third item\n   1. Nested item 1\n   2. Nested item 2\n4. Fourth item\n\n### Mixed Lists\n\n1. First ordered item\n   - Nested unordered item\n   - Another nested item\n2. Second ordered item\n   1. Nested ordered item\n   2. Another nested ordered\n\n---\n\n## Blockquotes\n\n> This is a blockquote.\n> It can span multiple lines.\n\n> Blockquotes can also be nested:\n>> This is a nested blockquote.\n>>> And even deeper!\n\n> You can also use **markdown** inside blockquotes:\n> - Lists work too\n> - Another item\n>\n> And paragraphs!\n\n---\n\n## Code Blocks\n\nInline code: \\`const x = 42;\\`\n\nMulti-line code block:\n\n\\`\\`\\`javascript\nfunction greet(name) {\n  console.log(\\`Hello, \\${name}!\\`);\n  return true;\n}\n\nconst result = greet(\"Nostr\");\n\\`\\`\\`\n\nAnother code block without language:\n\n\\`\\`\\`\nplain text code block\nwith multiple lines\nno syntax highlighting\n\\`\\`\\`\n\n---\n\n## Horizontal Rules\n\nYou can create horizontal rules in multiple ways:\n\n---\n\n***\n\n___\n\n---\n\n## Images\n\n![Placeholder Image](https://picsum.photos/600/300)\n\n---\n\n## Tables (if supported)\n\n| Header 1 | Header 2 | Header 3 |\n|----------|----------|----------|\n| Cell 1   | Cell 2   | Cell 3   |\n| Cell 4   | Cell 5   | Cell 6   |\n| Cell 7   | Cell 8   | Cell 9   |\n\n---\n\n## Task Lists (if supported)\n\n- [x] Completed task\n- [x] Another completed task\n- [ ] Incomplete task\n- [ ] Another incomplete task\n\n---\n\n## Mixed Content Example\n\nHere's a paragraph with **bold**, *italic*, ~~strikethrough~~, and \\`code\\` all together.\n\n1. Start with an ordered list\n2. Add some **formatting**\n   - Mix with unordered lists\n   - And [links](https://snort.social)\n3. Continue the ordered list\n\n> Then add a blockquote with *emphasis*\n\nAnd finish with \\`inline code\\` and a link: https://example.com\n\n---\n\n## Special Characters & Escaping\n\nYou can escape special characters: \\\\* \\\\_ \\\\# \\\\[ \\\\]\n\nMarkdown symbols: * # - + [ ] ( ) { }\n\n---\n\n## Long Paragraphs\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n\nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n---\n\n## Emphasis Combinations\n\n**Bold text with *italic inside* it**\n\n*Italic text with **bold inside** it*\n\n***All bold and italic***\n\n**Bold with \\`code\\` inside**\n\n*Italic with [link](https://example.com) inside*\n\n---\n\n## Line Breaks\n\nThis is line one.\nThis is line two (with two spaces before line break).\n\nThis is line three (new paragraph).\n\n---\n\n## Conclusion\n\nThis example covers all major markdown features including:\n- Headings (all 6 levels)\n- Text formatting (bold, italic, strikethrough)\n- Links and autolinks\n- Ordered and unordered lists\n- Nested lists\n- Blockquotes (including nested)\n- Code blocks and inline code\n- Horizontal rules\n- Images\n- Tables\n- Mixed content\n- Special characters\n- And more!\n`}\n            />\n          </div>\n        </div>\n      </section>\n\n      {/* Form Inputs Section */}\n      <section className=\"mb-12\">\n        <h2 className=\"text-2xl font-semibold mb-4 border-b pb-2\">Form Inputs</h2>\n        <div className=\"space-y-6\">\n          <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n            {/* Text Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Text Input</label>\n              <input type=\"text\" placeholder=\"Enter text...\" className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n\n            {/* Email Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Email Input</label>\n              <input type=\"email\" placeholder=\"email@example.com\" className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n\n            {/* Password Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Password Input</label>\n              <input type=\"password\" placeholder=\"Enter password...\" className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n\n            {/* Number Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Number Input</label>\n              <input type=\"number\" placeholder=\"0\" min=\"0\" max=\"100\" className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n\n            {/* Tel Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Tel Input</label>\n              <input type=\"tel\" placeholder=\"+1 (555) 123-4567\" className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n\n            {/* URL Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">URL Input</label>\n              <input type=\"url\" placeholder=\"https://example.com\" className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n\n            {/* Search Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Search Input</label>\n              <input type=\"search\" placeholder=\"Search...\" className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n\n            {/* Date Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Date Input</label>\n              <input type=\"date\" className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n\n            {/* Time Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Time Input</label>\n              <input type=\"time\" className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n\n            {/* Datetime-local Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Datetime-local Input</label>\n              <input type=\"datetime-local\" className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n\n            {/* Month Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Month Input</label>\n              <input type=\"month\" className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n\n            {/* Week Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Week Input</label>\n              <input type=\"week\" className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n\n            {/* Color Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Color Input</label>\n              <input type=\"color\" defaultValue=\"#ff6b00\" className=\"w-full h-10 border rounded cursor-pointer\" />\n            </div>\n\n            {/* Range Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Range Input</label>\n              <input type=\"range\" min=\"0\" max=\"100\" defaultValue=\"50\" className=\"w-full\" />\n            </div>\n\n            {/* File Input */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">File Input</label>\n              <input type=\"file\" className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n\n            {/* File Input (Multiple) */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">File Input (Multiple)</label>\n              <input type=\"file\" multiple className=\"w-full px-3 py-2 border rounded\" />\n            </div>\n          </div>\n\n          {/* Textarea */}\n          <div>\n            <label className=\"block text-sm font-medium mb-2\">Textarea</label>\n            <textarea\n              placeholder=\"Enter multiple lines of text...\"\n              rows={4}\n              className=\"w-full px-3 py-2 border rounded\"\n            />\n          </div>\n\n          {/* Select */}\n          <div className=\"grid grid-cols-1 md:grid-cols-2 gap-6\">\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Select</label>\n              <select className=\"w-full px-3 py-2 border rounded\">\n                <option value=\"\">Choose an option...</option>\n                <option value=\"1\">Option 1</option>\n                <option value=\"2\">Option 2</option>\n                <option value=\"3\">Option 3</option>\n              </select>\n            </div>\n\n            {/* Multiple Select */}\n            <div>\n              <label className=\"block text-sm font-medium mb-2\">Multiple Select</label>\n              <select multiple size={4} className=\"w-full px-3 py-2 border rounded\">\n                <option value=\"1\">Option 1</option>\n                <option value=\"2\">Option 2</option>\n                <option value=\"3\">Option 3</option>\n                <option value=\"4\">Option 4</option>\n              </select>\n            </div>\n          </div>\n\n          {/* Checkboxes */}\n          <div>\n            <label className=\"block text-sm font-medium mb-2\">Checkboxes</label>\n            <div className=\"space-y-2\">\n              <label className=\"flex items-center gap-2\">\n                <input type=\"checkbox\" className=\"w-4 h-4\" />\n                <span>Checkbox 1</span>\n              </label>\n              <label className=\"flex items-center gap-2\">\n                <input type=\"checkbox\" defaultChecked className=\"w-4 h-4\" />\n                <span>Checkbox 2 (checked)</span>\n              </label>\n              <label className=\"flex items-center gap-2\">\n                <input type=\"checkbox\" disabled className=\"w-4 h-4\" />\n                <span>Checkbox 3 (disabled)</span>\n              </label>\n              <label className=\"flex items-center gap-2\">\n                <input type=\"checkbox\" defaultChecked disabled className=\"w-4 h-4\" />\n                <span>Checkbox 4 (checked & disabled)</span>\n              </label>\n            </div>\n          </div>\n\n          {/* Radio Buttons */}\n          <div>\n            <label className=\"block text-sm font-medium mb-2\">Radio Buttons</label>\n            <div className=\"space-y-2\">\n              <label className=\"flex items-center gap-2\">\n                <input type=\"radio\" name=\"radio-group\" value=\"1\" className=\"w-4 h-4\" />\n                <span>Radio Option 1</span>\n              </label>\n              <label className=\"flex items-center gap-2\">\n                <input type=\"radio\" name=\"radio-group\" value=\"2\" defaultChecked className=\"w-4 h-4\" />\n                <span>Radio Option 2 (selected)</span>\n              </label>\n              <label className=\"flex items-center gap-2\">\n                <input type=\"radio\" name=\"radio-group\" value=\"3\" className=\"w-4 h-4\" />\n                <span>Radio Option 3</span>\n              </label>\n              <label className=\"flex items-center gap-2\">\n                <input type=\"radio\" name=\"radio-disabled\" value=\"4\" disabled className=\"w-4 h-4\" />\n                <span>Radio Option 4 (disabled)</span>\n              </label>\n            </div>\n          </div>\n\n          {/* Input States */}\n          <div>\n            <h3 className=\"text-lg font-semibold mb-3\">Input States</h3>\n            <div className=\"grid grid-cols-1 md:grid-cols-2 gap-4\">\n              <div>\n                <label className=\"block text-sm font-medium mb-2 text-font-color\">Normal Input</label>\n                <input type=\"text\" placeholder=\"Normal state\" className=\"w-full px-3 py-2 border rounded\" />\n              </div>\n              <div>\n                <label className=\"block text-sm font-medium mb-2 text-font-color\">Disabled Input</label>\n                <input type=\"text\" placeholder=\"Disabled state\" disabled className=\"w-full px-3 py-2 border rounded\" />\n              </div>\n              <div>\n                <label className=\"block text-sm font-medium mb-2 text-font-color\">Readonly Input</label>\n                <input type=\"text\" value=\"Read-only value\" readOnly className=\"w-full px-3 py-2 border rounded\" />\n              </div>\n              <div>\n                <label className=\"block text-sm font-medium mb-2 text-font-color\">Required Input</label>\n                <input type=\"text\" placeholder=\"Required field\" required className=\"w-full px-3 py-2 border rounded\" />\n              </div>\n            </div>\n          </div>\n\n          {/* Fieldset and Legend */}\n          <div>\n            <fieldset className=\"border rounded p-4\">\n              <legend className=\"px-2 font-semibold text-font-color\">Fieldset with Legend</legend>\n              <div className=\"space-y-3\">\n                <div>\n                  <label className=\"block text-sm mb-1 text-font-color\">Field 1</label>\n                  <input type=\"text\" placeholder=\"First field\" className=\"w-full px-3 py-2 border rounded\" />\n                </div>\n                <div>\n                  <label className=\"block text-sm mb-1 text-font-color\">Field 2</label>\n                  <input type=\"text\" placeholder=\"Second field\" className=\"w-full px-3 py-2 border rounded\" />\n                </div>\n              </div>\n            </fieldset>\n          </div>\n\n          {/* Datalist */}\n          <div>\n            <label className=\"block text-sm font-medium mb-2\">Input with Datalist</label>\n            <input\n              type=\"text\"\n              list=\"browsers\"\n              placeholder=\"Choose or type a browser...\"\n              className=\"w-full px-3 py-2 border rounded\"\n            />\n            <datalist id=\"browsers\">\n              <option value=\"Chrome\" />\n              <option value=\"Firefox\" />\n              <option value=\"Safari\" />\n              <option value=\"Edge\" />\n              <option value=\"Opera\" />\n            </datalist>\n          </div>\n\n          {/* Button types */}\n          <div>\n            <h3 className=\"text-lg font-semibold mb-3\">HTML Button Types</h3>\n            <div className=\"flex gap-3 flex-wrap\">\n              <button type=\"button\" className=\"px-4 py-2 border rounded\">\n                Button\n              </button>\n              <button type=\"submit\" className=\"px-4 py-2 border rounded\">\n                Submit\n              </button>\n              <button type=\"reset\" className=\"px-4 py-2 border rounded\">\n                Reset\n              </button>\n              <button type=\"button\" disabled className=\"px-4 py-2 border rounded\">\n                Disabled\n              </button>\n              <input type=\"button\" value=\"Input Button\" className=\"px-4 py-2 border rounded cursor-pointer\" />\n              <input type=\"submit\" value=\"Input Submit\" className=\"px-4 py-2 border rounded cursor-pointer\" />\n              <input type=\"reset\" value=\"Input Reset\" className=\"px-4 py-2 border rounded cursor-pointer\" />\n            </div>\n          </div>\n        </div>\n      </section>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Deck/Articles.tsx",
    "content": "import { use } from \"react\"\n\nimport Note, { type NoteProps } from \"@/Components/Event/EventComponent\"\nimport { useArticles } from \"@/Feed/ArticlesFeed\"\nimport { DeckContext } from \"@/Pages/Deck/DeckLayout\"\n\nexport default function Articles({ noteProps }: { noteProps?: Omit<NoteProps, \"data\"> }) {\n  const data = useArticles()\n  const deck = use(DeckContext)\n\n  return (\n    <>\n      {data.map(a => (\n        <Note\n          data={a}\n          key={a.id}\n          {...noteProps}\n          options={{\n            longFormPreview: true,\n            ...noteProps?.options,\n          }}\n          onClick={ev => {\n            deck?.setArticle(ev)\n            noteProps?.onClick?.(ev)\n          }}\n        />\n      ))}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Deck/Columns.tsx",
    "content": "import { NostrLink, type TaggedNostrEvent } from \"@snort/system\"\nimport { useCallback } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Outlet } from \"react-router-dom\"\n\nimport { RootTabs } from \"@/Components/Feed/RootTabs\"\nimport TimelineFollows from \"@/Components/Feed/TimelineFollows\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport { transformTextCached } from \"@/Hooks/useTextTransformCache\"\nimport Articles from \"@/Pages/Deck/Articles\"\nimport NotificationsPage from \"@/Pages/Notifications/Notifications\"\n\nexport function NotesCol() {\n  return (\n    <div>\n      <div className=\"deck-col-header flex\">\n        <div className=\"flex flex-1 gap-2\">\n          <Icon name=\"rows-01\" size={24} />\n          <FormattedMessage defaultMessage=\"Notes\" />\n        </div>\n        <div className=\"flex-1\">\n          <RootTabs base=\"/deck\" />\n        </div>\n      </div>\n      <div>\n        <Outlet />\n      </div>\n    </div>\n  )\n}\n\nexport function ArticlesCol() {\n  return (\n    <div>\n      <div className=\"deck-col-header flex gap-2\">\n        <Icon name=\"file-06\" size={24} />\n        <FormattedMessage defaultMessage=\"Articles\" />\n      </div>\n      <div>\n        <Articles />\n      </div>\n    </div>\n  )\n}\n\nexport function MediaCol({ setThread }: { setThread: (e: NostrLink) => void }) {\n  const noteOnClick = useCallback(\n    (e: TaggedNostrEvent) => {\n      setThread(NostrLink.fromEvent(e))\n    },\n    [setThread],\n  )\n\n  return (\n    <div>\n      <div className=\"flex items-center gap-2 p-2 border-b\">\n        <Icon name=\"camera-lens\" size={24} />\n        <FormattedMessage defaultMessage=\"Media\" />\n      </div>\n      <TimelineFollows\n        postsOnly={true}\n        noteFilter={e => {\n          const parsed = transformTextCached(e.id, e.content, e.tags)\n          const images = parsed.filter(a => a.type === \"media\" && a.mimeType?.startsWith(\"image/\"))\n          return images.length > 0\n        }}\n        noteOnClick={noteOnClick}\n      />\n    </div>\n  )\n}\n\nexport function NotificationsCol({ setThread }: { setThread: (e: NostrLink) => void }) {\n  return (\n    <div>\n      <div className=\"deck-col-header flex gap-2\">\n        <Icon name=\"bell-solid\" size={24} />\n        <FormattedMessage defaultMessage=\"Notifications\" />\n      </div>\n      <div>\n        <NotificationsPage onClick={setThread} />\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Deck/DeckLayout.tsx",
    "content": "import type { NostrLink, TaggedNostrEvent } from \"@snort/system\"\nimport { createContext, useEffect, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link, Navigate, useLocation } from \"react-router-dom\"\n\nimport ErrorBoundary from \"@/Components/ErrorBoundary\"\nimport { LongFormText } from \"@/Components/Event/LongFormText\"\nimport Modal from \"@/Components/Modal/Modal\"\nimport { SpotlightThreadModal } from \"@/Components/Spotlight/SpotlightThreadModal\"\nimport Toaster from \"@/Components/Toaster/Toaster\"\nimport useLoginFeed from \"@/Feed/LoginFeed\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { useLoginRelays } from \"@/Hooks/useLoginRelays\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { useTheme } from \"@/Hooks/useTheme\"\nimport { ArticlesCol, MediaCol, NotesCol, NotificationsCol } from \"@/Pages/Deck/Columns\"\nimport NavSidebar from \"@/Pages/Layout/NavSidebar\"\nimport { mapPlanName } from \"@/Pages/subscribe/utils\"\nimport { trackEvent } from \"@/Utils\"\nimport { getCurrentSubscription } from \"@/Utils/Subscription\"\n\ntype Cols = \"notes\" | \"articles\" | \"media\" | \"streams\" | \"notifications\"\n\ninterface DeckState {\n  thread?: NostrLink\n  article?: TaggedNostrEvent\n}\n\ninterface DeckScope {\n  setThread: (e?: NostrLink) => void\n  setArticle: (e?: TaggedNostrEvent) => void\n  reset: () => void\n}\n\nexport const DeckContext = createContext<DeckScope | undefined>(undefined)\n\nexport function SnortDeckLayout() {\n  const location = useLocation()\n  const login = useLogin(s => ({\n    publicKey: s.publicKey,\n    subscriptions: s.subscriptions,\n  }))\n  const telemetry = usePreferences(s => s.telemetry)\n  const [deckState, setDeckState] = useState<DeckState>({\n    thread: undefined,\n    article: undefined,\n  })\n  const sub = getCurrentSubscription(login.subscriptions)\n\n  useLoginFeed()\n  useTheme()\n  useLoginRelays()\n\n  useEffect(() => {\n    if (CONFIG.features.analytics && (telemetry ?? true)) {\n      trackEvent(\"pageview\", { path: location.pathname })\n    }\n  }, [location.pathname, telemetry])\n\n  if (!login.publicKey) return <Navigate to=\"/\" replace />\n  const showDeck = CONFIG.showDeck || !(CONFIG.deckSubKind !== undefined && (sub?.type ?? -1) < CONFIG.deckSubKind)\n  if (!showDeck) {\n    return (\n      <div className=\"deck-layout\">\n        <NavSidebar narrow={true} />\n        <div>\n          <div className=\"flex flex-col gap-2 m-2 bg-dark px-3 py-2 rounded-lg\">\n            <div className=\"text-xl font-bold\">\n              <FormattedMessage\n                defaultMessage=\"You must be a {tier} subscriber to access {app} deck\"\n                id=\"IOu4Xh\"\n                values={{\n                  app: CONFIG.appNameCapitalized,\n                  tier: mapPlanName(CONFIG.deckSubKind ?? -1),\n                }}\n              />\n            </div>\n            <div>\n              <Link to=\"/subscribe\">\n                <button>\n                  <FormattedMessage defaultMessage=\"Subscribe\" />\n                </button>\n              </Link>\n            </div>\n          </div>\n        </div>\n      </div>\n    )\n  }\n  const cols = [\"notes\", \"media\", \"notifications\", \"articles\"] as Array<Cols>\n  return (\n    <div className=\"deck-layout\">\n      <DeckContext.Provider\n        value={{\n          ...deckState,\n          setThread: (e?: NostrLink) => setDeckState({ thread: e }),\n          setArticle: (e?: TaggedNostrEvent) => setDeckState({ article: e }),\n          reset: () => setDeckState({}),\n        }}\n      >\n        <NavSidebar narrow={true} />\n        <ErrorBoundary>\n          <div className=\"deck-cols\">\n            {cols.map(c => {\n              switch (c) {\n                case \"notes\":\n                  return <NotesCol />\n                case \"media\":\n                  return <MediaCol setThread={t => setDeckState({ thread: t })} />\n                case \"articles\":\n                  return <ArticlesCol />\n                case \"notifications\":\n                  return <NotificationsCol setThread={t => setDeckState({ thread: t })} />\n              }\n            })}\n          </div>\n          {deckState.thread && (\n            <SpotlightThreadModal\n              thread={deckState.thread}\n              onClose={() => setDeckState({})}\n              onBack={() => setDeckState({})}\n            />\n          )}\n          {deckState.article && (\n            <Modal\n                id=\"deck-article\"\n                onClose={() => setDeckState({})}\n                className=\"long-form\"\n                onClick={() => setDeckState({})}\n              >\n                <div onClick={e => e.stopPropagation()}>\n                  <LongFormText ev={deckState.article} isPreview={false} />\n                </div>\n              </Modal>\n          )}\n          <Toaster />\n        </ErrorBoundary>\n      </DeckContext.Provider>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Discover.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\nimport { BlindSpots } from \"./Root/BlindSpots\"\nimport TabSelectors, { type Tab } from \"@/Components/TabSelectors/TabSelectors\"\nimport { type ReactNode, useState } from \"react\"\nimport SuggestedProfiles from \"@/Components/SuggestedProfiles\"\nimport { useNavigate } from \"react-router-dom\"\nimport { FollowedByFriendsTab } from \"./Root/FollowedByFriendsTab\"\nimport FollowSetsPage from \"./Root/FollowSets\"\n\ntype DiscoverTab = Tab & {\n  subTitle?: ReactNode\n}\nexport default function Discover() {\n  const navigate = useNavigate()\n  const tabs = [\n    {\n      text: <FormattedMessage defaultMessage=\"Popular\" />,\n      value: 0,\n      subTitle: <FormattedMessage defaultMessage=\"Recent content that people you follow have reacted to.\" />,\n    },\n    {\n      text: <FormattedMessage defaultMessage=\"Followed By Friends\" />,\n      value: 3,\n      subTitle: (\n        <FormattedMessage defaultMessage=\"Posts by users that you are not following directly, but your follows are following them.\" />\n      ),\n    },\n    {\n      text: <FormattedMessage defaultMessage=\"Follow Sets\" />,\n      value: 4,\n      subTitle: <FormattedMessage defaultMessage=\"Curated lists of people to follow.\" />,\n    },\n    {\n      text: <FormattedMessage defaultMessage=\"Suggested Follows\" />,\n      value: 2,\n      subTitle: <FormattedMessage defaultMessage=\"DVM suggested users to follow.\" />,\n    },\n    {\n      text: <FormattedMessage defaultMessage=\"Search\" />,\n      value: 1,\n    },\n  ] as Array<DiscoverTab>\n  const [tab, setTab] = useState<DiscoverTab>(tabs[0])\n\n  function renderTab() {\n    switch (tab.value) {\n      case 0:\n        return <BlindSpots />\n      case 1:\n        return <></>\n      case 2:\n        return <SuggestedProfiles />\n      case 3:\n        return <FollowedByFriendsTab />\n      case 4:\n        return <FollowSetsPage />\n    }\n  }\n\n  return (\n    <>\n      <TabSelectors\n        tab={tab}\n        tabs={tabs}\n        setTab={t => {\n          if (t.value === 1) {\n            navigate(\"/search\")\n          } else {\n            setTab(t)\n          }\n        }}\n        className=\"px-3\"\n      />\n      {tab.subTitle && <div className=\"text-sm text-neutral-500 px-3 my-2\">{tab.subTitle}</div>}\n      {renderTab()}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Donate/DonatePage.tsx",
    "content": "import { useEffect, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport Telegram from \"@/assets/img/telegram.svg\"\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport Copy from \"@/Components/Copy/Copy\"\nimport ZapButton from \"@/Components/Event/ZapButton\"\nimport Modal from \"@/Components/Modal/Modal\"\nimport QrCode from \"@/Components/QrCode\"\nimport ProfilePreview from \"@/Components/User/ProfilePreview\"\nimport SnortApi, { type RevenueSplit, type RevenueToday } from \"@/External/SnortApi\"\nimport { Contributors, DonateLNURL, Translators } from \"@/Pages/Donate/const\"\nimport { ZapPoolDonateSection } from \"@/Pages/Donate/ZapPoolDonateSection\"\nimport { SnortPubKey } from \"@/Utils/Const\"\nimport { bech32ToHex } from \"@snort/shared\"\n\nconst DonatePage = () => {\n  const [splits, setSplits] = useState<RevenueSplit[]>([])\n  const [today, setSumToday] = useState<RevenueToday>()\n  const [onChain, setOnChain] = useState(\"\")\n  const api = new SnortApi()\n\n  async function getOnChainAddress() {\n    const { address } = await api.onChainDonation()\n    setOnChain(address)\n  }\n\n  async function loadData() {\n    const rsp = await api.revenueSplits()\n    setSplits(rsp)\n    const rsp2 = await api.revenueToday()\n    setSumToday(rsp2)\n  }\n\n  useEffect(() => {\n    loadData().catch(console.warn)\n  }, [])\n\n  function actions(pk: string) {\n    const split = splits.find(a => bech32ToHex(a.pubKey) === pk)\n    if (split) {\n      return <>{(100 * split.split).toLocaleString()}%</>\n    }\n    return <></>\n  }\n\n  return (\n    <div className=\"px-3 py-2 flex flex-col gap-2\">\n      <div>\n        <FormattedMessage\n          defaultMessage=\"{app} is an open source project built by passionate people in their free time, your donations are greatly appreciated\"\n          values={{\n            app: CONFIG.appNameCapitalized,\n          }}\n        />\n      </div>\n      <div>\n        <FormattedMessage\n          defaultMessage=\"Check out the code {link}\"\n          id=\"LKw/ue\"\n          values={{\n            link: (\n              <a className=\"highlight underline\" href=\"https://github.com/v0l/snort\" rel=\"noreferrer\" target=\"_blank\">\n                here\n              </a>\n            ),\n          }}\n        />\n      </div>\n      <div>\n        <FormattedMessage\n          defaultMessage=\"To see a full list of changes you can view the changelog {here}\"\n          values={{\n            here: (\n              <Link to=\"/changelog\" className=\"highlight underline\">\n                <FormattedMessage defaultMessage=\"here\" />\n              </Link>\n            ),\n          }}\n        />\n      </div>\n      {CONFIG.chatChannels && CONFIG.chatChannels.length > 0 && (\n        <>\n          <h4>\n            <FormattedMessage defaultMessage=\"Public Chat Channels\" />\n          </h4>\n          <div className=\"flex gap-2\">\n            {CONFIG.chatChannels.map(a => {\n              switch (a.type) {\n                case \"telegram\": {\n                  return (\n                    <AsyncButton\n                      onClick={() => {\n                        window.open(a.value, \"_blank\", \"noreferrer\")\n                      }}\n                    >\n                      <img src={Telegram} width={24} height={24} />\n                      <FormattedMessage defaultMessage=\"Telegram\" />\n                    </AsyncButton>\n                  )\n                }\n              }\n            })}\n          </div>\n        </>\n      )}\n      <h3>\n        <FormattedMessage defaultMessage=\"Donate\" />\n      </h3>\n      <div className=\"layer-1\">\n        <div className=\"flex items-center justify-between\">\n          <FormattedMessage defaultMessage=\"Lightning Donation\" />\n          <ZapButton pubkey={bech32ToHex(SnortPubKey)} lnurl={DonateLNURL}>\n            <FormattedMessage defaultMessage=\"Donate\" />\n          </ZapButton>\n        </div>\n        {today && (\n          <small>\n            <FormattedMessage\n              defaultMessage=\"Total today (UTC): {amount} sats\"\n              values={{ amount: today.donations.toLocaleString() }}\n            />\n          </small>\n        )}\n      </div>\n      <div className=\"layer-1\">\n        <div className=\"flex items-center justify-between\">\n          <FormattedMessage defaultMessage=\"On-chain Donation\" />\n          <AsyncButton type=\"button\" onClick={getOnChainAddress}>\n            <FormattedMessage defaultMessage=\"Get Address\" />\n          </AsyncButton>\n        </div>\n      </div>\n      {onChain && (\n        <Modal onClose={() => setOnChain(\"\")} id=\"donate-on-chain\">\n          <div className=\"flex flex-col items-center gap-3\">\n            <h2>\n              <FormattedMessage defaultMessage=\"On-chain Donation Address\" />\n            </h2>\n            <QrCode data={onChain} link={`bitcoin:${onChain}`} />\n            <Copy text={onChain} />\n          </div>\n        </Modal>\n      )}\n      <ZapPoolDonateSection />\n      <h2>\n        <FormattedMessage defaultMessage=\"Contributors\" />\n      </h2>\n      {Contributors.map(a => (\n        <ProfilePreview pubkey={a} key={a} actions={actions(a)} />\n      ))}\n      <h2>\n        <FormattedMessage defaultMessage=\"Translators\" />\n      </h2>\n      {Translators.map(a => (\n        <ProfilePreview pubkey={a} key={a} actions={actions(a)} />\n      ))}\n    </div>\n  )\n}\n\nexport default DonatePage\n"
  },
  {
    "path": "packages/app/src/Pages/Donate/ZapPoolDonateSection.tsx",
    "content": "import { useSyncExternalStore } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport { ZapPoolTarget } from \"@/Pages/ZapPool/ZapPoolTarget\"\nimport { SnortPubKey } from \"@/Utils/Const\"\nimport { ZapPoolController, ZapPoolRecipientType } from \"@/Utils/ZapPoolController\"\nimport { bech32ToHex, unwrap } from \"@snort/shared\"\n\nexport function ZapPoolDonateSection() {\n  if (!CONFIG.features.zapPool) {\n    return\n  }\n  const zapPool = useSyncExternalStore(\n    c => unwrap(ZapPoolController).hook(c),\n    () => unwrap(ZapPoolController).snapshot(),\n  )\n\n  return (\n    <>\n      <h3>\n        <FormattedMessage defaultMessage=\"ZapPool\" />\n      </h3>\n      <p>\n        <FormattedMessage\n          defaultMessage=\"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n          id=\"x/Fx2P\"\n        />\n      </p>\n      <p>\n        <Link to=\"/zap-pool\" className=\"underline\">\n          <FormattedMessage defaultMessage=\"Configure zap pool\" />\n        </Link>\n      </p>\n      <ZapPoolTarget\n        target={\n          zapPool.find(b => b.pubkey === bech32ToHex(SnortPubKey) && b.type === ZapPoolRecipientType.Generic) ?? {\n            type: ZapPoolRecipientType.Generic,\n            pubkey: bech32ToHex(SnortPubKey),\n            split: 0,\n            sum: 0,\n          }\n        }\n      />\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Donate/const.ts",
    "content": "import { KieranPubKey } from \"@/Utils/Const\"\nimport { bech32ToHex } from \"@snort/shared\"\n\nexport const Contributors = [\n  bech32ToHex(KieranPubKey),\n  \"4523be58d395b1b196a9b8c82b038b6895cb02b683d0c253a955068dba1facd0\", // Martti\n  \"7fa56f5d6962ab1e3cd424e758c3002b8665f7b0d8dcee9fe9e288d7751ac194\", // verbiricha\n  \"1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411\", // Karnage\n  bech32ToHex(\"npub10djxr5pvdu97rjkde7tgcsjxzpdzmdguwacfjwlchvj7t88dl7nsdl54nf\"), // ivan\n  bech32ToHex(\"npub148jmlutaa49y5wl5mcll003ftj59v79vf7wuv3apcwpf75hx22vs7kk9ay\"), // liran cohen\n  bech32ToHex(\"npub1xdtducdnjerex88gkg2qk2atsdlqsyxqaag4h05jmcpyspqt30wscmntxy\"), // artur\n  bech32ToHex(\"npub1vp8fdcyejd4pqjyrjk9sgz68vuhq7pyvnzk8j0ehlljvwgp8n6eqsrnpsw\"), // samsamskies\n  bech32ToHex(\"npub179rec9sw2a5ngkr2wsjpjhwp2ksygjxn6uw5py9daj2ezhw3aw5swv3s6q\"), // h3y6e - JA + other stuff\n  bech32ToHex(\"npub17q5n2z8naw0xl6vu9lvt560lg33pdpe29k0k09umlfxm3vc4tqrq466f2y\"), // w3irdrobot\n  bech32ToHex(\"npub1ltx67888tz7lqnxlrg06x234vjnq349tcfyp52r0lstclp548mcqnuz40t\"), // Vivek\n  bech32ToHex(\"npub1wh30wunfpkezx5s7edqu9g0s0raeetf5dgthzm0zw7sk8wqygmjqqfljgh\"), // Fernando Porazzi\n  bech32ToHex(\"npub1gm7tuvr9atc6u7q3gevjfeyfyvmrlul4y67k7u7hcxztz67ceexs078rf6\"), // Giszmo - Master of bug reports\n  bech32ToHex(\"npub1cz2ve34nk0ukn0ph4yq2qx3ud8rfy5e0ak4epx42dn8gha0sdgpsgra9kv\"), // Kamal\n]\nexport const Translators = [\n  bech32ToHex(\"npub1s8zws5frm94esxnp9v6zf7vk60m3hum3305n78sr73t78kleus7q8zpwna\"), // middlingphys - JA\n  bech32ToHex(\"npub1z0ykz6lp3y8rjjntenns0ee02062g2f0n55u49w44xdemw35vcpsda5jhh\"), // noraglyphs - JA\n  bech32ToHex(\"npub13wa880se2h3l54k7x76edrkrt4p94sh4q090974mt0z6n09qtntqxp47uk\"), // numpad0 - JA\n  bech32ToHex(\"npub147ccm75um0zkn0lr9fg9wrag2g6yxfw234fpmhdwuvaqjyegrhgs46t2td\"), // ROBO358 - JA\n  bech32ToHex(\"npub1ppxgsqdv4ygvdnzznudahtwqc3vaqjz3824vawfgwchpegz0lsjqqys35r\"), // Kisato - JA\n\n  bech32ToHex(\"npub1ww8kjxz2akn82qptdpl7glywnchhkx3x04hez3d3rye397turrhssenvtp\"), // Zoltan - HU\n\n  bech32ToHex(\"npub1x8dzy9xegwmdk2vy30l8u08caspcqq2yzncxehdsa6kvnte9pr3qnt8pg4\"), // solobalbo - FR\n\n  bech32ToHex(\"npub1xwm9svxrlymymph0hka40zw9frg98m6adxmzcq26jhtm5gwlhjrshhgzfd\"), // meitsjustme - ZH\n  bech32ToHex(\"npub1raspu6ag9kfcw9jz0rz4z693qwmqe5sx6jdhhuvkwz5zy8rygztqnwfhd7\"), // ra5pvt1n - ZH\n\n  bech32ToHex(\"npub13tkge7eqeem5cz8gk7gdju76nytvvf064hm5mzmv3x26k2uvaxfqczet2j\"), // Mendace - IT\n\n  bech32ToHex(\"npub10529hxckjm5t5mchss5lnpsqrmavulglxhrmu5quuu4hs6yuyh3qc9gxd5\"), // aadbitcoin - ID\n\n  bech32ToHex(\"npub19jk45jz45gczwfm22y9z69xhaex3nwg47dz84zw096xl6z62amkqj99rv7\"), // Pextar - SV\n\n  bech32ToHex(\"npub1z9n5ktfjrlpyywds9t7ljekr9cm9jjnzs27h702te5fy8p2c4dgs5zvycf\"), // Felix - DE\n\n  bech32ToHex(\"npub1wh30wunfpkezx5s7edqu9g0s0raeetf5dgthzm0zw7sk8wqygmjqqfljgh\"), // Fernando Porazzi - pt-BR\n\n  bech32ToHex(\"npub1ust7u0v3qffejwhqee45r49zgcyewrcn99vdwkednd356c9resyqtnn3mj\"), // Petri - FI\n\n  bech32ToHex(\"npub1p94p6d4p04mhjt2hdpkhhvkl93v7j7ada4w9lztj0y0fzg2m959sux5h5k\"), // Jeremy - SV\n\n  bech32ToHex(\"npub1dnvslq0vvrs8d603suykc4harv94yglcxwna9sl2xu8grt2afm3qgfh0tp\"), // summoner001 - HU\n]\nexport const DonateLNURL = \"donate@snort.social\"\n"
  },
  {
    "path": "packages/app/src/Pages/ErrorPage.tsx",
    "content": "import debug from \"debug\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useRouteError } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\n\nconst log = debug(\"ErrorPage\")\n\nconst ErrorPage = () => {\n  const error = useRouteError()\n\n  console.error(error)\n\n  const clearOPFSData = async () => {\n    if (\"showDirectoryPicker\" in window && typeof window.showDirectoryPicker === \"function\") {\n      try {\n        // Request access to the root directory\n        const rootDirectoryHandle = await window.showDirectoryPicker()\n        // Recursively delete contents\n        for await (const entry of rootDirectoryHandle.values()) {\n          if (entry.kind === \"file\") {\n            await entry.remove()\n          } else if (entry.kind === \"directory\") {\n            await entry.removeRecursively()\n          }\n        }\n        log(\"OPFS data cleared successfully.\")\n      } catch (e) {\n        log(\"Error clearing OPFS data:\", e)\n      }\n    } else {\n      log(\"File System Access API is not supported in this browser.\")\n    }\n  }\n\n  const handleClearData = async () => {\n    globalThis.localStorage.clear() // Clear localStorage\n    await clearOPFSData() // Attempt to clear OPFS data\n    globalThis.location.href = \"/\" // Redirect to home\n  }\n\n  return (\n    <div className=\"p-2\">\n      <h4>\n        <FormattedMessage defaultMessage=\"An error has occured!\" />\n      </h4>\n      <AsyncButton onClick={handleClearData}>\n        <FormattedMessage defaultMessage=\"Clear cache and reload\" />\n      </AsyncButton>\n      {error instanceof Error && (\n        <>\n          <h5>{error.message}</h5>\n          <div className=\"my-2\">{error.message}</div>\n          <pre className=\"my-2 whitespace-pre-wrap\">{error.stack}</pre>\n        </>\n      )}\n    </div>\n  )\n}\n\nexport default ErrorPage\n"
  },
  {
    "path": "packages/app/src/Pages/FixedPage.tsx",
    "content": "import { type ReactNode, useEffect, useState } from \"react\"\n\nexport function FixedPage({ children, className }: { children?: ReactNode, className?: string }) {\n    const [topOffset, setTopOffset] = useState(0)\n\n    useEffect(() => {\n        const update = () => {\n            const header = document.querySelector(\"header\")\n            setTopOffset(header?.getBoundingClientRect().height ?? 0)\n        }\n        update()\n        window.addEventListener(\"resize\", update)\n        return () => window.removeEventListener(\"resize\", update)\n    }, [])\n\n\n    return <div\n        className={`${className} min-h-0 min-w-0 w-full fixed md:relative bg-background overflow-hidden`}\n        style={{ height: `calc(100dvh - ${topOffset}px)` }}\n    >\n        {children}\n    </div>\n}"
  },
  {
    "path": "packages/app/src/Pages/FreeNostrAddressPage.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\nimport messages from \"./messages\"\n\nexport default function FreeNostrAddressPage() {\n  return (\n    <div className=\"px-3 py-2\">\n      <h2>\n        <FormattedMessage defaultMessage=\"Get a free nostr address\" />\n      </h2>\n      <p>\n        <FormattedMessage {...messages.Nip05} />\n      </p>\n      <p>\n        <FormattedMessage {...messages.Nip05Pros} />\n      </p>\n      <ul className=\"list-disc\">\n        <li>\n          <FormattedMessage {...messages.AvoidImpersonators} />\n        </li>\n        <li>\n          <FormattedMessage {...messages.EasierToFind} />\n        </li>\n        <li>\n          <FormattedMessage {...messages.Funding} />\n        </li>\n      </ul>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/HashTagsPage.tsx",
    "content": "import { dedupe } from \"@snort/shared\"\nimport { EventKind, NostrHashtagLink, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport classNames from \"classnames\"\nimport { useMemo } from \"react\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\nimport { Link, useParams } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport Timeline from \"@/Components/Feed/Timeline\"\nimport type { TimelineSubject } from \"@/Feed/TimelineFeed\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { formatShort } from \"@/Utils/Number\"\nimport { AvatarGroup } from \"@/Components/User/AvatarGroup\"\nimport useWoT from \"@/Hooks/useWoT\"\n\nconst HashTagsPage = () => {\n  const params = useParams()\n  const tag = (params.tag ?? \"\").toLowerCase()\n  const subject = useMemo(\n    () =>\n      ({\n        type: \"hashtag\",\n        items: [tag],\n        discriminator: tag,\n      }) as TimelineSubject,\n    [tag],\n  )\n\n  return (\n    <>\n      <div className=\"bb px-3 py-2\">\n        <HashTagHeader tag={tag} />\n      </div>\n      <Timeline key={tag} subject={subject} postsOnly={false} method={\"TIME_RANGE\"} />\n    </>\n  )\n}\n\nexport default HashTagsPage\n\nexport function HashTagHeader({ tag, events, className }: { tag: string; events?: number; className?: string }) {\n  const { state } = useLogin(s => ({ v: s.state.version, state: s.state }))\n  const isFollowing = useMemo(() => {\n    return state.isOnList(EventKind.InterestsList, new NostrHashtagLink(tag))\n  }, [state, tag])\n\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(`hashtag-counts:${tag}`)\n    rb.withFilter().kinds([EventKind.InterestsList]).tag(\"t\", [tag.toLowerCase()])\n    return rb\n  }, [tag])\n  const followsTag = useRequestBuilder(sub)\n  const wot = useWoT()\n  const pubkeys = wot.sortPubkeys(dedupe(followsTag.map(a => a.pubkey)))\n\n  return (\n    <div className={classNames(\"flex flex-col\", className)}>\n      <div className=\"flex items-center justify-between\">\n        <div className=\"flex gap-2 items-center\">\n          <b className=\"text-xl\">\n            <Link to={`/t/${tag}`}>#{tag}</Link>\n          </b>\n          {events && (\n            <small>\n              <FormattedMessage\n                defaultMessage=\"{n} notes\"\n                values={{\n                  n: formatShort(events),\n                }}\n              />\n            </small>\n          )}\n        </div>\n        {isFollowing ? (\n          <AsyncButton\n            className=\"secondary\"\n            onClick={() => state.removeFromList(EventKind.InterestsList, new NostrHashtagLink(tag), true)}\n          >\n            <FormattedMessage defaultMessage=\"Unfollow\" />\n          </AsyncButton>\n        ) : (\n          <AsyncButton onClick={() => state.addToList(EventKind.InterestsList, new NostrHashtagLink(tag), true)}>\n            <FormattedMessage defaultMessage=\"Follow\" />\n          </AsyncButton>\n        )}\n      </div>\n      <div className=\"flex items-center gap-2\">\n        <AvatarGroup ids={pubkeys.slice(0, 5)} size={40} />\n        {pubkeys.length > 5 && (\n          <span>\n            +<FormattedNumber value={pubkeys.length - 5} />\n          </span>\n        )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/HelpPage.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport { KieranPubKey } from \"@/Utils/Const\"\nimport { bech32ToHex, encodeTLVEntries, TLVEntryType } from \"@snort/shared\"\n\nexport default function HelpPage() {\n  return (\n    <>\n      <h2>\n        <FormattedMessage defaultMessage=\"NIP-05\" />\n      </h2>\n      <p>\n        <FormattedMessage\n          defaultMessage=\"If you have an enquiry about your NIP-05 order please DM {link}\"\n          id=\"c35bj2\"\n          values={{\n            link: (\n              <Link\n                to={`/messages/${encodeTLVEntries(\"nchat17\", {\n                  type: TLVEntryType.Author,\n                  length: 64,\n                  value: bech32ToHex(KieranPubKey),\n                })}`}\n              >\n                Kieran\n              </Link>\n            ),\n          }}\n        />\n      </p>\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Layout/Footer.tsx",
    "content": "import classNames from \"classnames\"\nimport type React from \"react\"\nimport { useState } from \"react\"\n\nimport NavLink from \"@/Components/Button/NavLink\"\nimport { NoteCreatorButton } from \"@/Components/Event/Create/NoteCreatorButton\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport useWindowSize from \"@/Hooks/useWindowSize\"\n\nimport ProfileMenu from \"./ProfileMenu\"\n\ntype MenuItem = {\n  label?: string\n  icon?: string\n  link?: string\n  nonLoggedIn?: boolean\n  el?: React.ReactNode\n  hideReadOnly?: boolean\n}\n\nconst MENU_ITEMS: MenuItem[] = [\n  { link: \"/\", icon: \"home\" },\n  { link: \"/messages\", icon: \"mail\", hideReadOnly: true },\n  {\n    el: (\n      <div className=\"flex flex-grow items-center justify-center\">\n        <NoteCreatorButton alwaysShow={true} withModal={true} />\n      </div>\n    ),\n    hideReadOnly: true,\n  },\n  { link: \"/search\", icon: \"search\" },\n]\n\nconst Footer = () => {\n  const { readonly } = useLogin(s => ({\n    readonly: s.readonly,\n  }))\n  const pageSize = useWindowSize()\n  const isMobile = pageSize.width <= 768 //max-md\n  if (!isMobile) return\n\n  return (\n    <footer className=\"md:hidden fixed bottom-0 z-10 w-full pb-safe-area bg-layer-1\">\n      <div className=\"grid grid-flow-col\">\n        {MENU_ITEMS.map((item, index) => (\n          <FooterNavItem key={index} item={item} readonly={readonly} />\n        ))}\n\n        <ProfileMenu className=\"flex justify-center items-center\" />\n      </div>\n    </footer>\n  )\n}\n\nconst FooterNavItem = ({ item, readonly }: { item: MenuItem; readonly: boolean }) => {\n  const [isHovered, setIsHovered] = useState(false)\n\n  if (readonly && item.hideReadOnly) {\n    return null\n  }\n\n  if (item.el) {\n    return item.el\n  }\n\n  return (\n    <NavLink\n      to={item.link ?? \"/\"}\n      onMouseEnter={() => setIsHovered(true)}\n      onMouseLeave={() => setIsHovered(false)}\n      className={({ isActive }) =>\n        classNames({ active: isActive || isHovered }, \"flex flex-1 p-4 justify-center items-center cursor-pointer\")\n      }\n    >\n      <Icon name={`${item.icon}-solid`} className=\"icon-solid\" size={24} />\n      <Icon name={`${item.icon}-outline`} className=\"icon-outline\" size={24} />\n    </NavLink>\n  )\n}\n\nexport default Footer\n"
  },
  {
    "path": "packages/app/src/Pages/Layout/HasNotificationsMarker.tsx",
    "content": "import { useMemo } from \"react\"\n\nimport { useNotificationsView } from \"@/Feed/WorkerRelayView\"\nimport useLogin from \"@/Hooks/useLogin\"\n\nexport function HasNotificationsMarker() {\n  const readNotifications = useLogin(s => s.readNotifications)\n  const notifications = useNotificationsView()\n  const latestNotification = useMemo(\n    () => notifications.reduce((acc, n) => Math.max(acc, n.created_at), 0),\n    [notifications],\n  )\n  const hasNotifications = latestNotification * 1000 > readNotifications\n\n  if (hasNotifications) {\n    return (\n      <div className=\"relative\">\n        <span className=\"has-unread absolute top-0 right-0 rounded-full\"></span>\n      </div>\n    )\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Layout/Header.tsx",
    "content": "import { Bech32Regex, bech32ToHex, NostrPrefix, unwrap } from \"@snort/shared\"\nimport { EventKind, type NostrLink, tryParseNostrLink } from \"@snort/system\"\nimport { useEventFeed } from \"@snort/system-react\"\nimport classNames from \"classnames\"\nimport type React from \"react\"\nimport { useCallback, useMemo } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useLocation, useNavigate } from \"react-router-dom\"\n\nimport { rootTabItems } from \"@/Components/Feed/RootTabItems\"\nimport { RootTabs } from \"@/Components/Feed/RootTabs\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport KindName from \"@/Components/kind-name\"\nimport DisplayName from \"@/Components/User/DisplayName\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { LogoHeader } from \"@/Pages/Layout/LogoHeader\"\nimport NotificationsHeader from \"@/Pages/Layout/NotificationsHeader\"\nimport { findTag } from \"@/Utils\"\nimport { RelayName } from \"@/Components/Relay/name\"\n\nexport function Header() {\n  const navigate = useNavigate()\n  const location = useLocation()\n  const pathSplit = location.pathname.split(\"/\")\n  const pageName = decodeURIComponent(pathSplit[1])\n\n  const nostrLink = useMemo(() => {\n    const nostrEntity = pathSplit.find(a => a.match(Bech32Regex))\n    if (nostrEntity) {\n      return tryParseNostrLink(nostrEntity)\n    }\n  }, [pathSplit])\n\n  const { publicKey, tags } = useLogin(s => ({\n    publicKey: s.publicKey,\n    tags: s.state.getList(EventKind.InterestsList),\n  }))\n\n  const isRootTab = useMemo(() => {\n    // todo: clean this up, its also in other places\n    const hashTags = tags.filter(a => a.toEventTag()?.[0] === \"t\").map(a => unwrap(a.toEventTag())[1])\n    return (\n      location.pathname === \"/\" || rootTabItems(\"\", publicKey, hashTags).some(item => item.path === location.pathname)\n    )\n  }, [location.pathname, publicKey, tags])\n\n  const scrollUp = useCallback(() => {\n    window.scrollTo({ top: 0, behavior: \"instant\" })\n  }, [])\n\n  const handleBackButtonClick = () => {\n    const idx = window.history.state?.idx\n    if (idx === undefined || idx > 0) {\n      navigate(-1)\n    } else {\n      navigate(\"/\")\n    }\n  }\n  const showBackButton = location.pathname !== \"/\" && !isRootTab\n\n  let title: React.ReactNode = <span className=\"capitalize\">{pageName}</span>\n  if (location.pathname.startsWith(\"/search/\")) {\n    const searchTerm = decodeURIComponent(location.pathname.split(\"/search/\")[1])\n    title = (\n      <>\n        <FormattedMessage defaultMessage=\"Search\" />: {searchTerm}\n      </>\n    )\n  } else if (nostrLink) {\n    if (\n      nostrLink.type === NostrPrefix.Event ||\n      nostrLink.type === NostrPrefix.Note ||\n      nostrLink.type === NostrPrefix.Address\n    ) {\n      title = <NoteTitle link={nostrLink} />\n    } else if (nostrLink.type === NostrPrefix.PublicKey || nostrLink.type === NostrPrefix.Profile) {\n      try {\n        title = <DisplayName pubkey={bech32ToHex(pageName)} />\n      } catch (e) {\n        console.error(e)\n      }\n    }\n  } else if (location.pathname.startsWith(\"/t/\")) {\n    title = <span>#{location.pathname.split(\"/\").slice(-1)}</span>\n  } else if (location.pathname.startsWith(\"/relay\")) {\n    title = <RelayName url={decodeURIComponent(location.pathname.split(\"/\").pop()!)} />\n  }\n\n  return (\n    <header\n      className={classNames(\n        { \"md:hidden\": pageName === \"messages\" },\n        \"flex justify-between items-center self-stretch gap-6 sticky top-0 z-10 backdrop-blur-lg\",\n      )}\n    >\n      <div\n        onClick={handleBackButtonClick}\n        className={classNames({ hidden: !showBackButton }, \"p-2 md:p-3 cursor-pointer\")}\n      >\n        <Icon name=\"arrowBack\" />\n      </div>\n      {!showBackButton && (\n        <div className=\"p-2 md:p-0 md:invisible\">\n          <LogoHeader showText={false} />\n        </div>\n      )}\n      {isRootTab && <RootTabs base=\"\" />}\n      {!isRootTab && (\n        <div\n          onClick={scrollUp}\n          className=\"cursor-pointer flex-1 text-center p-2 overflow-hidden whitespace-nowrap truncate md:text-lg\"\n        >\n          {title}\n        </div>\n      )}\n      <div className=\"md:invisible\">\n        <NotificationsHeader />\n      </div>\n    </header>\n  )\n}\n\nfunction NoteTitle({ link }: { link: NostrLink }) {\n  const ev = useEventFeed(link)\n\n  if (!ev?.pubkey) {\n    return <FormattedMessage defaultMessage=\"Note\" />\n  }\n  const title = findTag(ev, \"title\")\n  return (\n    <FormattedMessage\n        defaultMessage=\"{note_type} by {name}{title}\"\n        values={{\n          note_type: <KindName kind={ev.kind} />,\n          name: <DisplayName pubkey={ev.pubkey} />,\n          title: title ? ` - ${title}` : \"\",\n        }}\n      />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Layout/LogoHeader.tsx",
    "content": "import { unixNowMs } from \"@snort/shared\"\nimport { Link } from \"react-router-dom\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport { mapPlanName } from \"@/Pages/subscribe/utils\"\nimport { Birthday, Day } from \"@/Utils/Const\"\n\nimport useLogin from \"../../Hooks/useLogin\"\nimport { isBirthday, isChristmas, isHalloween, isStPatricksDay } from \"../../Utils\"\nimport { getCurrentSubscription } from \"../../Utils/Subscription\"\n\nfunction ordinal_suffix_of(i: number) {\n  const j = i % 10\n  const k = i % 100\n  if (j === 1 && k !== 11) {\n    return `${i}st`\n  }\n  if (j === 2 && k !== 12) {\n    return `${i}nd`\n  }\n  if (j === 3 && k !== 13) {\n    return `${i}rd`\n  }\n  return `${i}th`\n}\n\nconst getExtra = () => {\n  if (isBirthday()) {\n    const age = Math.floor((unixNowMs() - Birthday.getTime()) / (Day * 365_000))\n    return (\n      <span className=\"text-sm\" title={`${ordinal_suffix_of(age)} Birthday`}>\n        {ordinal_suffix_of(age)} 🎂\n      </span>\n    )\n  }\n  if (isHalloween()) return <span title=\"Happy Halloween!\">🎃</span>\n  if (isStPatricksDay()) return <span title=\"Happy St. Patrick's Day!\">🍀</span>\n  if (isChristmas()) return <span title=\"Merry Christmas!\">🎄</span>\n}\n\nexport function LogoHeader({ showText = false }: { showText: boolean }) {\n  const subscriptions = useLogin(s => s.subscriptions)\n  const currentSubscription = getCurrentSubscription(subscriptions)\n\n  const appName = CONFIG.appName === \"iris\" && isStPatricksDay() ? \"Irish\" : CONFIG.appName\n\n  const handleLogoClick = () => {\n    window.scrollTo({ top: 0, behavior: \"instant\" })\n  }\n\n  const extra = getExtra()\n\n  return (\n    <Link to=\"/\" className=\"logo hover:no-underline\" onClick={handleLogoClick}>\n      <h1 className=\"flex flex-row items-center md:justify-center my-0 p-0 md:mx-3 font-bold text-3xl\">\n        {CONFIG.navLogo && <img src={CONFIG.navLogo} className=\"w-8\" />}\n        {!CONFIG.navLogo && (\n          <span className=\"p-3 md:p-5 text-xl md:text-3xl xl:hidden w-8 h-8 rounded-lg bg-dark flex items-center justify-center\">\n            {CONFIG.appName[0]}\n          </span>\n        )}\n        {showText && (\n          <div className=\"md:hidden xl:inline ml-2\">\n            {appName}\n            {extra && <span className=\"ml-1\">{extra}</span>}\n          </div>\n        )}\n      </h1>\n      {currentSubscription && (\n        <div className=\"flex items-center gap-1 text-sm font-semibold tracking-wider xl:ml-2\">\n          <Icon name=\"diamond\" size={16} className=\"text-pro\" />\n          {mapPlanName(currentSubscription.type)}\n        </div>\n      )}\n    </Link>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Layout/NavSidebar.tsx",
    "content": "import classNames from \"classnames\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport NavLink from \"@/Components/Button/NavLink\"\nimport { NoteCreatorButton } from \"@/Components/Event/Create/NoteCreatorButton\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport useWindowSize from \"@/Hooks/useWindowSize\"\nimport { HasNotificationsMarker } from \"@/Pages/Layout/HasNotificationsMarker\"\nimport { WalletBalance } from \"@/Pages/Layout/WalletBalance\"\nimport { subscribeToNotifications } from \"@/Utils/Notifications\"\n\nimport { LogoHeader } from \"./LogoHeader\"\nimport ProfileMenu from \"./ProfileMenu\"\n\nconst MENU_ITEMS = [\n  {\n    label: <FormattedMessage defaultMessage=\"Home\" />,\n    icon: \"home\",\n    link: \"/\",\n    nonLoggedIn: true,\n  },\n  {\n    label: <FormattedMessage defaultMessage=\"Discover\" />,\n    icon: \"search\",\n    link: \"/discover\",\n    nonLoggedIn: true,\n  },\n  {\n    label: <FormattedMessage defaultMessage=\"Notifications\" />,\n    icon: \"bell\",\n    link: \"/notifications\",\n  },\n  {\n    label: <FormattedMessage defaultMessage=\"Messages\" />,\n    icon: \"mail\",\n    link: \"/messages\",\n    hideReadOnly: true,\n  },\n  {\n    label: <FormattedMessage defaultMessage=\"Deck\" />,\n    icon: \"deck\",\n    link: \"/deck\",\n  },\n\n  {\n    label: <FormattedMessage defaultMessage=\"Settings\" />,\n    icon: \"settings\",\n    link: \"/settings\",\n  },\n]\n\nconst getNavLinkClass = (isActive: boolean, narrow: boolean) => {\n  const baseClasses =\n    \"rounded-full p-3 flex flex-row items-center transition-colors duration-200 hover:bg-secondary hover:no-underline\"\n  const activeClasses = \"active font-bold\"\n\n  return classNames(baseClasses, {\n    [activeClasses]: isActive,\n    \"xl:px-4\": !narrow,\n  })\n}\n\nexport default function NavSidebar({ narrow = false }: { narrow?: boolean }) {\n  const { publicKey, readonly } = useLogin(s => ({\n    publicKey: s.publicKey,\n    readonly: s.readonly,\n  }))\n\n  const navigate = useNavigate()\n  const { publisher } = useEventPublisher()\n\n  const pageSize = useWindowSize()\n  const isMobile = pageSize.width <= 768 //max-md\n  if (isMobile) return\n\n  const className = classNames(\n    { \"xl:w-56 xl:gap-2 xl:items-start\": !narrow },\n    \"select-none overflow-y-auto hide-scrollbar sticky items-center border-r top-0 z-20 h-screen max-h-screen flex flex-col px-2 py-4 flex-shrink-0 gap-1\",\n  )\n\n  return (\n    <div className={className}>\n      <LogoHeader showText={!narrow} />\n      <div className=\"mt-1 flex-grow flex flex-col justify-between w-full\">\n        <div\n          className={classNames(\n            { \"xl:items-start\": !narrow, \"xl:gap-2\": !narrow },\n            \"gap-1 flex flex-col items-center text-lg font-bold\",\n          )}\n        >\n          {!narrow && <WalletBalance />}\n          {MENU_ITEMS.filter(a => {\n            if ((CONFIG.hideFromNavbar ?? []).includes(a.link)) {\n              return false\n            }\n            if (!CONFIG.features.deck && a.link === \"/deck\") {\n              return false\n            }\n            if (readonly && a.hideReadOnly) {\n              return false\n            }\n            return true\n          }).map(item => {\n            if (!item.nonLoggedIn && !publicKey) {\n              return \"\"\n            }\n            const onClick = () => {\n              if (item.link === \"/notifications\" && publisher) {\n                subscribeToNotifications(publisher)\n              }\n            }\n            return (\n              <NavLink\n                onClick={onClick}\n                key={item.link}\n                to={item.link}\n                className={({ isActive }) => getNavLinkClass(isActive, narrow)}\n              >\n                <Icon name={`${item.icon}-outline`} className=\"icon-outline\" size={24} />\n                <Icon name={`${item.icon}-solid`} className=\"icon-solid\" size={24} />\n                {item.link === \"/notifications\" && <HasNotificationsMarker />}\n                {!narrow && <span className=\"hidden xl:inline ml-3\">{item.label}</span>}\n              </NavLink>\n            )\n          })}\n          {publicKey && !readonly ? (\n            <div className=\"mt-2\">\n              <NoteCreatorButton alwaysShow={false} showText={!narrow} withModal={true} />\n            </div>\n          ) : (\n            <div className=\"mt-2\">\n              <button onClick={() => navigate(\"/login/sign-up\")} className=\"flex flex-row items-center primary\">\n                <Icon name=\"sign-in\" size={24} />\n                {!narrow && (\n                  <span className=\"hidden xl:inline ml-3\">\n                    <FormattedMessage defaultMessage=\"Sign up\" />\n                  </span>\n                )}\n              </button>\n            </div>\n          )}\n        </div>\n      </div>\n      <ProfileMenu />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Layout/NotificationsHeader.tsx",
    "content": "import classNames from \"classnames\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport NavLink from \"@/Components/Button/NavLink\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useKeyboardShortcut from \"@/Hooks/useKeyboardShortcut\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { HasNotificationsMarker } from \"@/Pages/Layout/HasNotificationsMarker\"\nimport { isFormElement } from \"@/Utils\"\nimport { subscribeToNotifications } from \"@/Utils/Notifications\"\n\nconst NotificationsHeader = () => {\n  const navigate = useNavigate()\n\n  useKeyboardShortcut(\"/\", event => {\n    // if event happened in a form element, do nothing, otherwise focus on search input\n    if (event.target && !isFormElement(event.target as HTMLElement)) {\n      event.preventDefault()\n      document.querySelector<HTMLInputElement>(\".search input\")?.focus()\n    }\n  })\n\n  const { publicKey } = useLogin(s => ({\n    publicKey: s.publicKey,\n  }))\n  const { publisher } = useEventPublisher()\n\n  if (!publicKey || !publisher) {\n    return (\n      <button onClick={() => navigate(\"/login/sign-up\")} className=\"mr-3 primary p-2\">\n        <Icon name=\"sign-in\" size={20} className=\"md:hidden\" />\n      </button>\n    )\n  }\n\n  return (\n    <NavLink\n      className={({ isActive }) => classNames({ active: isActive }, \"px-2 py-3 flex\")}\n      to=\"/notifications\"\n      onClick={() => subscribeToNotifications(publisher)}\n    >\n      <Icon name=\"bell-solid\" className=\"icon-solid\" size={24} />\n      <Icon name=\"bell-outline\" className=\"icon-outline\" size={24} />\n      <HasNotificationsMarker />\n    </NavLink>\n  )\n}\n\nexport default NotificationsHeader\n"
  },
  {
    "path": "packages/app/src/Pages/Layout/ProfileMenu.tsx",
    "content": "import * as DropdownMenu from \"@radix-ui/react-dropdown-menu\"\nimport classNames from \"classnames\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport ProfilePreview from \"@/Components/User/ProfilePreview\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { useProfileLink } from \"@/Hooks/useProfileLink\"\nimport useWindowSize from \"@/Hooks/useWindowSize\"\nimport { LoginStore } from \"@/Utils/Login\"\n\nexport default function ProfileMenu({ className }: { className?: string }) {\n  const { publicKey, readonly } = useLogin(s => ({\n    publicKey: s.publicKey,\n    readonly: s.readonly,\n  }))\n  const logins = LoginStore.getSessions()\n  const navigate = useNavigate()\n  const link = useProfileLink(publicKey)\n\n  const pageSize = useWindowSize()\n  const isNarrow = pageSize.width <= 1280 //xl\n  function profile() {\n    return (\n      <ProfilePreview\n        pubkey={publicKey!}\n        className={isNarrow ? \"!justify-center\" : \"\"}\n        actions={!isNarrow && <Icon name=\"arrowFront\" className=\"rotate-90 align-end\" size={14} />}\n        profileImageProps={{\n          size: 40,\n          link: \"\",\n          showNip05: false,\n          showProfileCard: false,\n          showFollowDistance: false,\n          displayNameClassName: \"max-xl:hidden\",\n          subHeader: readonly ? (\n            <div className=\"max-xl:hidden text-heart text-sm\">\n              <FormattedMessage defaultMessage=\"Read Only\" />\n            </div>\n          ) : undefined,\n        }}\n      />\n    )\n  }\n\n  const itemClassName =\n    \"px-6 py-2 text-base font-semibold bg-layer-2 light:bg-white hover:bg-layer-3 light:hover:bg-neutral-200 cursor-pointer outline-none\"\n\n  if (!publicKey) return\n  return (\n    <div className={classNames(\"w-full cursor-pointer\", className)}>\n      <DropdownMenu.Root>\n        <DropdownMenu.Trigger asChild>\n          <div>{profile()}</div>\n        </DropdownMenu.Trigger>\n        <DropdownMenu.Portal>\n          <DropdownMenu.Content className=\"bg-layer-2 rounded-lg overflow-hidden z-[9999] min-w-48\" sideOffset={5}>\n            <DropdownMenu.Item\n              className={itemClassName}\n              onClick={e => {\n                e.stopPropagation()\n                navigate(link)\n              }}\n            >\n              <div className=\"flex gap-2 items-center\">\n                <Icon name=\"user\" />\n                <FormattedMessage defaultMessage=\"Profile\" />\n              </div>\n            </DropdownMenu.Item>\n            <DropdownMenu.Item className=\"px-6 py-2 uppercase text-xs font-medium text-gray-light bg-layer-2 light:bg-white outline-none cursor-default\">\n              <FormattedMessage defaultMessage=\"Switch accounts\" />\n            </DropdownMenu.Item>\n            {logins\n              .filter(a => a.pubkey !== publicKey)\n              .map(a => (\n                <DropdownMenu.Item key={a.id} className={itemClassName}>\n                  <ProfileImage\n                    pubkey={a.pubkey}\n                    link=\"\"\n                    size={24}\n                    showProfileCard={false}\n                    showFollowDistance={false}\n                    onClick={e => {\n                      e.stopPropagation()\n                      LoginStore.switchAccount(a.id)\n                    }}\n                  />\n                </DropdownMenu.Item>\n              ))}\n          </DropdownMenu.Content>\n        </DropdownMenu.Portal>\n      </DropdownMenu.Root>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Layout/RightColumn.tsx",
    "content": "import classNames from \"classnames\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport { RightColumnWidget } from \"@/Components/RightWidgets\"\nimport LatestArticlesWidget from \"@/Components/RightWidgets/articles\"\nimport { BaseWidget } from \"@/Components/RightWidgets/base\"\nimport InviteFriendsWidget from \"@/Components/RightWidgets/invite-friends\"\nimport MiniStreamWidget from \"@/Components/RightWidgets/mini-stream\"\nimport SearchBox from \"@/Components/SearchBox/SearchBox\"\nimport { TaskList } from \"@/Components/Tasks/TaskList\"\nimport TrendingHashtags from \"@/Components/Trending/TrendingHashtags\"\nimport TrendingNotes from \"@/Components/Trending/TrendingPosts\"\nimport TrendingUsers from \"@/Components/Trending/TrendingUsers\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport useWindowSize from \"@/Hooks/useWindowSize\"\nimport IconButton from \"@/Components/Button/IconButton\"\nimport { useState } from \"react\"\nimport { setPreference } from \"@/Utils/Login\"\nimport DvmSelector from \"@/Components/DvmSelector\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { AskSnortInput } from \"@/Components/AskSnort/AskSnortInput\"\n\nexport default function RightColumn() {\n  const { pubkey } = useLogin(s => ({ pubkey: s.publicKey }))\n  const hideRightColumnPaths = [\"/login\", \"/new\", \"/messages\"]\n  const show = !hideRightColumnPaths.some(path => globalThis.location.pathname.startsWith(path))\n  const isAiChatPage = globalThis.location.pathname.startsWith(\"/agent\")\n  const [showDvmSelector, setShowDvmSelector] = useState(false)\n  const currentProvider = usePreferences(s => s.trendingDvmPubkey)\n\n  const pageSize = useWindowSize()\n  const isDesktop = pageSize.width >= 1024 //max-xl\n  if (!isDesktop) return\n\n  const widgets = pubkey\n    ? [\n        ...(!isAiChatPage ? [RightColumnWidget.AskSnort] : []),\n        RightColumnWidget.TaskList,\n        RightColumnWidget.InviteFriends,\n        //RightColumnWidget.LiveStreams,\n        RightColumnWidget.TrendingNotes,\n        RightColumnWidget.LatestArticls,\n      ]\n    : [RightColumnWidget.TaskList]\n\n  const getWidget = (t: RightColumnWidget) => {\n    switch (t) {\n      case RightColumnWidget.TaskList:\n        return <TaskList />\n      case RightColumnWidget.AskSnort:\n        return <AskSnortInput />\n      case RightColumnWidget.TrendingNotes:\n        return (\n          <BaseWidget\n            title={<FormattedMessage defaultMessage=\"Trending Notes\" />}\n            contextMenu={\n              <IconButton onClick={() => setShowDvmSelector(true)} icon={{ name: \"settings-02\", size: 18 }} />\n            }\n          >\n            <TrendingNotes small={true} count={6} />\n          </BaseWidget>\n        )\n      case RightColumnWidget.TrendingPeople:\n        return (\n          <BaseWidget title={<FormattedMessage defaultMessage=\"Trending People\" />}>\n            <TrendingUsers\n              count={6}\n              followListProps={{\n                showFollowAll: false,\n                profilePreviewProps: {\n                  actions: pubkey ? undefined : <></>,\n                  profileImageProps: {\n                    size: 32,\n                  },\n                },\n              }}\n            />\n          </BaseWidget>\n        )\n      case RightColumnWidget.TrendingHashtags:\n        return (\n          <BaseWidget title={<FormattedMessage defaultMessage=\"Popular Hashtags\" />}>\n            <TrendingHashtags short={true} count={6} />\n          </BaseWidget>\n        )\n      case RightColumnWidget.InviteFriends:\n        return <InviteFriendsWidget />\n      case RightColumnWidget.LiveStreams:\n        return <MiniStreamWidget />\n      case RightColumnWidget.LatestArticls:\n        return <LatestArticlesWidget />\n    }\n  }\n\n  return (\n    <div\n      className={classNames(\"hidden lg:flex flex-col lg:w-1/3 sticky top-0 h-screen py-3 px-4 border-l\", {\n        \"lg:flex\": show,\n      })}\n    >\n      <SearchBox />\n      <span className=\"mb-4\"></span>\n      <div className=\"flex flex-col gap-4 overflow-y-auto hide-scrollbar flex-1\">{widgets.map(getWidget)}</div>\n      {showDvmSelector && (\n        <DvmSelector\n          kind={5300}\n          onClose={() => setShowDvmSelector(false)}\n          onSelect={p => {\n            setPreference({ trendingDvmPubkey: p })\n          }}\n          currentProvider={currentProvider}\n        />\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Layout/WalletBalance.tsx",
    "content": "import { useEffect, useState } from \"react\"\nimport { FormattedNumber } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport { getCurrency } from \"@/Components/IntlProvider/IntlProviderUtils\"\nimport { useRates } from \"@/Hooks/useRates\"\nimport { useWallet } from \"@/Wallet\"\n\nexport const WalletBalance = () => {\n  const [balance, setBalance] = useState<number>()\n  const wallet = useWallet()\n  const localCurrency = getCurrency()\n  const rates = useRates(`BTC${localCurrency}`)\n  const navigate = useNavigate()\n\n  useEffect(() => {\n    setBalance(undefined)\n    if (wallet.wallet?.canGetBalance()) {\n      wallet.wallet.getBalance().then(setBalance)\n    }\n  }, [wallet])\n\n  return (\n    <div className=\"w-full flex flex-col max-xl:hidden pl-3 py-2 cursor-pointer\" onClick={() => navigate(\"/wallet\")}>\n      <div className=\"grow flex items-center justify-between\">\n        <div className=\"flex gap-1 items-center text-xl\">\n          <Icon name=\"sats\" size={28} />\n          <FormattedNumber value={balance ?? 0} />\n        </div>\n        <Icon name=\"dots\" className=\"text-neutral-400\" />\n      </div>\n      <div className=\"text-neutral-400 text-xs flex justify-between items-center\">\n        <div>\n          ~\n          <FormattedNumber\n            style=\"currency\"\n            currency={localCurrency}\n            value={(rates?.ask ?? 0) * (balance ?? 0) * 1e-8}\n            currencyDisplay=\"narrowSymbol\"\n          />\n        </div>\n        <div>\n          <FormattedNumber\n            style=\"currency\"\n            currency={localCurrency}\n            value={rates?.ask ?? 0}\n            maximumFractionDigits={0}\n            currencyDisplay=\"narrowSymbol\"\n          />\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Layout/index.tsx",
    "content": "import { TraceTimelineOverlay } from \"@snort/system-react\"\nimport { useCallback, useEffect } from \"react\"\nimport { Outlet, useLocation } from \"react-router-dom\"\n\nimport CloseButton from \"@/Components/Button/CloseButton\"\nimport ErrorBoundary from \"@/Components/ErrorBoundary\"\nimport { LoginUnlock } from \"@/Components/PinPrompt/PinPrompt\"\nimport ScrollToTop from \"@/Components/ScrollToTop\"\nimport Toaster from \"@/Components/Toaster/Toaster\"\nimport useLoginFeed from \"@/Feed/LoginFeed\"\nimport { useCommunityLeaders } from \"@/Hooks/useCommunityLeaders\"\nimport useKeyboardShortcut from \"@/Hooks/useKeyboardShortcut\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { useLoginRelays } from \"@/Hooks/useLoginRelays\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { useTheme } from \"@/Hooks/useTheme\"\nimport { useTraceTimeline } from \"@/Hooks/useTraceTimeline\"\nimport { isFormElement, trackEvent } from \"@/Utils\"\nimport { LoginStore } from \"@/Utils/Login\"\n\nimport Footer from \"./Footer\"\nimport { Header } from \"./Header\"\nimport NavSidebar from \"./NavSidebar\"\nimport RightColumn from \"./RightColumn\"\n\nexport default function Index() {\n  const location = useLocation()\n  const { id, stalker } = useLogin(s => ({\n    id: s.id,\n    stalker: s.stalker ?? false,\n  }))\n  const telemetry = usePreferences(s => s.telemetry)\n  const traceTimeline = useTraceTimeline()\n\n  useTheme()\n  useLoginRelays()\n  useLoginFeed()\n  useCommunityLeaders()\n\n  const hideHeaderPaths = [\"/login\", \"/new\"]\n  const shouldHideFooter = location.pathname.startsWith(\"/messages/\")\n  const shouldHideHeader = hideHeaderPaths.some(path => location.pathname.startsWith(path))\n\n  const handleKeyboardShortcut = useCallback((event: Event) => {\n    if (event.target && !isFormElement(event.target as HTMLElement)) {\n      event.preventDefault()\n      window.scrollTo({ top: 0, behavior: \"instant\" })\n    }\n  }, [])\n\n  const handleTraceTimelineShortcut = useCallback(\n    (event: Event) => {\n      if (event.target && !isFormElement(event.target as HTMLElement)) {\n        event.preventDefault()\n        traceTimeline.toggle()\n      }\n    },\n    [traceTimeline],\n  )\n\n  useEffect(() => {\n    if (CONFIG.features.analytics && (telemetry ?? true)) {\n      trackEvent(\"pageview\")\n    }\n  }, [telemetry])\n\n  useKeyboardShortcut(\".\", handleKeyboardShortcut)\n  useKeyboardShortcut(\"t\", handleTraceTimelineShortcut)\n\n  const isStalker = !!stalker\n\n  return (\n    <ErrorBoundary>\n      <ScrollToTop />\n      <div className=\"flex justify-center\">\n        <div className=\"w-full max-w-screen-xl\">\n          <div className=\"flex\">\n            <NavSidebar />\n            <div\n              className={`flex flex-1 flex-col w-full md:w-1/3${shouldHideFooter ? \"\" : \" pb-safe-area-plus-footer\"}`}\n            >\n              {!shouldHideHeader && <Header />}\n              <ErrorBoundary>\n                <Outlet />\n              </ErrorBoundary>\n            </div>\n            <RightColumn />\n          </div>\n          <Toaster />\n        </div>\n        <LoginUnlock />\n        {isStalker && <StalkerModal id={id} />}\n        {!shouldHideFooter && <Footer />}\n        <TraceTimelineOverlay isOpen={traceTimeline.isOpen} onClose={() => traceTimeline.close()} />\n      </div>\n    </ErrorBoundary>\n  )\n}\n\nfunction StalkerModal({ id }: { id: string }) {\n  return (\n    <div className=\"stalker\" onClick={() => LoginStore.removeSession(id)}>\n      <CloseButton />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/ListFeedPage.tsx",
    "content": "import { dedupe, unwrap } from \"@snort/shared\"\nimport { parseNostrLink } from \"@snort/system\"\nimport { useEventFeed } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useParams } from \"react-router-dom\"\n\nimport Timeline from \"@/Components/Feed/Timeline\"\nimport PageSpinner from \"@/Components/PageSpinner\"\nimport type { TimelineSubject } from \"@/Feed/TimelineFeed\"\nimport { Hour } from \"@/Utils/Const\"\n\nexport function ListFeedPage() {\n  const { id } = useParams()\n  const link = parseNostrLink(unwrap(id))\n  const data = useEventFeed(link)\n\n  const pubkeys = dedupe(data?.tags.filter(a => a[0] === \"p\").map(a => a[1]) ?? [])\n  const subject = useMemo(\n    () =>\n      ({\n        type: \"pubkey\",\n        items: pubkeys,\n        discriminator: \"list-feed\",\n      }) as TimelineSubject,\n    [pubkeys],\n  )\n\n  if (!data) return <PageSpinner />\n  const hasPTags = data.tags.some(a => a[0] === \"p\")\n  if (!hasPTags) {\n    return (\n      <b>\n        <FormattedMessage defaultMessage=\"Must be a contact list or pubkey list\" />\n      </b>\n    )\n  }\n  return <Timeline subject={subject} postsOnly={true} method=\"TIME_RANGE\" window={Hour * 12} />\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Messages/ChatParticipant.tsx",
    "content": "import type { CachedMetadata } from \"@snort/system\"\n\nimport type { ChatParticipant } from \"@/chat\"\nimport NoteToSelf from \"@/Components/User/NoteToSelf\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport useLogin from \"@/Hooks/useLogin\"\n\nexport function ChatParticipantProfile({ participant }: { participant: ChatParticipant }) {\n  const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }))\n  if (participant.id === publicKey) {\n    return <NoteToSelf className=\"grow\" />\n  }\n  return (\n    <ProfileImage pubkey={participant.id} className=\"grow\" link=\"\" profile={participant.profile as CachedMetadata} />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Messages/DM.tsx",
    "content": "import { useCallback, useEffect, useRef, useState } from \"react\"\nimport { useInView } from \"react-intersection-observer\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport NoteTime from \"@/Components/Event/Note/NoteTime\"\nimport messages from \"@/Components/messages\"\nimport Text from \"@/Components/Text/Text\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport { type Chat, type ChatMessage, ChatType } from \"@/chat\"\nimport { getCachedDecryptedContent, setCachedDecryptedContent } from \"@/Cache/GiftWrapCache\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\n\nexport interface DMProps {\n  chat: Chat\n  data: ChatMessage\n}\n\nexport default function DM(props: DMProps) {\n  const { publicKey } = useLogin(s => ({ publicKey: s.publicKey }))\n  const { publisher } = useEventPublisher()\n  const msg = props.data\n  const [content, setContent] = useState<string>(() => getCachedDecryptedContent(msg.id))\n  const { ref, inView } = useInView({ triggerOnce: true })\n  const { formatMessage } = useIntl()\n  const isMe = msg.from === publicKey\n  const otherPubkey = isMe ? publicKey : msg.from\n  const msgRef = useRef(msg)\n  msgRef.current = msg\n\n  // biome-ignore lint/correctness/useExhaustiveDependencies: uses refs for stability\n  const decrypt = useCallback(async () => {\n    const m = msgRef.current\n    if (publisher && !getCachedDecryptedContent(m.id)) {\n      const decrypted = await m.decrypt(publisher)\n      const result = decrypted || \"<ERROR>\"\n      setCachedDecryptedContent(m.id, result)\n      setContent(result)\n      props.chat.markRead(m.id)\n    }\n  }, [publisher])\n\n  function sender() {\n    const isGroup = props.chat.type === ChatType.PrivateGroupChat || props.chat.type === ChatType.PublicGroupChat\n    if (isGroup && !isMe) {\n      return <ProfileImage pubkey={msg.from} />\n    }\n  }\n\n  // biome-ignore lint/correctness/useExhaustiveDependencies: only inView and content are real triggers\n  useEffect(() => {\n    if (inView && !content) {\n      if (msg.needsDecryption) {\n        decrypt().catch(console.error)\n      } else {\n        setContent(msg.content)\n      }\n    }\n  }, [inView, content])\n\n  return (\n    <div\n      className={\n        isMe\n          ? \"self-end mt-4 min-w-[100px] max-w-[90%] whitespace-pre-wrap align-self-end\"\n          : \"mt-4 min-w-[100px] max-w-[90%] whitespace-pre-wrap\"\n      }\n      ref={ref}\n    >\n      <div\n        className={\n          isMe\n            ? \"p-3 bg-[image:var(--dm-gradient)] rounded-tl-lg rounded-tr-lg rounded-bl-lg rounded-rounded-lg-none\"\n            : \"p-3 bg-layer-1 rounded-tl-lg rounded-tr-lg rounded-br-none rounded-bl-none\"\n        }\n      >\n        {sender()}\n        {content ? (\n          <Text id={msg.id} content={content} tags={[]} creator={otherPubkey} />\n        ) : (\n          <FormattedMessage defaultMessage=\"Loading...\" />\n        )}\n      </div>\n      <div className={isMe ? \"text-end text-gray-400 text-sm mt-1\" : \"text-gray-400 text-sm mt-1\"}>\n        <NoteTime from={msg.created_at * 1000} fallback={formatMessage(messages.JustNow)} />\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Messages/DmWindow.tsx",
    "content": "import { useEffect, useMemo, useRef, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport { type Chat, useChat } from \"@/chat\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport DM from \"@/Pages/Messages/DM\"\nimport WriteMessage from \"@/Pages/Messages/WriteMessage\"\n\nimport { ChatParticipantProfile } from \"./ChatParticipant\"\nimport { FixedPage } from \"../FixedPage\"\n\nexport default function DmWindow({ id }: { id: string }) {\n  const chat = useChat(id)\n  const scrollRef = useRef<HTMLDivElement>(null)\n\n  // biome-ignore lint/correctness/useExhaustiveDependencies: scroll to bottom when messages change\n  useEffect(() => {\n    if (scrollRef.current) {\n      requestAnimationFrame(() => {\n        if (scrollRef.current) {\n          scrollRef.current.scrollTop = scrollRef.current.scrollHeight\n        }\n      })\n    }\n  }, [chat?.messages])\n\n  function sender() {\n    if (!chat) return\n    if (chat.participants.length === 1) {\n      return <ChatParticipantProfile participant={chat.participants[0]} />\n    } else {\n      return (\n        <div className=\"flex -space-x-5 mb-2.5\">\n          {chat.participants.map(v => (\n            <ProfileImage key={v.id} pubkey={v.id} showUsername={false} />\n          ))}\n          {chat.title ?? <FormattedMessage defaultMessage=\"Secret Group Chat\" />}\n        </div>\n      )\n    }\n  }\n\n  return (\n    <FixedPage className=\"flex flex-1 flex-col\" >\n      <div className=\"p-3\">{sender()}</div>\n      <div ref={scrollRef} className=\"overflow-y-auto hide-scrollbar p-2.5 flex-grow min-w-0\">\n        {chat && <DmChatSelected chat={chat} />}\n      </div>\n      <div className=\"flex items-center gap-2.5 p-2.5 shrink-0\">{chat && <WriteMessage chat={chat} />}</div>\n    </FixedPage>\n  )\n}\n\nfunction DmChatSelected({ chat }: { chat: Chat }) {\n  const sortedDms = useMemo(() => {\n    const myDms = chat?.messages\n    if (myDms) {\n      return [...myDms].sort((a, b) => (a.created_at > b.created_at ? 1 : -1))\n    }\n    return []\n  }, [chat])\n\n  return (\n    <div className=\"flex flex-col\">\n      {sortedDms.map(a => (\n        <DM data={a} key={a.id} chat={chat} />\n      ))}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Messages/MessagesPage.tsx",
    "content": "import classNames from \"classnames\"\nimport type React from \"react\"\nimport { useMemo } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport { useNavigate, useParams } from \"react-router-dom\"\n\nimport { type Chat, type ChatType, useChatSystems } from \"@/chat\"\nimport { CollapsedSection } from \"@/Components/Collapsed\"\nimport NoteTime from \"@/Components/Event/Note/NoteTime\"\nimport NoteToSelf from \"@/Components/User/NoteToSelf\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport usePageDimensions from \"@/Hooks/usePageDimensions\"\nimport useWoT from \"@/Hooks/useWoT\"\nimport { ChatParticipantProfile } from \"@/Pages/Messages/ChatParticipant\"\nimport DmWindow from \"@/Pages/Messages/DmWindow\"\nimport NewChatWindow from \"@/Pages/Messages/NewChatWindow\"\nimport UnreadCount from \"@/Pages/Messages/UnreadCount\"\n\nconst TwoCol = 768\n\nexport default function MessagesPage() {\n  const login = useLogin()\n  const { formatMessage } = useIntl()\n  const navigate = useNavigate()\n  const { id } = useParams()\n  const { width: pageWidth } = usePageDimensions()\n\n  const chats = useChatSystems()\n  const wot = useWoT()\n  const myPubkey = login.publicKey\n  const trustedChats = chats.filter(a => {\n    const p = a.participants[0]\n    if (!p) return false\n    if (p.id === myPubkey) return true\n    return wot.followDistance(p.id) <= 2\n  })\n  const otherChats = chats.filter(a => {\n    const p = a.participants[0]\n    if (!p) return false\n    if (p.id === myPubkey) return false\n    return wot.followDistance(p.id) > 2\n  })\n\n  const unreadTrustedCount = useMemo(() => trustedChats.reduce((p, c) => p + c.unread, 0), [trustedChats])\n  const unreadOtherCount = useMemo(() => otherChats.reduce((p, c) => p + c.unread, 0), [otherChats])\n\n  function openChat(e: React.MouseEvent<HTMLDivElement>, _type: ChatType, id: string) {\n    e.stopPropagation()\n    e.preventDefault()\n    navigate(`/messages/${encodeURIComponent(id)}`)\n  }\n\n  function noteToSelf(chat: Chat) {\n    return (\n      <div className=\"flex px-3 py-2\" key={chat.id} onClick={e => openChat(e, chat.type, chat.id)}>\n        <NoteToSelf className=\"grow\" />\n      </div>\n    )\n  }\n\n  function conversationIdent(cx: Chat) {\n    if (cx.participants.length === 1) {\n      return <ChatParticipantProfile participant={cx.participants[0]} />\n    } else {\n      return (\n        <div className=\"flex items-center grow pfp-overlap\">\n          {cx.participants.map(v => (\n            <ProfileImage key={v.id} pubkey={v.id} link=\"\" showUsername={false} profile={v.profile} />\n          ))}\n          {cx.title ?? <FormattedMessage defaultMessage=\"Group Chat\" />}\n        </div>\n      )\n    }\n  }\n\n  function conversation(cx: Chat) {\n    if (!login.publicKey) return null\n    const participants = cx.participants.map(a => a.id)\n    if (participants.length === 1 && participants[0] === login.publicKey) return noteToSelf(cx)\n\n    const isActive = cx.id === id\n    return (\n      <div\n        className={classNames(\"flex items-center px-3 py-2 cursor-pointer justify-between\", { active: isActive })}\n        key={cx.id}\n        onClick={e => openChat(e, cx.type, cx.id)}\n      >\n        {conversationIdent(cx)}\n        <div className=\"whitespace-nowrap\">\n          <small>\n            <NoteTime\n              from={cx.lastMessage * 1000}\n              fallback={formatMessage({ defaultMessage: \"Just now\", id: \"bxv59V\" })}\n            />\n          </small>\n          {cx.unread > 0 && <UnreadCount unread={cx.unread} />}\n        </div>\n      </div>\n    )\n  }\n\n  function sortMessages(a: Chat, b: Chat) {\n    const aSelf = a.participants.length === 1 && a.participants[0].id === login.publicKey\n    const bSelf = b.participants.length === 1 && b.participants[0].id === login.publicKey\n    if (aSelf || bSelf) {\n      return aSelf ? -1 : 1\n    }\n    return b.lastMessage > a.lastMessage ? 1 : -1\n  }\n\n  return (\n    <div className=\"flex flex-1 min-h-0 overflow-hidden\">\n      {(pageWidth >= TwoCol || !id) && (\n        <div className=\"overflow-y-auto p-2 w-full md:w-1/3 flex-shrink-0 flex flex-col gap-2\">\n          <div className=\"flex items-center justify-between\">\n            <button\n              disabled={unreadTrustedCount <= 0}\n              type=\"button\"\n              className=\"text-sm font-semibold\"\n              onClick={() => {\n                for (const c of chats) c.markRead()\n              }}\n            >\n              <FormattedMessage defaultMessage=\"Mark all read\" />\n            </button>\n            <NewChatWindow />\n          </div>\n          {trustedChats.sort(sortMessages).map(conversation)}\n          {otherChats.sort(sortMessages).length > 0 && (\n            <CollapsedSection\n              title={\n                <div className=\"text-xl flex items-center gap-4\">\n                  <FormattedMessage defaultMessage=\"Other Chats\" />\n                  {unreadOtherCount > 0 && <div className=\"has-unread\" />}\n                </div>\n              }\n            >\n              {otherChats.map(conversation)}\n            </CollapsedSection>\n          )}\n        </div>\n      )}\n      {id ? <DmWindow id={id} /> : pageWidth >= TwoCol && <div className=\"flex-1 rt-border\"></div>}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Messages/NewChatWindow.tsx",
    "content": "import { useUserSearch } from \"@snort/system-react\"\nimport { useEffect, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport { ChatType, createChatLink } from \"@/chat\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport Modal from \"@/Components/Modal/Modal\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport ProfilePreview from \"@/Components/User/ProfilePreview\"\nimport useFollowsControls from \"@/Hooks/useFollowControls\"\nimport { appendDedupe, debounce } from \"@/Utils\"\n\nexport default function NewChatWindow() {\n  const [show, setShow] = useState(false)\n  const [newChat, setNewChat] = useState<Array<string>>([])\n  const [results, setResults] = useState<Array<string>>([])\n  const [term, setSearchTerm] = useState(\"\")\n  const navigate = useNavigate()\n  const search = useUserSearch()\n  const { followList } = useFollowsControls()\n\n  useEffect(() => {\n    setNewChat([])\n    setSearchTerm(\"\")\n    setResults(followList.slice(0, 5))\n  }, [followList.slice])\n\n  useEffect(() => {\n    return debounce(500, () => {\n      if (term) {\n        search(term).then(setResults)\n      } else {\n        setResults(followList)\n      }\n    })\n  }, [term, followList, search])\n\n  function togglePubkey(a: string) {\n    setNewChat(c => (c.includes(a) ? c.filter(v => v !== a) : appendDedupe(c, [a])))\n  }\n\n  function startChat() {\n    setShow(false)\n    if (newChat.length === 1) {\n      navigate(createChatLink(ChatType.PrivateDirectMessage, newChat[0]))\n    } else {\n      navigate(createChatLink(ChatType.PrivateGroupChat, ...newChat))\n    }\n  }\n\n  return (\n    <>\n      <button type=\"button\" className=\"flex justify-center new-chat\" onClick={() => setShow(true)}>\n        <Icon name=\"plus\" size={16} />\n      </button>\n      {show && (\n        <Modal id=\"new-chat\" onClose={() => setShow(false)} className=\"new-chat-modal\">\n          <div className=\"flex flex-col gap-4\">\n            <div className=\"flex justify-between\">\n              <h2>\n                <FormattedMessage defaultMessage=\"New Chat\" />\n              </h2>\n              <button onClick={startChat}>\n                <FormattedMessage defaultMessage=\"Start chat\" />\n              </button>\n            </div>\n            <div className=\"flex flex-col gap-2\">\n              <h3>\n                <FormattedMessage defaultMessage=\"Search users\" />\n              </h3>\n              <input\n                type=\"text\"\n                placeholder=\"npub/nprofile/nostr address\"\n                value={term}\n                onChange={e => setSearchTerm(e.target.value)}\n              />\n            </div>\n            <div className=\"flex\">\n              {newChat.map(a => (\n                <ProfileImage\n                  key={`selected-${a}`}\n                  pubkey={a}\n                  showUsername={false}\n                  link=\"\"\n                  onClick={() => togglePubkey(a)}\n                />\n              ))}\n            </div>\n            <div>\n              <p>\n                <FormattedMessage defaultMessage=\"People you follow\" />\n              </p>\n              <div className=\"user-list flex flex-col gap-0.5\">\n                {results.map(a => {\n                  return (\n                    <ProfilePreview\n                      pubkey={a}\n                      key={`option-${a}`}\n                      profileImageProps={{\n                        link: \"\",\n                      }}\n                      options={{ about: false }}\n                      actions={<></>}\n                      onClick={() => togglePubkey(a)}\n                      className={newChat.includes(a) ? \"active\" : undefined}\n                    />\n                  )\n                })}\n              </div>\n            </div>\n          </div>\n        </Modal>\n      )}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Messages/UnreadCount.tsx",
    "content": "const UnreadCount = ({ unread }: { unread: number }) => {\n  return (\n    <span\n      className={`text-font-color text-sm inline-block px-2 py-0.5 rounded-[10px] select-none mx-1 my-0.5 hover:cursor-pointer ${unread > 0 ? \"bg-highlight light:text-white\" : \"bg-neutral-800\"}`}\n    >\n      {unread}\n    </span>\n  )\n}\n\nexport default UnreadCount\n"
  },
  {
    "path": "packages/app/src/Pages/Messages/WriteMessage.tsx",
    "content": "import { useState } from \"react\"\n\nimport type { Chat } from \"@/chat\"\nimport { AsyncIcon } from \"@/Components/Button/AsyncIcon\"\nimport Textarea from \"@/Components/Textarea/Textarea\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\n\nexport default function WriteMessage({ chat }: { chat: Chat }) {\n  const [msg, setMsg] = useState(\"\")\n  const { publisher, system } = useEventPublisher()\n\n  async function sendMessage() {\n    if (msg && publisher && chat) {\n      const ev = await chat.createMessage(msg, publisher)\n      await chat.sendMessage(ev, system)\n      setMsg(\"\")\n    }\n  }\n\n  function onChange(e: React.ChangeEvent<HTMLTextAreaElement>) {\n    setMsg(e.target.value)\n  }\n\n  async function onEnter(e: React.KeyboardEvent<HTMLTextAreaElement>) {\n    const isEnter = e.code === \"Enter\"\n    if (isEnter && !e.shiftKey) {\n      e.preventDefault()\n      await sendMessage()\n    }\n  }\n\n  return (\n    <>\n      <div className=\"grow\">\n        <Textarea\n          autoFocus={true}\n          placeholder=\"\"\n          value={msg}\n          onChange={e => onChange(e)}\n          onKeyDown={e => onEnter(e)}\n          onFocus={() => {\n            // ignored\n          }}\n        />\n      </div>\n      <AsyncIcon\n        className=\"rounded-full flex items-center button\"\n        iconName=\"arrow-right\"\n        onClick={() => sendMessage()}\n      />\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/NostrAddressPage.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nimport Nip5Service from \"@/Components/Nip5Service\"\nimport { SnortNostrAddressService } from \"@/Pages/settings/SnortNostrAddressService\"\n\nconst Nip5Services = [SnortNostrAddressService]\n\nexport default function NostrAddressPage() {\n  return (\n    <div className=\"px-3 py-2 flex flex-col gap-4\">\n      <h2>\n        <FormattedMessage defaultMessage=\"Buy nostr address\" />\n      </h2>\n      <p>\n        <FormattedMessage\n          defaultMessage=\"Nostr address' use the <a>NIP-05</a> specification which is a DNS based verification spec which helps to validate you as a real user.\"\n          values={{\n            a: c => (\n              <a href=\"https://nostr-nips.com/nip-05\" target=\"_blank\" className=\"!underline\" rel=\"noopener\">\n                {c}\n              </a>\n            ),\n          }}\n        />\n      </p>\n\n      {Nip5Services.map(a => (\n        <Nip5Service key={a.name} {...a} />\n      ))}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/NostrLinkHandler.tsx",
    "content": "import { fetchNip05Pubkey, NostrPrefix } from \"@snort/shared\"\nimport { tryParseNostrLink } from \"@snort/system\"\nimport { useCallback, useEffect, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useLocation, useParams } from \"react-router-dom\"\n\nimport { ThreadRoute } from \"@/Components/Event/Thread/ThreadRoute\"\nimport Spinner from \"@/Components/Icons/Spinner\"\nimport ProfilePage from \"@/Pages/Profile/ProfilePage\"\n\nexport default function NostrLinkHandler() {\n  const { state } = useLocation()\n  const { link } = useParams()\n\n  const determineInitialComponent = useCallback(\n    (link: string | undefined) => {\n      const nav = link ? tryParseNostrLink(link) : undefined\n      if (nav) {\n        switch (nav.type) {\n          case NostrPrefix.Event:\n          case NostrPrefix.Note:\n          case NostrPrefix.Address:\n            return <ThreadRoute key={link} id={nav.encode()} />\n          case NostrPrefix.PublicKey:\n          case NostrPrefix.Profile:\n            return <ProfilePage key={link} id={nav.encode()} state={state} />\n          default:\n            return null\n        }\n      } else {\n        return state ? <ProfilePage key={link} state={state} /> : null\n      }\n    },\n    [state],\n  )\n\n  const [loading, setLoading] = useState(() => !determineInitialComponent(link))\n  const [renderComponent, setRenderComponent] = useState(() => determineInitialComponent(link))\n\n  const handleLink = useCallback(\n    async (link: string | undefined) => {\n      if (link && !tryParseNostrLink(link)) {\n        try {\n          const pubkey = await fetchNip05Pubkey(link, CONFIG.nip05Domain)\n          if (pubkey) {\n            setRenderComponent(<ProfilePage key={link} id={pubkey} state={state} />)\n          }\n        } catch {\n          // Ignored\n        }\n        setLoading(false)\n      }\n    },\n    [state],\n  )\n\n  useEffect(() => {\n    setRenderComponent(determineInitialComponent(link))\n    handleLink(link)\n  }, [link, determineInitialComponent, handleLink])\n\n  if (renderComponent) {\n    return renderComponent\n  }\n\n  return (\n    <div className=\"flex items-center\">\n      {loading ? (\n        <Spinner width={50} height={50} />\n      ) : (\n        <b className=\"error\">\n          <FormattedMessage defaultMessage=\"Nothing found :/\" />\n        </b>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Notifications/NotificationGroup.tsx",
    "content": "import { unwrap } from \"@snort/shared\"\nimport { EventKind, type NostrLink, parseZap, type TaggedNostrEvent } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport { useMemo } from \"react\"\nimport { useInView } from \"react-intersection-observer\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport NoteTime from \"@/Components/Event/Note/NoteTime\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport useWoT from \"@/Hooks/useWoT\"\nimport { dedupe, getDisplayName } from \"@/Utils\"\nimport { formatShort } from \"@/Utils/Number\"\n\nimport { getNotificationContext } from \"./getNotificationContext\"\nimport { NotificationContext } from \"./notificationContext\"\nimport { AvatarGroup } from \"@/Components/User/AvatarGroup\"\nimport { WarningNotice } from \"@/Components/WarningNotice/WarningNotice\"\n\nexport function NotificationGroup({\n  evs,\n  onClick,\n}: {\n  evs: Array<TaggedNostrEvent>\n  onClick?: (link: NostrLink) => void\n}) {\n  const { ref, inView } = useInView({ triggerOnce: true })\n  const { formatMessage } = useIntl()\n  const wot = useWoT()\n  const kind = evs[0].kind\n  const navigate = useNavigate()\n\n  const zaps = useMemo(() => {\n    return evs.filter(a => a.kind === EventKind.ZapReceipt).map(a => parseZap(a))\n  }, [evs])\n  const pubkeys = dedupe(\n    evs.map(a => {\n      if (a.kind === EventKind.ZapReceipt) {\n        const zap = unwrap(zaps.find(b => b.id === a.id))\n        return zap.anonZap ? \"anon\" : (zap.sender ?? a.pubkey)\n      }\n      return a.pubkey\n    }),\n  )\n  const firstPubkey = pubkeys[0]\n  const firstPubkeyProfile = useUserProfile(inView ? (firstPubkey === \"anon\" ? \"\" : firstPubkey) : \"\")\n  const context = getNotificationContext(evs[0])\n  const totalZaps = zaps.reduce((acc, v) => acc + v.amount, 0)\n\n  const iconName = () => {\n    switch (kind) {\n      case EventKind.Reaction:\n        return \"heart-solid\"\n      case EventKind.ZapReceipt:\n        return \"zap-solid\"\n      case EventKind.Repost:\n        return \"repeat\"\n      case EventKind.TextNote:\n        return \"reverse-left\"\n    }\n    return \"\"\n  }\n\n  const actionName = (n: number, name: string) => {\n    switch (kind) {\n      case EventKind.TextNote: {\n        return \"\"\n      }\n      case EventKind.Reaction: {\n        return (\n          <FormattedMessage\n            defaultMessage=\"{n,plural,=0{{name} liked} other{{name} & {n} others liked}}\"\n            values={{\n              n,\n              name,\n            }}\n          />\n        )\n      }\n      case EventKind.Repost: {\n        return (\n          <FormattedMessage\n            defaultMessage=\"{n,plural,=0{{name} reposted} other{{name} & {n} others reposted}}\"\n            values={{\n              n,\n              name,\n            }}\n          />\n        )\n      }\n      case EventKind.ZapReceipt: {\n        return (\n          <FormattedMessage\n            defaultMessage=\"{n,plural,=0{{name} zapped} other{{name} & {n} others zapped}}\"\n            values={{\n              n,\n              name,\n            }}\n          />\n        )\n      }\n    }\n    return `${kind}'d your post`\n  }\n\n  return (\n    <div\n      className=\"flex gap-2 py-4 pr-4 cursor-pointer w-full overflow-hidden border-b\"\n      ref={ref}\n      onClick={() => {\n        if (!context) return\n        if (onClick) {\n          onClick(context)\n        } else {\n          navigate(`/${context.encode(CONFIG.eventLinkPrefix)}`)\n        }\n      }}\n    >\n      {inView && (\n        <>\n          <div className=\"flex flex-col items-center gap-2 w-[64px] min-w-[64px]\">\n            <Icon name={iconName()} size={24} className={iconName()} />\n            <div>{kind === EventKind.ZapReceipt && formatShort(totalZaps)}</div>\n          </div>\n          <div className=\"flex flex-col gap-2 overflow-hidden break-all w-full\">\n            <div className=\"flex flex-row justify-between items-center\">\n              <AvatarGroup\n                ids={wot.sortPubkeys(pubkeys.filter(a => a !== \"anon\")).slice(0, 12)}\n                showUsername={kind === EventKind.TextNote}\n                size={40}\n              />\n              <div className=\"text-neutral-500\">\n                <NoteTime from={evs[0].created_at * 1000} />\n              </div>\n            </div>\n            {kind !== EventKind.TextNote && (\n              <div className=\"font-bold\">\n                {actionName(\n                  pubkeys.length - 1,\n                  firstPubkey === \"anon\"\n                    ? formatMessage({ defaultMessage: \"Anon\" })\n                    : getDisplayName(firstPubkeyProfile, firstPubkey),\n                )}\n              </div>\n            )}\n            {window.location.search === \"?debug=true\" && <pre>{JSON.stringify(evs, undefined, 2)}</pre>}\n            {context && <NotificationContext link={context} />}\n            {!context && (\n              <>\n                <WarningNotice>\n                  <FormattedMessage defaultMessage=\"Invalid notification context\" />\n                </WarningNotice>\n                <pre>{JSON.stringify(evs[0], undefined, 2)}</pre>\n              </>\n            )}\n          </div>\n        </>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Notifications/Notifications.tsx",
    "content": "import { unwrap } from \"@snort/shared\"\nimport { EventKind, type NostrEvent, type NostrLink, type TaggedNostrEvent } from \"@snort/system\"\nimport classNames from \"classnames\"\nimport { useEffect, useMemo, useState } from \"react\"\n\nimport { AsyncIcon } from \"@/Components/Button/AsyncIcon\"\nimport { AutoLoadMore } from \"@/Components/Event/LoadMore\"\nimport { useNotificationsView } from \"@/Feed/WorkerRelayView\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport useModeration from \"@/Hooks/useModeration\"\nimport { markNotificationsRead, LoginStore } from \"@/Utils/Login\"\n\nimport { getNotificationContext } from \"./getNotificationContext\"\nimport { NotificationGroup } from \"./NotificationGroup\"\n\nenum NotificationSummaryFilter {\n  Reactions = 1,\n  Reposts = 2,\n  Mentions = 4,\n  Zaps = 8,\n  All = 255,\n}\n\nconst hasFlag = (v: number, f: NotificationSummaryFilter) => {\n  return (v & f) > 0\n}\n\nconst groupInterval = 3600 * 6\n\nconst timeKey = (ev: NostrEvent) => {\n  const onHour = ev.created_at - (ev.created_at % groupInterval)\n  return onHour.toString()\n}\n\nfunction FilterIcon({\n  f,\n  icon,\n  iconActiveClass,\n  filter,\n  setFilter,\n}: {\n  f: NotificationSummaryFilter\n  icon: string\n  iconActiveClass: string\n  filter: number\n  setFilter: (fn: (v: number) => number) => void\n}) {\n  const active = hasFlag(filter, f)\n  return (\n    <AsyncIcon\n      className={classNames(\"button-icon-sm transparent\", { active, [iconActiveClass]: active })}\n      onClick={() => setFilter(v => v ^ f)}\n      name={\"\"}\n      iconName={icon}\n    />\n  )\n}\n\nexport default function NotificationsPage({ onClick }: { onClick?: (link: NostrLink) => void }) {\n  const login = useLogin()\n  const { isMuted } = useModeration()\n  const [limit, setLimit] = useState(100)\n  const [filter, setFilter] = useState(NotificationSummaryFilter.All)\n\n  useEffect(() => {\n    markNotificationsRead(LoginStore.snapshot())\n  }, [login.publicKey])\n\n  const notifications = useNotificationsView()\n\n  const myNotifications = useMemo(() => {\n    return notifications\n      .sort((a, b) => (a.created_at > b.created_at ? -1 : 1))\n      .slice(0, limit)\n      .filter(a => !isMuted(a.pubkey) && a.tags.some(b => b[0] === \"p\" && b[1] === login.publicKey))\n      .filter(a => {\n        if (a.kind === EventKind.TextNote) {\n          return hasFlag(filter, NotificationSummaryFilter.Mentions)\n        } else if (a.kind === EventKind.Reaction) {\n          return hasFlag(filter, NotificationSummaryFilter.Reactions)\n        } else if (a.kind === EventKind.Repost) {\n          return hasFlag(filter, NotificationSummaryFilter.Reposts)\n        } else if (a.kind === EventKind.ZapReceipt) {\n          return hasFlag(filter, NotificationSummaryFilter.Zaps)\n        }\n        return true\n      })\n  }, [notifications, login.publicKey, limit, filter, isMuted])\n\n  const timeGrouped = useMemo(() => {\n    return myNotifications.reduce((acc, v) => {\n      const key = `${timeKey(v)}:${getNotificationContext(v)?.encode()}:${v.kind}`\n      if (acc.has(key)) {\n        unwrap(acc.get(key)).push(v)\n      } else {\n        acc.set(key, [v])\n      }\n      return acc\n    }, new Map<string, Array<TaggedNostrEvent>>())\n  }, [myNotifications])\n\n  return (\n    <div>\n      <div className=\"flex justify-between items-center mx-1\">\n        <div></div>\n        <div className=\"flex items-center gap-2\">\n          <FilterIcon\n            f={NotificationSummaryFilter.Reactions}\n            icon=\"heart-solid\"\n            iconActiveClass=\"text-heart\"\n            filter={filter}\n            setFilter={setFilter}\n          />\n          <FilterIcon\n            f={NotificationSummaryFilter.Zaps}\n            icon=\"zap-solid\"\n            iconActiveClass=\"text-zap\"\n            filter={filter}\n            setFilter={setFilter}\n          />\n          <FilterIcon\n            f={NotificationSummaryFilter.Reposts}\n            icon=\"repeat\"\n            iconActiveClass=\"text-repost\"\n            filter={filter}\n            setFilter={setFilter}\n          />\n          <FilterIcon\n            f={NotificationSummaryFilter.Mentions}\n            icon=\"at-sign\"\n            iconActiveClass=\"text-mention\"\n            filter={filter}\n            setFilter={setFilter}\n          />\n        </div>\n      </div>\n\n      {login.publicKey &&\n        [...timeGrouped.entries()].map(([k, g]) => <NotificationGroup key={k} evs={g} onClick={onClick} />)}\n\n      <AutoLoadMore\n        onClick={() => {\n          setLimit(l => l + 100)\n        }}\n      />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Notifications/getNotificationContext.tsx",
    "content": "import { EventKind, Nip10, NostrLink, type TaggedNostrEvent } from \"@snort/system\"\n\nexport function getNotificationContext(ev: TaggedNostrEvent) {\n  switch (ev.kind) {\n    case EventKind.ZapReceipt: {\n      const aTag = ev.tags.find(a => a[0] === \"a\")\n      if (aTag) {\n        return NostrLink.fromTag(aTag)\n      }\n      const eTag = ev.tags.find(a => a[0] === \"e\")\n      if (eTag) {\n        return NostrLink.fromTag(eTag)\n      }\n      const pTag = ev.tags.find(a => a[0] === \"p\")\n      if (pTag) {\n        return NostrLink.fromTag(pTag)\n      }\n      break\n    }\n    case EventKind.Repost: {\n      const thread = Nip10.parseThread(ev)\n      return thread?.replyTo ?? thread?.root ?? thread?.mentions[0]\n    }\n    case EventKind.Reaction: {\n      const thread = Nip10.parseThread(ev)\n      return thread?.replyTo ?? thread?.root ?? thread?.mentions[0]\n    }\n    case EventKind.TextNote: {\n      return NostrLink.fromEvent(ev)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Notifications/notificationContext.tsx",
    "content": "import { EventKind, type NostrLink } from \"@snort/system\"\nimport { useEventFeed } from \"@snort/system-react\"\n\nimport { LiveEvent } from \"@/Components/LiveStream/LiveEvent\"\nimport Text from \"@/Components/Text/Text\"\nimport ProfilePreview from \"@/Components/User/ProfilePreview\"\nimport { NostrPrefix } from \"@snort/shared\"\nimport { FormattedMessage } from \"react-intl\"\n\nexport function NotificationContext({ link }: { link: NostrLink }) {\n  const ev = useEventFeed(link)\n  if (link.type === NostrPrefix.PublicKey) {\n    return <ProfilePreview pubkey={link.id} actions={<></>} />\n  }\n  if (!ev)\n    return (\n      <FormattedMessage defaultMessage=\"Loading context...\" />\n    )\n  if (ev.kind === EventKind.LiveEvent) {\n    return <LiveEvent ev={ev} />\n  }\n  return (\n    <Text\n      id={ev.id}\n      content={ev.content}\n      tags={ev.tags}\n      creator={ev.pubkey}\n      truncate={160}\n      disableLinkPreview={true}\n      disableGallery={true}\n      className=\"text-neutral-400\"\n    />\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Profile/AvatarSection.tsx",
    "content": "import { encodeTLVEntries, hexToBech32, type LNURL, NostrPrefix, TLVEntryType } from \"@snort/shared\"\nimport { type CachedMetadata, NostrLink } from \"@snort/system\"\nimport type { ZapTarget } from \"@snort/wallet\"\nimport { use, useMemo, useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport { Link, useNavigate } from \"react-router-dom\"\n\nimport { UserRelays } from \"@/Cache\"\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport IconButton from \"@/Components/Button/IconButton\"\nimport Copy from \"@/Components/Copy/Copy\"\nimport Modal from \"@/Components/Modal/Modal\"\nimport QrCode from \"@/Components/QrCode\"\nimport { SpotlightContext } from \"@/Components/Spotlight/context\"\nimport Avatar from \"@/Components/User/Avatar\"\nimport FollowButton from \"@/Components/User/FollowButton\"\nimport MuteButton from \"@/Components/User/MuteButton\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport ZapModal from \"@/Components/ZapModal/ZapModal\"\nimport useModeration from \"@/Hooks/useModeration\"\nimport { LoginSessionType, LoginStore } from \"@/Utils/Login\"\n\nconst AvatarSection = ({\n  user,\n  id,\n  loginPubKey,\n  readonly,\n  lnurl,\n}: {\n  user?: CachedMetadata\n  id?: string\n  loginPubKey?: string\n  lnurl?: LNURL\n  readonly?: boolean\n}) => {\n  const [showProfileQr, setShowProfileQr] = useState<boolean>(false)\n  const spotlight = use(SpotlightContext)\n  const [showLnQr, setShowLnQr] = useState<boolean>(false)\n  const [prefix, setPrefix] = useState<NostrPrefix>(CONFIG.profileLinkPrefix)\n\n  const { mute, unmute, isMuted } = useModeration()\n  const navigate = useNavigate()\n  const relays = UserRelays.getFromCache(id)\n  const isMe = loginPubKey === id\n  const canWrite = !!loginPubKey && !readonly\n  const intl = useIntl()\n  const muted = id ? isMuted(id) : false\n\n  const profileId = useMemo(() => {\n    if (!id) return\n\n    if (prefix === NostrPrefix.PublicKey) {\n      return hexToBech32(NostrPrefix.PublicKey, id)\n    } else if (prefix === NostrPrefix.Profile) {\n      return NostrLink.profile(\n        id,\n        relays?.relays.filter(a => a.settings.write).map(a => a.url),\n      ).encode()\n    }\n  }, [id, relays, prefix])\n\n  const renderButtons = () => {\n    if (!id) return null\n\n    return (\n      <>\n        <IconButton onClick={() => setShowProfileQr(true)} icon={{ name: \"qr\", size: 16 }} />\n        {showProfileQr && (\n          <Modal id=\"profile-qr\" className=\"qr-modal\" onClose={() => setShowProfileQr(false)}>\n            <ProfileImage pubkey={id} />\n            <div className=\"flex flex-col items-center gap-3\">\n              <div className=\"grid gap-2 grid-cols-2\">\n                <AsyncButton onClick={() => setPrefix(NostrPrefix.PublicKey)}>NPUB</AsyncButton>\n                <AsyncButton onClick={() => setPrefix(NostrPrefix.Profile)}>NPROFILE</AsyncButton>\n              </div>\n              <QrCode data={`nostr:${profileId}`} />\n              <Copy text={profileId ?? \"\"} />\n            </div>\n          </Modal>\n        )}\n        {isMe ? (\n          <>\n            <Link className=\"md:hidden\" to=\"/settings\">\n              <button>\n                <FormattedMessage defaultMessage=\"Settings\" />\n              </button>\n            </Link>\n            <Link className=\"hidden md:inline\" to=\"/settings/profile\">\n              <button>\n                <FormattedMessage defaultMessage=\"Edit\" />\n              </button>\n            </Link>\n          </>\n        ) : (\n          <>\n            {lnurl && <IconButton onClick={() => setShowLnQr(true)} icon={{ name: \"zap\", size: 16 }} />}\n            {canWrite && (\n              <IconButton\n                onClick={() =>\n                  navigate(\n                    `/messages/${encodeTLVEntries(\"nchat17\", {\n                      type: TLVEntryType.Author,\n                      length: 64,\n                      value: id,\n                    })}`,\n                  )\n                }\n                icon={{ name: \"envelope\", size: 16 }}\n              />\n            )}\n            {canWrite && muted && <MuteButton pubkey={id} />}\n            {canWrite && !muted && (\n              <IconButton\n                className={muted ? \"bg-success\" : \"!bg-error\"}\n                onClick={async () => {\n                  if (muted) {\n                    await unmute(id)\n                  } else {\n                    await mute(id)\n                  }\n                }}\n                icon={{ name: \"mute\", size: 16 }}\n              />\n            )}\n            {!canWrite && !isMe && (\n              <IconButton\n                onClick={() => {\n                  if (confirm(intl.formatMessage({ defaultMessage: \"View as user?\", id: \"LBAnc7\" }))) {\n                    LoginStore.loginWithPubkey(id, LoginSessionType.PublicKey)\n                  }\n                }}\n                icon={{ name: \"openeye\", size: 16, className: \"translate-y-0.5\" }}\n              />\n            )}\n          </>\n        )}\n      </>\n    )\n  }\n\n  return (\n    <div className=\"flex justify-between\">\n      <Avatar\n        pubkey={id ?? \"\"}\n        user={user}\n        onClick={() => {\n          if (user?.picture) {\n            spotlight?.showImages([user?.picture])\n          }\n        }}\n        className=\"pointer\"\n        size={100}\n      />\n      <div className=\"flex gap-2 items-center\">\n        {renderButtons()}\n        {!isMe && id && <FollowButton pubkey={id} />}\n      </div>\n      <ZapModal\n        targets={\n          lnurl?.lnurl && id\n            ? [\n                {\n                  type: \"lnurl\",\n                  value: lnurl.lnurl,\n                  weight: 1,\n                  name: user?.display_name || user?.name,\n                  zap: { pubkey: id, anon: false },\n                } as ZapTarget,\n              ]\n            : undefined\n        }\n        show={showLnQr}\n        onClose={() => setShowLnQr(false)}\n      />\n    </div>\n  )\n}\n\nexport default AvatarSection\n"
  },
  {
    "path": "packages/app/src/Pages/Profile/MusicStatus.tsx",
    "content": "import { ProxyImg } from \"@/Components/ProxyImg\"\nimport { useStatusFeed } from \"@/Feed/StatusFeed\"\nimport { findTag, unwrap } from \"@/Utils\"\n\nexport const MusicStatus = ({ id }: { id: string }) => {\n  const status = useStatusFeed(id, true)\n\n  if (!status.music) return null\n\n  const link = findTag(status.music, \"r\")\n  const cover = findTag(status.music, \"cover\")\n\n  const content = (\n    <div className=\"flex gap-2\">\n      {cover && <ProxyImg src={cover} size={40} />}🎵 {unwrap(status.music).content}\n    </div>\n  )\n\n  return link ? (\n    <a href={link} rel=\"noopener noreferrer\" target=\"_blank\" className=\"text-highlight no-underline hover:underline\">\n      {content}\n    </a>\n  ) : (\n    content\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Profile/ProfileDetails.tsx",
    "content": "import type { LNURL } from \"@snort/shared\"\nimport type { CachedMetadata } from \"@snort/system\"\nimport { useState } from \"react\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport Text from \"@/Components/Text/Text\"\nimport { ProfileBadges } from \"@/Components/User/BadgeList\"\nimport DisplayName from \"@/Components/User/DisplayName\"\nimport FollowedBy from \"@/Components/User/FollowedBy\"\nimport FollowsYou from \"@/Components/User/FollowsYou\"\nimport Nip05 from \"@/Components/User/Nip05\"\nimport { UserWebsiteLink } from \"@/Components/User/UserWebsiteLink\"\nimport ZapModal from \"@/Components/ZapModal/ZapModal\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { MusicStatus } from \"@/Pages/Profile/MusicStatus\"\n\nconst ProfileDetails = ({\n  user,\n  loginPubKey,\n  id,\n  aboutText,\n  lnurl,\n  follows,\n}: {\n  user?: CachedMetadata\n  loginPubKey?: string\n  showLnQr: boolean\n  id?: string\n  aboutText: string\n  lnurl?: LNURL\n  follows: string[]\n}) => {\n  const { showStatus, showBadges } = usePreferences(s => ({\n    showStatus: s.showStatus ?? false,\n    showBadges: s.showBadges ?? false,\n  }))\n  const [showLnQr, setShowLnQr] = useState<boolean>(false)\n\n  if (!user) {\n    return null\n  }\n\n  const username = () => (\n    <>\n      <div className=\"flex flex-col gap-1\">\n        <h2 className=\"flex items-center gap-2\">\n          <DisplayName user={user} pubkey={user?.pubkey ?? \"\"} />\n          <FollowsYou followsMe={user?.pubkey !== loginPubKey && follows.includes(loginPubKey ?? \"\")} />\n        </h2>\n        {user?.nip05 && <Nip05 pubkey={user.pubkey} showBadges={true} />}\n      </div>\n      {showBadges && id && <ProfileBadges pubkey={id} />}\n      {showStatus && id && <MusicStatus id={id} />}\n      {links()}\n    </>\n  )\n\n  const links = () => (\n    <div className=\"flex flex-col gap-1\">\n      <UserWebsiteLink user={user} />\n      {lnurl && (\n        <div className=\"flex gap-2 items-center\" onClick={() => setShowLnQr(true)}>\n          <Icon name=\"zapCircle\" size={16} />\n          <div className=\"text-ellipsis overflow-hidden hover:underline cursor-pointer\">{lnurl.name}</div>\n        </div>\n      )}\n      <ZapModal\n        targets={\n          lnurl?.lnurl && id\n            ? [\n                {\n                  type: \"lnurl\",\n                  value: lnurl?.lnurl,\n                  weight: 1,\n                  name: user?.display_name || user?.name,\n                  zap: { pubkey: id, anon: false },\n                },\n              ]\n            : undefined\n        }\n        show={showLnQr}\n        onClose={() => setShowLnQr(false)}\n      />\n    </div>\n  )\n\n  const bio = () =>\n    aboutText.length > 0 && (\n      <Text\n        id={id ?? user?.pubkey ?? \"unknown-profile-about\"}\n        content={aboutText}\n        tags={[]}\n        creator={id!}\n        disableMedia={true}\n        disableLinkPreview={true}\n      />\n    )\n\n  return (\n    <div className=\"flex flex-col gap-4\">\n      {username()}\n      {bio()}\n      {user?.pubkey && loginPubKey && (\n        <FollowedBy\n          pubkey={user.pubkey}\n          showUsername={false}\n          link=\"\"\n          showFollowDistance={false}\n          showProfileCard={false}\n          size={24}\n        />\n      )}\n    </div>\n  )\n}\n\nexport default ProfileDetails\n"
  },
  {
    "path": "packages/app/src/Pages/Profile/ProfilePage.tsx",
    "content": "import { fetchNip05Pubkey, LNURL, NostrPrefix } from \"@snort/shared\"\nimport { type CachedMetadata, tryParseNostrLink } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport { use, useEffect, useMemo, useState } from \"react\"\nimport { useLocation, useNavigate, useParams } from \"react-router-dom\"\n\nimport { ProxyImg } from \"@/Components/ProxyImg\"\nimport { SpotlightContext } from \"@/Components/Spotlight/context\"\nimport TabSelectors, { type Tab } from \"@/Components/TabSelectors/TabSelectors\"\nimport FollowsList from \"@/Components/User/FollowListBase\"\nimport MutedList from \"@/Components/User/MutedList\"\nimport useFollowsFeed from \"@/Feed/FollowsFeed\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport AvatarSection from \"@/Pages/Profile/AvatarSection\"\nimport ProfileDetails from \"@/Pages/Profile/ProfileDetails\"\nimport {\n  BookMarksTab,\n  FollowersTab,\n  FollowsTab,\n  ProfileNotesTab,\n  ReactionsTab,\n  RelaysTab,\n  ZapsProfileTab,\n} from \"@/Pages/Profile/ProfileTabComponents\"\nimport ProfileTabSelectors from \"@/Pages/Profile/ProfileTabSelectors\"\nimport { ProfileTabType } from \"@/Pages/Profile/ProfileTabType\"\nimport { parseId, unwrap } from \"@/Utils\"\nimport { EmailRegex } from \"@/Utils/Const\"\n\ninterface ProfilePageProps {\n  id?: string\n  state?: CachedMetadata\n}\n\nexport default function ProfilePage({ id: propId, state }: ProfilePageProps) {\n  const params = useParams()\n  const location = useLocation()\n  const spotlight = use(SpotlightContext)\n  const profileState = (location.state as CachedMetadata | undefined) || state\n  const navigate = useNavigate()\n  const [id, setId] = useState<string | undefined>(profileState?.pubkey)\n  const [relays, setRelays] = useState<Array<string>>()\n  const user = useUserProfile(profileState ? undefined : id) || profileState\n  const { loginPubKey, readonly } = useLogin(s => ({\n    loginPubKey: s.publicKey,\n    readonly: s.readonly,\n  }))\n  const isMe = loginPubKey === id\n  const aboutText = user?.about || \"\"\n\n  const lnurl = useMemo(() => {\n    try {\n      return new LNURL(user?.lud16 || user?.lud06 || \"\")\n    } catch {\n      // ignored\n    }\n  }, [user])\n\n  // feeds\n  const follows = useFollowsFeed(id)\n\n  // tabs\n  const [tab, setTab] = useState<Tab>(ProfileTabSelectors.Notes)\n  const optionalTabs = [ProfileTabSelectors.Zaps, ProfileTabSelectors.Relays, ProfileTabSelectors.Bookmarks].filter(a =>\n    unwrap(a),\n  ) as Tab[]\n\n  useEffect(() => {\n    if (\n      user?.nip05?.endsWith(`@${CONFIG.nip05Domain}`) &&\n      (!(\"isNostrAddressValid\" in user) || user.isNostrAddressValid)\n    ) {\n      const [username] = user.nip05.split(\"@\")\n      navigate(`/${username}`, { replace: true })\n    }\n  }, [user, navigate])\n\n  const resolvedParamId = propId || params.id\n  useEffect(() => {\n    if (!id) {\n      if (resolvedParamId?.match(EmailRegex)) {\n        const [name, domain] = resolvedParamId.split(\"@\")\n        fetchNip05Pubkey(name, domain).then(a => {\n          setId(a)\n        })\n      } else {\n        const nav = tryParseNostrLink(resolvedParamId ?? \"\")\n        if (nav?.type === NostrPrefix.PublicKey || nav?.type === NostrPrefix.Profile) {\n          setId(nav.id)\n          setRelays(nav.relays)\n        } else {\n          setId(parseId(resolvedParamId ?? \"\"))\n        }\n      }\n      setTab(ProfileTabSelectors.Notes)\n    }\n  }, [id, resolvedParamId])\n\n  function tabContent() {\n    if (!id) return null\n\n    switch (tab.value) {\n      case ProfileTabType.NOTES:\n        return <ProfileNotesTab id={id} relays={relays} isMe={isMe} />\n      case ProfileTabType.ZAPS: {\n        return <ZapsProfileTab id={id} />\n      }\n      case ProfileTabType.FOLLOWS: {\n        if (isMe) {\n          return <FollowsList pubkeys={follows ?? []} showFollowAll={!isMe} className=\"px-3 py-2\" />\n        } else {\n          return <FollowsTab id={id} />\n        }\n      }\n      case ProfileTabType.FOLLOWERS: {\n        return <FollowersTab id={id} />\n      }\n      case ProfileTabType.RELAYS: {\n        return <RelaysTab id={id} />\n      }\n      case ProfileTabType.BOOKMARKS: {\n        return <BookMarksTab id={id} />\n      }\n      case ProfileTabType.REACTIONS: {\n        return <ReactionsTab id={id} />\n      }\n      case ProfileTabType.MUTED: {\n        return <MutedList />\n      }\n    }\n  }\n\n  const bannerWidth = Math.min(window.innerWidth, 940)\n  return (\n    <>\n      <div>\n        {user?.banner && (\n          <ProxyImg\n            alt=\"banner\"\n            className=\"cursor-pointer max-h-[200px] object-cover -mb-6\"\n            src={user.banner}\n            size={bannerWidth}\n            onClick={() => {\n              if (user.banner) {\n                spotlight?.showImages([user.banner])\n              }\n            }}\n            missingImageElement={<></>}\n          />\n        )}\n        <div className=\"px-4\">\n          <AvatarSection id={id} loginPubKey={loginPubKey} user={user} readonly={readonly} lnurl={lnurl} />\n          <ProfileDetails\n            user={user}\n            loginPubKey={loginPubKey}\n            id={id}\n            aboutText={aboutText}\n            lnurl={lnurl}\n            showLnQr={true}\n            follows={follows}\n          />\n        </div>\n      </div>\n      <div>\n        <TabSelectors\n          tabs={[\n            ProfileTabSelectors.Notes,\n            ProfileTabSelectors.Reactions,\n            ProfileTabSelectors.Followers,\n            ProfileTabSelectors.Follows,\n          ].concat(isMe ? [...optionalTabs, ProfileTabSelectors.Muted] : optionalTabs)}\n          className=\"px-3 py-2\"\n          tab={tab}\n          setTab={setTab}\n        />\n      </div>\n      <div>{tabContent()}</div>\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Profile/ProfileTabComponents.tsx",
    "content": "import { EventKind, NostrLink, type ParsedZap } from \"@snort/system\"\nimport { useMemo } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport { Note } from \"@/Components/Event/Note/Note\"\nimport Timeline from \"@/Components/Feed/Timeline\"\nimport { RelayFavicon } from \"@/Components/Relay/RelaysMetadata\"\nimport Bookmarks from \"@/Components/User/Bookmarks\"\nimport FollowsList from \"@/Components/User/FollowListBase\"\nimport ProfilePreview from \"@/Components/User/ProfilePreview\"\nimport ZapAmount from \"@/Components/zap-amount\"\nimport useFollowersFeed from \"@/Feed/FollowersFeed\"\nimport useFollowsFeed from \"@/Feed/FollowsFeed\"\nimport useRelaysFeed from \"@/Feed/RelaysFeed\"\nimport type { TimelineSubject } from \"@/Feed/TimelineFeed\"\nimport useZapsFeed from \"@/Feed/ZapsFeed\"\nimport { useBookmarkList, usePinList } from \"@/Hooks/useLists\"\nimport { NostrPrefix } from \"@snort/shared\"\n\nexport function ZapsProfileTab({ id }: { id: string }) {\n  const zaps = useZapsFeed(new NostrLink(NostrPrefix.PublicKey, id))\n  const zapsTotal = zaps.reduce((acc, z) => acc + z.amount, 0)\n  const fromGrouped = zaps.reduce(\n    (acc, v) => {\n      if (!v.sender) return acc\n      acc[v.sender] ??= []\n      acc[v.sender].push(v)\n      return acc\n    },\n    {} as Record<string, Array<ParsedZap>>,\n  )\n\n  return (\n    <>\n      <div className=\"px-3 py-2 text-2xl font-medium flex justify-between\">\n        <div>\n          <FormattedMessage defaultMessage=\"Profile Zaps\" />\n        </div>\n        <ZapAmount n={zapsTotal} />\n      </div>\n      {Object.entries(fromGrouped)\n        .map(a => ({\n          pubkey: a[0],\n          total: a[1].reduce((acc, v) => acc + v.amount, 0),\n          topZap: a[1].reduce((acc, v) => (v.amount > acc.amount ? v : acc), a[1][0]),\n          zaps: a[1],\n        }))\n        .sort((a, b) => {\n          return b.total > a.total ? 1 : -1\n        })\n        .map(a => (\n          <div\n            className=\"px-4 py-1 hover:bg-neutral-800 cursor:pointer rounded-lg flex items-center justify-between\"\n            key={a.pubkey}\n          >\n            <ProfilePreview\n              pubkey={a.pubkey}\n              profileImageProps={{\n                subHeader: a.topZap.content ? <div className=\"about\">&quot;{a.topZap.content}&quot;</div> : undefined,\n              }}\n              options={{\n                about: false,\n              }}\n              actions={<></>}\n            />\n            <div>\n              <ZapAmount n={a.total} />\n            </div>\n          </div>\n        ))}\n    </>\n  )\n}\n\nexport function FollowersTab({ id }: { id: string }) {\n  const followers = useFollowersFeed(id)\n  return (\n    <FollowsList\n      pubkeys={followers.map(a => a.pubkey)}\n      className=\"px-3 py-2 flex flex-col gap-1\"\n      profilePreviewProps={{\n        options: {\n          about: true,\n        },\n      }}\n    />\n  )\n}\n\nexport function FollowsTab({ id }: { id: string }) {\n  const follows = useFollowsFeed(id)\n  return (\n    <FollowsList\n      pubkeys={follows}\n      className=\"px-3 py-2 flex flex-col gap-1\"\n      profilePreviewProps={{\n        options: {\n          about: true,\n        },\n      }}\n    />\n  )\n}\n\nexport function RelaysTab({ id }: { id: string }) {\n  const relays = useRelaysFeed(id)\n  return (\n    <div className=\"flex flex-col gap-1\">\n      {relays?.map(({ url, settings }) => {\n        return (\n          <div key={url} className=\"flex gap-2 layer-1\">\n            <RelayFavicon url={url} />\n            <code className=\"grow f-ellipsis\">{url}</code>\n            <div className=\"flex gap-2\">\n              {settings.read && <span>R</span>}\n              {settings.write && <span>W</span>}\n            </div>\n          </div>\n        )\n      })}\n    </div>\n  )\n}\n\nexport function BookMarksTab({ id }: { id: string }) {\n  const bookmarks = useBookmarkList(id)\n  return <Bookmarks pubkey={id} bookmarks={bookmarks} />\n}\n\nexport function ReactionsTab({ id }: { id: string }) {\n  const subject = useMemo(\n    () =>\n      ({\n        type: \"pubkey\",\n        items: [id],\n        discriminator: `reactions:${id.slice(0, 12)}`,\n        kinds: [EventKind.Reaction],\n      }) as TimelineSubject,\n    [id],\n  )\n  return (\n    <Timeline subject={subject} postsOnly={false} method={\"LIMIT_UNTIL\"} ignoreModeration={true} window={60 * 60 * 6} />\n  )\n}\n\nexport function ProfileNotesTab({ id, relays, isMe }: { id: string; relays?: Array<string>; isMe: boolean }) {\n  const pinned = usePinList(id)\n  const options = useMemo(() => ({ showTime: false, showPinned: true, canUnpin: isMe }), [isMe])\n  const subject = useMemo(\n    () =>\n      ({\n        type: \"pubkey\",\n        items: [id],\n        discriminator: `profile:${id.slice(0, 12)}`,\n        relay: relays,\n      }) as TimelineSubject,\n    [id, relays],\n  )\n  return (\n    <>\n      {pinned\n        .filter(a => a.kind === EventKind.TextNote)\n        .map(n => {\n          return <Note key={`pinned-${n.id}`} data={n} options={options} />\n        })}\n      <Timeline\n        key={id}\n        subject={subject}\n        postsOnly={false}\n        method={\"LIMIT_UNTIL\"}\n        ignoreModeration={true}\n        window={60 * 60 * 6}\n      />\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Profile/ProfileTabSelectors.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport type { Tab } from \"@/Components/TabSelectors/TabSelectors\"\nimport { ProfileTabType } from \"@/Pages/Profile/ProfileTabType\"\n\nconst ProfileTabSelectors = {\n  Notes: {\n    text: (\n      <>\n        <Icon name=\"pencil\" size={16} />\n        <FormattedMessage defaultMessage=\"Notes\" />\n      </>\n    ),\n    value: ProfileTabType.NOTES,\n  },\n  Reactions: {\n    text: (\n      <>\n        <Icon name=\"heart-solid\" size={16} />\n        <FormattedMessage defaultMessage=\"Reactions\" />\n      </>\n    ),\n    value: ProfileTabType.REACTIONS,\n  },\n  Followers: {\n    text: (\n      <>\n        <Icon name=\"user-v2\" size={16} />\n        <FormattedMessage defaultMessage=\"Followers\" />\n      </>\n    ),\n    value: ProfileTabType.FOLLOWERS,\n  },\n  Follows: {\n    text: (\n      <>\n        <Icon name=\"stars\" size={16} />\n        <FormattedMessage defaultMessage=\"Follows\" />\n      </>\n    ),\n    value: ProfileTabType.FOLLOWS,\n  },\n  Zaps: {\n    text: (\n      <>\n        <Icon name=\"zap-solid\" size={16} />\n        <FormattedMessage defaultMessage=\"Zaps\" />\n      </>\n    ),\n    value: ProfileTabType.ZAPS,\n  },\n  Muted: {\n    text: (\n      <>\n        <Icon name=\"mute\" size={16} />\n        <FormattedMessage defaultMessage=\"Muted\" />\n      </>\n    ),\n    value: ProfileTabType.MUTED,\n  },\n  Relays: {\n    text: (\n      <>\n        <Icon name=\"wifi\" size={16} />\n        <FormattedMessage defaultMessage=\"Relays\" />\n      </>\n    ),\n    value: ProfileTabType.RELAYS,\n  },\n  Bookmarks: {\n    text: (\n      <>\n        <Icon name=\"bookmark-solid\" size={16} />\n        <FormattedMessage defaultMessage=\"Bookmarks\" />\n      </>\n    ),\n    value: ProfileTabType.BOOKMARKS,\n  },\n} as { [key: string]: Tab }\n\nexport default ProfileTabSelectors\n"
  },
  {
    "path": "packages/app/src/Pages/Profile/ProfileTabType.tsx",
    "content": "export enum ProfileTabType {\n  NOTES = 0,\n  REACTIONS = 1,\n  FOLLOWERS = 2,\n  FOLLOWS = 3,\n  ZAPS = 4,\n  MUTED = 5,\n  RELAYS = 7,\n  BOOKMARKS = 8,\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Root/BlindSpots.tsx",
    "content": "import { TimelineRenderer } from \"@/Components/Feed/TimelineRenderer\"\nimport { useBlindSpot } from \"@/Hooks/useBlindSpot\"\n\nexport function BlindSpots() {\n  const data = useBlindSpot()\n\n  const frag = {\n    events: data,\n    refTime: 0,\n  }\n\n  return <TimelineRenderer frags={frag} latest={[]} showLatest={() => {}} />\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Root/ConversationsTab.tsx",
    "content": "import TimelineFollows from \"@/Components/Feed/TimelineFollows\"\n\nexport const ConversationsTab = () => {\n  return <TimelineFollows postsOnly={false} />\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Root/DefaultTab.tsx",
    "content": "import { Navigate } from \"react-router-dom\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport usePreferences from \"@/Hooks/usePreferences\"\n\nexport const DefaultTab = () => {\n  const { publicKey } = useLogin(s => ({\n    publicKey: s.publicKey,\n  }))\n  const defaultRootTab = usePreferences(s => s.defaultRootTab)\n  const tab = publicKey ? defaultRootTab : `trending/notes`\n  return <Navigate to={`/${tab}`} replace />\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Root/FollowSets.tsx",
    "content": "import { dedupe } from \"@snort/shared\"\nimport { EventKind, NostrLink, RequestBuilder } from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport { AutoLoadMore } from \"@/Components/Event/LoadMore\"\nimport { AvatarGroup } from \"@/Components/User/AvatarGroup\"\nimport DisplayName from \"@/Components/User/DisplayName\"\nimport { ProfileLink } from \"@/Components/User/ProfileLink\"\nimport useFollowsControls from \"@/Hooks/useFollowControls\"\nimport useWoT from \"@/Hooks/useWoT\"\nimport { findTag } from \"@/Utils\"\n\nexport default function FollowSetsPage() {\n  const sub = new RequestBuilder(\"follow-sets\")\n  sub.withFilter().kinds([EventKind.StarterPackSet, EventKind.FollowSet])\n  const { formatMessage } = useIntl()\n\n  const data = useRequestBuilder(sub)\n  const wot = useWoT()\n  const control = useFollowsControls()\n  const dataSorted = wot.sortEvents(data)\n  const [showN, setShowN] = useState(10)\n  const [search, setSearch] = useState(\"\")\n\n  const filtered = dataSorted.filter(s => {\n    if (search) {\n      const ss = search.toLowerCase()\n      return s.content.toLowerCase().includes(ss) || s.tags.some(t => t[1].toLowerCase().includes(ss))\n    } else {\n      return true\n    }\n  })\n  return (\n    <div className=\"px-3 py-2 flex flex-col gap-4\">\n      <input\n        type=\"text\"\n        placeholder={formatMessage({ defaultMessage: \"Search sets..\" })}\n        value={search}\n        onChange={e => setSearch(e.target.value)}\n      />\n      {filtered.slice(0, showN).map(a => {\n        const title = findTag(a, \"title\") ?? findTag(a, \"d\") ?? a.content\n        const pTags = wot.sortPubkeys(dedupe(a.tags.filter(a => a[0] === \"p\").map(a => a[1])))\n        const isFollowingAll = pTags.every(a => control.isFollowing(a))\n        if (pTags.length === 0) return\n        const link = NostrLink.fromEvent(a)\n        return (\n          <div key={a.id} className=\"px-3 py-2 rounded-lg bg-layer-1 flex flex-col gap-4\">\n            <div className=\"flex items-center justify-between\">\n              <div className=\"flex flex-col\">\n                <div className=\"text-xl\">{title}</div>\n                <div className=\"text-neutral-500 font-medium flex items-center gap-2\">\n                  <Link to={`/${link.encode()}`} state={a}>\n                    <FormattedMessage defaultMessage=\"{n} people\" values={{ n: pTags.length }} />\n                  </Link>\n                  -\n                  <Link to={`/list-feed/${link.encode()}`}>\n                    <FormattedMessage defaultMessage=\"View Feed\" />\n                  </Link>\n                </div>\n              </div>\n              {!isFollowingAll && (\n                <div className=\"flex gap-4\">\n                  <AsyncButton\n                    className=\"secondary\"\n                    onClick={async () => {\n                      await control.addFollow(pTags)\n                    }}\n                  >\n                    <FormattedMessage defaultMessage=\"Follow All\" />\n                  </AsyncButton>\n                </div>\n              )}\n            </div>\n            <AvatarGroup ids={pTags.slice(0, 10)} size={40} />\n            <div>\n              <FormattedMessage\n                defaultMessage=\"<dark>Created by</dark> {name}\"\n                values={{\n                  dark: c => <span className=\"text-neutral-500\">{c}</span>,\n                  name: (\n                    <ProfileLink pubkey={a.pubkey}>\n                      <DisplayName pubkey={a.pubkey} />\n                    </ProfileLink>\n                  ),\n                }}\n              />\n            </div>\n          </div>\n        )\n      })}\n      {filtered.length > showN && <AutoLoadMore onClick={() => setShowN(n => n + 10)} />}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Root/FollowedByFriendsTab.tsx",
    "content": "import Timeline from \"@/Components/Feed/Timeline\"\nimport type { TimelineSubject } from \"@/Feed/TimelineFeed\"\nimport useLogin from \"@/Hooks/useLogin\"\n\nexport const FollowedByFriendsTab = () => {\n  const { publicKey } = useLogin()\n  const subject: TimelineSubject = {\n    type: \"global\",\n    items: [],\n    discriminator: `followed-by-friends-${publicKey}`,\n  }\n\n  return <Timeline followDistance={2} subject={subject} postsOnly={true} method={\"TIME_RANGE\"} />\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Root/ForYouTab.tsx",
    "content": "import { EventKind, type NostrEvent, RequestBuilder, type TaggedNostrEvent } from \"@snort/system\"\nimport { WorkerRelayInterface } from \"@snort/worker-relay\"\nimport { memo, useCallback, useEffect, useMemo, useState } from \"react\"\nimport { useNavigationType } from \"react-router-dom\"\n\nimport { Relay } from \"@/Cache\"\nimport { TimelineRenderer } from \"@/Components/Feed/TimelineRenderer\"\nimport useTimelineFeed, { type TimelineFeedOptions, type TimelineSubject } from \"@/Feed/TimelineFeed\"\nimport useFollowsControls from \"@/Hooks/useFollowControls\"\nimport useHistoryState from \"@/Hooks/useHistoryState\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { System } from \"@/system\"\n\nlet forYouFeed = {\n  events: [] as NostrEvent[],\n  created_at: 0,\n}\n\nlet getForYouFeedPromise: Promise<NostrEvent[]> | null = null\nlet reactionsRequested = false\n\nconst getReactedByFollows = (follows: string[]) => {\n  const rb1 = new RequestBuilder(\"follows:reactions\")\n  rb1.withFilter().kinds([EventKind.Reaction, EventKind.ZapReceipt]).authors(follows).limit(100)\n  const q = System.Query(rb1)\n  setTimeout(() => {\n    q.cancel()\n    const reactedIds = new Set<string>()\n    q.snapshot.forEach((ev: TaggedNostrEvent) => {\n      const reactedTo = ev.tags.find((t: string[]) => t[0] === \"e\")?.[1]\n      if (reactedTo) {\n        reactedIds.add(reactedTo)\n      }\n    })\n    const rb2 = new RequestBuilder(\"follows:reactedEvents\")\n    rb2.withFilter().ids(Array.from(reactedIds))\n    System.Query(rb2)\n  }, 500)\n}\n\nexport const ForYouTab = memo(function ForYouTab() {\n  const [notes, setNotes] = useState<NostrEvent[]>(forYouFeed.events)\n  const login = useLogin(s => ({\n    publicKey: s.publicKey,\n    tags: s.state.getList(EventKind.InterestSet),\n  }))\n  const navigationType = useNavigationType()\n  const [openedAt] = useHistoryState(Math.floor(Date.now() / 1000), \"openedAt\")\n  const { followList } = useFollowsControls()\n\n  if (!reactionsRequested && login.publicKey) {\n    reactionsRequested = true\n    // on first load, ask relays for reactions to events by follows\n    getReactedByFollows(followList)\n  }\n\n  const subject = useMemo(\n    () =>\n      ({\n        type: \"pubkey\",\n        items: followList,\n        discriminator: login.publicKey?.slice(0, 12),\n        extra: rb => {\n          if (login.tags.length > 0) {\n            rb.withFilter().kinds([EventKind.TextNote]).tags(login.tags)\n          }\n        },\n      }) as TimelineSubject,\n    [login.publicKey, followList, login.tags],\n  )\n  // also get \"follows\" feed so data is loaded from relays and there's a fallback if \"for you\" feed is empty\n  const latestFeed = useTimelineFeed(subject, { method: \"TIME_RANGE\", now: openedAt } as TimelineFeedOptions)\n  const filteredLatestFeed = useMemo(() => {\n    return (\n      latestFeed.main?.filter((ev: NostrEvent) => {\n        // no replies\n        return !ev.tags.some((tag: string[]) => tag[0] === \"e\")\n      }) ?? []\n    )\n  }, [latestFeed.main])\n\n  const getFeed = useCallback(() => {\n    if (!login.publicKey) {\n      return []\n    }\n    if (!getForYouFeedPromise && Relay instanceof WorkerRelayInterface) {\n      getForYouFeedPromise = Relay.forYouFeed(login.publicKey)\n    }\n    getForYouFeedPromise?.then(notes => {\n      getForYouFeedPromise = null\n      if (notes.length < 10) {\n        setTimeout(() => {\n          if (Relay instanceof WorkerRelayInterface) {\n            getForYouFeedPromise = Relay.forYouFeed(login.publicKey!)\n          }\n        }, 1000)\n      }\n      forYouFeed = {\n        events: notes,\n        created_at: Date.now(),\n      }\n      setNotes(notes)\n    })\n  }, [login.publicKey])\n\n  useEffect(() => {\n    if (\n      forYouFeed.events.length < 10 ||\n      (navigationType !== \"POP\" && Date.now() - forYouFeed.created_at > 1000 * 60 * 2)\n    ) {\n      getFeed()\n    }\n  }, [navigationType, getFeed])\n\n  const combinedFeed = useMemo(() => {\n    const seen = new Set<string>()\n    const combined = []\n    let i = 0 // Index for `notes`\n    let j = 0 // Index for `latestFeed.main`\n    let count = 0 // Combined feed count to decide when to insert from `latestFeed`\n\n    while (i < notes.length || j < (filteredLatestFeed.length ?? 0)) {\n      // Insert approximately 1 event from `latestFeed` for every 4 events from `notes`\n      if (count % 5 === 0 && j < (filteredLatestFeed.length ?? 0)) {\n        const ev = filteredLatestFeed[j]\n        if (!seen.has(ev.id) && !ev.tags.some((a: string[]) => a[0] === \"e\")) {\n          seen.add(ev.id)\n          combined.push(ev)\n        }\n        j++\n      } else if (i < notes.length) {\n        // Add from `notes` otherwise\n        const ev = notes[i]\n        if (!seen.has(ev.id)) {\n          seen.add(ev.id)\n          combined.push(ev)\n        }\n        i++\n      }\n      count++\n    }\n    return combined\n  }, [notes, filteredLatestFeed])\n\n  const frags = useMemo(() => {\n    return [\n      {\n        events: combinedFeed as Array<TaggedNostrEvent>,\n        refTime: Date.now(),\n      },\n    ]\n  }, [combinedFeed])\n\n  return <TimelineRenderer frags={frags} latest={[]} loadMore={() => latestFeed.loadMore()} showLatest={() => {}} />\n})\n"
  },
  {
    "path": "packages/app/src/Pages/Root/Media.tsx",
    "content": "import { EventKind } from \"@snort/system\"\n\nimport TimelineFollows from \"@/Components/Feed/TimelineFollows\"\nimport { Day } from \"@/Utils/Const\"\n\nexport default function MediaPosts() {\n  return (\n    <div className=\"py-2\">\n      <TimelineFollows\n        id=\"media\"\n        postsOnly={true}\n        kinds={[EventKind.Photo, EventKind.Video, EventKind.ShortVideo]}\n        firstChunkSize={Day * 7}\n        windowSize={Day}\n      />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Root/NotesTab.tsx",
    "content": "import { type NostrEvent, NostrLink } from \"@snort/system\"\nimport { use, useMemo } from \"react\"\n\nimport TimelineFollows from \"@/Components/Feed/TimelineFollows\"\nimport { DeckContext } from \"@/Pages/Deck/DeckLayout\"\n\nexport const NotesTab = () => {\n  // eslint-disable-next-line @typescript-eslint/no-unused-vars\n  const deckContext = use(DeckContext)\n\n  const noteOnClick = useMemo(() => {\n    if (deckContext) {\n      return (ev: NostrEvent) => {\n        deckContext.setThread(NostrLink.fromEvent(ev))\n      }\n    }\n    return undefined\n  }, [deckContext])\n\n  return <TimelineFollows postsOnly={true} noteOnClick={noteOnClick} />\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Root/RelayFeedPage.tsx",
    "content": "import Timeline from \"@/Components/Feed/Timeline\"\nimport type { TimelineSubject } from \"@/Feed/TimelineFeed\"\nimport { sanitizeRelayUrl } from \"@snort/shared\"\nimport { useMemo } from \"react\"\nimport { useParams } from \"react-router-dom\"\n\nexport default function RelayFeedPage() {\n  const relayParam = useParams().relay as string | undefined\n  const relay = useMemo(() => {\n    if (relayParam) {\n      let u = relayParam\n      if (!u?.startsWith(\"ws\")) {\n        u = `wss://${u}`\n      }\n      return sanitizeRelayUrl(u)\n    }\n  }, [relayParam])\n\n  const subject = useMemo(\n    () =>\n      ({\n        type: \"global\",\n        discriminator: `relays:${relayParam}`,\n        relay: relay ? [relay] : undefined,\n      }) as TimelineSubject,\n    [relay, relayParam],\n  )\n\n  return <Timeline postsOnly={false} subject={subject} method={\"LIMIT_UNTIL\"} />\n}\n"
  },
  {
    "path": "packages/app/src/Pages/Root/RootRoutes.tsx",
    "content": "import { lazy } from \"react\"\nimport { Outlet, type RouteObject, useLocation } from \"react-router-dom\"\n\nimport { LiveStreams } from \"@/Components/LiveStream/LiveStreams\"\nimport { RootTabRoutes } from \"@/Pages/Root/RootTabRoutes\"\nimport { getCurrentRefCode } from \"@/Utils\"\n\nconst InviteModal = lazy(() => import(\"@/Components/Invite\"))\nexport default function RootPage() {\n  const code = getCurrentRefCode()\n  const location = useLocation()\n  return (\n    <>\n      {(location.pathname === \"/\" || location.pathname === \"/following\") && <LiveStreams />}\n      <Outlet />\n      {code && <InviteModal />}\n    </>\n  )\n}\nexport const RootRoutes = [\n  {\n    path: \"/\",\n    element: <RootPage />,\n    children: RootTabRoutes,\n  },\n] as RouteObject[]\n"
  },
  {
    "path": "packages/app/src/Pages/Root/RootTabRoutes.tsx",
    "content": "import type { RouteObject } from \"react-router-dom\"\n\nexport type RootTabRoutePath =\n  | \"\"\n  | \"for-you\"\n  | \"following\"\n  | \"followed-by-friends\"\n  | \"conversations\"\n  | \"discover\"\n  | \"tag/:tag\"\n  | \"trending/notes\"\n  | \"trending/hashtags\"\n  | \"suggested\"\n  | \"t/:tag\"\n  | \"topics\"\n  | \"media\"\n  | \"follow-sets\"\n  | \"relay\"\n\nexport type RootTabRoute = RouteObject\n\nexport const RootTabRoutes: RootTabRoute[] = [\n  {\n    index: true,\n    async lazy() {\n      const { DefaultTab } = await import(\"@/Pages/Root/DefaultTab\")\n      return { Component: DefaultTab }\n    },\n  },\n  {\n    path: \"for-you\",\n    async lazy() {\n      const { ForYouTab } = await import(\"@/Pages/Root/ForYouTab\")\n      return { Component: ForYouTab }\n    },\n  },\n  {\n    path: \"following\",\n    async lazy() {\n      const { NotesTab } = await import(\"@/Pages/Root/NotesTab\")\n      return { Component: NotesTab }\n    },\n  },\n  {\n    path: \"followed-by-friends\",\n    async lazy() {\n      const { FollowedByFriendsTab } = await import(\"@/Pages/Root/FollowedByFriendsTab\")\n      return { Component: FollowedByFriendsTab }\n    },\n  },\n  {\n    path: \"conversations\",\n    async lazy() {\n      const { ConversationsTab } = await import(\"@/Pages/Root/ConversationsTab\")\n      return { Component: ConversationsTab }\n    },\n  },\n  {\n    path: \"discover\",\n    async lazy() {\n      const { default: Discover } = await import(\"@/Pages/Discover\")\n      return { Component: Discover }\n    },\n  },\n  {\n    path: \"tag/:tag\",\n    async lazy() {\n      const { TagsTab } = await import(\"@/Pages/Root/TagsTab\")\n      return { Component: TagsTab }\n    },\n  },\n  {\n    path: \"trending/notes\",\n    async lazy() {\n      const { default: TrendingNotes } = await import(\"@/Components/Trending/TrendingPosts\")\n      return { Component: TrendingNotes }\n    },\n  },\n  {\n    path: \"trending/hashtags\",\n    async lazy() {\n      const { default: TrendingHashtags } = await import(\"@/Components/Trending/TrendingHashtags\")\n      const Wrapper = () => (\n        <div className=\"px-2\">\n          <TrendingHashtags />\n        </div>\n      )\n      return { Component: Wrapper }\n    },\n  },\n  {\n    path: \"t/:tag\",\n    async lazy() {\n      const { default: HashTagsPage } = await import(\"@/Pages/HashTagsPage\")\n      return { Component: HashTagsPage }\n    },\n  },\n  {\n    path: \"topics\",\n    async lazy() {\n      const { TopicsPage } = await import(\"@/Pages/TopicsPage\")\n      return { Component: TopicsPage }\n    },\n  },\n  {\n    path: \"media\",\n    async lazy() {\n      const { default: MediaPosts } = await import(\"@/Pages/Root/Media\")\n      return { Component: MediaPosts }\n    },\n  },\n  {\n    path: \"follow-sets\",\n    async lazy() {\n      const { default: FollowSetsPage } = await import(\"@/Pages/Root/FollowSets\")\n      return { Component: FollowSetsPage }\n    },\n  },\n  {\n    path: \"relay/:relay?\",\n    async lazy() {\n      const { default: RelayFeedPage } = await import(\"@/Pages/Root/RelayFeedPage\")\n      return { Component: RelayFeedPage }\n    },\n  },\n  {\n    path: \"suggested\",\n    async lazy() {\n      const { default: SuggestedProfiles } = await import(\"@/Components/SuggestedProfiles\")\n      return { Component: SuggestedProfiles }\n    },\n  },\n  {\n    path: \"agent\",\n    async lazy() {\n      const { default: AgentPage } = await import(\"@/Pages/Agent/AgentPage\")\n      return { Component: AgentPage }\n    },\n  },\n]\n"
  },
  {
    "path": "packages/app/src/Pages/Root/TagsTab.tsx",
    "content": "import { useMemo } from \"react\"\nimport { useParams } from \"react-router-dom\"\n\nimport Timeline from \"@/Components/Feed/Timeline\"\nimport type { TimelineSubject } from \"@/Feed/TimelineFeed\"\n\nexport const TagsTab = (params: { tag?: string }) => {\n  const { tag } = useParams()\n  const t = params.tag ?? tag ?? \"\"\n  const subject: TimelineSubject = useMemo(\n    () => ({\n      type: \"hashtag\",\n      items: [t],\n      discriminator: `tags-${t}`,\n      streams: true,\n    }),\n    [t],\n  )\n\n  return <Timeline subject={subject} postsOnly={false} method={\"TIME_RANGE\"} />\n}\n"
  },
  {
    "path": "packages/app/src/Pages/SearchPage.tsx",
    "content": "import { useMemo, useState } from \"react\"\nimport { useIntl } from \"react-intl\"\nimport { useNavigate, useParams } from \"react-router-dom\"\n\nimport Timeline from \"@/Components/Feed/Timeline\"\nimport TabSelectors, { type Tab } from \"@/Components/TabSelectors/TabSelectors\"\nimport FollowListBase from \"@/Components/User/FollowListBase\"\nimport type { TimelineSubject } from \"@/Feed/TimelineFeed\"\nimport useProfileSearch from \"@/Hooks/useProfileSearch\"\n\nconst NOTES = 0\nconst PROFILES = 1\n\nconst Profiles = ({ keyword }: { keyword: string }) => {\n  const searchFn = useProfileSearch()\n  const results = useMemo(() => searchFn(keyword), [keyword, searchFn])\n  const ids = useMemo(() => results.map(r => r.pubkey), [results])\n  if (!keyword) return\n  return (\n    <div className=\"px-3\">\n      <FollowListBase\n        pubkeys={ids}\n        profilePreviewProps={{\n          options: { about: true },\n        }}\n      />\n    </div>\n  )\n}\n\nconst SearchPage = () => {\n  const params = useParams()\n  const { formatMessage } = useIntl()\n  const [search, setSearch] = useState<string>(params.keyword ?? \"\")\n  // tabs\n  const SearchTab = [\n    { text: formatMessage({ defaultMessage: \"Notes\" }), value: NOTES },\n    { text: formatMessage({ defaultMessage: \"People\" }), value: PROFILES },\n  ]\n  const [tab, setTab] = useState<Tab>(SearchTab[0])\n  const navigate = useNavigate()\n\n  const subject = useMemo(() => {\n    return {\n      type: \"post_keyword\",\n      items: [search],\n      discriminator: search,\n    } as TimelineSubject\n  }, [search])\n\n  const content = useMemo(() => {\n    if (tab.value === PROFILES) {\n      return <Profiles keyword={params.keyword ?? \"\"} />\n    }\n\n    if (!params.keyword) {\n      return\n    }\n\n    return <Timeline key={params.keyword} subject={subject} postsOnly={false} method={\"LIMIT_UNTIL\"} />\n  }, [params.keyword, tab, subject])\n\n  return (\n    <div>\n      <div className=\"px-3 py-2 flex flex-col gap-2\">\n        <input\n          type=\"search\"\n          placeholder={formatMessage({ defaultMessage: \"Search...\" })}\n          value={search}\n          onChange={e => setSearch(e.target.value)}\n          onSubmit={() => navigate(`/search/${encodeURIComponent(search)}`)}\n          onKeyDown={k => {\n            if (k.key === \"Enter\") {\n              navigate(`/search/${encodeURIComponent(search)}`)\n            }\n          }}\n        />\n        <TabSelectors tabs={SearchTab} tab={tab} setTab={setTab} />\n      </div>\n      {content}\n    </div>\n  )\n}\n\nexport default SearchPage\n"
  },
  {
    "path": "packages/app/src/Pages/TopicsPage.tsx",
    "content": "import { unwrap } from \"@snort/shared\"\nimport { EventKind, NostrHashtagLink } from \"@snort/system\"\nimport { useMemo } from \"react\"\n\nimport Timeline from \"@/Components/Feed/Timeline\"\nimport type { TimelineSubject } from \"@/Feed/TimelineFeed\"\nimport useLogin from \"@/Hooks/useLogin\"\n\nexport function TopicsPage() {\n  const { tags, pubKey } = useLogin(s => ({\n    pubKey: s.publicKey,\n    tags: s.state.getList(EventKind.InterestSet),\n  }))\n  const subject = useMemo(\n    () =>\n      ({\n        type: \"hashtag\",\n        items: tags.filter(a => a instanceof NostrHashtagLink).map(a => unwrap(a.toEventTag())[1]),\n        discriminator: pubKey ?? \"\",\n      }) as TimelineSubject,\n    [tags, pubKey],\n  )\n\n  return <Timeline subject={subject} postsOnly={true} method=\"TIME_RANGE\" window={60 * 60 * 6} />\n}\n"
  },
  {
    "path": "packages/app/src/Pages/ZapPool/ZapPool.css",
    "content": ".zap-pool input[type=\"range\"] {\n  width: 200px;\n}\n\n.zap-pool h4 {\n  margin: 0;\n}\n"
  },
  {
    "path": "packages/app/src/Pages/ZapPool/ZapPool.tsx",
    "content": "import \"./ZapPool.css\"\n\nimport { ZapPoolPageInner } from \"@/Pages/ZapPool/ZapPoolPageInner\"\nimport { ZapPoolController } from \"@/Utils/ZapPoolController\"\n\nexport default function ZapPoolPage() {\n  if (!ZapPoolController) {\n    return null\n  }\n  return <ZapPoolPageInner />\n}\n"
  },
  {
    "path": "packages/app/src/Pages/ZapPool/ZapPoolPageInner.tsx",
    "content": "import { SnortContext } from \"@snort/system-react\"\nimport { use, useMemo, useSyncExternalStore } from \"react\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { ZapPoolTarget } from \"@/Pages/ZapPool/ZapPoolTarget\"\nimport { getRelayName, trackEvent, unwrap } from \"@/Utils\"\nimport { SnortPubKey } from \"@/Utils/Const\"\nimport { UploaderServices } from \"@/Utils/Upload\"\nimport { ZapPoolController, ZapPoolRecipientType } from \"@/Utils/ZapPoolController\"\nimport { useWallet } from \"@/Wallet\"\nimport { bech32ToHex } from \"@snort/shared\"\n\nconst DataProviders = [\n  {\n    name: \"nostr.band\",\n    owner: bech32ToHex(\"npub1sx9rnd03vs34lp39fvfv5krwlnxpl90f3dzuk8y3cuwutk2gdhdqjz6g8m\"),\n  },\n]\n\nexport function ZapPoolPageInner() {\n  const defaultZapAmount = usePreferences(s => s.defaultZapAmount)\n  const system = use(SnortContext)\n  const zapPool = useSyncExternalStore(\n    c => unwrap(ZapPoolController).hook(c),\n    () => unwrap(ZapPoolController).snapshot(),\n  )\n  const { wallet } = useWallet()\n\n  const relayConnections = useMemo(() => {\n    return [...system.pool]\n      .map(([, a]) => {\n        if (a.info?.pubkey && !a.ephemeral) {\n          return {\n            address: a.address,\n            pubkey: a.info.pubkey,\n          }\n        }\n      })\n      .filter(a => a !== undefined)\n      .map(unwrap)\n  }, [system.pool])\n\n  const sumPending = zapPool.reduce((acc, v) => acc + v.sum, 0)\n  return (\n    <div className=\"zap-pool px-3 py-2\">\n      <h1>\n        <FormattedMessage defaultMessage=\"Zap Pool\" />\n      </h1>\n      <p>\n        <FormattedMessage\n          defaultMessage=\"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n          id=\"x/Fx2P\"\n        />\n      </p>\n      <p>\n        <FormattedMessage\n          defaultMessage=\"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n          id=\"QWhotP\"\n        />\n      </p>\n      <p>\n        <FormattedMessage\n          defaultMessage=\"Your default zap amount is {number} sats, example values are calculated from this.\"\n          id=\"Xopqkl\"\n          values={{\n            number: (\n              <b>\n                <FormattedNumber value={defaultZapAmount} />\n              </b>\n            ),\n          }}\n        />\n      </p>\n      <p>\n        <FormattedMessage\n          defaultMessage=\"A single zap of {nIn} sats will allocate {nOut} sats to the zap pool.\"\n          id=\"eSzf2G\"\n          values={{\n            nIn: (\n              <b>\n                <FormattedNumber value={defaultZapAmount} />\n              </b>\n            ),\n            nOut: (\n              <b>\n                <FormattedNumber value={ZapPoolController?.calcAllocation(defaultZapAmount) ?? 0} />\n              </b>\n            ),\n          }}\n        />\n      </p>\n      <p>\n        <FormattedMessage\n          defaultMessage=\"You currently have {number} sats in your zap pool.\"\n          id=\"Qxv0B2\"\n          values={{\n            number: (\n              <b>\n                <FormattedNumber value={sumPending} />\n              </b>\n            ),\n          }}\n        />\n      </p>\n      <p>\n        {wallet && (\n          <AsyncButton\n            onClick={async () => {\n              trackEvent(\"ZapPool\", { manual: true })\n              await ZapPoolController?.payout(wallet)\n            }}\n          >\n            <FormattedMessage defaultMessage=\"Payout Now\" />\n          </AsyncButton>\n        )}\n      </p>\n      <div>\n        <ZapPoolTarget\n          target={\n            zapPool.find(b => b.pubkey === bech32ToHex(SnortPubKey) && b.type === ZapPoolRecipientType.Generic) ?? {\n              type: ZapPoolRecipientType.Generic,\n              pubkey: bech32ToHex(SnortPubKey),\n              split: 0,\n              sum: 0,\n            }\n          }\n        />\n      </div>\n      <h3>\n        <FormattedMessage defaultMessage=\"Relays\" />\n      </h3>\n      {relayConnections.map(a => (\n        <div key={a.address}>\n          <h4>{getRelayName(a.address)}</h4>\n          <ZapPoolTarget\n            target={\n              zapPool.find(b => b.pubkey === a.pubkey && b.type === ZapPoolRecipientType.Relay) ?? {\n                type: ZapPoolRecipientType.Relay,\n                pubkey: a.pubkey,\n                split: 0,\n                sum: 0,\n              }\n            }\n          />\n        </div>\n      ))}\n      <h3>\n        <FormattedMessage defaultMessage=\"File hosts\" />\n      </h3>\n      {UploaderServices.map(a => (\n        <div key={a.name}>\n          <h4>{a.name}</h4>\n          <ZapPoolTarget\n            target={\n              zapPool.find(b => b.pubkey === a.owner && b.type === ZapPoolRecipientType.FileHost) ?? {\n                type: ZapPoolRecipientType.FileHost,\n                pubkey: a.owner,\n                split: 0,\n                sum: 0,\n              }\n            }\n          />\n        </div>\n      ))}\n      <h3>\n        <FormattedMessage defaultMessage=\"Data Providers\" />\n      </h3>\n      {DataProviders.map(a => (\n        <div key={a.name}>\n          <h4>{a.name}</h4>\n          <ZapPoolTarget\n            target={\n              zapPool.find(b => b.pubkey === a.owner && b.type === ZapPoolRecipientType.DataProvider) ?? {\n                type: ZapPoolRecipientType.DataProvider,\n                pubkey: a.owner,\n                split: 0,\n                sum: 0,\n              }\n            }\n          />\n        </div>\n      ))}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/ZapPool/ZapPoolTarget.tsx",
    "content": "import { useUserProfile } from \"@snort/system-react\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\n\nimport ProfilePreview from \"@/Components/User/ProfilePreview\"\nimport usePreferences from \"@/Hooks/usePreferences\"\nimport { ZapPoolController, type ZapPoolRecipient } from \"@/Utils/ZapPoolController\"\n\nfunction ZapPoolTargetInner({ target }: { target: ZapPoolRecipient }) {\n  const profile = useUserProfile(target.pubkey)\n  const hasAddress = profile?.lud16 || profile?.lud06\n  const defaultZapMount = usePreferences(s => s.defaultZapAmount * (target.split / 100))\n  return (\n    <ProfilePreview\n      pubkey={target.pubkey}\n      actions={\n        hasAddress ? (\n          <div>\n            <div>\n              <FormattedNumber value={target.split} />% (\n              <FormattedMessage defaultMessage=\"{n} sats\" values={{ n: defaultZapMount }} />)\n            </div>\n            <input\n              type=\"range\"\n              min={0}\n              max={100}\n              step={0.5}\n              value={target.split}\n              onChange={e =>\n                ZapPoolController?.set({\n                  ...target,\n                  split: e.target.valueAsNumber,\n                })\n              }\n            />\n          </div>\n        ) : (\n          <FormattedMessage defaultMessage=\"No lightning address\" />\n        )\n      }\n    />\n  )\n}\n\nexport function ZapPoolTarget({ target }: { target: ZapPoolRecipient }) {\n  if (!ZapPoolController) {\n    return null\n  }\n  return <ZapPoolTargetInner target={target} />\n}\n"
  },
  {
    "path": "packages/app/src/Pages/messages.ts",
    "content": "import { defineMessages } from \"react-intl\"\n\nexport default defineMessages({\n  Login: { defaultMessage: \"Login\", id: \"AyGauy\" },\n  Global: { defaultMessage: \"Global\", id: \"EWyQH5\" },\n  NewUsers: { defaultMessage: \"New users page\", id: \"NndBJE\" },\n  Reactions: { defaultMessage: \"Reactions\", id: \"XgWvGA\" },\n  Followers: { defaultMessage: \"Followers\", id: \"pzTOmv\" },\n  FollowersCount: { defaultMessage: \"{n} Followers\", id: \"3tVy+Z\" },\n  Follows: { defaultMessage: \"Following\", id: \"cPIKU2\" },\n  FollowsCount: { defaultMessage: \"{n} Following\", id: \"1nYUGC\" },\n  Zaps: { defaultMessage: \"Zaps\", id: \"OEW7yJ\" },\n  ZapsCount: { defaultMessage: \"{n} Zaps\", id: \"FDguSC\" },\n  Muted: { defaultMessage: \"Muted\", id: \"HOzFdo\" },\n  MutedCount: { defaultMessage: \"{n} Muted\", id: \"CmZ9ls\" },\n  Blocked: { defaultMessage: \"Blocked\", id: \"qUJTsT\" },\n  BlockedCount: { defaultMessage: \"{n} Blocked\", id: \"W2PiAr\" },\n  Sats: { defaultMessage: \"{n} {n, plural, =1 {sat} other {sats}}\", id: \"jA3OE/\" },\n  Following: { defaultMessage: \"Following {n}\", id: \"lnaT9F\" },\n  Settings: { defaultMessage: \"Settings\", id: \"D3idYv\" },\n  Messages: { defaultMessage: \"Messages\", id: \"hMzcSq\" },\n  MarkAllRead: { defaultMessage: \"Mark All Read\", id: \"e7qqly\" },\n  GetVerified: { defaultMessage: \"Get Verified\", id: \"eJj8HD\" },\n  Nip05: {\n    defaultMessage: `NIP-05 is a DNS based verification spec which helps to validate you as a real user.`,\n    id: \"vZ4quW\",\n  },\n  Nip05Pros: { defaultMessage: `Getting NIP-05 verified can help:`, id: \"thnRpU\" },\n  AvoidImpersonators: { defaultMessage: \"Prevent fake accounts from imitating you\", id: \"iGT1eE\" },\n  EasierToFind: { defaultMessage: \"Make your profile easier to find and share\", id: \"/d6vEc\" },\n  Funding: { defaultMessage: \"Fund developers and platforms providing NIP-05 verification services\", id: \"a5UPxh\" },\n  NostrPlebsNip: {\n    defaultMessage: `Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices`,\n    id: \"4Vmpt4\",\n  },\n  Relays: {\n    defaultMessage: \"Relays\",\n    id: \"RoOyAh\",\n  },\n  RelaysCount: {\n    defaultMessage: \"{n} Relays\",\n    id: \"QDFTjG\",\n  },\n  Bookmarks: { defaultMessage: \"Bookmarks\", id: \"nGBrvw\" },\n  BookmarksCount: { defaultMessage: \"{n} Bookmarks\", id: \"2a2YiP\" },\n  KeyPlaceholder: { defaultMessage: \"nsec, npub, nip-05, hex\", id: \"B6H7eJ\" },\n})\n"
  },
  {
    "path": "packages/app/src/Pages/onboarding/discover.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\nimport { useLocation, useNavigate } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport TrendingUsers from \"@/Components/Trending/TrendingUsers\"\n\nimport type { NewUserState } from \".\"\n\nexport default function Discover() {\n  const location = useLocation()\n  const navigate = useNavigate()\n  const state = location.state as NewUserState\n\n  return (\n    <div className=\"flex flex-col gap-6\">\n      <h1 className=\"text-center\">\n        <FormattedMessage\n          defaultMessage=\"{site} is more fun together!\"\n          values={{\n            site: CONFIG.appNameCapitalized,\n          }}\n        />\n      </h1>\n      <div className=\"new-trending\">\n        <TrendingUsers\n          count={10}\n          title={\n            <h3>\n              <FormattedMessage defaultMessage=\"Trending Users\" />\n            </h3>\n          }\n        />\n      </div>\n      <AsyncButton\n        className=\"primary\"\n        onClick={() =>\n          navigate(\"/login/sign-up/moderation\", {\n            state,\n          })\n        }\n      >\n        <FormattedMessage defaultMessage=\"Next\" />\n      </AsyncButton>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/onboarding/fixedModeration.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nexport const FixedModeration = {\n  /*hateSpeech: {\n    title: <FormattedMessage defaultMessage=\"Hate Speech\" />,\n    words: [],\n    canEdit: false,\n  },\n  derogatory: {\n    title: <FormattedMessage defaultMessage=\"Derogatory\" />,\n    words: [],\n    canEdit: false,\n  },*/\n  nsfw: {\n    title: <FormattedMessage defaultMessage=\"NSFW\" />,\n    words: [\n      \"adult content\",\n      \"explicit\",\n      \"mature audiences\",\n      \"18+\",\n      \"sensitive content\",\n      \"graphic content\",\n      \"age-restricted\",\n      \"explicit material\",\n      \"adult material\",\n      \"nsfw\",\n      \"explicit images\",\n      \"adult film\",\n      \"adult video\",\n      \"mature themes\",\n      \"sexual content\",\n      \"graphic violence\",\n      \"strong language\",\n      \"explicit language\",\n      \"adult-only\",\n      \"mature language\",\n      \"sex\",\n    ],\n    canEdit: false,\n  },\n  crypto: {\n    title: <FormattedMessage defaultMessage=\"Crypto\" />,\n    words: [\n      \"bitcoin\",\n      \"btc\",\n      \"satoshi\",\n      \"crypto\",\n      \"blockchain\",\n      \"mining\",\n      \"wallet\",\n      \"exchange\",\n      \"halving\",\n      \"hash rate\",\n      \"ledger\",\n      \"crypto trading\",\n      \"digital currency\",\n      \"virtual currency\",\n      \"cryptocurrency investment\",\n      \"altcoin\",\n      \"decentralized finance\",\n      \"defi\",\n      \"token\",\n      \"ico\",\n      \"crypto wallet\",\n      \"satoshi nakamoto\",\n    ],\n    canEdit: false,\n  },\n  politics: {\n    title: <FormattedMessage defaultMessage=\"Politics\" />,\n    words: [\n      \"politics\",\n      \"election\",\n      \"democrat\",\n      \"republican\",\n      \"senate\",\n      \"congress\",\n      \"parliament\",\n      \"president\",\n      \"prime minister\",\n      \"policy\",\n      \"legislation\",\n      \"vote\",\n      \"campaign\",\n      \"government\",\n      \"political party\",\n      \"lobbying\",\n      \"referendum\",\n      \"bill\",\n      \"conservative\",\n      \"liberal\",\n      \"left-wing\",\n      \"right-wing\",\n      \"socialist\",\n      \"capitalist\",\n      \"diplomacy\",\n      \"sanction\",\n      \"geopolitics\",\n      \"activism\",\n      \"protest\",\n      \"rally\",\n    ],\n    canEdit: false,\n  },\n}\n"
  },
  {
    "path": "packages/app/src/Pages/onboarding/fixedTopics.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nexport const FixedTopics = {\n  life: {\n    text: <FormattedMessage defaultMessage=\"Life\" />,\n    tags: [\n      \"life\",\n      \"lifestyle\",\n      \"dailyinspiration\",\n      \"motivation\",\n      \"lifelessons\",\n      \"personaldevelopment\",\n      \"happiness\",\n      \"wellbeing\",\n      \"mindfulness\",\n      \"selfcare\",\n      \"positivity\",\n      \"growth\",\n      \"inspiration\",\n      \"lifegoals\",\n      \"mindset\",\n      \"joy\",\n      \"balance\",\n      \"fulfillment\",\n      \"purpose\",\n      \"living\",\n      \"lifetips\",\n      \"lifehacks\",\n      \"wellness\",\n      \"lifejourney\",\n      \"enjoylife\",\n      \"simplepleasures\",\n      \"gratitude\",\n      \"lifeadvice\",\n      \"lifecoaching\",\n      \"lifelove\",\n    ],\n  },\n  science: {\n    text: <FormattedMessage defaultMessage=\"Science\" />,\n    tags: [\n      \"science\",\n      \"research\",\n      \"innovation\",\n      \"technology\",\n      \"biology\",\n      \"physics\",\n      \"chemistry\",\n      \"astronomy\",\n      \"environment\",\n      \"ecology\",\n      \"geology\",\n      \"neuroscience\",\n      \"genetics\",\n      \"data\",\n      \"experiment\",\n      \"theory\",\n      \"discovery\",\n      \"engineering\",\n      \"mathematics\",\n      \"robotics\",\n      \"artificialintelligence\",\n      \"climate\",\n      \"space\",\n      \"quantum\",\n      \"microbiology\",\n      \"biotechnology\",\n      \"nanotechnology\",\n      \"pharmacology\",\n      \"astrophysics\",\n      \"scientificmethod\",\n    ],\n  },\n  nature: {\n    text: <FormattedMessage defaultMessage=\"Nature\" />,\n    tags: [\n      \"nature\",\n      \"wildlife\",\n      \"forest\",\n      \"mountains\",\n      \"rivers\",\n      \"oceans\",\n      \"flora\",\n      \"fauna\",\n      \"ecosystem\",\n      \"biodiversity\",\n      \"conservation\",\n      \"habitat\",\n      \"landscape\",\n      \"outdoors\",\n      \"environment\",\n      \"geography\",\n      \"earth\",\n      \"climate\",\n      \"naturalbeauty\",\n      \"wilderness\",\n      \"green\",\n      \"sustainability\",\n      \"wildlifeconservation\",\n      \"nationalpark\",\n      \"gardening\",\n      \"hiking\",\n      \"birdwatching\",\n      \"ecotourism\",\n      \"photography\",\n      \"naturelovers\",\n    ],\n  },\n  business: {\n    text: <FormattedMessage defaultMessage=\"Business\" />,\n    tags: [\n      \"business\",\n      \"entrepreneurship\",\n      \"marketing\",\n      \"finance\",\n      \"innovation\",\n      \"management\",\n      \"startup\",\n      \"leadership\",\n      \"economics\",\n      \"strategy\",\n      \"branding\",\n      \"sales\",\n      \"technology\",\n      \"investment\",\n      \"networking\",\n      \"growth\",\n      \"corporate\",\n      \"customer\",\n      \"market\",\n      \"productivity\",\n      \"advertising\",\n      \"ecommerce\",\n      \"analytics\",\n      \"humanresources\",\n      \"globalbusiness\",\n      \"digitalmarketing\",\n      \"socialmedia\",\n      \"sustainability\",\n      \"entrepreneur\",\n      \"businessdevelopment\",\n    ],\n  },\n  game: {\n    text: <FormattedMessage defaultMessage=\"Game\" />,\n    tags: [\n      \"gaming\",\n      \"videogames\",\n      \"esports\",\n      \"multiplayer\",\n      \"onlinegaming\",\n      \"gameplay\",\n      \"streaming\",\n      \"gamer\",\n      \"console\",\n      \"pcgaming\",\n      \"mobilegaming\",\n      \"gamedevelopment\",\n      \"virtualreality\",\n      \"roleplaying\",\n      \"strategygames\",\n      \"actiongames\",\n      \"simulation\",\n      \"indiegames\",\n      \"adventuregames\",\n      \"puzzle\",\n      \"fantasy\",\n      \"scifi\",\n      \"horror\",\n      \"sports\",\n      \"racing\",\n      \"fighting\",\n      \"platformer\",\n      \"mmorpg\",\n      \"retrogaming\",\n      \"arcade\",\n    ],\n  },\n  sport: {\n    text: <FormattedMessage defaultMessage=\"Sport\" />,\n    tags: [\n      \"sports\",\n      \"athletics\",\n      \"soccer\",\n      \"basketball\",\n      \"baseball\",\n      \"football\",\n      \"tennis\",\n      \"golf\",\n      \"swimming\",\n      \"running\",\n      \"cycling\",\n      \"volleyball\",\n      \"hockey\",\n      \"skiing\",\n      \"boxing\",\n      \"martialarts\",\n      \"gymnastics\",\n      \"cricket\",\n      \"rugby\",\n      \"tabletennis\",\n      \"badminton\",\n      \"fishing\",\n      \"archery\",\n      \"bowling\",\n      \"surfing\",\n      \"skateboarding\",\n      \"motorsports\",\n      \"equestrian\",\n      \"fitness\",\n      \"yoga\",\n    ],\n  },\n  photography: {\n    text: <FormattedMessage defaultMessage=\"Photography\" />,\n    tags: [\n      \"photography\",\n      \"landscape\",\n      \"portrait\",\n      \"naturephotography\",\n      \"streetphotography\",\n      \"blackandwhite\",\n      \"travelphotography\",\n      \"macro\",\n      \"wildlifephotography\",\n      \"urbanphotography\",\n      \"nightphotography\",\n      \"fashionphotography\",\n      \"fineartphotography\",\n      \"documentary\",\n      \"sportsphotography\",\n      \"foodphotography\",\n      \"architecturalphotography\",\n      \"candid\",\n      \"aerialphotography\",\n      \"underwaterphotography\",\n      \"filmphotography\",\n      \"digitalphotography\",\n      \"photographytips\",\n      \"photoediting\",\n      \"photographygear\",\n      \"lighting\",\n      \"composition\",\n      \"exposure\",\n      \"photographyworkshop\",\n      \"photographyart\",\n    ],\n  },\n}\n"
  },
  {
    "path": "packages/app/src/Pages/onboarding/index.tsx",
    "content": "import { Outlet } from \"react-router-dom\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport { AllLanguageCodes } from \"@/Components/IntlProvider/IntlProviderUtils\"\nimport { useLocale } from \"@/Components/IntlProvider/useLocale\"\n\nimport Discover from \"./discover\"\nimport Moderation from \"./moderation\"\nimport Profile from \"./profile\"\nimport SignIn from \"./sign-in\"\nimport SignUp from \"./sign-up\"\nimport Topics from \"./topics\"\n\nexport { Discover, Moderation, Profile, SignIn, SignUp, Topics }\n\nexport interface NewUserState {\n  name?: string\n  picture?: string\n  topics?: Array<string>\n  muteLists?: Array<string>\n}\n\nexport function OnboardingLayout() {\n  const { lang, setOverride } = useLocale()\n\n  return (\n    <div className=\"p-6\">\n      <div className=\"float-right flex gap-2 items-center\">\n        <Icon name=\"translate\" />\n        <select value={lang} onChange={e => setOverride(e.target.value)} className=\"capitalize\">\n          {AllLanguageCodes.sort().map(a => (\n            <option key={a} value={a}>\n              {new Intl.DisplayNames([a], {\n                type: \"language\",\n              }).of(a)}\n            </option>\n          ))}\n        </select>\n      </div>\n      <div className=\"w-[460px] max-w-full mx-auto my-auto mt-[15vh] rounded-lg px-8 py-7 layer-1\">\n        <Outlet />\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/onboarding/moderation.tsx",
    "content": "import { useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport { ToggleSwitch } from \"@/Components/Icons/Toggle\"\nimport useModeration from \"@/Hooks/useModeration\"\nimport { FixedModeration } from \"@/Pages/onboarding/fixedModeration\"\nimport { appendDedupe } from \"@/Utils\"\n\nexport default function Moderation() {\n  const [topics, setTopics] = useState<Array<string>>(Object.keys(FixedModeration))\n  const [extraTerms, setExtraTerms] = useState(\"\")\n  const navigate = useNavigate()\n  const { addMutedWord } = useModeration()\n\n  return (\n    <div className=\"flex flex-col gap-6\">\n      <div className=\"flex flex-col gap-2 text-center\">\n        <h1>\n          <FormattedMessage defaultMessage=\"Clean up your feed\" />\n        </h1>\n        <FormattedMessage defaultMessage=\"Your space the way you want it 😌\" />\n      </div>\n      <div className=\"flex flex-col gap-2\">\n        <div className=\"flex gap-2 items-center\">\n          <small className=\"grow uppercase\">\n            <FormattedMessage defaultMessage=\"Lists to mute:\" />\n          </small>\n          <span className=\"font-medium\">\n            <FormattedMessage defaultMessage=\"Toggle all\" />\n          </span>\n          <ToggleSwitch\n            size={50}\n            onClick={() =>\n              topics.length === Object.keys(FixedModeration).length\n                ? setTopics([])\n                : setTopics(Object.keys(FixedModeration))\n            }\n            className={topics.length === Object.keys(FixedModeration).length ? \"active\" : \"\"}\n          />\n        </div>\n        {Object.entries(FixedModeration).map(([k, v]) => (\n          <div className=\"flex gap-2 items-center bb\" key={k}>\n            <div className=\"font-semibold grow\">{v.title}</div>\n            {v.canEdit && (\n              <div>\n                <FormattedMessage defaultMessage=\"edit\" />\n              </div>\n            )}\n            <ToggleSwitch\n              size={50}\n              className={topics.includes(k) ? \"active\" : \"\"}\n              onClick={() => setTopics(s => (topics.includes(k) ? s.filter(a => a !== k) : appendDedupe(s, [k])))}\n            />\n          </div>\n        ))}\n      </div>\n      <div className=\"flex flex-col gap-2\">\n        <span className=\"font-semibold\">\n          <FormattedMessage defaultMessage=\"Additional Terms:\" />\n        </span>\n        <small>\n          <FormattedMessage defaultMessage=\"Use commas to separate words e.g. word1, word2, word3\" />\n        </small>\n        <textarea onChange={e => setExtraTerms(e.target.value)} value={extraTerms}></textarea>\n      </div>\n      <AsyncButton\n        className=\"primary\"\n        onClick={async () => {\n          const words = Object.entries(FixedModeration)\n            .filter(([k]) => topics.includes(k))\n            .flatMap(([, v]) => v.words)\n            .concat(\n              extraTerms\n                .split(\",\")\n                .map(a => a.trim())\n                .filter(a => a.length > 1),\n            )\n          if (words.length > 0) {\n            await addMutedWord(words)\n          }\n          navigate(\"/\")\n        }}\n      >\n        <FormattedMessage defaultMessage=\"Finish\" />\n      </AsyncButton>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/onboarding/profile.tsx",
    "content": "import { NotEncrypted } from \"@snort/system\"\nimport { SnortContext } from \"@snort/system-react\"\nimport { use, useEffect, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useLocation, useNavigate } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport AvatarEditor from \"@/Components/User/AvatarEditor\"\nimport { trackEvent } from \"@/Utils\"\nimport { generateNewLogin, generateNewLoginKeys } from \"@/Utils/Login\"\n\nimport type { NewUserState } from \".\"\n\nexport default function Profile() {\n  const system = use(SnortContext)\n  const [keys, setNewKeys] = useState<{ entropy: Uint8Array; privateKey: string }>()\n  const [picture, setPicture] = useState<string>()\n  const [error, setError] = useState(\"\")\n  const navigate = useNavigate()\n  const location = useLocation()\n  const state = location.state as NewUserState\n\n  useEffect(() => {\n    generateNewLoginKeys().then(setNewKeys)\n  }, [])\n\n  async function loginNewKeys() {\n    try {\n      if (!keys) return\n      setError(\"\")\n      await generateNewLogin(keys, system, key => Promise.resolve(new NotEncrypted(key)), {\n        name: state.name,\n        picture,\n      })\n      trackEvent(\"Login\", { newAccount: true })\n      navigate(\"/login/sign-up/topics\")\n    } catch (e) {\n      if (e instanceof Error) {\n        setError(e.message)\n      }\n    }\n  }\n\n  return (\n    <div className=\"flex flex-col gap-6 text-center\">\n      <h1>\n        <FormattedMessage defaultMessage=\"Profile Image\" />\n      </h1>\n      <AvatarEditor picture={picture} onPictureChange={p => setPicture(p)} privKey={keys?.privateKey} />\n      <AsyncButton className=\"primary\" onClick={() => loginNewKeys()}>\n        <FormattedMessage defaultMessage=\"Next\" />\n      </AsyncButton>\n      {error && <b className=\"error\">{error}</b>}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/onboarding/routes.ts",
    "content": "export const OnboardingRoutes = {\n  path: \"/login\",\n  async lazy() {\n    const { OnboardingLayout } = await import(\".\")\n    return { Component: OnboardingLayout }\n  },\n  children: [\n    {\n      index: true,\n      async lazy() {\n        const { SignIn } = await import(\".\")\n        return { Component: SignIn }\n      },\n    },\n    {\n      path: \"sign-up\",\n      async lazy() {\n        const { SignUp } = await import(\".\")\n        return { Component: SignUp }\n      },\n    },\n    {\n      path: \"sign-up/profile\",\n      async lazy() {\n        const { Profile } = await import(\".\")\n        return { Component: Profile }\n      },\n    },\n    {\n      path: \"sign-up/topics\",\n      async lazy() {\n        const { Topics } = await import(\".\")\n        return { Component: Topics }\n      },\n    },\n    {\n      path: \"sign-up/discover\",\n      async lazy() {\n        const { Discover } = await import(\".\")\n        return { Component: Discover }\n      },\n    },\n    {\n      path: \"sign-up/moderation\",\n      async lazy() {\n        const { Moderation } = await import(\".\")\n        return { Component: Moderation }\n      },\n    },\n  ],\n}\n"
  },
  {
    "path": "packages/app/src/Pages/onboarding/sign-in.tsx",
    "content": "import { Nip46Signer, Nip7Signer, NotEncrypted, PrivateKeySigner } from \"@snort/system\"\nimport classNames from \"classnames\"\nimport { useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport { Link, useNavigate } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport useLoginHandler from \"@/Hooks/useLoginHandler\"\nimport { trackEvent } from \"@/Utils\"\nimport { LoginSessionType, LoginStore } from \"@/Utils/Login\"\n\nimport { Bech32Regex, unwrap } from \"@snort/shared\"\n\nconst isAndroid = /Android/i.test(navigator.userAgent)\n\nconst NIP46_PERMS =\n  \"nip04_encrypt,nip04_decrypt,sign_event:0,sign_event:1,sign_event:3,sign_event:4,sign_event:6,sign_event:7,sign_event:30078\"\n\nexport default function SignIn() {\n  const navigate = useNavigate()\n  const { formatMessage } = useIntl()\n  const [key, setKey] = useState(\"\")\n  const [error, setError] = useState(\"\")\n  const [useKey, setUseKey] = useState(false)\n  const loginHandler = useLoginHandler()\n\n  const hasNip7 = \"nostr\" in window\n  const hasNip46 = isAndroid\n\n  async function doNip07Login() {\n    setError(\"\")\n    try {\n      const signer = new Nip7Signer()\n      const pubKey = await signer.getPubKey()\n      LoginStore.loginWithPubkey(pubKey, LoginSessionType.Nip7)\n      trackEvent(\"Login\", { type: \"NIP7\" })\n      navigate(\"/\")\n    } catch (e) {\n      setError(e instanceof Error ? e.message : formatMessage({ defaultMessage: \"Unknown login error\", id: \"OLEm6z\" }))\n    }\n  }\n\n  async function doNip46Login() {\n    setError(\"\")\n    try {\n      const clientSigner = PrivateKeySigner.random()\n      const clientPubkey = await clientSigner.getPubKey()\n      const secret = crypto.randomUUID().replace(/-/g, \"\")\n      const relay = Object.keys(CONFIG.defaultRelays)[0]\n      const connectUrl = `nostrconnect://${clientPubkey}?relay=${encodeURIComponent(relay)}&secret=${secret}&perms=${NIP46_PERMS}`\n\n      const nip46 = new Nip46Signer(connectUrl, clientSigner)\n\n      const onVisible = () => {\n        if (document.visibilityState === \"visible\") {\n          globalThis.location.href = connectUrl\n        }\n      }\n      document.addEventListener(\"visibilitychange\", onVisible)\n\n      const relayReady = new Promise<void>(resolve => {\n        nip46.once(\"ready\", () => resolve())\n      })\n      const initPromise = nip46.init()\n\n      await relayReady\n      globalThis.location.href = connectUrl\n\n      await initPromise\n      document.removeEventListener(\"visibilitychange\", onVisible)\n\n      const loginPubkey = await nip46.getPubKey()\n      LoginStore.loginWithPubkey(\n        loginPubkey,\n        LoginSessionType.Nip46,\n        undefined,\n        nip46.relays,\n        new NotEncrypted(unwrap(nip46.privateKey)),\n      )\n      nip46.close()\n      trackEvent(\"Login\", { type: \"NIP46\" })\n      navigate(\"/\")\n    } catch (e) {\n      setError(e instanceof Error ? e.message : formatMessage({ defaultMessage: \"Unknown login error\", id: \"OLEm6z\" }))\n    }\n  }\n\n  async function onSubmit(e: Event) {\n    e.preventDefault()\n    doLogin(key)\n  }\n\n  async function doLogin(key: string) {\n    setError(\"\")\n    try {\n      await loginHandler.doLogin(key, key => Promise.resolve(new NotEncrypted(key)))\n      trackEvent(\"Login\", { type: \"Key\" })\n      navigate(\"/\")\n    } catch (e) {\n      if (e instanceof Error) {\n        setError(e.message)\n      } else {\n        setError(\n          formatMessage({\n            defaultMessage: \"Unknown login error\",\n            id: \"OLEm6z\",\n          }),\n        )\n      }\n      console.error(e)\n    }\n  }\n\n  const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const val = e.target.value\n    if (val.match(Bech32Regex)) {\n      doLogin(val)\n    } else {\n      setKey(val)\n    }\n  }\n\n  const signerExtLogin = (hasNip7 || hasNip46) && !useKey\n  return (\n    <div className=\"flex flex-col gap-6\">\n      <img src={CONFIG.icon} width={48} height={48} className=\"rounded-lg mr-auto ml-auto\" alt=\"\" />\n      <div className=\"flex flex-col gap-4 items-center\">\n        <h1>\n          <FormattedMessage defaultMessage=\"Sign In\" />\n        </h1>\n        {signerExtLogin && <FormattedMessage defaultMessage=\"Use a nostr signer extension to sign in\" />}\n      </div>\n      {error && <b className=\"text-error\">{error}</b>}\n      <div className={classNames(\"flex flex-col gap-4\", { \"items-center\": signerExtLogin })}>\n        {signerExtLogin && (\n          <>\n            {hasNip7 && (\n              <AsyncButton onClick={doNip07Login}>\n                <div className=\"rounded-full bg-warning p-3 text-white\">\n                  <Icon name=\"key\" />\n                </div>\n                <FormattedMessage defaultMessage=\"Sign in with Nostr Extension\" />\n              </AsyncButton>\n            )}\n            {hasNip46 && (\n              <AsyncButton onClick={doNip46Login}>\n                <div className=\"rounded-full bg-warning p-3 text-white\">\n                  <Icon name=\"key\" />\n                </div>\n                <FormattedMessage defaultMessage=\"Sign in with Nostr Connect\" />\n              </AsyncButton>\n            )}\n            <Link to=\"\" className=\"highlight\">\n              <FormattedMessage defaultMessage=\"Supported Extensions\" />\n            </Link>\n            <AsyncButton onClick={() => setUseKey(true)}>\n              <FormattedMessage defaultMessage=\"Sign in with key\" />\n            </AsyncButton>\n          </>\n        )}\n        {(!signerExtLogin || useKey) && (\n          <form onSubmit={onSubmit} className=\"flex flex-col gap-4\">\n            <input\n              type=\"text\"\n              placeholder={formatMessage({\n                defaultMessage: \"nsec, npub, nip-05, hex, mnemonic\",\n              })}\n              value={key}\n              onChange={onChange}\n              className=\"new-username\"\n            />\n            <div className=\"flex justify-center\">\n              <AsyncButton onClick={onSubmit} className=\"primary\">\n                <FormattedMessage defaultMessage=\"Login\" />\n              </AsyncButton>\n            </div>\n          </form>\n        )}\n      </div>\n      <div className=\"flex flex-col gap-4 items-center\">\n        <Link to={\"/login/sign-up\"}>\n          <FormattedMessage defaultMessage=\"Don't have an account?\" />\n        </Link>\n        <AsyncButton className=\"secondary\" onClick={() => navigate(\"/login/sign-up\")}>\n          <FormattedMessage defaultMessage=\"Sign Up\" />\n        </AsyncButton>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/onboarding/sign-up.tsx",
    "content": "import AsyncButton from \"@/Components/Button/AsyncButton\"\nimport { trackEvent } from \"@/Utils\"\nimport { generateNewLogin, generateNewLoginKeys } from \"@/Utils/Login\"\nimport { NotEncrypted } from \"@snort/system\"\nimport { SnortContext } from \"@snort/system-react\"\nimport { useState, use, type FormEvent } from \"react\"\nimport { useIntl, FormattedMessage } from \"react-intl\"\nimport { useNavigate, Link } from \"react-router-dom\"\nimport type { NewUserState } from \".\"\nimport { Bech32Regex } from \"@snort/shared\"\n\nexport default function SignUp() {\n  const { formatMessage } = useIntl()\n  const navigate = useNavigate()\n  const [name, setName] = useState(\"\")\n  const system = use(SnortContext)\n\n  const onSubmit = async (e: FormEvent) => {\n    e.preventDefault()\n    if (CONFIG.signUp.quickStart) {\n      return generateNewLogin(await generateNewLoginKeys(), system, key => Promise.resolve(new NotEncrypted(key)), {\n        name,\n      }).then(() => {\n        trackEvent(\"Login\", { newAccount: true })\n        navigate(\"/trending/notes\")\n      })\n    }\n    navigate(\"/login/sign-up/profile\", {\n      state: {\n        name: name,\n      } as NewUserState,\n    })\n  }\n\n  const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n    const val = e.target.value\n    if (val.match(Bech32Regex)) {\n      e.preventDefault()\n    } else {\n      setName(val)\n    }\n  }\n\n  return (\n    <div className=\"flex flex-col gap-6\">\n      <img src={CONFIG.icon} width={48} height={48} className=\"rounded-lg mr-auto ml-auto\" />\n      <div className=\"flex flex-col gap-4 items-center\">\n        <h1>\n          <FormattedMessage defaultMessage=\"Sign Up\" />\n        </h1>\n        <FormattedMessage defaultMessage=\"What should we call you?\" />\n      </div>\n      <form onSubmit={onSubmit} className=\"flex flex-col gap-4\">\n        <input\n          type=\"text\"\n          placeholder={formatMessage({\n            defaultMessage: \"Name or nym\",\n            id: \"aHje0o\",\n          })}\n          value={name}\n          onChange={onChange}\n          className=\"new-username\"\n        />\n        <AsyncButton className=\"primary\" disabled={name.length === 0} onClick={onSubmit}>\n          {CONFIG.signUp.quickStart ? (\n            <FormattedMessage\n              description=\"Button text after entering username in quick signup\"\n              defaultMessage=\"Go\"\n              id=\"0zASjL\"\n            />\n          ) : (\n            <FormattedMessage defaultMessage=\"Next\" />\n          )}\n        </AsyncButton>\n      </form>\n      <div className=\"flex flex-col gap-4 items-center\">\n        <Link to={\"/login\"}>\n          <FormattedMessage defaultMessage=\"Already have an account?\" />\n        </Link>\n        <AsyncButton className=\"secondary\" onClick={() => navigate(\"/login\")}>\n          <FormattedMessage defaultMessage=\"Sign In\" />\n        </AsyncButton>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/onboarding/topics.tsx",
    "content": "import { EventKind } from \"@snort/system\"\nimport classNames from \"classnames\"\nimport { type ReactNode, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport { FixedTopics } from \"@/Pages/onboarding/fixedTopics\"\nimport { appendDedupe } from \"@/Utils\"\n\nexport default function Topics() {\n  const { publisher, system } = useEventPublisher()\n  const [topics, setTopics] = useState<Array<string>>([])\n  const navigate = useNavigate()\n\n  function tab(name: string, text: ReactNode) {\n    const active = topics.includes(name)\n    return (\n      <div\n        className={classNames(\n          \"flex gap-2 items-center px-4 py-2 my-1 border cursor-pointer font-semibold layer-2 !rounded-full\",\n          \"hover:drop-shadow-sm\",\n          {\n            \"!bg-white !text-black\": active,\n          },\n        )}\n        onClick={() => setTopics(s => (active ? s.filter(a => a !== name) : appendDedupe(s, [name])))}\n      >\n        {text}\n      </div>\n    )\n  }\n\n  return (\n    <div className=\"flex flex-col gap-6 text-center\">\n      <h1>\n        <FormattedMessage defaultMessage=\"Pick a few topics of interest\" />\n      </h1>\n      <div className=\"flex gap-2 flex-wrap justify-center\">\n        {Object.entries(FixedTopics).map(([k, v]) => tab(k, v.text))}\n      </div>\n      <AsyncButton\n        className=\"primary\"\n        onClick={async () => {\n          const tags = Object.entries(FixedTopics)\n            .filter(([k]) => topics.includes(k))\n            .flatMap(([, v]) => v.tags)\n\n          if (tags.length > 0) {\n            const ev = await publisher?.generic(eb => {\n              eb.kind(EventKind.InterestsList)\n              tags.forEach(a => eb.tag([\"t\", a]))\n              return eb\n            })\n            if (ev) {\n              await system.BroadcastEvent(ev)\n            }\n          }\n          navigate(\"/login/sign-up/discover\")\n        }}\n      >\n        <FormattedMessage defaultMessage=\"Next\" />\n      </AsyncButton>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/Accounts.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport ProfilePreview from \"@/Components/User/ProfilePreview\"\nimport { LoginStore } from \"@/Utils/Login\"\nimport { getActiveSubscriptions } from \"@/Utils/Subscription\"\n\nexport default function AccountsPage() {\n  const logins = LoginStore.getSessions()\n  const sub = getActiveSubscriptions(LoginStore.allSubscriptions())\n\n  return (\n    <div className=\"flex flex-col gap-2\">\n      <h3>\n        <FormattedMessage defaultMessage=\"Logins\" />\n      </h3>\n      {logins.map(a => (\n        <div key={a.id}>\n          <ProfilePreview\n            pubkey={a.pubkey}\n            options={{\n              about: false,\n            }}\n            actions={\n              <div className=\"align-end flex gap-2\">\n                <button onClick={() => LoginStore.switchAccount(a.id)}>\n                  <FormattedMessage defaultMessage=\"Switch\" />\n                </button>\n                <button onClick={() => LoginStore.removeSession(a.id)}>\n                  <FormattedMessage defaultMessage=\"Logout\" />\n                </button>\n              </div>\n            }\n          />\n        </div>\n      ))}\n\n      {sub && (\n        <Link to={\"/login\"}>\n          <button type=\"button\">\n            <FormattedMessage defaultMessage=\"Add Account\" />\n          </button>\n        </Link>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/Cache.tsx",
    "content": "import type { CachedTable } from \"@snort/shared\"\nimport { ConnectionCacheRelay } from \"@snort/system\"\nimport { WorkerRelayInterface } from \"@snort/worker-relay\"\nimport { type ReactNode, use, useEffect, useState, } from \"react\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport { GiftsCache, Relay, tryUseLocalRelay, } from \"@/Cache\"\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { SnortContext } from \"@snort/system-react\"\nimport { CollapsedSection } from \"@/Components/Collapsed\"\n\nexport function CacheSettings() {\n  const system = use(SnortContext)\n  return (\n    <div className=\"flex flex-col gap-2\">\n      <h3>\n        <FormattedMessage defaultMessage=\"Cache\" />\n      </h3>\n      {Relay && <RelayCacheStats />}\n      <CacheDetails cache={system.config.profiles} name={<FormattedMessage defaultMessage=\"Profiles\" />} />\n      <CacheDetails cache={system.config.relays} name={<FormattedMessage defaultMessage=\"Relays\" />} />\n      <CacheDetails cache={system.config.contactLists} name={<FormattedMessage defaultMessage=\"Follow Lists\" />} />\n      <CacheDetails cache={GiftsCache} name={<FormattedMessage defaultMessage=\"Gift Wraps\" />} />\n    </div>\n  )\n}\n\nfunction CacheDetails<T>({ cache, name }: { cache: CachedTable<T>; name: ReactNode }) {\n  const [snapshot, setSnapshot] = useState<Array<T>>(cache.snapshot())\n  useEffect(() => {\n    const h = () => {\n      setSnapshot(cache.snapshot())\n    }\n    cache.on(\"change\", h)\n    return () => {\n      cache.off(\"change\", h)\n    }\n  }, [cache])\n\n  return (\n    <div className=\"flex justify-between layer-1\">\n      <div className=\"flex flex-col gap-1\">\n        {name}\n        <small>\n          <FormattedMessage\n            defaultMessage=\"{count} ({count2} in memory)\"\n            values={{\n              count: <FormattedNumber value={cache.keysOnTable().length} />,\n              count2: <FormattedNumber value={snapshot.length} />,\n            }}\n          />\n        </small>\n      </div>\n      <div>\n        <AsyncButton onClick={() => cache.clear()}>\n          <FormattedMessage defaultMessage=\"Clear\" />\n        </AsyncButton>\n      </div>\n    </div>\n  )\n}\n\nfunction RelayCacheStats() {\n  const [counts, setCounts] = useState<Record<string, number>>({})\n  const [myEvents, setMyEvents] = useState<number>(0)\n  const login = useLogin()\n  const navigate = useNavigate()\n\n  useEffect(() => {\n    if (Relay instanceof WorkerRelayInterface) {\n      Relay.summary().then(setCounts)\n      if (login.publicKey) {\n        Relay.count([\"REQ\", \"my\", { authors: [login.publicKey] }]).then(setMyEvents)\n      }\n    }\n  }, [login.publicKey])\n\n  function relayType() {\n    if (Relay instanceof WorkerRelayInterface) {\n      return <FormattedMessage defaultMessage=\"Browser\" />\n    } else if (Relay instanceof ConnectionCacheRelay) {\n      return <FormattedMessage defaultMessage=\"Local\" />\n    }\n  }\n\n  return (\n    <div className=\"flex justify-between gap-4 layer-1\">\n      <div className=\"grow flex flex-col gap-4\">\n        <div>\n          <FormattedMessage\n            defaultMessage=\"{type} Worker Relay\"\n            values={{\n              type: relayType(),\n            }}\n          />\n        </div>\n        {myEvents > 0 && (\n          <div>\n            <FormattedMessage\n              defaultMessage=\"My events: {n}\"\n              values={{\n                n: <FormattedNumber value={myEvents} />,\n              }}\n            />\n          </div>\n        )}\n        <CollapsedSection title={<FormattedMessage defaultMessage=\"Events Breakdown\" />}>\n          <table className=\"text-neutral-400 table-auto w-full\">\n            <thead>\n              <tr>\n                <th className=\"text-left\">\n                  <FormattedMessage defaultMessage=\"Kind\" />\n                </th>\n                <th className=\"text-left\">\n                  <FormattedMessage defaultMessage=\"Count\" />\n                </th>\n              </tr>\n            </thead>\n            <tbody>\n              {Object.entries(counts)\n                .sort(([, a], [, b]) => (a > b ? -1 : 1))\n                .map(([k, v]) => {\n                  return (\n                    <tr key={k}>\n                      <td>\n                        <FormattedNumber value={Number(k)} />\n                      </td>\n                      <td>\n                        <FormattedNumber value={v} />\n                      </td>\n                    </tr>\n                  )\n                })}\n            </tbody>\n          </table>\n        </CollapsedSection>\n      </div>\n      <div className=\"flex flex-col gap-2\">\n        {Relay instanceof WorkerRelayInterface && (\n          <>\n            <AsyncButton\n              onClick={async () => {\n                if (Relay instanceof WorkerRelayInterface) {\n                  await Relay.wipe()\n                  window.location.reload()\n                }\n              }}\n            >\n              <FormattedMessage defaultMessage=\"Clear\" />\n            </AsyncButton>\n            <AsyncButton\n              onClick={async () => {\n                const data = Relay instanceof WorkerRelayInterface ? await Relay.dump() : undefined\n                if (data) {\n                  const url = URL.createObjectURL(\n                    new File([data.buffer as ArrayBuffer], \"snort.db\", {\n                      type: \"application/octet-stream\",\n                    }),\n                  )\n                  const a = document.createElement(\"a\")\n                  a.href = url\n                  a.download = \"snort.db\"\n                  a.click()\n                }\n              }}\n            >\n              <FormattedMessage defaultMessage=\"Dump\" />\n            </AsyncButton>\n          </>\n        )}\n        <AsyncButton onClick={() => navigate(\"/cache-debug\")}>\n          <FormattedMessage defaultMessage=\"Debug\" />\n        </AsyncButton>\n\n        {!(Relay instanceof ConnectionCacheRelay) && (\n          <AsyncButton\n            onClick={async () => {\n              if (await tryUseLocalRelay()) {\n                window.location.reload()\n              } else {\n                alert(\"No local relay found\")\n              }\n            }}\n          >\n            <FormattedMessage defaultMessage=\"Use Local Relay\" />\n          </AsyncButton>\n        )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/Keys.css",
    "content": ".mnemonic-grid {\n  display: grid;\n  text-align: center;\n  grid-template-columns: repeat(4, 1fr);\n  gap: 8px;\n}\n\n.mnemonic-grid > div {\n  border: 1px solid #222222;\n  border-radius: 5px;\n  overflow: hidden;\n  user-select: none;\n}\n\n.mnemonic-grid .word > div:nth-of-type(1) {\n  background-color: var(--color-neutral-700);\n  padding: 4px 8px;\n  min-width: 2em;\n  font-variant-numeric: ordinal;\n}\n\n.mnemonic-grid .word > div:nth-of-type(2) {\n  flex-grow: 1;\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/Keys.tsx",
    "content": "import \"./Keys.css\"\n\nimport { KeyStorage } from \"@snort/system\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport Copy from \"@/Components/Copy/Copy\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { seedToMnemonic } from \"@/Utils/nip6\"\nimport { encodeTLV, hexToBech32, NostrPrefix } from \"@snort/shared\"\nimport { hexToBytes } from \"@noble/hashes/utils.js\"\n\nexport default function ExportKeys() {\n  const { publicKey, privateKeyData, generatedEntropy } = useLogin()\n  const copyClass = \"p-3 rounded-lg border border-dashed\"\n  return (\n    <div className=\"flex flex-col gap-3\">\n      <div className=\"text-xl\">\n        <FormattedMessage defaultMessage=\"Public Key\" />\n      </div>\n      <small>\n        <FormattedMessage\n          defaultMessage=\"The public key is like your username, you can share it with anyone.\"\n          id=\"dK2CcV\"\n        />\n      </small>\n      <Copy text={hexToBech32(\"npub\", publicKey ?? \"\")} className={copyClass} />\n      <Copy text={encodeTLV(NostrPrefix.Profile, hexToBytes(publicKey ?? \"\"))} className={copyClass} />\n      {privateKeyData instanceof KeyStorage && (\n        <>\n          <div className=\"text-xl\">\n            <FormattedMessage defaultMessage=\"Private Key\" />\n          </div>\n          <small>\n            <FormattedMessage\n              defaultMessage=\"The private key is like a password, but it cannot be reset. Guard it carefully and never show it to anyone. Once someone has your private key, they will have access to your account forever.\"\n              id=\"QJfhKt\"\n            />\n          </small>\n          <Copy text={hexToBech32(\"nsec\", privateKeyData.value)} className={copyClass} mask=\"*\" />\n        </>\n      )}\n      {generatedEntropy && (\n        <>\n          <div className=\"text-xl\">\n            <FormattedMessage defaultMessage=\"Mnemonic\" />\n          </div>\n          <div className=\"mnemonic-grid\">\n            {seedToMnemonic(generatedEntropy ?? \"\")\n              .split(\" \")\n              .map((a, i) => (\n                <div key={a} className=\"flex items-center word\">\n                  <div>{i + 1}</div>\n                  <div>{a}</div>\n                </div>\n              ))}\n          </div>\n        </>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/Menu/Menu.tsx",
    "content": "import { type ReactNode, useCallback } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport useLogin from \"@/Hooks/useLogin\"\nimport { SettingsMenuComponent } from \"@/Pages/settings/Menu/SettingsMenuComponent\"\nimport { LoginStore, logout } from \"@/Utils/Login\"\nimport { getCurrentSubscription } from \"@/Utils/Subscription\"\n\nexport type SettingsMenuItems = Array<{\n  title: ReactNode\n  items: Array<{\n    icon: string\n    iconBg: string\n    message: ReactNode\n    path?: string\n    action?: () => void\n  }>\n}>\n\nconst SettingsIndex = () => {\n  const login = useLogin()\n  const navigate = useNavigate()\n  const sub = getCurrentSubscription(LoginStore.allSubscriptions())\n\n  const handleLogout = useCallback(() => {\n    logout(login.id)\n    navigate(\"/\")\n  }, [login.id, navigate])\n\n  const settingsGroups = [\n    {\n      title: <FormattedMessage defaultMessage=\"Account\" />,\n      items: [\n        {\n          icon: \"profile\",\n          iconBg: \"bg-green-500\",\n          message: <FormattedMessage defaultMessage=\"Profile\" />,\n          path: \"profile\",\n        },\n        {\n          icon: \"key\",\n          iconBg: \"bg-amber-500\",\n          message: <FormattedMessage defaultMessage=\"Export Keys\" />,\n          path: \"keys\",\n        },\n        ...(CONFIG.features.nostrAddress\n          ? [\n              {\n                icon: \"badge\",\n                iconBg: \"bg-pink-500\",\n                message: <FormattedMessage defaultMessage=\"Nostr Address\" />,\n                path: \"handle\",\n              },\n            ]\n          : []),\n        {\n          icon: \"gear\",\n          iconBg: \"bg-slate-500\",\n          message: <FormattedMessage defaultMessage=\"Preferences\" />,\n          path: \"preferences\",\n        },\n        {\n          icon: \"wallet\",\n          iconBg: \"bg-emerald-500\",\n          message: <FormattedMessage defaultMessage=\"Wallet\" />,\n          path: \"wallet\",\n        },\n        ...(sub\n          ? [\n              {\n                icon: \"code-circle\",\n                iconBg: \"bg-indigo-500\",\n                message: <FormattedMessage defaultMessage=\"Accounts\" />,\n                path: \"accounts\",\n              },\n            ]\n          : []),\n        {\n          icon: \"tool\",\n          iconBg: \"bg-slate-800\",\n          message: <FormattedMessage defaultMessage=\"Tools\" />,\n          path: \"tools\",\n        },\n      ],\n    },\n    {\n      title: <FormattedMessage defaultMessage=\"Interaction\" />,\n      items: [\n        {\n          icon: \"relay\",\n          iconBg: \"bg-dark bg-opacity-20\",\n          message: <FormattedMessage defaultMessage=\"Relays\" />,\n          path: \"relays\",\n        },\n        {\n          icon: \"shield-tick\",\n          iconBg: \"bg-yellow-500\",\n          message: <FormattedMessage defaultMessage=\"Moderation\" />,\n          path: \"moderation\",\n        },\n        ...(CONFIG.features.pushNotifications\n          ? [\n              {\n                icon: \"bell-outline\",\n                iconBg: \"bg-red-500\",\n                message: <FormattedMessage defaultMessage=\"Notifications\" />,\n                path: \"notifications\",\n              },\n            ]\n          : []),\n        ...(CONFIG.features.communityLeaders\n          ? [\n              {\n                icon: \"link\",\n                iconBg: \"bg-blue-500\",\n                message: <FormattedMessage defaultMessage=\"Invite\" />,\n                path: \"invite\",\n              },\n            ]\n          : []),\n        {\n          icon: \"hard-drive\",\n          iconBg: \"bg-cyan-500\",\n          message: <FormattedMessage defaultMessage=\"Cache\" />,\n          path: \"cache\",\n        },\n        {\n          icon: \"camera-plus\",\n          iconBg: \"bg-lime-500\",\n          message: <FormattedMessage defaultMessage=\"Media\" />,\n          path: \"media\",\n        },\n      ],\n    },\n    {\n      title: <FormattedMessage defaultMessage=\"Support\" />,\n      items: [\n        {\n          icon: \"heart\",\n          iconBg: \"bg-purple-500\",\n          message: <FormattedMessage defaultMessage=\"Donate\" />,\n          path: \"/about\",\n        },\n        ...(CONFIG.features.subscriptions\n          ? [\n              {\n                icon: \"diamond\",\n                iconBg: \"bg-violet-500\",\n                message: <FormattedMessage defaultMessage=\"Subscription\" />,\n                path: \"/subscribe/manage\",\n              },\n            ]\n          : []),\n        ...(CONFIG.features.zapPool\n          ? [\n              {\n                icon: \"piggy-bank\",\n                iconBg: \"bg-rose-500\",\n                message: <FormattedMessage defaultMessage=\"Zap Pool\" />,\n                path: \"/zap-pool\",\n              },\n            ]\n          : []),\n      ],\n    },\n    {\n      title: <FormattedMessage defaultMessage=\"Log Out\" />,\n      items: [\n        {\n          icon: \"logout\",\n          iconBg: \"bg-red-500\",\n          message: <FormattedMessage defaultMessage=\"Log Out\" />,\n          action: handleLogout,\n        },\n      ],\n    },\n  ] as SettingsMenuItems\n\n  return <SettingsMenuComponent menu={settingsGroups} />\n}\n\nexport default SettingsIndex\n"
  },
  {
    "path": "packages/app/src/Pages/settings/Menu/SettingsMenuComponent.tsx",
    "content": "import classNames from \"classnames\"\nimport { Link } from \"react-router-dom\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport type { SettingsMenuItems } from \"@/Pages/settings/Menu/Menu\"\n\nexport function SettingsMenuComponent({ menu }: { menu: SettingsMenuItems }) {\n  return (\n    <div className=\"flex flex-col\">\n      {menu.map((group, groupIndex) => (\n        <div key={groupIndex} className=\"mb-4\">\n          <div className=\"p-2 font-bold uppercase text-neutral-400 text-xs tracking-wide\">{group.title}</div>\n          {group.items.map(({ icon, iconBg, message, path, action }, index) => (\n            <Link\n              to={path || \"#\"}\n              onClick={action}\n              key={path || index}\n              className={classNames(\"px-2.5 py-1.5 flex justify-between items-center border\", {\n                \"rounded-t-xl\": index === 0,\n                \"rounded-b-xl\": index === group.items.length - 1,\n                \"border-t-0\": index !== 0,\n              })}\n            >\n              <div className=\"flex items-center gap-3\">\n                <div className={`p-1 ${iconBg} rounded-lg flex justify-center items-center text-white`}>\n                  <Icon name={icon} size={18} className=\"relative\" />\n                </div>\n                <span className=\"text-base font-semibold flex-grow\">{message}</span>\n              </div>\n              <Icon name=\"arrowFront\" size={12} className=\"text-neutral-400\" />\n            </Link>\n          ))}\n        </div>\n      ))}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/Moderation.tsx",
    "content": "import { useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport useModeration from \"@/Hooks/useModeration\"\nimport { useAllPreferences } from \"@/Hooks/usePreferences\"\n\nexport default function ModerationSettingsPage() {\n  const { addMutedWord, removeMutedWord, getMutedWords } = useModeration()\n  const preferences = useAllPreferences()\n  const [muteWord, setMuteWord] = useState(\"\")\n\n  return (\n    <>\n      <h2>\n        <FormattedMessage defaultMessage=\"Moderation\" />\n      </h2>\n\n      <div className=\"py-4 flex flex-col gap-2\">\n        <div className=\"flex items-center mb-2\">\n          <input\n            type=\"checkbox\"\n            checked={preferences.preferences.showContentWarningPosts}\n            onChange={() =>\n              preferences.update({\n                ...preferences.preferences,\n                showContentWarningPosts: !preferences.preferences.showContentWarningPosts,\n              })\n            }\n            className=\"mr-2\"\n            id=\"showContentWarningPosts\"\n          />\n          <label htmlFor=\"showContentWarningPosts\">\n            <FormattedMessage defaultMessage=\"Show posts that have a content warning tag\" />\n          </label>\n        </div>\n      </div>\n\n      <h3>\n        <FormattedMessage defaultMessage=\"Muted Words\" />\n      </h3>\n      <div className=\"flex flex-col gap-3\">\n        <div className=\"flex gap-2\">\n          <input\n            type=\"text\"\n            placeholder=\"eg. crypto\"\n            className=\"w-max\"\n            value={muteWord}\n            onChange={e => setMuteWord(e.target.value.toLowerCase())}\n          />\n          <AsyncButton\n            onClick={async () => {\n              await addMutedWord(muteWord)\n              setMuteWord(\"\")\n            }}\n          >\n            <FormattedMessage defaultMessage=\"Add\" />\n          </AsyncButton>\n        </div>\n        {getMutedWords().map(v => (\n          <div key={v} className=\"px-3 py-2 rounded-lg border flex items-center justify-between\">\n            <div>{v}</div>\n            <AsyncButton onClick={() => removeMutedWord(v)}>\n              <FormattedMessage defaultMessage=\"Delete\" />\n            </AsyncButton>\n          </div>\n        ))}\n      </div>\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/Notifications.tsx",
    "content": "import { useEffect, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { subscribeToNotifications } from \"@/Utils/Notifications\"\n\nimport messages from \"./messages\"\n\ninterface StatusIndicatorProps {\n  status: boolean\n  enabledMessage: React.ComponentProps<typeof FormattedMessage>\n  disabledMessage: React.ComponentProps<typeof FormattedMessage>\n}\n\nconst StatusIndicator = ({ status, enabledMessage, disabledMessage }: StatusIndicatorProps) => {\n  return status ? (\n    <div className=\"flex items-center\">\n      <Icon name=\"check\" size={20} className=\"text-green-500 mr-2\" />\n      <FormattedMessage {...enabledMessage} />\n    </div>\n  ) : (\n    <div className=\"flex items-center\">\n      <Icon name=\"close\" size={20} className=\"text-red-500 mr-2\" />\n      <FormattedMessage {...disabledMessage} />\n    </div>\n  )\n}\n\nconst PreferencesPage = () => {\n  const login = useLogin()\n  const { publisher } = useEventPublisher()\n  const [serviceWorkerReady, setServiceWorkerReady] = useState(false)\n  const hasNotificationsApi = \"Notification\" in window\n  const [notificationsAllowed, setNotificationsAllowed] = useState(\n    hasNotificationsApi && Notification.permission === \"granted\",\n  )\n  const [subscribedToPush, setSubscribedToPush] = useState(false)\n  const allGood = !login.readonly && hasNotificationsApi && notificationsAllowed && serviceWorkerReady\n\n  useEffect(() => {\n    if (\"serviceWorker\" in navigator) {\n      navigator.serviceWorker.ready.then(registration => {\n        if (registration.active) {\n          setServiceWorkerReady(true)\n        }\n      })\n    }\n  }, [])\n\n  const trySubscribePush = async () => {\n    try {\n      if (allGood && publisher && !subscribedToPush) {\n        await subscribeToNotifications(publisher)\n        setSubscribedToPush(true)\n      }\n    } catch (e) {\n      console.error(e)\n    }\n  }\n\n  useEffect(() => {\n    trySubscribePush()\n  }, [trySubscribePush])\n\n  const requestNotificationPermission = () => {\n    Notification.requestPermission().then(permission => {\n      const allowed = permission === \"granted\"\n      setNotificationsAllowed(allowed)\n      if (!allowed) {\n        alert(\"Please allow notifications in your browser settings and try again.\")\n      }\n    })\n  }\n\n  if (!login.publicKey) {\n    return null\n  }\n\n  return (\n    <div className=\"flex flex-col\">\n      <h3>\n        <FormattedMessage defaultMessage=\"Notifications\" />\n      </h3>\n\n      <h4>\n        <FormattedMessage defaultMessage=\"Push notifications\" />\n      </h4>\n\n      <div className=\"flex flex-col space-y-4\">\n        <StatusIndicator\n          status={!login.readonly}\n          enabledMessage={messages.HasWriteAccess}\n          disabledMessage={messages.NoWriteAccess}\n        />\n        <StatusIndicator\n          status={hasNotificationsApi}\n          enabledMessage={messages.NotificationsApiEnabled}\n          disabledMessage={messages.NotificationsApiDisabled}\n        />\n        <div className=\"flex items-center gap-2\">\n          <StatusIndicator\n            status={notificationsAllowed}\n            enabledMessage={messages.NotificationsAllowed}\n            disabledMessage={messages.NotificationsNotAllowed}\n          />\n          {hasNotificationsApi && !notificationsAllowed && (\n            <button onClick={requestNotificationPermission}>\n              <FormattedMessage defaultMessage=\"Allow\" />\n            </button>\n          )}\n        </div>\n        <StatusIndicator\n          status={serviceWorkerReady}\n          enabledMessage={messages.ServiceWorkerRunning}\n          disabledMessage={messages.ServiceWorkerNotRunning}\n        />\n        <div className=\"flex items-center gap-2\">\n          <StatusIndicator\n            status={subscribedToPush}\n            enabledMessage={messages.SubscribedToPush}\n            disabledMessage={messages.NotSubscribedToPush}\n          />\n          {allGood && !subscribedToPush && (\n            <button onClick={trySubscribePush}>\n              <FormattedMessage defaultMessage=\"Subscribe\" />\n            </button>\n          )}\n        </div>\n      </div>\n    </div>\n  )\n}\n\nexport default PreferencesPage\n"
  },
  {
    "path": "packages/app/src/Pages/settings/Preferences.tsx",
    "content": "import { type ReactNode, useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport { AllLanguageCodes } from \"@/Components/IntlProvider/IntlProviderUtils\"\nimport { useLocale } from \"@/Components/IntlProvider/useLocale\"\nimport { useAllPreferences } from \"@/Hooks/usePreferences\"\nimport { unwrap } from \"@/Utils\"\nimport { DefaultImgProxy } from \"@/Utils/Const\"\nimport type { UserPreferences } from \"@/Utils/Login\"\n\nimport messages from \"./messages\"\n\nconst PreferencesPage = () => {\n  const { formatMessage } = useIntl()\n  const { preferences: pref, update: setPref, save } = useAllPreferences()\n  const [error, _setError] = useState(\"\")\n  const { lang } = useLocale()\n\n  function row(title: ReactNode, description: ReactNode | undefined, control: ReactNode) {\n    return (\n      <div className=\"flex justify-between\">\n        <div className=\"flex flex-col gap-2\">\n          <h4>{title}</h4>\n          {description && <small>{description}</small>}\n        </div>\n        <div>{control}</div>\n      </div>\n    )\n  }\n\n  return (\n    <div className=\"flex flex-col gap-6\">\n      <h3>\n        <FormattedMessage defaultMessage=\"Preferences\" />\n      </h3>\n      <AsyncButton onClick={() => save()}>\n        <FormattedMessage defaultMessage=\"Save\" />\n      </AsyncButton>\n      {error && <b className=\"warning\">{error}</b>}\n\n      {/** START CONTROLS */}\n\n      {row(\n        <FormattedMessage defaultMessage=\"Language\" />,\n        undefined,\n        <select\n          value={pref.language ?? lang}\n          onChange={e =>\n            setPref({\n              ...pref,\n              language: e.target.value,\n            })\n          }\n          style={{ textTransform: \"capitalize\" }}\n        >\n          {AllLanguageCodes.sort().map(a => (\n            <option key={a} value={a}>\n              {new Intl.DisplayNames([a], {\n                type: \"language\",\n              }).of(a)}\n            </option>\n          ))}\n        </select>,\n      )}\n\n      {row(\n        <FormattedMessage {...messages.Theme} />,\n        undefined,\n        <select\n          value={pref.theme}\n          onChange={e =>\n            setPref({\n              ...pref,\n              theme: e.target.value,\n            } as UserPreferences)\n          }\n        >\n          <option value=\"system\">\n            <FormattedMessage {...messages.System} />\n          </option>\n          <option value=\"light\">\n            <FormattedMessage {...messages.Light} />\n          </option>\n          <option value=\"dark\">\n            <FormattedMessage {...messages.Dark} />\n          </option>\n        </select>,\n      )}\n      {row(\n        <FormattedMessage {...messages.DefaultRootTab} />,\n        undefined,\n        <select\n          value={pref.defaultRootTab}\n          onChange={e =>\n            setPref({\n              ...pref,\n              defaultRootTab: e.target.value,\n            } as UserPreferences)\n          }\n        >\n          <option value=\"for-you\">\n            <FormattedMessage defaultMessage=\"For you\" />\n          </option>\n          <option value=\"following\">\n            <FormattedMessage defaultMessage=\"Notes\" />\n          </option>\n          <option value=\"conversations\">\n            <FormattedMessage {...messages.Conversations} />\n          </option>\n          <option value=\"global\">\n            <FormattedMessage {...messages.Global} />\n          </option>\n        </select>,\n      )}\n\n      {row(\n        <FormattedMessage defaultMessage=\"Send usage metrics\" />,\n        <FormattedMessage defaultMessage=\"Send anonymous usage metrics\" />,\n        <input\n          type=\"checkbox\"\n          checked={pref.telemetry ?? true}\n          onChange={e => setPref({ ...pref, telemetry: e.target.checked })}\n        />,\n      )}\n      {row(\n        <FormattedMessage {...messages.AutoloadMedia} />,\n        <FormattedMessage {...messages.AutoloadMediaHelp} />,\n        <select\n          className=\"w-max\"\n          value={pref.autoLoadMedia}\n          onChange={e =>\n            setPref({\n              ...pref,\n              autoLoadMedia: e.target.value,\n            } as UserPreferences)\n          }\n        >\n          <option value=\"none\">\n            <FormattedMessage {...messages.None} />\n          </option>\n          <option value=\"follows-only\">\n            <FormattedMessage {...messages.FollowsOnly} />\n          </option>\n          <option value=\"all\">\n            <FormattedMessage {...messages.All} />\n          </option>\n        </select>,\n      )}\n\n      {row(\n        <FormattedMessage defaultMessage=\"Check Signatures\" />,\n        <FormattedMessage defaultMessage=\"Check all event signatures received from relays\" />,\n        <input\n          type=\"checkbox\"\n          checked={pref.checkSigs}\n          onChange={e => setPref({ ...pref, checkSigs: e.target.checked })}\n        />,\n      )}\n\n      {row(\n        <FormattedMessage defaultMessage=\"WoT Filter\" />,\n        <FormattedMessage defaultMessage=\"Mute notes from people who are outside your web of trust\" />,\n        <input\n          type=\"checkbox\"\n          checked={pref.muteWithWoT}\n          onChange={e => setPref({ ...pref, muteWithWoT: e.target.checked })}\n        />,\n      )}\n\n      {row(\n        <FormattedMessage defaultMessage=\"Hide muted notes\" />,\n        <FormattedMessage defaultMessage=\"Muted notes will not be shown\" />,\n        <input\n          type=\"checkbox\"\n          checked={pref.hideMutedNotes}\n          onChange={e => setPref({ ...pref, hideMutedNotes: e.target.checked })}\n        />,\n      )}\n\n      {row(\n        <FormattedMessage defaultMessage=\"Auto Translate\" />,\n        <FormattedMessage defaultMessage=\"Automatically translate notes to your local language\" />,\n        <input\n          type=\"checkbox\"\n          checked={pref.autoTranslate}\n          onChange={e => setPref({ ...pref, autoTranslate: e.target.checked })}\n        />,\n      )}\n\n      {row(\n        <FormattedMessage defaultMessage=\"Proof of Work\" />,\n        <FormattedMessage defaultMessage=\"Amount of work to apply to all published events\" />,\n        <input\n          type=\"number\"\n          defaultValue={pref.pow}\n          min={0}\n          className=\"w-20\"\n          onChange={e => setPref({ ...pref, pow: parseInt(e.target.value || \"0\", 10) })}\n        />,\n      )}\n\n      {row(\n        <FormattedMessage defaultMessage=\"Default Zap amount\" />,\n        undefined,\n        <input\n          type=\"number\"\n          defaultValue={pref.defaultZapAmount}\n          min={1}\n          className=\"w-20\"\n          onChange={e => setPref({ ...pref, defaultZapAmount: parseInt(e.target.value || \"0\", 10) })}\n        />,\n      )}\n\n      {row(\n        <FormattedMessage defaultMessage=\"Show Badges\" />,\n        <FormattedMessage defaultMessage=\"Show badges on profile pages\" />,\n        <input\n          type=\"checkbox\"\n          checked={pref.showBadges ?? false}\n          onChange={e => setPref({ ...pref, showBadges: e.target.checked })}\n        />,\n      )}\n\n      {row(\n        <FormattedMessage defaultMessage=\"Show Status\" />,\n        <FormattedMessage defaultMessage=\"Show status messages on profile pages\" />,\n        <input\n          type=\"checkbox\"\n          checked={pref.showStatus ?? true}\n          onChange={e => setPref({ ...pref, showStatus: e.target.checked })}\n        />,\n      )}\n\n      {row(\n        <FormattedMessage defaultMessage=\"Auto Zap\" />,\n        <FormattedMessage defaultMessage=\"Automatically zap every note when loaded\" />,\n        <input\n          type=\"checkbox\"\n          checked={pref.autoZap}\n          onChange={e => setPref({ ...pref, autoZap: e.target.checked })}\n        />,\n      )}\n      {row(\n        <FormattedMessage {...messages.ImgProxy} />,\n        <FormattedMessage {...messages.ImgProxyHelp} />,\n        <input\n          type=\"checkbox\"\n          checked={pref.imgProxyConfig !== undefined}\n          onChange={e =>\n            setPref({\n              ...pref,\n              imgProxyConfig: e.target.checked ? DefaultImgProxy : undefined,\n            })\n          }\n        />,\n      )}\n\n      {pref.imgProxyConfig && (\n        <div className=\"flex flex-col gap-2\">\n          <div className=\"flex items-center justify-between\">\n            <div>\n              <FormattedMessage defaultMessage=\"Server\" />\n            </div>\n            <input\n              type=\"text\"\n              value={pref.imgProxyConfig?.url}\n              placeholder={formatMessage({\n                defaultMessage: \"URL..\",\n                description: \"Placeholder text for imgproxy url textbox\",\n              })}\n              onChange={e =>\n                setPref({\n                  ...pref,\n                  imgProxyConfig: {\n                    ...unwrap(pref.imgProxyConfig),\n                    url: e.target.value,\n                  },\n                })\n              }\n            />\n          </div>\n          <div className=\"flex items-center justify-between\">\n            <div>\n              <FormattedMessage {...messages.ServiceKey} />\n            </div>\n            <input\n              type=\"password\"\n              value={pref.imgProxyConfig?.key}\n              placeholder={formatMessage({\n                defaultMessage: \"Hex Key..\",\n                description: \"Hexidecimal 'key' input for improxy\",\n              })}\n              onChange={e =>\n                setPref({\n                  ...pref,\n                  imgProxyConfig: {\n                    ...unwrap(pref.imgProxyConfig),\n                    key: e.target.value,\n                  },\n                })\n              }\n            />\n          </div>\n          <div className=\"flex items-center justify-between\">\n            <div>\n              <FormattedMessage {...messages.ServiceSalt} />\n            </div>\n            <div className=\"w-max\">\n              <input\n                type=\"password\"\n                value={pref.imgProxyConfig?.salt}\n                placeholder={formatMessage({\n                  defaultMessage: \"Hex Salt..\",\n                  description: \"Hexidecimal 'salt' input for imgproxy\",\n                })}\n                onChange={e =>\n                  setPref({\n                    ...pref,\n                    imgProxyConfig: {\n                      ...unwrap(pref.imgProxyConfig),\n                      salt: e.target.value,\n                    },\n                  })\n                }\n              />\n            </div>\n          </div>\n        </div>\n      )}\n\n      {row(\n        <FormattedMessage {...messages.EnableReactions} />,\n        <FormattedMessage {...messages.EnableReactionsHelp} />,\n        <input\n          type=\"checkbox\"\n          checked={pref.enableReactions}\n          onChange={e => setPref({ ...pref, enableReactions: e.target.checked })}\n        />,\n      )}\n\n      {row(\n        <FormattedMessage {...messages.AgentUrl} />,\n        <FormattedMessage defaultMessage=\"URL for AI Agent service\" />,\n        <input\n          type=\"text\"\n          value={pref.agentUrl ?? \"\"}\n          placeholder=\"https://example.com/v1\"\n          onChange={e => setPref({ ...pref, agentUrl: e.target.value })}\n          className=\"w-64\"\n        />,\n      )}\n\n      {row(\n        <FormattedMessage {...messages.AgentKey} />,\n        <FormattedMessage defaultMessage=\"API key for AI Agent service\" />,\n        <input\n          type=\"password\"\n          value={pref.agentKey ?? \"\"}\n          placeholder=\"sk-...\"\n          onChange={e => setPref({ ...pref, agentKey: e.target.value })}\n          className=\"w-64\"\n        />,\n      )}\n\n      {pref.agentUrl && (\n        <div className=\"flex flex-col gap-2\">\n          <div className=\"flex items-center justify-between\">\n            <div>\n              <FormattedMessage defaultMessage=\"Agent Model\" />\n            </div>\n            <input\n              type=\"text\"\n              value={pref.agentModel ?? \"\"}\n              placeholder=\"Model name (e.g., code)\"\n              onChange={e => setPref({ ...pref, agentModel: e.target.value })}\n              className=\"w-64\"\n            />\n          </div>\n          <small className=\"text-gray-500\">\n            <FormattedMessage defaultMessage=\"Leave empty to use default model from agent service\" />\n          </small>\n        </div>\n      )}\n\n      {row(\n        <FormattedMessage {...messages.ReactionEmoji} />,\n        <FormattedMessage {...messages.ReactionEmojiHelp} />,\n        <input\n          type=\"text\"\n          value={pref.reactionEmoji}\n          onChange={e => {\n            const split = e.target.value.match(/[\\p{L}\\S]{1}/u)\n            setPref({\n              ...pref,\n              reactionEmoji: split?.[0] ?? \"\",\n            })\n          }}\n        />,\n      )}\n\n      {row(\n        <FormattedMessage {...messages.ConfirmReposts} />,\n        <FormattedMessage {...messages.ConfirmRepostsHelp} />,\n        <input\n          type=\"checkbox\"\n          checked={pref.confirmReposts}\n          onChange={e => setPref({ ...pref, confirmReposts: e.target.checked })}\n        />,\n      )}\n\n      {row(\n        <FormattedMessage {...messages.ShowLatest} />,\n        <FormattedMessage {...messages.ShowLatestHelp} />,\n        <input\n          type=\"checkbox\"\n          checked={pref.autoShowLatest}\n          onChange={e => setPref({ ...pref, autoShowLatest: e.target.checked })}\n        />,\n      )}\n\n      {row(\n        <FormattedMessage {...messages.DebugMenus} />,\n        <FormattedMessage {...messages.DebugMenusHelp} />,\n        <input\n          type=\"checkbox\"\n          checked={pref.showDebugMenus}\n          onChange={e => setPref({ ...pref, showDebugMenus: e.target.checked })}\n        />,\n      )}\n\n      <AsyncButton onClick={() => save()}>\n        <FormattedMessage defaultMessage=\"Save\" />\n      </AsyncButton>\n      {error && <b className=\"error\">{error}</b>}\n    </div>\n  )\n}\nexport default PreferencesPage\n"
  },
  {
    "path": "packages/app/src/Pages/settings/Profile.tsx",
    "content": "import { fetchNip05Pubkey, LNURL } from \"@snort/shared\"\nimport { mapEventToProfile } from \"@snort/system\"\nimport { useUserProfile } from \"@snort/system-react\"\nimport { useCallback, useEffect, useRef, useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport { ErrorOrOffline } from \"@/Components/ErrorOrOffline\"\nimport messages from \"@/Components/messages\"\nimport AvatarEditor from \"@/Components/User/AvatarEditor\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { debounce, openFile } from \"@/Utils\"\nimport { MaxAboutLength, MaxUsernameLength } from \"@/Utils/Const\"\nimport useFileUpload from \"@/Utils/Upload\"\n\nexport interface ProfileSettingsProps {\n  avatar?: boolean\n  banner?: boolean\n}\n\nexport default function ProfileSettings(props: ProfileSettingsProps) {\n  const { formatMessage } = useIntl()\n  const { id, publicKey, readonly } = useLogin(s => ({ id: s.id, publicKey: s.publicKey, readonly: s.readonly }))\n  const user = useUserProfile(publicKey ?? \"\")\n  const { publisher, system } = useEventPublisher()\n  const uploader = useFileUpload()\n  const [error, setError] = useState<Error>()\n  const isDirty = useRef(false)\n\n  const [name, setName] = useState<string>()\n  const [picture, setPicture] = useState<string>()\n  const [banner, setBanner] = useState<string>()\n  const [about, setAbout] = useState<string>()\n  const [website, setWebsite] = useState<string>()\n  const [nip05, setNip05] = useState<string>()\n  const [lud16, setLud16] = useState<string>()\n  const [nip05AddressValid, setNip05AddressValid] = useState<boolean>()\n  const [invalidNip05AddressMessage, setInvalidNip05AddressMessage] = useState<string>()\n  const [usernameValid, setUsernameValid] = useState<boolean>()\n  const [invalidUsernameMessage, setInvalidUsernameMessage] = useState<string>()\n  const [aboutValid, setAboutValid] = useState<boolean>()\n  const [invalidAboutMessage, setInvalidAboutMessage] = useState<string>()\n  const [lud16Valid, setLud16Valid] = useState<boolean>()\n  const [invalidLud16Message, setInvalidLud16Message] = useState<string>()\n\n  useEffect(() => {\n    if (user && !isDirty.current) {\n      setName(user.name)\n      setPicture(user.picture)\n      setBanner(user.banner)\n      setAbout(user.about)\n      setWebsite(user.website)\n      setNip05(user.nip05)\n      setLud16(user.lud16)\n    }\n  }, [user])\n\n  const nip05NostrAddressVerification = useCallback(\n    async (nip05Domain: string | undefined, nip05Name: string | undefined) => {\n      try {\n        const result = await fetchNip05Pubkey(nip05Name!, nip05Domain!)\n        if (result) {\n          if (result === publicKey) {\n            setNip05AddressValid(true)\n          } else {\n            setInvalidNip05AddressMessage(\n              formatMessage({ defaultMessage: \"Nostr address does not belong to you\", id: \"01iNut\" }),\n            )\n          }\n        } else {\n          setNip05AddressValid(false)\n          setInvalidNip05AddressMessage(formatMessage(messages.InvalidNip05Address))\n        }\n      } catch (_e) {\n        setNip05AddressValid(false)\n        setInvalidNip05AddressMessage(formatMessage(messages.InvalidNip05Address))\n      }\n    },\n    [publicKey, formatMessage],\n  )\n\n  useEffect(() => {\n    return debounce(500, async () => {\n      if (lud16) {\n        try {\n          await new LNURL(lud16).load()\n          setLud16Valid(true)\n          setInvalidLud16Message(\"\")\n        } catch (_e) {\n          setLud16Valid(false)\n          setInvalidLud16Message(formatMessage(messages.InvalidLud16))\n        }\n      } else {\n        setInvalidLud16Message(\"\")\n      }\n    })\n  }, [lud16, formatMessage])\n\n  useEffect(() => {\n    return debounce(500, async () => {\n      const Nip05AddressElements = nip05?.split(\"@\") ?? []\n      if ((nip05?.length ?? 0) === 0) {\n        setNip05AddressValid(false)\n        setInvalidNip05AddressMessage(\"\")\n      } else if (Nip05AddressElements.length < 2) {\n        setNip05AddressValid(false)\n        setInvalidNip05AddressMessage(formatMessage(messages.InvalidNip05Address))\n      } else if (Nip05AddressElements.length === 2) {\n        nip05NostrAddressVerification(Nip05AddressElements.pop(), Nip05AddressElements.pop())\n      } else {\n        setNip05AddressValid(false)\n      }\n    })\n  }, [nip05, formatMessage, nip05NostrAddressVerification])\n\n  async function saveProfile() {\n    // copy user object and delete internal fields\n    const userCopy = {\n      ...user,\n      name,\n      about,\n      picture,\n      banner,\n      website,\n      nip05,\n      lud16,\n    } as Record<string, string | number | undefined | boolean>\n    delete userCopy.loaded\n    delete userCopy.created\n    delete userCopy.pubkey\n    delete userCopy.npub\n    delete userCopy.deleted\n    delete userCopy.zapService\n    delete userCopy.isNostrAddressValid\n    console.debug(userCopy)\n\n    if (publisher) {\n      const ev = await publisher.metadata(userCopy)\n      await system.BroadcastEvent(ev)\n\n      const newProfile = mapEventToProfile(ev)\n      if (newProfile) {\n        await system.config.profiles.set(newProfile)\n      }\n    }\n  }\n\n  async function uploadFile() {\n    try {\n      setError(undefined)\n      const file = await openFile()\n      if (file && uploader) {\n        const rsp = await uploader.upload(file)\n        if (\"error\" in rsp && typeof rsp?.error === \"string\") {\n          throw new Error(`Upload failed ${rsp.error}`)\n        }\n        return rsp.url\n      }\n    } catch (e) {\n      if (e instanceof Error) {\n        setError(e)\n      }\n    }\n  }\n\n  async function setNewBanner() {\n    const rsp = await uploadFile()\n    if (rsp) {\n      setBanner(rsp)\n    }\n  }\n\n  async function _setNewAvatar() {\n    const rsp = await uploadFile()\n    if (rsp) {\n      setPicture(rsp)\n    }\n  }\n\n  async function onNip05Change(e: React.ChangeEvent<HTMLInputElement>) {\n    isDirty.current = true\n    const Nip05Address = e.target.value.toLowerCase()\n    setNip05(Nip05Address)\n  }\n\n  async function onLimitCheck(val: string, field: string) {\n    isDirty.current = true\n    if (field === \"username\") {\n      setName(val)\n      if (val?.length >= MaxUsernameLength) {\n        setUsernameValid(false)\n        setInvalidUsernameMessage(\n          formatMessage(messages.UserNameLengthError, {\n            limit: MaxUsernameLength,\n          }),\n        )\n      } else {\n        setUsernameValid(true)\n        setInvalidUsernameMessage(\"\")\n      }\n    } else if (field === \"about\") {\n      setAbout(val)\n      if (val?.length >= MaxAboutLength) {\n        setAboutValid(false)\n        setInvalidAboutMessage(\n          formatMessage(messages.AboutLengthError, {\n            limit: MaxAboutLength,\n          }),\n        )\n      } else {\n        setAboutValid(true)\n        setInvalidAboutMessage(\"\")\n      }\n    }\n  }\n\n  async function onLud16Change(address: string) {\n    isDirty.current = true\n    setLud16(address)\n  }\n\n  function editor() {\n    return (\n      <div className=\"flex flex-col gap-4\">\n        <div className=\"flex flex-col gap-2\">\n          <h4>\n            <FormattedMessage defaultMessage=\"Name\" />\n          </h4>\n          <input\n            className=\"\"\n            type=\"text\"\n            value={name}\n            onChange={e => onLimitCheck(e.target.value, \"username\")}\n            disabled={readonly}\n            maxLength={MaxUsernameLength}\n          />\n          <div>{usernameValid === false ? <span className=\"warning\">{invalidUsernameMessage}</span> : <></>}</div>\n        </div>\n        <div className=\"flex flex-col gap-2\">\n          <h4>\n            <FormattedMessage defaultMessage=\"About\" />\n          </h4>\n          <textarea\n            className=\"\"\n            onChange={e => onLimitCheck(e.target.value, \"about\")}\n            value={about}\n            disabled={readonly}\n            maxLength={MaxAboutLength}\n          ></textarea>\n          <div>{aboutValid === false ? <span className=\"warning\">{invalidAboutMessage}</span> : <></>}</div>\n        </div>\n        <div className=\"flex flex-col gap-2\">\n          <h4>\n            <FormattedMessage defaultMessage=\"Website\" />\n          </h4>\n          <input\n            className=\"\"\n            type=\"text\"\n            value={website}\n            onChange={e => {\n              isDirty.current = true\n              setWebsite(e.target.value)\n            }}\n            disabled={readonly}\n          />\n        </div>\n        <div className=\"flex flex-col gap-2\">\n          <h4>\n            <FormattedMessage defaultMessage=\"Nostr Address\" />\n          </h4>\n          <div className=\"flex flex-col gap-2 \">\n            <input type=\"text\" className=\"\" value={nip05} onChange={e => onNip05Change(e)} disabled={readonly} />\n            <div>{!nip05AddressValid && <span className=\"warning\">{invalidNip05AddressMessage}</span>}</div>\n            <small>\n              <FormattedMessage defaultMessage=\"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\" />\n            </small>\n            <div className=\"flex gap-3\">\n              <Link to=\"/nostr-address\">\n                <button>\n                  <FormattedMessage defaultMessage=\"Buy nostr address\" />\n                </button>\n              </Link>\n              {/* <Link to=\"/free-nostr-address\">\n                <button className=\"secondary\">\n                  <FormattedMessage defaultMessage=\"Get a free one\" />\n                </button>\n              </Link> */}\n            </div>\n          </div>\n        </div>\n        <div className=\"flex flex-col gap-2\">\n          <h4>\n            <FormattedMessage defaultMessage=\"Lightning Address\" />\n          </h4>\n          <input\n            className=\"\"\n            type=\"text\"\n            value={lud16}\n            onChange={e => onLud16Change(e.target.value.toLowerCase())}\n            disabled={readonly}\n          />\n          <div>{lud16Valid === false ? <span className=\"warning\">{invalidLud16Message}</span> : <></>}</div>\n        </div>\n        <AsyncButton className=\"primary\" onClick={() => saveProfile()} disabled={readonly}>\n          <FormattedMessage defaultMessage=\"Save\" />\n        </AsyncButton>\n      </div>\n    )\n  }\n\n  function settings() {\n    if (!publicKey) return null\n    return (\n      <>\n        <div className=\"flex flex-col gap-2\">\n          {(props.banner ?? true) && (\n            <div\n              style={{\n                background: (banner?.length ?? 0) > 0 ? `no-repeat center/cover url(\"${banner}\")` : undefined,\n              }}\n              className=\"bg-layer-1 -mx-3 min-h-[140px] flex items-center justify-center\"\n            >\n              <AsyncButton onClick={() => setNewBanner()} disabled={readonly}>\n                <FormattedMessage defaultMessage=\"Upload Banner\" />\n              </AsyncButton>\n            </div>\n          )}\n          {(props.avatar ?? true) && <AvatarEditor onPictureChange={p => setPicture(p)} picture={picture} />}\n        </div>\n        {error && <ErrorOrOffline error={error} />}\n        {editor()}\n      </>\n    )\n  }\n\n  return <div className=\"settings\">{settings()}</div>\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/Referrals.tsx",
    "content": "import { useCallback } from \"react\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport { LeaderBadge } from \"@/Components/CommunityLeaders/LeaderBadge\"\nimport Copy from \"@/Components/Copy/Copy\"\nimport SnortApi, { type RefCodeResponse } from \"@/External/SnortApi\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport { useCached } from \"@snort/system-react\"\n\nexport function ReferralsPage() {\n  const { publisher } = useEventPublisher()\n  const loader = useCallback(() => {\n    const api = new SnortApi(undefined, publisher?.signer)\n    return api.getRefCode()\n  }, [publisher])\n  const { data: refCode, reloadNow } = useCached<RefCodeResponse>(\n    publisher ? `ref:${publisher.pubKey}` : undefined,\n    loader,\n    60 * 60 * 24,\n  )\n\n  async function applyNow() {\n    const api = new SnortApi(undefined, publisher?.signer)\n    await api.applyForLeader()\n    await reloadNow()\n  }\n\n  function becomeLeader() {\n    return (\n      <>\n        <h2>\n          <FormattedMessage defaultMessage=\"Become a leader\" />\n        </h2>\n        <div className=\"flex items-center justify-between\">\n          <Link to=\"https://community.snort.social/\" target=\"_blank\">\n            <button>\n              <FormattedMessage defaultMessage=\"Learn more\" />\n            </button>\n          </Link>\n\n          <LeaderBadge />\n        </div>\n        <p>\n          <AsyncButton className=\"primary\" onClick={applyNow}>\n            <FormattedMessage defaultMessage=\"Apply Now\" />\n          </AsyncButton>\n        </p>\n      </>\n    )\n  }\n\n  function leaderPending() {\n    return (\n      <>\n        <h2>\n          <FormattedMessage defaultMessage=\"Become a leader\" />\n        </h2>\n        <div className=\"flex items-center justify-between\">\n          <Link to=\"https://community.snort.social/\" target=\"_blank\">\n            <button>\n              <FormattedMessage defaultMessage=\"Learn more\" />\n            </button>\n          </Link>\n\n          <LeaderBadge />\n        </div>\n        <h3>\n          <FormattedMessage defaultMessage=\"Your application is pending\" />\n        </h3>\n      </>\n    )\n  }\n\n  function leaderInfo() {\n    return (\n      <>\n        <h2>\n          <FormattedMessage defaultMessage=\"Leader Info\" />\n        </h2>\n        <p>\n          <FormattedMessage\n            defaultMessage=\"You are a community leader and are earning <b>{percent}</b> of referred users subscriptions!\"\n            id=\"bF1MYT\"\n            values={{\n              b: c => <b>{c}</b>,\n              percent: <FormattedNumber style=\"percent\" value={refCode?.revShare ?? 0} />,\n            }}\n          />\n        </p>\n        <p>\n          <FormattedMessage defaultMessage=\"Use your invite code to earn sats!\" />\n        </p>\n      </>\n    )\n  }\n\n  return (\n    <>\n      <h1>\n        <FormattedMessage defaultMessage=\"Invite your friends\" />\n      </h1>\n      <p>\n        <FormattedMessage\n          defaultMessage=\"Your referral code is {code}\"\n          id=\"UxgyeY\"\n          values={{\n            code: <span className=\"font-mono text-highlight select-all\">{refCode?.code}</span>,\n          }}\n        />\n      </p>\n      <p>\n        <FormattedMessage\n          defaultMessage=\"Send this link to your friends and share the magic of the nostr.\"\n          id=\"Ml7+RS\"\n        />\n      </p>\n      <div className=\"border rounded-lg px-3 py-2\">\n        <Copy text={`https://${window.location.host}?ref=${refCode?.code}`} maxSize={Number.MAX_VALUE} />\n      </div>\n      {refCode?.leaderState === undefined && becomeLeader()}\n      {refCode?.leaderState === \"pending\" && leaderPending()}\n      {refCode?.leaderState === \"approved\" && leaderInfo()}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/RelayInfo.tsx",
    "content": "import { Nip11, type RelayInfoDocument } from \"@snort/system\"\nimport { useEffect, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link, useParams } from \"react-router-dom\"\n\nimport { CollapsedSection } from \"@/Components/Collapsed\"\nimport NipDescription from \"@/Components/nip\"\nimport RelayPaymentLabel from \"@/Components/Relay/paid\"\nimport RelayPermissions from \"@/Components/Relay/permissions\"\nimport { RelayFavicon } from \"@/Components/Relay/RelaysMetadata\"\nimport RelaySoftware from \"@/Components/Relay/software\"\nimport RelayStatusLabel from \"@/Components/Relay/status-label\"\nimport RelayUptime from \"@/Components/Relay/uptime\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport useRelayState from \"@/Feed/RelayState\"\nimport { getRelayName, parseId } from \"@/Utils\"\n\nconst RelayInfo = () => {\n  const params = useParams()\n  const [info, setInfo] = useState<RelayInfoDocument>()\n\n  const conn = useRelayState(params.id ?? \"\")\n\n  useEffect(() => {\n    let cancelled = false\n    Nip11.loadRelayDocument(params.id ?? \"\")\n      .then(info => {\n        if (!cancelled) setInfo(info)\n      })\n      .catch(console.error)\n    return () => {\n      cancelled = true\n    }\n  }, [params.id])\n\n  return (\n    <div className=\"flex flex-col gap-4\">\n        <div className=\"flex justify-between\">\n          <div className=\"flex gap-4 items-center\">\n            <RelayFavicon url={params.id ?? \"\"} size={80} />\n            <div className=\"flex flex-col gap-2\">\n              <div className=\"flex items-center gap-2\">\n                <div className=\"text-2xl font-bold\">{info?.name ?? getRelayName(params.id ?? \"\")}</div>\n                {info && <RelayPaymentLabel info={info} />}\n              </div>\n              <div className=\"text-gray-light\">{params.id}</div>\n            </div>\n          </div>\n        </div>\n\n        {info && (\n          <div className=\"grid grid-cols-3 gap-4\">\n            <div className=\"flex flex-col gap-2\">\n              <div className=\"uppercase text-neutral-400 font-bold text-sm\">\n                <FormattedMessage defaultMessage=\"Admin\" />\n              </div>\n              <div>{info?.pubkey && <ProfileImage pubkey={parseId(info.pubkey)} size={30} />}</div>\n            </div>\n            <div className=\"flex flex-col gap-2\">\n              <div className=\"uppercase text-neutral-400 font-bold text-sm\">\n                <FormattedMessage defaultMessage=\"Contact\" />\n              </div>\n              <div>\n                {info?.contact && (\n                  <a\n                    href={`${info.contact.startsWith(\"mailto:\") ? \"\" : \"mailto:\"}${info.contact}`}\n                    target=\"_blank\"\n                    rel=\"noreferrer\"\n                  >\n                    {info.contact.replace(\"mailto:\", \"\")}\n                  </a>\n                )}\n              </div>\n            </div>\n            <div className=\"flex flex-col gap-2\">\n              <div className=\"uppercase text-neutral-400 font-bold text-sm\">\n                <FormattedMessage defaultMessage=\"Software\" />\n              </div>\n              <div>{info?.software && <RelaySoftware software={info.software} />}</div>\n            </div>\n            {conn && (\n              <>\n                <div className=\"flex flex-col gap-2\">\n                  <div className=\"uppercase text-neutral-400 font-bold text-sm\">\n                    <FormattedMessage defaultMessage=\"Status\" />\n                  </div>\n                  <div>\n                    <RelayStatusLabel conn={conn} />\n                  </div>\n                </div>\n                <div className=\"flex flex-col gap-2\">\n                  <div className=\"uppercase text-neutral-400 font-bold text-sm\">\n                    <FormattedMessage defaultMessage=\"Permissions\" />\n                  </div>\n                  <div>\n                    <RelayPermissions conn={conn} />\n                  </div>\n                </div>\n                <div className=\"flex flex-col gap-2\">\n                  <div className=\"uppercase text-neutral-400 font-bold text-sm\">\n                    <FormattedMessage defaultMessage=\"Uptime\" />\n                  </div>\n                  <div>\n                    <RelayUptime url={conn.address} />\n                  </div>\n                </div>\n              </>\n            )}\n          </div>\n        )}\n\n        <hr />\n        <div className=\"flex gap-4\">\n          <Link to={`/relay/${encodeURIComponent(params.id ?? \"\")}`}>\n            <button>\n              <FormattedMessage defaultMessage=\"View Feed\" />\n            </button>\n          </Link>\n        </div>\n        <hr />\n\n        {/* {stats && (\n          <CollapsedSection\n            title={\n              <div className=\"text-xl font-semibold\">\n                <FormattedMessage defaultMessage=\"Relay Stats\" />\n              </div>\n            }\n            startClosed={false}>\n            <ul className=\"list-disc\">\n              <li>\n                <span className=\"text-gray-light\">\n                  <FormattedMessage defaultMessage=\"Total Events:\" />\n                </span>\n                &nbsp;\n                <FormattedNumber value={stats.events} />\n              </li>\n              <li>\n                <span className=\"text-gray-light\">\n                  <FormattedMessage defaultMessage=\"Connection Success:\" />\n                </span>\n                &nbsp;\n                <FormattedNumber value={stats.connects} />\n              </li>\n              <li>\n                <span className=\"text-gray-light\">\n                  <FormattedMessage defaultMessage=\"Connection Failed:\" />\n                </span>\n                &nbsp;\n                <FormattedNumber value={stats.disconnects} />\n              </li>\n              <li>\n                <span className=\"text-gray-light\">\n                  <FormattedMessage defaultMessage=\"Average Latency:\" />\n                </span>\n                &nbsp;\n                <FormattedMessage\n                  defaultMessage=\"{n} ms\"\n                  values={{\n                    n: (\n                      <FormattedNumber\n                        maximumFractionDigits={0}\n                        value={stats.latency.reduce((acc, v) => acc + v, 0) / stats.latency.length}\n                      />\n                    ),\n                  }}\n                />\n              </li>\n              <li>\n                <span className=\"text-gray-light\">\n                  <FormattedMessage defaultMessage=\"Last Seen:\" />\n                </span>\n                &nbsp;\n                {new Date(stats.lastSeen).toLocaleString()}\n              </li>\n            </ul>\n          </CollapsedSection>\n        )} */}\n        <hr />\n        {info?.supported_nips && (\n          <CollapsedSection\n            title={\n              <div className=\"text-xl font-semibold\">\n                <FormattedMessage defaultMessage=\"Supported NIPs\" />\n              </div>\n            }\n            startClosed={false}\n          >\n            <ul className=\"list-disc\">\n              {info.supported_nips.map(n => (\n                <li key={n}>\n                  <Link\n                    target=\"_blank\"\n                    to={`https://github.com/nostr-protocol/nips/blob/master/${n.toString().padStart(2, \"0\")}.md`}\n                  >\n                    <NipDescription nip={n} />\n                  </Link>\n                </li>\n              ))}\n            </ul>\n          </CollapsedSection>\n        )}\n      </div>\n  )\n}\n\nexport default RelayInfo\n"
  },
  {
    "path": "packages/app/src/Pages/settings/Relays.tsx",
    "content": "import { removeUndefined } from \"@snort/shared\"\nimport { useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport Relay from \"@/Components/Relay/Relay\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport useRelays from \"@/Hooks/useRelays\"\nimport { saveRelays } from \"@/Pages/settings/saveRelays\"\nimport { sanitizeRelayUrl } from \"@/Utils\"\n\nimport { DiscoverRelays } from \"./relays/discover\"\n\nconst RelaySettingsPage = () => {\n  const { publisher, system } = useEventPublisher()\n  const relays = useRelays()\n  const { readonly, state } = useLogin(s => ({ v: s.state.version, state: s.state, readonly: s.readonly }))\n  const [newRelay, setNewRelay] = useState<string>()\n\n  async function addNewRelay() {\n    const urls = removeUndefined(\n      (newRelay?.trim()?.split(\"\\n\") ?? []).map(a => {\n        if (!a.startsWith(\"wss://\") && !a.startsWith(\"ws://\")) {\n          a = `wss://${a}`\n        }\n        return sanitizeRelayUrl(a)\n      }),\n    )\n    for (const url of urls) {\n      state.addRelay(url, { read: true, write: true })\n    }\n    // Note: Not saving here - caller should handle persistence if needed\n    setNewRelay(\"\")\n  }\n\n  function addRelay() {\n    return (\n      <div className=\"flex flex-col gap-2\">\n        <div className=\"text-xl\">\n          <FormattedMessage defaultMessage=\"Add Relays\" />\n        </div>\n        <small>\n          <FormattedMessage defaultMessage=\"You can add a single or multiple relays, one per line.\" />\n        </small>\n        <textarea\n          placeholder=\"wss://my-relay.com\"\n          rows={4}\n          value={newRelay}\n          onChange={e => setNewRelay(e.target.value)}\n        />\n        <div>\n          <AsyncButton className=\"secondary\" onClick={() => addNewRelay()}>\n            <FormattedMessage defaultMessage=\"Add\" />\n          </AsyncButton>\n        </div>\n      </div>\n    )\n  }\n\n  function myRelays() {\n    return (\n      <div className=\"flex flex-col gap-2\">\n        <div className=\"text-xl font-medium\">\n          <FormattedMessage defaultMessage=\"My Relays\" />\n        </div>\n        <small>\n          <FormattedMessage defaultMessage=\"Relays are servers you connect to for sending and receiving events. Aim for 4-8 relays.\" />\n        </small>\n        <small>\n          <FormattedMessage defaultMessage=\"The relay name shown is not the same as the full URL entered.\" />\n        </small>\n        <table className=\"table-auto w-full\">\n          <thead>\n            <tr className=\"uppercase text-neutral-400\">\n              <th>\n                <FormattedMessage defaultMessage=\"Relay\" description=\"Relay name (URL)\" />\n              </th>\n              <th>\n                <FormattedMessage defaultMessage=\"Status\" />\n              </th>\n              <th>\n                <FormattedMessage defaultMessage=\"Permissions\" />\n              </th>\n              <th>\n                <FormattedMessage defaultMessage=\"Uptime\" />\n              </th>\n              <th></th>\n            </tr>\n          </thead>\n          <tbody>\n            {Object.keys(relays || {}).map(a => (\n              <Relay addr={a} key={a} />\n            ))}\n          </tbody>\n        </table>\n        <div>\n          <AsyncButton onClick={() => saveRelays(system, publisher, relays)} disabled={readonly}>\n            <FormattedMessage defaultMessage=\"Save\" />\n          </AsyncButton>\n        </div>\n      </div>\n    )\n  }\n\n  return (\n    <div className=\"flex flex-col gap-4\">\n      {myRelays()}\n      {addRelay()}\n      <DiscoverRelays />\n    </div>\n  )\n}\n\nexport default RelaySettingsPage\n"
  },
  {
    "path": "packages/app/src/Pages/settings/Routes.tsx",
    "content": "import { Outlet } from \"react-router-dom\"\n\nimport { ManageHandleRoutes } from \"@/Pages/settings/handle/routes\"\n\nimport { ToolsPages } from \"./tools/routes\"\nimport { WalletSettingsRoutes } from \"./wallet/routes\"\n\nexport default [\n  {\n    path: \"/settings\",\n    element: (\n      <div className=\"px-3\">\n        <Outlet />\n      </div>\n    ),\n    children: [\n      {\n        path: \"\",\n        async lazy() {\n          const { Menu } = await import(\".\")\n          return { Component: Menu }\n        },\n      },\n      {\n        path: \"profile\",\n        async lazy() {\n          const { Profile } = await import(\".\")\n          return { Component: Profile }\n        },\n      },\n      {\n        path: \"relays\",\n        async lazy() {\n          const { Relay } = await import(\".\")\n          return { Component: Relay }\n        },\n      },\n      {\n        path: \"relays/:id\",\n        async lazy() {\n          const { RelayInfo } = await import(\".\")\n          return { Component: RelayInfo }\n        },\n      },\n      {\n        path: \"preferences\",\n        async lazy() {\n          const { Preferences } = await import(\".\")\n          return { Component: Preferences }\n        },\n      },\n      {\n        path: \"notifications\",\n        async lazy() {\n          const { Notifications } = await import(\".\")\n          return { Component: Notifications }\n        },\n      },\n      {\n        path: \"accounts\",\n        async lazy() {\n          const { AccountsPage } = await import(\".\")\n          return { Component: AccountsPage }\n        },\n      },\n      {\n        path: \"keys\",\n        async lazy() {\n          const { ExportKeys } = await import(\".\")\n          return { Component: ExportKeys }\n        },\n      },\n      {\n        path: \"moderation\",\n        async lazy() {\n          const { ModerationSettings } = await import(\".\")\n          return { Component: ModerationSettings }\n        },\n      },\n      {\n        path: \"cache\",\n        async lazy() {\n          const { CacheSettings } = await import(\".\")\n          return { Component: CacheSettings }\n        },\n      },\n      {\n        path: \"media\",\n        async lazy() {\n          const { MediaSettingsPage } = await import(\".\")\n          return { Component: MediaSettingsPage }\n        },\n      },\n      {\n        path: \"invite\",\n        async lazy() {\n          const { ReferralsPage } = await import(\".\")\n          return { Component: ReferralsPage }\n        },\n      },\n      {\n        path: \"tools\",\n        async lazy() {\n          const { ToolsPage } = await import(\".\")\n          return { Component: ToolsPage }\n        },\n        children: ToolsPages,\n      },\n      ...ManageHandleRoutes,\n      ...WalletSettingsRoutes,\n    ],\n  },\n]\n"
  },
  {
    "path": "packages/app/src/Pages/settings/SnortNostrAddressService.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\nimport { ApiHost } from \"@/Utils/Const\"\n\nexport const SnortNostrAddressService = {\n  name: CONFIG.appNameCapitalized,\n  service: `${ApiHost}/api/v1/n5sp`,\n  link: `https://${CONFIG.hostname}`,\n  supportLink: `https://${CONFIG.hostname}/help`,\n  about: (\n    <FormattedMessage defaultMessage=\"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\" />\n  ),\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/WalletSettings.tsx",
    "content": "import type { ReactNode } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport AlbyIcon from \"@/Components/Icons/Alby\"\nimport BlueWallet from \"@/Components/Icons/BlueWallet\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport NWCIcon from \"@/Components/Icons/NWC\"\nimport { getAlbyOAuth } from \"@/Pages/settings/wallet/utils\"\n\nconst WalletRow = (props: {\n  logo: ReactNode\n  name: ReactNode\n  url: string\n  desc?: ReactNode\n  onClick?: () => void\n}) => {\n  const navigate = useNavigate()\n  return (\n    <div\n      className=\"flex items-center gap-4 px-4 py-2 layer-1-hover\"\n      onClick={() => {\n        if (props.onClick) {\n          props.onClick()\n        } else {\n          if (props.url.startsWith(\"http\")) {\n            window.location.href = props.url\n          } else {\n            navigate(props.url)\n          }\n        }\n      }}\n    >\n      <div className=\"aspect-square layer-2 p-3 flex items-center justify-center\">{props.logo}</div>\n      <div className=\"flex flex-col gap-1 grow justify-center\">\n        <div className=\"text-xl font-bold\">{props.name}</div>\n        <small>{props.desc}</small>\n      </div>\n      <Icon name=\"arrowFront\" />\n    </div>\n  )\n}\n\nconst WalletSettings = () => {\n  return (\n    <>\n      <h3>\n        <FormattedMessage defaultMessage=\"Connect Wallet\" />\n      </h3>\n      <div className=\"flex flex-col gap-3 cursor-pointer\">\n        <WalletRow\n          logo={<NWCIcon width={64} height={64} />}\n          name=\"Nostr Wallet Connect\"\n          url=\"/settings/wallet/nwc\"\n          desc={<FormattedMessage defaultMessage=\"Native nostr wallet connection\" />}\n        />\n        <WalletRow\n          logo={<BlueWallet width={64} height={64} />}\n          name=\"LNDHub\"\n          url=\"/settings/wallet/lndhub\"\n          desc={<FormattedMessage defaultMessage=\"Generic LNDHub wallet (BTCPayServer / Alby / LNBits)\" />}\n        />\n        {CONFIG.alby && (\n          <WalletRow\n            logo={<AlbyIcon size={64} />}\n            name=\"Alby\"\n            url={\"\"}\n            onClick={() => {\n              const alby = getAlbyOAuth()\n              window.location.href = alby.getAuthUrl()\n            }}\n            desc={<FormattedMessage defaultMessage=\"Alby wallet connection\" />}\n          />\n        )}\n      </div>\n    </>\n  )\n}\n\nexport default WalletSettings\n"
  },
  {
    "path": "packages/app/src/Pages/settings/handle/LNAddress.tsx",
    "content": "import { LNURL } from \"@snort/shared\"\nimport { useEffect, useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport { ApiHost } from \"@/Utils/Const\"\nimport SnortServiceProvider, { ForwardType, type ManageHandle } from \"@/Utils/Nip05/SnortServiceProvider\"\n\nexport default function LNForwardAddress({ handle }: { handle: ManageHandle }) {\n  const { formatMessage } = useIntl()\n  const { publisher } = useEventPublisher()\n\n  const [newAddress, setNewAddress] = useState(handle.lnAddress ?? \"\")\n  const [fwdType, setFwdType] = useState(handle.forwardType ?? ForwardType.Redirect)\n  const [error, setError] = useState(\"\")\n\n  useEffect(() => {\n    setNewAddress(handle.lnAddress ?? \"\")\n    setFwdType(handle.forwardType ?? ForwardType.Redirect)\n  }, [handle.lnAddress, handle.forwardType])\n\n  async function startUpdate() {\n    if (!publisher) return\n\n    const req = {\n      lnAddress: newAddress,\n      forwardType: fwdType,\n    }\n\n    setError(\"\")\n    try {\n      const svc = new LNURL(newAddress)\n      await svc.load()\n    } catch {\n      setError(\n        formatMessage({\n          defaultMessage: \"Invalid LNURL\",\n          id: \"0jOEtS\",\n        }),\n      )\n      return\n    }\n\n    const sp = new SnortServiceProvider(publisher, `${ApiHost}/api/v1/n5sp`)\n    const rsp = await sp.patch(handle.id, req)\n    if (\"error\" in rsp) {\n      setError(rsp.error)\n    }\n  }\n\n  return (\n    <>\n      <h4>\n        <FormattedMessage defaultMessage=\"Update Lightning Address\" />\n      </h4>\n      <FormattedMessage defaultMessage=\"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\" />\n\n      <ul className=\"list-disc\">\n        <li>\n          <FormattedMessage defaultMessage=\"Redirect issues HTTP redirect to the supplied lightning address\" />\n        </li>\n        <li>\n          <FormattedMessage defaultMessage=\"Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node\" />\n        </li>\n      </ul>\n      <div className=\"flex gap-2\">\n        <input\n          type=\"text\"\n          className=\"grow\"\n          placeholder={formatMessage({\n            defaultMessage: \"LNURL or Lightning Address\",\n          })}\n          value={newAddress}\n          onChange={e => setNewAddress(e.target.value)}\n        />\n        <select value={fwdType} onChange={e => setFwdType(Number(e.target.value))}>\n          <option value={ForwardType.Redirect}>Redirect</option>\n          <option value={ForwardType.ProxyDirect}>Proxy</option>\n        </select>\n        <AsyncButton onClick={() => startUpdate()}>\n          <FormattedMessage defaultMessage=\"Update\" />\n        </AsyncButton>\n      </div>\n      {error && <b className=\"error\">{error}</b>}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/handle/ListHandles.tsx",
    "content": "import { useCallback, useEffect, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport { ErrorOrOffline } from \"@/Components/ErrorOrOffline\"\nimport Nip05 from \"@/Components/User/Nip05\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport { ApiHost } from \"@/Utils/Const\"\nimport SnortServiceProvider, { type ManageHandle } from \"@/Utils/Nip05/SnortServiceProvider\"\n\nexport default function ListHandles() {\n  const { publisher } = useEventPublisher()\n  const [handles, setHandles] = useState<Array<ManageHandle>>([])\n  const [error, setError] = useState<Error>()\n\n  const loadHandles = useCallback(async () => {\n    if (!publisher) return\n    const sp = new SnortServiceProvider(publisher, `${ApiHost}/api/v1/n5sp`)\n    const list = await sp.list()\n    setHandles(list as Array<ManageHandle>)\n  }, [publisher])\n\n  useEffect(() => {\n    let cancelled = false\n    loadHandles().catch(e => {\n      if (!cancelled && e instanceof Error) {\n        setError(e)\n      }\n    })\n    return () => {\n      cancelled = true\n    }\n  }, [loadHandles])\n\n  return (\n    <div className=\"flex flex-col gap-4\">\n      {handles.length === 0 && (\n        <small>\n          <FormattedMessage defaultMessage=\"No handles found\" />\n        </small>\n      )}\n      {handles.map(a => (\n        <div className=\"flex items-center justify-between\" key={a.id}>\n          <h4>{publisher?.pubKey && <Nip05 pubkey={publisher?.pubKey} nip05={`${a.handle}@${a.domain}`} />}</h4>\n          <Link to=\"manage\" state={a}>\n            <button>\n              <FormattedMessage defaultMessage=\"Manage\" />\n            </button>\n          </Link>\n        </div>\n      ))}\n      <Link to=\"/nostr-address\">\n        <button>\n          <FormattedMessage defaultMessage=\"Buy Nostr Address\" />\n        </button>\n      </Link>\n\n      {error && <ErrorOrOffline error={error} onRetry={loadHandles} />}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/handle/Manage.tsx",
    "content": "import { Navigate, useLocation } from \"react-router-dom\"\n\nimport type { ManageHandle } from \"@/Utils/Nip05/SnortServiceProvider\"\n\nimport LNForwardAddress from \"./LNAddress\"\nimport TransferHandle from \"./TransferHandle\"\nimport Nip05 from \"@/Components/User/Nip05\"\n\nexport default function ManageHandleIndex() {\n  const location = useLocation()\n  const handle = location.state as ManageHandle\n  if (!handle) {\n    return <Navigate to=\"/settings/handle\" />\n  }\n  return (\n    <div className=\"flex flex-col gap-4\">\n      <h4>\n        <Nip05 nip05={`${handle.handle}@${handle.domain}`} />\n      </h4>\n      <LNForwardAddress handle={handle} />\n      <TransferHandle handle={handle} />\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/handle/TransferHandle.tsx",
    "content": "import { useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport { ApiHost } from \"@/Utils/Const\"\nimport type { ServiceError } from \"@/Utils/Nip05/ServiceProvider\"\nimport SnortServiceProvider, { type ManageHandle } from \"@/Utils/Nip05/SnortServiceProvider\"\n\nexport default function TransferHandle({ handle }: { handle: ManageHandle }) {\n  const { publisher } = useEventPublisher()\n  const navigate = useNavigate()\n  const { formatMessage } = useIntl()\n\n  const [newKey, setNewKey] = useState(\"\")\n  const [error, setError] = useState<Array<string>>([])\n\n  async function startTransfer() {\n    if (!newKey || !publisher) return\n    const sp = new SnortServiceProvider(publisher, `${ApiHost}/api/v1/n5sp`)\n    setError([])\n    const rsp = await sp.transfer(handle.id, newKey)\n    if (\"error\" in rsp) {\n      setError((rsp as ServiceError).errors)\n      return\n    }\n    navigate(-1)\n  }\n\n  return (\n    <>\n      <h4>\n        <FormattedMessage defaultMessage=\"Transfer to Pubkey\" />\n      </h4>\n      <div className=\"flex items-center gap-2\">\n        <input\n          type=\"text\"\n          className=\"grow\"\n          placeholder={formatMessage({\n            defaultMessage: \"Public key (npub/nprofile)\",\n          })}\n          value={newKey}\n          onChange={e => setNewKey(e.target.value)}\n        />\n        <AsyncButton onClick={() => startTransfer()}>\n          <FormattedMessage defaultMessage=\"Transfer\" />\n        </AsyncButton>\n      </div>\n      {error && <b className=\"error\">{error}</b>}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/handle/index.tsx",
    "content": "export { default as ListHandles } from \"./ListHandles\"\nexport { default as ManageHandleIndex } from \"./Manage\"\n"
  },
  {
    "path": "packages/app/src/Pages/settings/handle/routes.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\nimport { Link, Outlet, type RouteObject } from \"react-router-dom\"\n\nfunction ManageHandlePage() {\n  return (\n    <>\n      <Link to={ManageHandleRoutes[0].path!}>\n        <h3>\n          <FormattedMessage defaultMessage=\"Nostr Address\" />\n        </h3>\n      </Link>\n      <Outlet />\n    </>\n  )\n}\n\nexport const ManageHandleRoutes = [\n  {\n    path: \"/settings/handle\",\n    element: <ManageHandlePage />,\n    children: [\n      {\n        index: true,\n        async lazy() {\n          const { ListHandles } = await import(\"..\")\n          return { Component: ListHandles }\n        },\n      },\n      {\n        path: \"manage\",\n        async lazy() {\n          const { ManageHandleIndex } = await import(\"..\")\n          return { Component: ManageHandleIndex }\n        },\n      },\n    ],\n  },\n] as Array<RouteObject>\n"
  },
  {
    "path": "packages/app/src/Pages/settings/index.tsx",
    "content": "// Main settings pages\nexport { default as AccountsPage } from \"./Accounts\"\nexport { CacheSettings } from \"./Cache\"\nexport { default as ExportKeys } from \"./Keys\"\nexport { default as MediaSettingsPage } from \"./media-settings\"\nexport { default as Menu } from \"./Menu/Menu\"\nexport { default as ModerationSettings } from \"./Moderation\"\nexport { default as Notifications } from \"./Notifications\"\nexport { default as Preferences } from \"./Preferences\"\nexport { default as Profile } from \"./Profile\"\nexport { ReferralsPage } from \"./Referrals\"\nexport { default as RelayInfo } from \"./RelayInfo\"\nexport { default as Relay } from \"./Relays\"\n\n// Tools pages\nexport { FollowsRelayHealth, PruneFollowList, SyncAccountTool, ToolsPage } from \"./tools\"\n\n// Wallet pages\nexport { WalletSettings, AlbyOAuth, ConnectLNDHub, ConnectNostrWallet } from \"./wallet\"\n\n// Handle pages\nexport { ListHandles, ManageHandleIndex } from \"./handle\"\n"
  },
  {
    "path": "packages/app/src/Pages/settings/media-settings.tsx",
    "content": "import { sanitizeRelayUrl, unwrap } from \"@snort/shared\"\nimport { EventKind, UnknownTag } from \"@snort/system\"\nimport { useState } from \"react\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport IconButton from \"@/Components/Button/IconButton\"\nimport { CollapsedSection } from \"@/Components/Collapsed\"\nimport { RelayFavicon } from \"@/Components/Relay/RelaysMetadata\"\nimport useDiscoverMediaServers from \"@/Hooks/useDiscoverMediaServers\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { getRelayName } from \"@/Utils\"\n\nexport default function MediaSettingsPage() {\n  const { state } = useLogin(s => ({ v: s.state.version, state: s.state }))\n  const list = state.getList(EventKind.BlossomServerList)\n  const [newServer, setNewServer] = useState(\"\")\n  const knownServers = useDiscoverMediaServers()\n\n  return (\n    <div className=\"flex flex-col gap-3\">\n      <div className=\"text-xl\">\n        <FormattedMessage defaultMessage=\"Media Servers\" />\n      </div>\n      <p>\n        <FormattedMessage defaultMessage=\"Media servers store media which you can share in notes as images and videos\" />\n      </p>\n      <div className=\"flex flex-col gap-3\">\n        {list.map(a => {\n          const [, addr] = unwrap(a.toEventTag())\n          return (\n            <div key={addr} className=\"layer-1 flex justify-between items-center\">\n              {addr}\n              <IconButton\n                icon={{\n                  name: \"trash\",\n                  size: 15,\n                }}\n                onClick={async () => {\n                  state.removeFromList(EventKind.BlossomServerList, [new UnknownTag([\"server\", addr])], true)\n                }}\n              />\n            </div>\n          )\n        })}\n        {list.length === 0 && (\n          <small>\n            <FormattedMessage defaultMessage=\"You dont have any media servers, try adding some.\" />\n          </small>\n        )}\n      </div>\n      <div className=\"layer-1 flex flex-col gap-2\">\n        <div className=\"text-lg\">\n          <FormattedMessage defaultMessage=\"Add Server\" />\n        </div>\n        <div className=\"flex gap-2\">\n          <input\n            type=\"text\"\n            className=\"flex-grow\"\n            placeholder=\"https://my-files.com/\"\n            value={newServer}\n            onChange={e => setNewServer(e.target.value)}\n          />\n          <AsyncButton\n            onClick={async () => {\n              if (sanitizeRelayUrl(newServer)) {\n                state.addToList(\n                  EventKind.BlossomServerList,\n                  [new UnknownTag([\"server\", new URL(newServer).toString()])],\n                  true,\n                )\n                setNewServer(\"\")\n              }\n            }}\n          >\n            <FormattedMessage defaultMessage=\"Add\" />\n          </AsyncButton>\n        </div>\n      </div>\n      <CollapsedSection\n        title={\n          <div className=\"text-xl font-medium\">\n            <FormattedMessage defaultMessage=\"Popular Servers\" />\n          </div>\n        }\n      >\n        <small>\n          <FormattedMessage defaultMessage=\"Popular media servers.\" />\n        </small>\n        <table className=\"table-auto w-full\">\n          <thead>\n            <tr className=\"uppercase text-neutral-400\">\n              <th>\n                <FormattedMessage defaultMessage=\"Server\" />\n              </th>\n              <th>\n                <FormattedMessage defaultMessage=\"Users\" />\n              </th>\n              <th></th>\n            </tr>\n          </thead>\n          <tbody>\n            {Object.entries(knownServers)\n              .sort((a, b) => (b[1] < a[1] ? -1 : 1))\n              .slice(0, 20)\n              .map(([k, v]) => (\n                <tr key={k}>\n                  <td className=\"flex gap-2 items-center\">\n                    <RelayFavicon url={k} />\n                    {getRelayName(k)}\n                  </td>\n                  <td className=\"text-center\">\n                    <FormattedNumber value={v} />\n                  </td>\n                  <td className=\"text-end\">\n                    <AsyncButton\n                      className=\"!py-1 mb-1\"\n                      disabled={list.some(b => b.equals(new UnknownTag([\"server\", k])))}\n                      onClick={async () => {\n                        state.addToList(EventKind.BlossomServerList, [new UnknownTag([\"server\", k])], true)\n                      }}\n                    >\n                      <FormattedMessage defaultMessage=\"Add\" />\n                    </AsyncButton>\n                  </td>\n                </tr>\n              ))}\n          </tbody>\n        </table>\n      </CollapsedSection>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/messages.ts",
    "content": "import { defineMessages } from \"react-intl\"\n\nexport default defineMessages({\n  Profile: { defaultMessage: \"Profile\", id: \"itPgxd\" },\n  Relays: { defaultMessage: \"Relays\", id: \"RoOyAh\" },\n  Owner: { defaultMessage: \"Owner\", id: \"zINlao\" },\n  Software: { defaultMessage: \"Software\", id: \"r3C4x/\" },\n  Contact: { defaultMessage: \"Contact\", id: \"zFegDD\" },\n  Supports: { defaultMessage: \"Supports\", id: \"hY4lzx\" },\n  Remove: { defaultMessage: \"Remove\", id: \"G/yZLu\" },\n  Preferences: { defaultMessage: \"Preferences\", id: \"PCSt5T\" },\n  Donate: { defaultMessage: \"Donate\", id: \"2IFGap\" },\n  LogOut: { defaultMessage: \"Log Out\", id: \"H0JBH6\" },\n  Theme: { defaultMessage: \"Theme\", id: \"Pe0ogR\" },\n  System: { defaultMessage: \"System (Default)\", id: \"P7FD0F\" },\n  Light: { defaultMessage: \"Light\", id: \"3cc4Ct\" },\n  Dark: { defaultMessage: \"Dark\", id: \"tOdNiY\" },\n  DefaultRootTab: { defaultMessage: \"Default Page\", id: \"MWTx65\" },\n  Conversations: { defaultMessage: \"Conversations\", id: \"1udzha\" },\n  Global: { defaultMessage: \"Global\", id: \"EWyQH5\" },\n  AutoloadMedia: { defaultMessage: \"Automatically load media\", id: \"xbVgIm\" },\n  AutoloadMediaHelp: {\n    defaultMessage: \"Media in notes will automatically be shown for selected people, otherwise only the link will show\",\n    id: \"TDR5ge\",\n  },\n  None: { defaultMessage: \"None\", id: \"450Fty\" },\n  FollowsOnly: { defaultMessage: \"Follows only\", id: \"odFwjL\" },\n  All: { defaultMessage: \"All\", id: \"zQvVDJ\" },\n  ImgProxy: { defaultMessage: \"Image proxy service\", id: \"ll3xBp\" },\n  ImgProxyHelp: { defaultMessage: \"Use imgproxy to compress images\", id: \"4Z3t5i\" },\n  ServiceUrl: { defaultMessage: \"Service URL\", id: \"YDURw6\" },\n  ServiceKey: { defaultMessage: \"Key\", id: \"EcglP9\" },\n  ServiceSalt: { defaultMessage: \"Salt\", id: \"GFOoEE\" },\n  EnableReactions: { defaultMessage: \"Enable reactions\", id: \"YXA3AH\" },\n  EnableReactionsHelp: {\n    defaultMessage: \"Reactions will be shown on every page, if disabled no reactions will be shown\",\n    id: \"PrsIg7\",\n  },\n  ConfirmReposts: { defaultMessage: \"Confirm Reposts\", id: \"89q5wc\" },\n  ConfirmRepostsHelp: { defaultMessage: \"Reposts need to be manually confirmed\", id: \"uSV4Ti\" },\n  ShowLatest: { defaultMessage: \"Automatically show latest notes\", id: \"zvCDao\" },\n  ShowLatestHelp: { defaultMessage: \"Notes will stream in real time into global and notes tab\", id: \"a7TDNm\" },\n  FileUpload: { defaultMessage: \"File upload service\", id: \"mKh2HS\" },\n  FileUploadHelp: { defaultMessage: \"Pick which upload service you want to upload attachments to\", id: \"VOjC1i\" },\n  Default: { defaultMessage: \"(Default)\", id: \"rfuMjE\" },\n  DebugMenus: { defaultMessage: \"Debug Menus\", id: \"M3Oirc\" },\n  DebugMenusHelp: {\n    defaultMessage: `Shows \"Copy ID\" and \"Copy Event JSON\" in the context menu on each message`,\n    id: \"MBAYRO\",\n  },\n  EditProfile: { defaultMessage: \"Edit Profile\", id: \"usAvMr\" },\n  About: { defaultMessage: \"About\", id: \"g5pX+a\" },\n  LnAddress: { defaultMessage: \"LN Address\", id: \"d7d0/x\" },\n  Avatar: { defaultMessage: \"Avatar\", id: \"VnXp8Z\" },\n  Banner: { defaultMessage: \"Banner\", id: \"25V4l1\" },\n  Edit: { defaultMessage: \"Edit\", id: \"wEQDC6\" },\n  PrivateKey: { defaultMessage: \"Your Private Key Is (do not share this with anyone)\", id: \"qdGuQo\" },\n  Add: { defaultMessage: \"Add\", id: \"2/2yg+\" },\n  AddRelays: { defaultMessage: \"Add Relays\", id: \"rT14Ow\" },\n  Name: { defaultMessage: \"Name\", id: \"HAlOn1\" },\n  Website: { defaultMessage: \"Website\", id: \"JkLHGw\" },\n  Save: { defaultMessage: \"Save\", id: \"jvo0vs\" },\n  DisplayName: { defaultMessage: \"Display name\", id: \"dOQCL8\" },\n  Buy: { defaultMessage: \"Buy\", id: \"EnCOBJ\" },\n  Nip05: { defaultMessage: \"NIP-05\", id: \"7hp70g\" },\n  ReactionEmoji: { defaultMessage: \"Reaction emoji\", id: \"eHAneD\" },\n  ReactionEmojiHelp: { defaultMessage: \"Emoji to send when reactiong to a note\", id: \"gDzDRs\" },\n  SocialGraph: { defaultMessage: \"Social Graph\", id: \"CzHZoc\" },\n  HasWriteAccess: { defaultMessage: \"Logged in with write access\", id: \"+UjDmN\" },\n  NoWriteAccess: { defaultMessage: \"Logged in with read-only access\", id: \"bMphls\" },\n  NotificationsApiEnabled: { defaultMessage: \"Notifications API Enabled\", id: \"5PRWs7\" },\n  NotificationsApiDisabled: { defaultMessage: \"Notifications API Disabled\", id: \"qcJFEJ\" },\n  NotificationsAllowed: { defaultMessage: \"Notifications Allowed\", id: \"nGGDsi\" },\n  NotificationsNotAllowed: { defaultMessage: \"Notifications Not Allowed\", id: \"J1iLmb\" },\n  ServiceWorkerRunning: { defaultMessage: \"Service Worker Running\", id: \"bG00/W\" },\n  ServiceWorkerNotRunning: { defaultMessage: \"Service Worker Not Running\", id: \"RDha9y\" },\n  SubscribedToPush: { defaultMessage: \"Subscribed to Push\", id: \"G3A56c\" },\n  NotSubscribedToPush: { defaultMessage: \"Not Subscribed to Push\", id: \"d2ebEu\" },\n  AgentUrl: { defaultMessage: \"Agent URL\", id: \"AgentUrl1\" },\n  AgentKey: { defaultMessage: \"Agent Key\", id: \"AgentKey1\" },\n})\n"
  },
  {
    "path": "packages/app/src/Pages/settings/relays/discover.tsx",
    "content": "import { dedupe } from \"@snort/shared\"\nimport { OutboxModel } from \"@snort/system\"\nimport { SnortContext } from \"@snort/system-react\"\nimport { use, useMemo } from \"react\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\nimport { Link } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport { CollapsedSection } from \"@/Components/Collapsed\"\nimport { RelayFavicon } from \"@/Components/Relay/RelaysMetadata\"\nimport RelayUptime from \"@/Components/Relay/uptime\"\nimport Uptime from \"@/Components/Relay/uptime\"\nimport { useCloseRelays } from \"@/Hooks/useCloseRelays\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { getRelayName } from \"@/Utils\"\n\nexport function DiscoverRelays() {\n  const { follows, relays, state } = useLogin(l => ({\n    follows: l.state.follows,\n    relays: l.state.relays,\n    v: l.state.version,\n    state: l.state,\n  }))\n  const system = use(SnortContext)\n\n  const topWriteRelays = useMemo(() => {\n    const outbox = OutboxModel.fromSystem(system)\n    return outbox\n      .pickTopRelays(follows ?? [], 1e31, \"write\")\n      .filter(a => !(relays?.some(b => b.url === a.key) ?? false))\n  }, [follows, relays, system])\n\n  // const metrics = useSyncExternalStore(\n  //   c => RelayMetrics.hook(c, \"*\"),\n  //   () => RelayMetrics.snapshot(),\n  // );\n  // /// Using collected relay metrics\n  // const reliableRelays = useMemo(\n  //   () =>\n  //     removeUndefined(\n  //       RelayMetrics.snapshot().map(a => {\n  //         const addr = sanitizeRelayUrl(a.addr);\n  //         if (!addr) return;\n  //         return {\n  //           ...a,\n  //           addr,\n  //           avgLatency: a.latency.reduce((acc, v) => acc + v, 0) / a.latency.length,\n  //         };\n  //       }),\n  //     )\n  //       .filter(a => a.connects > 0 && a.addr.startsWith(\"wss://\") && !relays?.some(b => b.url === a.addr))\n  //       .sort((a, b) =>\n  //         (isNaN(b.avgLatency) ? 99999 : b.avgLatency) > (isNaN(a.avgLatency) ? 99999 : a.avgLatency) ? -1 : 1,\n  //       ),\n  //   [relays, metrics],\n  // );\n\n  const closeRelays = useCloseRelays()\n  return (\n    <div className=\"flex flex-col gap-4\">\n      <CollapsedSection\n        title={\n          <div className=\"text-xl\">\n            <FormattedMessage defaultMessage=\"Popular Relays\" />\n          </div>\n        }\n      >\n        <small>\n          <FormattedMessage defaultMessage=\"Popular relays used by people you follow.\" />\n        </small>\n        <table className=\"table-auto w-full\">\n          <thead>\n            <tr className=\"text-gray-light uppercase\">\n              <th>\n                <FormattedMessage defaultMessage=\"Relay\" description=\"Relay name (URL)\" />\n              </th>\n              <th>\n                <FormattedMessage defaultMessage=\"Uptime\" />\n              </th>\n              <th>\n                <FormattedMessage defaultMessage=\"Users\" />\n              </th>\n              <th></th>\n            </tr>\n          </thead>\n          <tbody>\n            {dedupe(topWriteRelays.flatMap(a => a.relays))\n              .map(a => ({ relay: a, count: topWriteRelays.filter(b => b.relays.includes(a)).length }))\n              .sort((a, b) => (a.count > b.count ? -1 : 1))\n              .filter(a => !relays?.some(b => b.url === a.relay))\n              .slice(0, 20)\n              .map(a => (\n                <tr key={a.relay}>\n                  <td>\n                    <Link to={`/settings/relays/${encodeURIComponent(a.relay)}`} className=\"flex gap-2 items-center\">\n                      <RelayFavicon url={a.relay} />\n                      {getRelayName(a.relay)}\n                    </Link>\n                  </td>\n                  <td className=\"text-center\">\n                    <RelayUptime url={a.relay} />\n                  </td>\n                  <td className=\"text-center\">{a.count}</td>\n                  <td className=\"text-end\">\n                    <AsyncButton\n                      className=\"!py-1 mb-1\"\n                      onClick={() => {\n                        state.addRelay(a.relay, { read: true, write: true })\n                      }}\n                    >\n                      <FormattedMessage defaultMessage=\"Add\" />\n                    </AsyncButton>\n                  </td>\n                </tr>\n              ))}\n          </tbody>\n        </table>\n      </CollapsedSection>\n      {/* <CollapsedSection\n        title={\n          <div className=\"text-xl\">\n            <FormattedMessage defaultMessage=\"Reliable Relays\" />\n          </div>\n        }>\n        <small>\n          <FormattedMessage defaultMessage=\"Relays which you have connected to before and appear to be reliable.\" />\n        </small>\n        <table className=\"table-auto w-full\">\n          <thead>\n            <tr className=\"text-gray-light uppercase\">\n              <th>\n                <FormattedMessage defaultMessage=\"Relay\" description=\"Relay name (URL)\" />\n              </th>\n              <th>\n                <FormattedMessage defaultMessage=\"Uptime\" />\n              </th>\n              <th></th>\n            </tr>\n          </thead>\n          <tbody>\n            {reliableRelays.slice(0, 40).map(a => (\n              <tr key={a.addr}>\n                <td title={a.addr}>\n                  <Link to={`/settings/relays/${encodeURIComponent(a.addr)}`} className=\"flex gap-2 items-center\">\n                    <RelayFavicon url={a.addr} />\n                    {getRelayName(a.addr)}\n                  </Link>\n                </td>\n                <td className=\"text-center\">\n                  <UptimeLabel avgPing={a.avgLatency} />\n                </td>\n                <td className=\"text-end\">\n                  <AsyncButton\n                    className=\"!py-1 mb-1\"\n                    onClick={() => {\n                      state.addRelay(a.addr, { read: true, write: true });\n                    }}>\n                    <FormattedMessage defaultMessage=\"Add\" />\n                  </AsyncButton>\n                </td>\n              </tr>\n            ))}\n          </tbody>\n        </table>\n      </CollapsedSection> */}\n\n      <CollapsedSection\n        title={\n          <div className=\"text-xl\">\n            <FormattedMessage defaultMessage=\"Close Relays\" />\n          </div>\n        }\n      >\n        <small>\n          <FormattedMessage defaultMessage=\"Relays close to your geographic location.\" />\n        </small>\n        <table className=\"table-auto w-full\">\n          <thead>\n            <tr className=\"text-gray-light uppercase\">\n              <th>\n                <FormattedMessage defaultMessage=\"Relay\" description=\"Relay name (URL)\" />\n              </th>\n              <th>\n                <FormattedMessage defaultMessage=\"Distance\" />\n              </th>\n              <th>\n                <FormattedMessage defaultMessage=\"Uptime\" />\n              </th>\n              <th></th>\n            </tr>\n          </thead>\n          <tbody>\n            {closeRelays\n              .filter(a => !Number.isNaN(a.distance))\n              .slice(0, 100)\n              .map(a => (\n                <tr key={a.addr}>\n                  <td title={a.addr}>\n                    <Link to={`/settings/relays/${encodeURIComponent(a.addr)}`} className=\"flex gap-2 items-center\">\n                      <RelayFavicon url={a.addr} />\n                      {getRelayName(a.addr)}\n                    </Link>\n                  </td>\n                  <td className=\"text-center\">\n                    <FormattedMessage\n                      defaultMessage=\"{n} km\"\n                      values={{\n                        n: <FormattedNumber value={a.distance / 1000} maximumFractionDigits={0} />,\n                      }}\n                    />\n                  </td>\n                  <td className=\"text-center\">\n                    <Uptime url={a.addr} />\n                  </td>\n                  <td className=\"text-end\">\n                    <AsyncButton\n                      className=\"!py-1 mb-1\"\n                      onClick={async () => {\n                        state.addRelay(a.addr, { read: true, write: true })\n                      }}\n                    >\n                      <FormattedMessage defaultMessage=\"Add\" />\n                    </AsyncButton>\n                  </td>\n                </tr>\n              ))}\n          </tbody>\n        </table>\n      </CollapsedSection>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/saveRelays.tsx",
    "content": "import type { EventPublisher, FullRelaySettings, RelaySettings, SystemInterface } from \"@snort/system\"\n\nimport { Blasters } from \"@/Utils/Const\"\n\nexport async function saveRelays(\n  system: SystemInterface,\n  publisher: EventPublisher | undefined,\n  relays: Array<FullRelaySettings> | Record<string, RelaySettings>,\n) {\n  if (publisher) {\n    const ev = await publisher.relayList(relays)\n    system.BroadcastEvent(ev)\n    Promise.all(Blasters.map(a => system.WriteOnceToRelay(a, ev)))\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/tools/follows-relay-health.tsx",
    "content": "import { dedupe } from \"@snort/shared\"\nimport { OutboxModel } from \"@snort/system\"\nimport { SnortContext } from \"@snort/system-react\"\nimport { type ReactNode, use, useMemo } from \"react\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\n\nimport { CollapsedSection } from \"@/Components/Collapsed\"\nimport ProfilePreview from \"@/Components/User/ProfilePreview\"\nimport useFollowsControls from \"@/Hooks/useFollowControls\"\nimport { getRelayName } from \"@/Utils\"\n\nexport function FollowsRelayHealth({\n  withTitle,\n  popularRelays,\n  missingRelaysActions,\n}: {\n  withTitle?: boolean\n  popularRelays?: boolean\n  missingRelaysActions?: (k: string) => ReactNode\n}) {\n  const system = use(SnortContext)\n  const { followList: follows } = useFollowsControls()\n  const uniqueFollows = dedupe(follows)\n\n  const hasRelays = useMemo(() => {\n    return uniqueFollows.filter(a => (system.config.relays.getFromCache(a)?.relays.length ?? 0) > 0)\n  }, [uniqueFollows, system])\n\n  const missingRelays = useMemo(() => {\n    return uniqueFollows.filter(a => !hasRelays.includes(a))\n  }, [uniqueFollows, hasRelays])\n\n  const topWriteRelays = useMemo(() => {\n    const outbox = OutboxModel.fromSystem(system)\n    return outbox.pickTopRelays(uniqueFollows, 1e31, \"write\")\n  }, [uniqueFollows, system])\n\n  return (\n    <div className=\"flex flex-col gap-4\">\n      {(withTitle ?? true) && (\n        <div className=\"text-2xl font-semibold\">\n          <FormattedMessage defaultMessage=\"Follows Relay Health\" />\n        </div>\n      )}\n      <div>\n        <FormattedMessage\n          defaultMessage=\"{x}/{y} have relays ({percent})\"\n          id=\"p9Ps2l\"\n          values={{\n            x: hasRelays.length,\n            y: uniqueFollows.length,\n            percent: <FormattedNumber style=\"percent\" value={hasRelays.length / uniqueFollows.length} />,\n          }}\n        />\n      </div>\n      {missingRelays.length > 0 && (\n        <CollapsedSection\n          title={\n            <div className=\"text-lg\">\n              <FormattedMessage defaultMessage=\"Missing Relays\" />\n            </div>\n          }\n        >\n          <div className=\"flex flex-col gap-2\">\n            {missingRelays.map(a => (\n              <ProfilePreview\n                key={a}\n                pubkey={a}\n                options={{\n                  about: false,\n                }}\n                actions={missingRelaysActions?.(a)}\n              />\n            ))}\n          </div>\n        </CollapsedSection>\n      )}\n      {(popularRelays ?? true) && (\n        <div>\n          <div className=\"text-xl font-medium\">Popular Relays</div>\n          {dedupe(topWriteRelays.flatMap(a => a.relays))\n            .map(a => ({ relay: a, count: topWriteRelays.filter(b => b.relays.includes(a)).length }))\n            .sort((a, b) => (a.count > b.count ? -1 : 1))\n            .slice(0, 10)\n            .map(a => (\n              <div key={a.relay} className=\"flex justify-between\">\n                <div>{getRelayName(a.relay)}</div>\n                <div>\n                  {a.count} (<FormattedNumber style=\"percent\" value={a.count / uniqueFollows.length} />)\n                </div>\n              </div>\n            ))}\n        </div>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/tools/index.tsx",
    "content": "import { Outlet } from \"react-router-dom\"\n\nexport { FollowsRelayHealth } from \"./follows-relay-health\"\nexport { PruneFollowList } from \"./prune-follows\"\nexport { default as SyncAccountTool } from \"./sync-account\"\n\nexport function ToolsPage() {\n  return <Outlet />\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/tools/prune-follows.tsx",
    "content": "import { dedupe, unixNow } from \"@snort/shared\"\nimport { RequestBuilder } from \"@snort/system\"\nimport { useMemo, useState } from \"react\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport ProfileImage from \"@/Components/User/ProfileImage\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useFollowsControls from \"@/Hooks/useFollowControls\"\nimport { Day } from \"@/Utils/Const\"\n\nimport { FollowsRelayHealth } from \"./follows-relay-health\"\n\nenum PruneStage {\n  FetchLastPostTimestamp,\n  Done,\n}\n\nexport function PruneFollowList() {\n  const followControls = useFollowsControls()\n  const { system } = useEventPublisher()\n  const uniqueFollows = dedupe(followControls.followList)\n  const [status, setStatus] = useState<PruneStage>()\n  const [progress, setProgress] = useState(0)\n  const [lastPost, setLastPosts] = useState<Record<string, number>>()\n  const [unfollow, setUnfollow] = useState<Array<string>>([])\n\n  async function fetchLastPosts() {\n    setStatus(PruneStage.FetchLastPostTimestamp)\n    setProgress(0)\n    setLastPosts(undefined)\n\n    const BatchSize = 10\n    const chunks = uniqueFollows.reduce(\n      (acc, v, i) => {\n        const batch = Math.floor(i / BatchSize).toString()\n        acc[batch] ??= []\n        acc[batch].push(v)\n        return acc\n      },\n      {} as Record<string, Array<string>>,\n    )\n\n    const result = {} as Record<string, number>\n    const batches = Math.ceil(uniqueFollows.length / BatchSize)\n    for (const [batch, pubkeys] of Object.entries(chunks)) {\n      console.debug(batch, pubkeys)\n      const req = new RequestBuilder(`prune-${batch}`)\n      req.withOptions({\n        outboxPickN: 10,\n        timeout: 10_000,\n      })\n      pubkeys.forEach(p => req.withFilter().limit(1).kinds([0, 1, 3, 5, 6, 7, 10002]).authors([p]))\n      const results = await system.Fetch(req)\n      console.debug(results)\n      for (const rx of results) {\n        if ((result[rx.pubkey] ?? 0) < rx.created_at) {\n          result[rx.pubkey] = rx.created_at\n        }\n      }\n      setProgress(Number(batch) / batches)\n    }\n\n    for (const pk of uniqueFollows) {\n      result[pk] ??= 0\n    }\n    setLastPosts(result)\n    setStatus(PruneStage.Done)\n  }\n\n  const newFollowList = useMemo(() => {\n    return uniqueFollows.filter(a => !unfollow.includes(a) && a.length === 64)\n  }, [uniqueFollows, unfollow])\n\n  async function publishFollowList() {\n    await followControls.setFollows(newFollowList)\n  }\n\n  function getStatus() {\n    switch (status) {\n      case PruneStage.FetchLastPostTimestamp:\n        return (\n          <FormattedMessage\n            defaultMessage=\"Searching for account activity ({progress})\"\n            id=\"nIchMQ\"\n            values={{\n              progress: <FormattedNumber style=\"percent\" value={progress} />,\n            }}\n          />\n        )\n    }\n  }\n\n  function personToggle(k: string) {\n    return (\n      <div className=\"flex gap-1\">\n        <input\n          type=\"checkbox\"\n          onChange={e => setUnfollow(v => (e.target.checked ? dedupe([...v, k]) : v.filter(a => a !== k)))}\n          checked={unfollow.includes(k)}\n        />\n        <FormattedMessage defaultMessage=\"Unfollow\" />\n      </div>\n    )\n  }\n\n  return (\n    <div className=\"flex flex-col gap-4\">\n      <div className=\"text-2xl font-semibold\">\n        <FormattedMessage defaultMessage=\"Prune follow list\" />\n      </div>\n      <p>\n        <FormattedMessage\n          defaultMessage=\"This tool will search for the last event published by all of your follows and remove those who have not posted in 6 months\"\n          id=\"vU/Q5i\"\n        />\n      </p>\n      <div>\n        <FormattedMessage\n          defaultMessage=\"{x} follows ({y} duplicates)\"\n          id=\"iICVoL\"\n          values={{\n            x: followControls.followList.length,\n            y: followControls.followList.length - uniqueFollows.length,\n          }}\n        />\n      </div>\n      <FollowsRelayHealth withTitle={false} popularRelays={false} missingRelaysActions={k => personToggle(k)} />\n      <AsyncButton onClick={fetchLastPosts}>\n        <FormattedMessage defaultMessage=\"Compute prune list\" />\n      </AsyncButton>\n      {getStatus()}\n      <div className=\"flex flex-col gap-1\">\n        {lastPost &&\n          Object.entries(lastPost)\n            .filter(([, v]) => v <= unixNow() - 90 * Day)\n            .sort(([, a], [, b]) => (a > b ? -1 : 1))\n            .map(([k, v]) => {\n              return (\n                <div key={k} className=\"flex justify-between\">\n                  <ProfileImage pubkey={k} />\n                  <div className=\"flex flex-col gap-1\">\n                    <FormattedMessage\n                      defaultMessage=\"Last post {time}\"\n                      id=\"I1AoOu\"\n                      values={{\n                        time: new Date(v * 1000).toLocaleDateString(),\n                      }}\n                    />\n                    {personToggle(k)}\n                  </div>\n                </div>\n              )\n            })}\n      </div>\n      <div className=\"px-4 pb-5 pt-2 rounded-lg bg-secondary\">\n        <p>\n          <FormattedMessage\n            defaultMessage=\"New follow list length {length}\"\n            id=\"6559gb\"\n            values={{ length: newFollowList.length }}\n          />\n        </p>\n        <AsyncButton onClick={publishFollowList}>\n          <FormattedMessage defaultMessage=\"Save\" />\n        </AsyncButton>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/tools/routes.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\nimport type { RouteObject } from \"react-router-dom\"\n\nimport { SettingsMenuComponent } from \"@/Pages/settings/Menu/SettingsMenuComponent\"\n\nimport type { SettingsMenuItems } from \"../Menu/Menu\"\n\nconst ToolMenuItems = [\n  {\n    title: <FormattedMessage defaultMessage=\"Follow List\" />,\n    items: [\n      {\n        icon: \"trash\",\n        iconBg: \"bg-red-500\",\n        message: <FormattedMessage defaultMessage=\"Prune Follow List\" />,\n        path: \"prune-follows\",\n      },\n      {\n        icon: \"medical-cross\",\n        iconBg: \"bg-green-800\",\n        message: <FormattedMessage defaultMessage=\"Follows Relay Health\" />,\n        path: \"follows-relay-health\",\n      },\n    ],\n  },\n  {\n    title: <FormattedMessage defaultMessage=\"Account Data\" />,\n    items: [\n      {\n        icon: \"repost\",\n        iconBg: \"bg-blue-800\",\n        message: <FormattedMessage defaultMessage=\"Sync Account\" />,\n        path: \"sync-account\",\n      },\n    ],\n  },\n] as SettingsMenuItems\n\nexport const ToolsPages = [\n  {\n    path: \"\",\n    element: (\n      <>\n        <h2>\n          <FormattedMessage defaultMessage=\"Tools\" />\n        </h2>\n        <SettingsMenuComponent menu={ToolMenuItems} />\n      </>\n    ),\n  },\n  {\n    path: \"prune-follows\",\n    async lazy() {\n      const { PruneFollowList } = await import(\"..\")\n      return { Component: PruneFollowList }\n    },\n  },\n  {\n    path: \"follows-relay-health\",\n    async lazy() {\n      const { FollowsRelayHealth } = await import(\"..\")\n      return { Component: FollowsRelayHealth }\n    },\n  },\n  {\n    path: \"sync-account\",\n    async lazy() {\n      const { SyncAccountTool } = await import(\"..\")\n      return { Component: SyncAccountTool }\n    },\n  },\n] as Array<RouteObject>\n"
  },
  {
    "path": "packages/app/src/Pages/settings/tools/sync-account.tsx",
    "content": "import { unwrap } from \"@snort/shared\"\nimport { RangeSync, type TaggedNostrEvent } from \"@snort/system\"\nimport { SnortContext } from \"@snort/system-react\"\nimport { use, useState } from \"react\"\nimport { FormattedMessage, FormattedNumber } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport useRelays from \"@/Hooks/useRelays\"\nimport { SearchRelays } from \"@/Utils/Const\"\n\nexport default function SyncAccountTool() {\n  const system = use(SnortContext)\n  const login = useLogin()\n  const [scan, setScan] = useState<number>()\n  const [results, setResults] = useState<Array<TaggedNostrEvent>>([])\n  const myRelays = useRelays()\n\n  async function start() {\n    const relays = Object.entries(myRelays)\n      .filter(([, v]) => v.write)\n      .map(([k]) => k)\n    const sync = RangeSync.forSystem(system)\n    sync.on(\"event\", evs => {\n      setResults(r => [...r, ...evs])\n    })\n    sync.on(\"scan\", t => setScan(t))\n    await sync.sync({\n      authors: [unwrap(login.publicKey)],\n      relays: [...relays, ...Object.keys(CONFIG.defaultRelays), ...SearchRelays],\n    })\n  }\n  return (\n    <>\n      <p>\n        <FormattedMessage defaultMessage=\"Sync all events for your profile into local cache\" />\n      </p>\n\n      {results.length > 0 && (\n        <h3>\n          <FormattedMessage\n            defaultMessage=\"Found {n} events\"\n            id=\"ufvXH1\"\n            values={{\n              n: <FormattedNumber value={results.length} />,\n            }}\n          />\n        </h3>\n      )}\n      {scan !== undefined && (\n        <h4>\n          <FormattedMessage\n            defaultMessage=\"Scanning {date}\"\n            id=\"OxPdQ0\"\n            values={{\n              date: new Date(scan * 1000).toLocaleDateString(),\n            }}\n          />\n        </h4>\n      )}\n      <AsyncButton onClick={start}>\n        <FormattedMessage defaultMessage=\"Start\" />\n      </AsyncButton>\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/wallet/Alby.tsx",
    "content": "import { AlbyWallet, WalletKind } from \"@snort/wallet\"\nimport { useEffect, useState } from \"react\"\nimport { useLocation, useNavigate } from \"react-router-dom\"\nimport { v4 as uuid } from \"uuid\"\n\nimport PageSpinner from \"@/Components/PageSpinner\"\nimport { getAlbyOAuth } from \"@/Pages/settings/wallet/utils\"\nimport { type WalletConfig, Wallets } from \"@/Wallet\"\n\nexport default function AlbyOAuth() {\n  const navigate = useNavigate()\n  const location = useLocation()\n  const alby = getAlbyOAuth()\n  const [error, setError] = useState(\"\")\n\n  async function setupWallet(token: string) {\n    try {\n      const auth = await alby.getToken(token)\n      const connection = new AlbyWallet(auth)\n      const info = await connection.getInfo()\n\n      const newWallet = {\n        id: uuid(),\n        kind: WalletKind.Alby,\n        active: true,\n        info,\n        data: JSON.stringify(auth),\n      } as WalletConfig\n      Wallets.add(newWallet)\n\n      navigate(\"/settings/wallet\")\n    } catch (e) {\n      setError((e as Error).message)\n    }\n  }\n\n  useEffect(() => {\n    if (location.search) {\n      const params = new URLSearchParams(location.search)\n      const token = params.get(\"code\")\n      if (token) {\n        setupWallet(token).catch(e => {\n          setError((e as Error).message)\n        })\n      }\n    }\n  }, [location, setupWallet])\n\n  if (!location.search) return\n  return (\n    <>\n      <h1>Alby Wallet Connection</h1>\n      {!error && <PageSpinner />}\n      {error && <b className=\"warning\">{error}</b>}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/settings/wallet/LNDHub.tsx",
    "content": "import { LNDHubWallet, WalletKind } from \"@snort/wallet\"\nimport { useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\nimport { v4 as uuid } from \"uuid\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport { unwrap } from \"@/Utils\"\nimport { type WalletConfig, Wallets } from \"@/Wallet\"\n\nconst ConnectLNDHub = () => {\n  const navigate = useNavigate()\n  const { formatMessage } = useIntl()\n  const [config, setConfig] = useState<string>()\n  const [error, setError] = useState<string>()\n\n  async function tryConnect(config: string) {\n    try {\n      const connection = new LNDHubWallet(config)\n      await connection.login()\n      const info = await connection.getInfo()\n\n      const newWallet = {\n        id: uuid(),\n        kind: WalletKind.LNDHub,\n        active: true,\n        info,\n        data: config,\n      } as WalletConfig\n      Wallets.add(newWallet)\n\n      navigate(\"/settings/wallet\")\n    } catch (e) {\n      if (e instanceof Error) {\n        setError((e as Error).message)\n      } else {\n        setError(\n          formatMessage({\n            defaultMessage: \"Unknown error\",\n            id: \"qDwvZ4\",\n          }),\n        )\n      }\n    }\n  }\n\n  return (\n    <>\n      <h4>\n        <FormattedMessage defaultMessage=\"Enter LNDHub config\" />\n      </h4>\n      <div className=\"flex\">\n        <div className=\"grow mr10\">\n          <input\n            type=\"text\"\n            placeholder=\"lndhub://username:password@lndhub.io\"\n            className=\"w-max\"\n            value={config}\n            onChange={e => setConfig(e.target.value)}\n          />\n        </div>\n        <AsyncButton onClick={() => tryConnect(unwrap(config))} disabled={!config}>\n          <FormattedMessage defaultMessage=\"Connect\" />\n        </AsyncButton>\n      </div>\n      {error && <b className=\"error p-2.5\">{error}</b>}\n    </>\n  )\n}\n\nexport default ConnectLNDHub\n"
  },
  {
    "path": "packages/app/src/Pages/settings/wallet/NWC.tsx",
    "content": "import { NostrConnectWallet, WalletKind } from \"@snort/wallet\"\nimport { useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\nimport { Link, useNavigate } from \"react-router-dom\"\nimport { v4 as uuid } from \"uuid\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport { unwrap } from \"@/Utils\"\nimport { type WalletConfig, Wallets } from \"@/Wallet\"\n\nconst ConnectNostrWallet = () => {\n  const navigate = useNavigate()\n  const { formatMessage } = useIntl()\n  const [config, setConfig] = useState<string>()\n  const [error, setError] = useState<string>()\n\n  async function tryConnect(config: string) {\n    try {\n      const connection = new NostrConnectWallet(config)\n      await connection.login()\n      const info = await connection.getInfo()\n\n      const newWallet = {\n        id: uuid(),\n        kind: WalletKind.NWC,\n        active: true,\n        info,\n        data: config,\n      } as WalletConfig\n      Wallets.add(newWallet)\n\n      navigate(\"/settings/wallet\")\n    } catch (e) {\n      if (e instanceof Error) {\n        setError((e as Error).message)\n      } else {\n        setError(\n          formatMessage({\n            defaultMessage: \"Unknown error\",\n            id: \"qDwvZ4\",\n          }),\n        )\n      }\n    }\n  }\n\n  return (\n    <>\n      <h4>\n        <FormattedMessage defaultMessage=\"Enter Nostr Wallet Connect config\" />\n      </h4>\n      <div className=\"flex\">\n        <div className=\"grow mr10\">\n          <input\n            type=\"text\"\n            placeholder=\"nostr+walletconnect:<pubkey>?relay=<relay>&secret=<secret>\"\n            className=\"w-max\"\n            value={config}\n            onChange={e => setConfig(e.target.value)}\n          />\n        </div>\n        <AsyncButton onClick={() => tryConnect(unwrap(config))} disabled={!config}>\n          <FormattedMessage defaultMessage=\"Connect\" />\n        </AsyncButton>\n      </div>\n      {error && <b className=\"error p-2.5\">{error}</b>}\n      <p>\n        <FormattedMessage\n          defaultMessage=\"Using Alby? Go to {link} to get your NWC config!\"\n          id=\"cFbU1B\"\n          values={{\n            link: (\n              <Link to=\"https://nwc.getalby.com/\" target=\"_blank\">\n                nwc.getalby.com\n              </Link>\n            ),\n          }}\n        />\n      </p>\n    </>\n  )\n}\n\nexport default ConnectNostrWallet\n"
  },
  {
    "path": "packages/app/src/Pages/settings/wallet/index.tsx",
    "content": "export { default as WalletSettings } from \"../WalletSettings\"\nexport { default as AlbyOAuth } from \"./Alby\"\nexport { default as ConnectLNDHub } from \"./LNDHub\"\nexport { default as ConnectNostrWallet } from \"./NWC\"\n"
  },
  {
    "path": "packages/app/src/Pages/settings/wallet/routes.tsx",
    "content": "import type { RouteObject } from \"react-router-dom\"\n\nexport const WalletSettingsRoutes = [\n  {\n    path: \"/settings/wallet\",\n    async lazy() {\n      const { WalletSettings } = await import(\"..\")\n      return { Component: WalletSettings }\n    },\n  },\n  {\n    path: \"/settings/wallet/lndhub\",\n    async lazy() {\n      const { ConnectLNDHub } = await import(\"..\")\n      return { Component: ConnectLNDHub }\n    },\n  },\n  {\n    path: \"/settings/wallet/nwc\",\n    async lazy() {\n      const { ConnectNostrWallet } = await import(\"..\")\n      return { Component: ConnectNostrWallet }\n    },\n  },\n  {\n    path: \"/settings/wallet/alby\",\n    async lazy() {\n      const { AlbyOAuth } = await import(\"..\")\n      return { Component: AlbyOAuth }\n    },\n  },\n] as Array<RouteObject>\n"
  },
  {
    "path": "packages/app/src/Pages/settings/wallet/utils.ts",
    "content": "import { sha256 } from \"@noble/hashes/sha2.js\"\nimport { randomBytes, utf8ToBytes } from \"@noble/hashes/utils.js\"\nimport { base64, base64urlnopad, hex } from \"@scure/base\"\nimport { unixNow } from \"@snort/shared\"\n\nexport function getAlbyOAuth() {\n  const clientId = CONFIG.alby?.clientId ?? \"\"\n  const clientSecret = CONFIG.alby?.clientSecret ?? \"\"\n  const redirectUrl = `${window.location.protocol}//${window.location.host}/settings/wallet/alby`\n  const scopes = [\n    \"invoices:create\",\n    \"invoices:read\",\n    \"transactions:read\",\n    \"balance:read\",\n    \"payments:send\",\n    \"account:read\",\n  ]\n\n  const ec = new TextEncoder()\n  const tokenUrl = \"https://api.getalby.com/oauth/token\"\n\n  return {\n    tokenUrl,\n    getAuthUrl: () => {\n      const code_verifier = hex.encode(randomBytes(64))\n      window.sessionStorage.setItem(\"alby-code\", code_verifier)\n\n      const params = new URLSearchParams()\n      params.set(\"client_id\", clientId)\n      params.set(\"response_type\", \"code\")\n      params.set(\"code_challenge\", base64urlnopad.encode(sha256(utf8ToBytes(code_verifier))))\n      params.set(\"code_challenge_method\", \"S256\")\n      params.set(\"redirect_uri\", redirectUrl)\n      params.set(\"scope\", scopes.join(\" \"))\n\n      return `https://getalby.com/oauth?${params}`\n    },\n    getToken: async (token: string) => {\n      const code = window.sessionStorage.getItem(\"alby-code\")\n      if (!code) throw new Error(\"Alby code is missing!\")\n      window.sessionStorage.removeItem(\"alby-code\")\n\n      const form = new URLSearchParams()\n      form.set(\"client_id\", clientId)\n      form.set(\"code_verifier\", code)\n      form.set(\"grant_type\", \"authorization_code\")\n      form.set(\"redirect_uri\", redirectUrl)\n      form.set(\"code\", token)\n\n      const req = await fetch(tokenUrl, {\n        method: \"POST\",\n        headers: {\n          accept: \"application/json\",\n          \"content-type\": \"application/x-www-form-urlencoded\",\n          authorization: `Basic ${base64.encode(ec.encode(`${clientId}:${clientSecret}`))}`,\n        },\n        body: form,\n      })\n\n      const data = await req.json()\n      if (req.ok) {\n        return { ...data, created_at: unixNow(), clientId, clientSecret } as OAuthToken\n      } else {\n        throw new Error(data.error_description as string)\n      }\n    },\n  }\n}\n\nexport interface OAuthToken {\n  access_token: string\n  created_at: number\n  expires_in: number\n  refresh_token: string\n  scope: string\n  token_type: string\n  clientId: string\n  clientSecret: string\n}\n"
  },
  {
    "path": "packages/app/src/Pages/subscribe/ManageSubscription.tsx",
    "content": "import { useEffect, useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport { Link, useNavigate } from \"react-router-dom\"\n\nimport { ErrorOrOffline } from \"@/Components/ErrorOrOffline\"\nimport PageSpinner from \"@/Components/PageSpinner\"\nimport SnortApi, { type Subscription, SubscriptionError } from \"@/External/SnortApi\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport { mapSubscriptionErrorCode } from \"@/Pages/subscribe/utils\"\n\nimport SubscriptionCard from \"./SubscriptionCard\"\n\nexport default function ManageSubscriptionPage() {\n  const { publisher } = useEventPublisher()\n  const api = new SnortApi(undefined, publisher?.signer)\n  const navigate = useNavigate()\n\n  const [subs, setSubs] = useState<Array<Subscription>>()\n  const [error, setError] = useState<Error>()\n\n  async function loadSubs() {\n    setError(undefined)\n    try {\n      const s = await api.listSubscriptions()\n      setSubs(s)\n    } catch (e) {\n      if (e instanceof Error) {\n        setError(e)\n      }\n    }\n  }\n  useEffect(() => {\n    loadSubs()\n  }, [])\n\n  if (!(error instanceof SubscriptionError) && error instanceof Error)\n    return <ErrorOrOffline error={error} onRetry={loadSubs} className=\"px-3 py-2\" />\n  if (subs === undefined) {\n    return <PageSpinner />\n  }\n  return (\n    <div className=\"px-3 py-2 flex flex-col gap-4\">\n      <h2>\n        <FormattedMessage defaultMessage=\"Subscriptions\" />\n      </h2>\n      {subs.map(a => (\n        <SubscriptionCard sub={a} key={a.id} />\n      ))}\n      {subs.length !== 0 && (\n        <button className=\"primary\" onClick={() => navigate(\"/subscribe\")}>\n          <FormattedMessage defaultMessage=\"Buy Subscription\" />\n        </button>\n      )}\n      {subs.length === 0 && (\n        <p>\n          <FormattedMessage\n            defaultMessage=\"It looks like you dont have any subscriptions, you can get one {link}\"\n            id=\"W1yoZY\"\n            values={{\n              link: (\n                <Link to=\"/subscribe\">\n                  <FormattedMessage defaultMessage=\"here\" />\n                </Link>\n              ),\n            }}\n          />\n        </p>\n      )}\n      {error instanceof SubscriptionError && <b className=\"error\">{mapSubscriptionErrorCode(error)}</b>}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/subscribe/RenewSub.tsx",
    "content": "import { unixNow, unwrap } from \"@snort/shared\"\nimport { useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport ZapModal from \"@/Components/ZapModal/ZapModal\"\nimport SnortApi, { type Subscription, SubscriptionError } from \"@/External/SnortApi\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport { mapPlanName, mapSubscriptionErrorCode } from \"@/Pages/subscribe/utils\"\nimport { mostRecentSubscription } from \"@/Utils/Subscription\"\n\nexport function RenewSub({ sub: s }: { sub?: Subscription }) {\n  const { subscriptions } = useLogin(s => ({ subscriptions: s.subscriptions }))\n  const { publisher } = useEventPublisher()\n  const { formatMessage } = useIntl()\n\n  const [invoice, setInvoice] = useState(\"\")\n  const [error, setError] = useState<SubscriptionError>()\n  const [months, setMonths] = useState(1)\n\n  const recentSub = mostRecentSubscription(subscriptions)\n  const sub =\n    s ??\n    (recentSub\n      ? ({\n          id: unwrap(recentSub).id,\n          type: unwrap(recentSub).type,\n          created: unwrap(recentSub).start,\n          expires: unwrap(recentSub).end,\n          state: unwrap(recentSub).end > unixNow() ? \"expired\" : \"paid\",\n        } as Subscription)\n      : undefined)\n\n  async function renew(id: string, months: number) {\n    const api = new SnortApi(undefined, publisher?.signer)\n    try {\n      const rsp = await api.renewSubscription(id, months)\n      setInvoice(rsp.pr)\n    } catch (e) {\n      if (e instanceof SubscriptionError) {\n        setError(e)\n      }\n    }\n  }\n\n  if (!sub) return\n  return (\n    <>\n      <div className=\"flex gap-2\">\n        <div className=\"flex flex-col gap-1\">\n          <small>\n            <FormattedMessage defaultMessage=\"Months\" />\n          </small>\n          <input type=\"number\" value={months} onChange={e => setMonths(Number(e.target.value))} min={1} />\n        </div>\n\n        <div className=\"flex flex-col gap-1\">\n          <span>&nbsp;</span>\n          <AsyncButton onClick={() => renew(sub.id, months)}>\n            {sub.state === \"expired\" ? (\n              <FormattedMessage\n                defaultMessage=\"Renew {tier}\"\n                id=\"qZsKBR\"\n                values={{\n                  tier: mapPlanName(sub.type),\n                }}\n              />\n            ) : (\n              <FormattedMessage defaultMessage=\"Pay Now\" />\n            )}\n          </AsyncButton>\n        </div>\n      </div>\n      <ZapModal\n        invoice={invoice}\n        show={invoice !== \"\"}\n        onClose={() => setInvoice(\"\")}\n        title={formatMessage({\n          defaultMessage: \"Pay for subscription\",\n          id: \"Mrpkot\",\n        })}\n      />\n      {error && <b className=\"error\">{mapSubscriptionErrorCode(error)}</b>}\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/subscribe/SubscriptionCard.tsx",
    "content": "import { FormattedDate, FormattedMessage, FormattedNumber } from \"react-intl\"\n\nimport Icon from \"@/Components/Icons/Icon\"\nimport Nip5Service from \"@/Components/Nip5Service\"\nimport Nip05 from \"@/Components/User/Nip05\"\nimport type { Subscription } from \"@/External/SnortApi\"\nimport { SnortNostrAddressService } from \"@/Pages/settings/SnortNostrAddressService\"\nimport { mapPlanName } from \"@/Pages/subscribe/utils\"\n\nimport { RenewSub } from \"./RenewSub\"\n\nexport default function SubscriptionCard({ sub }: { sub: Subscription }) {\n  const created = new Date(sub.created * 1000)\n  const expires = new Date(sub.expires * 1000)\n  const now = new Date()\n  const daysToExpire = Math.floor((expires.getTime() - now.getTime()) / 8.64e7)\n  const hoursToExpire = Math.floor((expires.getTime() - now.getTime()) / 3.6e6)\n  const isExpired = sub.state === \"expired\"\n  const isNew = sub.state === \"new\"\n  const isPaid = sub.state === \"paid\"\n\n  function subFeatures() {\n    return (\n      <>\n        {!sub.handle && (\n          <>\n            <h3>\n              <FormattedMessage\n                defaultMessage=\"Claim your included {app} nostr address\"\n                values={{ app: CONFIG.appNameCapitalized }}\n              />\n            </h3>\n            <Nip5Service\n              {...SnortNostrAddressService}\n              helpText={false}\n              forSubscription={sub.id}\n              onSuccess={h => (sub.handle = h)}\n            />\n          </>\n        )}\n        {sub.handle && <Nip05 nip05={sub.handle} pubkey={\"\"} forceVerified={true} />}\n      </>\n    )\n  }\n\n  return (\n    <div className=\"px-3 py-2 subtier\">\n        <div className=\"flex\">\n          <Icon name=\"badge\" className=\"mr5\" size={25} />\n          {mapPlanName(sub.type)}\n        </div>\n        <div className=\"flex\">\n          <p className=\"flex-1\">\n            <FormattedMessage defaultMessage=\"Created\" />\n            :&nbsp;\n            <time dateTime={created.toISOString()}>\n              <FormattedDate value={created} dateStyle=\"medium\" />\n            </time>\n          </p>\n          {daysToExpire >= 1 && (\n            <p className=\"flex-1\">\n              <FormattedMessage defaultMessage=\"Expires\" />\n              :&nbsp;\n              <time dateTime={expires.toISOString()}>\n                <FormattedMessage\n                  defaultMessage=\"{n} days\"\n                  id=\"rmdsT4\"\n                  values={{\n                    n: <FormattedNumber value={daysToExpire} maximumFractionDigits={0} />,\n                  }}\n                />\n              </time>\n            </p>\n          )}\n          {daysToExpire >= 0 && daysToExpire < 1 && (\n            <p className=\"flex-1\">\n              <FormattedMessage defaultMessage=\"Expires\" />\n              :&nbsp;\n              <time dateTime={expires.toISOString()}>\n                <FormattedMessage\n                  defaultMessage=\"{n} hours\"\n                  id=\"2ukA4d\"\n                  values={{\n                    n: <FormattedNumber value={hoursToExpire} maximumFractionDigits={0} />,\n                  }}\n                />\n              </time>\n            </p>\n          )}\n          {isExpired && (\n            <p className=\"flex-1 error\">\n              <FormattedMessage defaultMessage=\"Expired\" />\n            </p>\n          )}\n          {isNew && (\n            <p className=\"flex-1\">\n              <FormattedMessage defaultMessage=\"Unpaid\" />\n            </p>\n          )}\n        </div>\n        {(isExpired || isNew) && <RenewSub sub={sub} />}\n        {isPaid && subFeatures()}\n      </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/subscribe/index.css",
    "content": ".subscribe-page > div {\n  margin: 5px;\n  min-height: 400px;\n  user-select: none;\n  flex: 1;\n}\n\n.subscribe-page h2 {\n  text-align: center;\n}\n\n.subscribe-page ul {\n  padding-inline-start: 20px;\n}\n\n@media (max-width: 720px) {\n  .subscribe-page {\n    flex-direction: column;\n  }\n\n  .subscribe-page > div {\n    flex: unset;\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Pages/subscribe/index.tsx",
    "content": "import \"./index.css\"\n\nimport classNames from \"classnames\"\nimport { useState } from \"react\"\nimport { FormattedMessage } from \"react-intl\"\nimport type { RouteObject } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport ZapModal from \"@/Components/ZapModal/ZapModal\"\nimport SnortApi, { SubscriptionError } from \"@/External/SnortApi\"\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport ManageSubscriptionPage from \"@/Pages/subscribe/ManageSubscription\"\nimport { mapFeatureName, mapPlanName, mapSubscriptionErrorCode } from \"@/Pages/subscribe/utils\"\nimport { getRefCode } from \"@/Utils\"\nimport { formatShort } from \"@/Utils/Number\"\nimport { Plans } from \"@/Utils/Subscription\"\n\nexport function SubscribePage() {\n  const { publisher } = useEventPublisher()\n  const api = new SnortApi(undefined, publisher?.signer)\n  const [invoice, setInvoice] = useState(\"\")\n  const [error, setError] = useState<SubscriptionError>()\n\n  async function subscribe(type: number) {\n    setError(undefined)\n    try {\n      const ref = getRefCode()\n      const rsp = await api.createSubscription(type, ref)\n      setInvoice(rsp.pr)\n    } catch (e) {\n      if (e instanceof SubscriptionError) {\n        setError(e)\n      }\n    }\n  }\n\n  return (\n    <>\n      <div className=\"flex subscribe-page\">\n        {Plans.map(a => {\n          const lower = Plans.filter(b => b.id < a.id)\n          return (\n            <div key={a.id} className={classNames(\"p flex flex-col gap-2\", { disabled: a.disabled })}>\n              <div className=\"grow\">\n                <h2>{mapPlanName(a.id)}</h2>\n                <p>\n                  <FormattedMessage\n                    defaultMessage=\"Subscribe to {site_name} {plan} for {price} and receive the following rewards\"\n                    id=\"JSx7y9\"\n                    values={{\n                      site_name: CONFIG.appNameCapitalized,\n                      plan: mapPlanName(a.id),\n                      price: <b>{formatShort(a.price)} sats/mo</b>,\n                    }}\n                  />\n                  :\n                </p>\n                <ul className=\"list-disc\">\n                  {a.unlocks.map(b => (\n                    <li key={`unlocks-${b}`}>{mapFeatureName(b)} </li>\n                  ))}\n                  {lower.map(b => (\n                    <li key={`lower-${b}`}>\n                      <FormattedMessage\n                        defaultMessage=\"Everything in {plan}\"\n                        id=\"l+ikU1\"\n                        values={{\n                          plan: mapPlanName(b.id),\n                        }}\n                      />\n                    </li>\n                  ))}\n                </ul>\n              </div>\n              <div className=\"flex justify-center\">\n                <AsyncButton className=\"button\" disabled={a.disabled} onClick={() => subscribe(a.id)}>\n                  {a.disabled ? (\n                    <FormattedMessage defaultMessage=\"Coming soon\" />\n                  ) : (\n                    <FormattedMessage defaultMessage=\"Subscribe\" />\n                  )}\n                </AsyncButton>\n              </div>\n            </div>\n          )\n        })}\n      </div>\n      {error && <b className=\"error\">{mapSubscriptionErrorCode(error)}</b>}\n      <ZapModal invoice={invoice} show={invoice !== \"\"} onClose={() => setInvoice(\"\")} />\n    </>\n  )\n}\n\nexport const SubscribeRoutes = [\n  {\n    path: \"/subscribe\",\n    element: <SubscribePage />,\n  },\n  {\n    path: \"/subscribe/manage\",\n    element: <ManageSubscriptionPage />,\n  },\n] as RouteObject[]\n"
  },
  {
    "path": "packages/app/src/Pages/subscribe/utils.tsx",
    "content": "import { FormattedMessage } from \"react-intl\"\n\nimport { type SubscriptionError, SubscriptionErrorCode } from \"@/External/SnortApi\"\nimport { LockedFeatures, SubscriptionType } from \"@/Utils/Subscription\"\n\nexport function mapPlanName(id: number) {\n  switch (id) {\n    case SubscriptionType.Supporter:\n      return <FormattedMessage defaultMessage=\"FAN\" />\n    case SubscriptionType.Premium:\n      return <FormattedMessage defaultMessage=\"PRO\" />\n  }\n}\n\nexport function mapFeatureName(k: LockedFeatures) {\n  switch (k) {\n    case LockedFeatures.MultiAccount:\n      return <FormattedMessage defaultMessage=\"Multi account support\" />\n    case LockedFeatures.NostrAddress:\n      return <FormattedMessage defaultMessage=\"{app} nostr address\" values={{ app: CONFIG.appNameCapitalized }} />\n    case LockedFeatures.Badge:\n      return <FormattedMessage defaultMessage=\"Supporter Badge\" />\n    case LockedFeatures.DeepL:\n      return <FormattedMessage defaultMessage=\"DeepL translations\" />\n    case LockedFeatures.RelayRetention:\n      return (\n        <FormattedMessage\n          defaultMessage=\"Unlimited note retention on {app} relay\"\n          values={{ app: CONFIG.appNameCapitalized }}\n        />\n      )\n    case LockedFeatures.RelayBackup:\n      return (\n        <FormattedMessage\n          defaultMessage=\"Downloadable backups from {app} relay\"\n          values={{ app: CONFIG.appNameCapitalized }}\n        />\n      )\n    case LockedFeatures.RelayAccess:\n      return (\n        <FormattedMessage\n          defaultMessage=\"Write access to {app} relay, with 1 year of event retention\"\n          values={{ app: CONFIG.appNameCapitalized }}\n        />\n      )\n    case LockedFeatures.LNProxy:\n      return <FormattedMessage defaultMessage=\"LN Address Proxy\" />\n    case LockedFeatures.EmailBridge:\n      return (\n        <FormattedMessage\n          defaultMessage=\"Email <> DM bridge for your {app} nostr address\"\n          values={{ app: CONFIG.appNameCapitalized }}\n        />\n      )\n  }\n}\n\nexport function mapSubscriptionErrorCode(c: SubscriptionError) {\n  switch (c.code) {\n    case SubscriptionErrorCode.InternalError:\n      return <FormattedMessage defaultMessage=\"Internal error: {msg}\" values={{ msg: c.message }} />\n    case SubscriptionErrorCode.SubscriptionActive:\n      return <FormattedMessage defaultMessage=\"You subscription is still active, you can't renew yet\" />\n    case SubscriptionErrorCode.Duplicate:\n      return (\n        <FormattedMessage\n          defaultMessage=\"You already have a subscription of this type, please renew or pay\"\n          id=\"NAuFNH\"\n        />\n      )\n    default:\n      return c.message\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Pages/wallet/index.tsx",
    "content": "/* eslint-disable max-lines */\nimport type { LNWallet, Sats, WalletInvoice } from \"@snort/wallet\"\nimport classNames from \"classnames\"\nimport { lazy, Suspense, useCallback, useEffect, useState } from \"react\"\nimport { FormattedMessage, FormattedNumber, useIntl } from \"react-intl\"\nimport { useNavigate } from \"react-router-dom\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport { AsyncIcon } from \"@/Components/Button/AsyncIcon\"\nimport NoteTime from \"@/Components/Event/Note/NoteTime\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport { useRates } from \"@/Hooks/useRates\"\nimport { unwrap } from \"@/Utils\"\nimport { useWallet, Wallets } from \"@/Wallet\"\n\nconst PriceChart = lazy(async () => await import(\"./price-chart\"))\n\nexport default function WalletPage(props: { showHistory: boolean }) {\n  const navigate = useNavigate()\n  const { formatMessage } = useIntl()\n  const [balance, setBalance] = useState<Sats>()\n  const [history, setHistory] = useState<WalletInvoice[]>()\n  const [walletPassword, setWalletPassword] = useState<string>()\n  const [error, setError] = useState<string>()\n  const walletState = useWallet()\n  const wallet = walletState.wallet\n  const rates = useRates(\"BTCUSD\")\n\n  const loadWallet = useCallback(\n    async (wallet: LNWallet) => {\n      try {\n        setError(undefined)\n        setBalance(0)\n        setHistory(undefined)\n        if (wallet.canGetBalance()) {\n          const b = await wallet.getBalance()\n          setBalance(b as Sats)\n        }\n        if (wallet.canGetInvoices() && (props.showHistory ?? true)) {\n          const h = await wallet.getInvoices()\n          setHistory((h as WalletInvoice[]).sort((a, b) => b.timestamp - a.timestamp))\n        }\n      } catch (e) {\n        if (e instanceof Error) {\n          setError((e as Error).message)\n        } else {\n          setError(formatMessage({ defaultMessage: \"Unknown error\", id: \"qDwvZ4\" }))\n        }\n      }\n    },\n    [props.showHistory, formatMessage],\n  )\n\n  useEffect(() => {\n    if (wallet?.isReady()) {\n      let cancelled = false\n      loadWallet(wallet).catch(e => {\n        if (!cancelled) console.warn(e)\n      })\n      return () => {\n        cancelled = true\n      }\n    }\n  }, [wallet, loadWallet])\n\n  async function loginWallet(pw: string) {\n    if (wallet) {\n      await wallet.login(pw)\n      await loadWallet(wallet)\n      setWalletPassword(undefined)\n    }\n  }\n\n  function unlockWallet() {\n    if (!wallet || wallet.isReady()) return null\n    return (\n      <>\n        <h3>\n          <FormattedMessage defaultMessage=\"Enter wallet password\" />\n        </h3>\n        <div className=\"flex w-max\">\n          <div className=\"grow mr10\">\n            <input\n              type=\"password\"\n              placeholder={formatMessage({\n                defaultMessage: \"Wallet password\",\n                id: \"MP54GY\",\n                description: \"Wallet password input placeholder\",\n              })}\n              className=\"w-max\"\n              value={walletPassword}\n              onChange={e => setWalletPassword(e.target.value)}\n            />\n          </div>\n          <AsyncButton onClick={() => loginWallet(unwrap(walletPassword))} disabled={(walletPassword?.length ?? 0) < 8}>\n            <FormattedMessage defaultMessage=\"Unlock\" />\n          </AsyncButton>\n        </div>\n      </>\n    )\n  }\n\n  function walletList() {\n    if (walletState.configs.length === 0) {\n      return (\n        <div className=\"flex flex-col gap-4\">\n          <div>\n            <button onClick={() => navigate(\"/settings/wallet\")}>\n              <FormattedMessage defaultMessage=\"Connect Wallet\" />\n            </button>\n          </div>\n          <small>\n            <FormattedMessage defaultMessage=\"Connect a wallet to send instant payments\" />\n          </small>\n        </div>\n      )\n    }\n    return (\n      <div className=\"flex items-center\">\n        <h4 className=\"grow\">\n          <FormattedMessage defaultMessage=\"Select Wallet\" />\n        </h4>\n        <div>\n          <select className=\"w-max\" onChange={e => Wallets.switch(e.target.value)} value={walletState.config?.id}>\n            {Wallets.list().map(a => {\n              return (\n                <option value={a.id} key={a.id}>\n                  {a.info.alias}\n                </option>\n              )\n            })}\n          </select>\n        </div>\n      </div>\n    )\n  }\n\n  function walletHistory() {\n    if (!wallet?.canGetInvoices() || !(props.showHistory ?? true)) return\n\n    return (\n      <div className=\"flex flex-col gap-1\">\n        <h3>\n          <FormattedMessage defaultMessage=\"Payments\" />\n        </h3>\n        {history === undefined && (\n          <small>\n            <FormattedMessage defaultMessage=\"Your sent and received payments will show up here.\" />\n          </small>\n        )}\n        {history?.map(a => {\n          const dirClassname = {\n            \"text-[--success]\": a.direction === \"in\",\n            \"text-[--error]\": a.direction === \"out\",\n          }\n          return (\n            <div className=\"flex gap-4 p-2 hover:bg-neutral-800 rounded-lg items-center\" key={a.timestamp}>\n              <div>\n                <div className=\"rounded-full aspect-square p-2 bg-layer-1\">\n                  <Icon\n                    name=\"arrow-up-right\"\n                    className={classNames(dirClassname, {\n                      \"rotate-180\": a.direction === \"in\",\n                    })}\n                  />\n                </div>\n              </div>\n              <div className=\"grow flex justify-between\">\n                <div className=\"flex flex-col gap-1\">\n                  <div>{a.memo?.length === 0 ? CONFIG.appNameCapitalized : a.memo}</div>\n                  <div className=\"text-neutral-400 text-sm\">\n                    <NoteTime\n                      from={a.timestamp * 1000}\n                      fallback={formatMessage({ defaultMessage: \"now\", id: \"kaaf1E\" })}\n                    />\n                  </div>\n                </div>\n                <div className=\"flex flex-col gap-1 text-right\">\n                  <div className={classNames(dirClassname)}>\n                    <FormattedMessage\n                      defaultMessage=\"{sign} {amount} sats\"\n                      id=\"tj6kdX\"\n                      values={{\n                        sign: a.direction === \"in\" ? \"+\" : \"-\",\n                        amount: <FormattedNumber value={a.amount / 1e3} />,\n                      }}\n                    />\n                  </div>\n                  <div className=\"text-neutral-400 text-sm\">\n                    <FormattedMessage\n                      defaultMessage=\"~{amount}\"\n                      id=\"3QwfJR\"\n                      values={{\n                        amount: (\n                          <FormattedNumber\n                            style=\"currency\"\n                            currency=\"USD\"\n                            value={(rates?.ask ?? 0) * a.amount * 1e-11}\n                          />\n                        ),\n                      }}\n                    />\n                  </div>\n                </div>\n              </div>\n            </div>\n          )\n        })}\n      </div>\n    )\n  }\n\n  function walletBalance() {\n    if (!wallet?.canGetBalance()) return\n    return (\n      <div className=\"flex items-center gap-2\">\n        <FormattedMessage\n          defaultMessage=\"<big>{amount}</big> <small>sats</small>\"\n          id=\"E5ZIPD\"\n          values={{\n            big: c => <span className=\"text-5xl font-bold\">{c}</span>,\n            small: c => <span className=\"text-neutral-400 text-sm\">{c}</span>,\n            amount: <FormattedNumber value={balance ?? 0} />,\n          }}\n        />\n        <AsyncIcon size={20} className=\"text-neutral-400 cursor-pointer\" iconName=\"closedeye\" />\n      </div>\n    )\n  }\n\n  function walletInfo() {\n    if (!wallet) return\n\n    return (\n      <>\n        <div className=\"flex flex-col items-center px-6 py-4 bg-layer-1 rounded-lg gap-1\">\n          {walletBalance()}\n          <div className=\"text-neutral-400\">\n            <FormattedMessage\n              defaultMessage=\"~{amount}\"\n              id=\"3QwfJR\"\n              values={{\n                amount: (\n                  <FormattedNumber style=\"currency\" currency=\"USD\" value={(rates?.ask ?? 0) * (balance ?? 0) * 1e-8} />\n                ),\n              }}\n            />\n          </div>\n          <div className=\"flex gap-2\">\n            {wallet?.canCreateInvoice() && (\n              <AsyncButton className=\"secondary\" onClick={() => navigate(\"/wallet/receive\")}>\n                <FormattedMessage defaultMessage=\"Receive\" />\n                <Icon name=\"arrow-up-right\" className=\"rotate-180\" />\n              </AsyncButton>\n            )}\n            {wallet?.canPayInvoice() && (\n              <AsyncButton onClick={() => navigate(\"/wallet/send\")} className=\"primary\">\n                <FormattedMessage defaultMessage=\"Send\" />\n                <Icon name=\"arrow-up-right\" />\n              </AsyncButton>\n            )}\n          </div>\n        </div>\n        {walletHistory()}\n      </>\n    )\n  }\n\n  return (\n    <div>\n      <div className=\"px-6 py-4 bg-layer-1 rounded-lg mb-4\">\n        <Suspense>\n          <PriceChart />\n        </Suspense>\n      </div>\n      {walletList()}\n      {error && <b className=\"warning\">{error}</b>}\n      {unlockWallet()}\n      {walletInfo()}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/wallet/price-chart.tsx",
    "content": "import { useMemo, useState } from \"react\"\nimport { FormattedNumber } from \"react-intl\"\nimport { Line, LineChart, ResponsiveContainer, Tooltip, type TooltipProps, XAxis, YAxis } from \"recharts\"\n\nimport { useRateHistory } from \"@/Hooks/useRates\"\n\ntype TimeRange = \"1D\" | \"1W\" | \"1M\" | \"3M\" | \"1Y\" | \"ALL\"\n\ninterface ChartData {\n  time: number\n  ask: number\n  bid: number\n}\n\nfunction CustomTooltip({ active, payload }: TooltipProps<number, string>) {\n  if (!active || !payload || payload.length === 0) {\n    return null\n  }\n\n  const data = payload[0].payload as ChartData\n  const date = new Date(data.time * 1000)\n\n  return (\n    <div className=\"bg-layer-2 px-3 py-2 rounded border border-neutral-700\">\n      <div className=\"text-xs text-neutral-400 mb-1\">\n        {date.toLocaleDateString(undefined, {\n          year: \"numeric\",\n          month: \"short\",\n          day: \"numeric\",\n          hour: \"2-digit\",\n          minute: \"2-digit\",\n        })}\n      </div>\n      <div className=\"font-medium\">\n        <FormattedNumber value={data.ask} style=\"currency\" currency=\"USD\" />\n      </div>\n    </div>\n  )\n}\n\nconst TIME_RANGES: Record<TimeRange, { interval: number; range: number }> = {\n  \"1D\": { interval: 3600, range: 3600 * 24 },\n  \"1W\": { interval: 3600 * 4, range: 3600 * 24 * 7 },\n  \"1M\": { interval: 3600 * 24, range: 3600 * 24 * 30 },\n  \"3M\": { interval: 3600 * 24, range: 3600 * 24 * 90 },\n  \"1Y\": { interval: 3600 * 24 * 7, range: 3600 * 24 * 365 },\n  ALL: { interval: 3600 * 24 * 7, range: 3600 * 24 * 365 * 5 },\n}\n\nexport default function PriceChart() {\n  const [selectedRange, setSelectedRange] = useState<TimeRange>(\"1D\")\n  const { interval, range } = TIME_RANGES[selectedRange]\n  const history = useRateHistory(\"BTCUSD\", range, true)\n\n  const reduced = useMemo(() => {\n    if (history.length === 0) {\n      return { data: [], min: 0, max: 0, minAsk: 0, maxAsk: 0 }\n    }\n\n    let minAsk = Number.MAX_SAFE_INTEGER\n    let maxAsk = 0\n\n    // Group data points by interval buckets\n    const buckets = new Map<number, { time: number; ask: number; bid: number }>()\n\n    for (const point of history) {\n      const bucketKey = Math.floor(point.time / interval) * interval\n\n      // Keep the most recent value in each bucket\n      if (!buckets.has(bucketKey) || point.time > buckets.get(bucketKey)?.time) {\n        buckets.set(bucketKey, { time: bucketKey, ask: point.ask, bid: point.bid })\n      }\n\n      if (point.ask > maxAsk) maxAsk = point.ask\n      if (point.ask < minAsk) minAsk = point.ask\n    }\n\n    // Convert to sorted array\n    const data = Array.from(buckets.values()).sort((a, b) => a.time - b.time)\n    const min = data[0]?.time ?? 0\n    const max = data[data.length - 1]?.time ?? 0\n\n    return { data, min, max, minAsk, maxAsk }\n  }, [history, interval])\n\n  const lastRate = useMemo(() => {\n    return history.reduce(\n      (acc, v) => {\n        if (acc.time < v.time) {\n          acc = v\n        }\n        return acc\n      },\n      { time: 0, ask: 0, bid: 0 } as { time: number; ask: number; bid: number },\n    )\n  }, [history])\n\n  const priceChange = useMemo(() => {\n    if (reduced.data.length < 2) {\n      return { absolute: 0, percentage: 0 }\n    }\n    const firstPrice = reduced.data[0].ask\n    const lastPrice = reduced.data[reduced.data.length - 1].ask\n    const absolute = lastPrice - firstPrice\n    const percentage = (absolute / firstPrice) * 100\n    return { absolute, percentage }\n  }, [reduced.data])\n\n  return (\n    <>\n      <div className=\"flex justify-between items-center mb-4\">\n        <div className=\"flex gap-2\">\n          {(Object.keys(TIME_RANGES) as TimeRange[]).map(rangeKey => (\n            <div\n              key={rangeKey}\n              onClick={() => setSelectedRange(rangeKey)}\n              className={`px-3 py-1 rounded text-sm cursor-pointer ${\n                selectedRange === rangeKey ? \"bg-primary text-white\" : \"bg-layer-2 text-neutral-400 hover:bg-layer-3\"\n              }`}\n            >\n              {rangeKey}\n            </div>\n          ))}\n        </div>\n        <div className=\"text-right\">\n          <h3>\n            <FormattedNumber value={lastRate.ask} style=\"currency\" currency=\"USD\" />\n          </h3>\n          <div className={`text-xs font-medium ${priceChange.absolute >= 0 ? \"text-success\" : \"text-error\"}`}>\n            {priceChange.absolute >= 0 ? \"+\" : \"\"}\n            <FormattedNumber value={priceChange.absolute} style=\"currency\" currency=\"USD\" /> (\n            {priceChange.percentage >= 0 ? \"+\" : \"\"}\n            {priceChange.percentage.toFixed(2)}%)\n          </div>\n        </div>\n      </div>\n      <ResponsiveContainer height={200}>\n        <LineChart data={reduced.data}>\n          <XAxis dataKey=\"time\" type=\"number\" scale=\"time\" domain={[\"dataMin\", \"dataMax\"]} hide={true} />\n          <YAxis\n            dataKey=\"ask\"\n            type=\"number\"\n            scale=\"auto\"\n            domain={[\"dataMin - 100\", \"dataMax + 100\"]}\n            tickFormatter={v => Number(v).toLocaleString()}\n            hide={true}\n          />\n          <Tooltip content={<CustomTooltip />} />\n          <Line dataKey=\"ask\" type=\"monotone\" dot={false} connectNulls={false} stroke=\"var(--primary)\" />\n        </LineChart>\n      </ResponsiveContainer>\n    </>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/wallet/receive.tsx",
    "content": "import { useState } from \"react\"\nimport { FormattedMessage, useIntl } from \"react-intl\"\n\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport Copy from \"@/Components/Copy/Copy\"\nimport QrCode from \"@/Components/QrCode\"\nimport { useWallet } from \"@/Wallet\"\n\nexport function WalletReceivePage() {\n  const wallets = useWallet()\n  const { formatMessage } = useIntl()\n  const [invoice, setInvoice] = useState(\"\")\n  const [error, setError] = useState(\"\")\n  const [amount, setAmount] = useState(0)\n  const [comment, setComment] = useState(\"\")\n\n  return (\n    <div className=\"px-3 py-2 flex flex-col gap-4\">\n      <div className=\"text-2xl font-bold\">\n        <FormattedMessage defaultMessage=\"Receive\" />\n      </div>\n      <p>\n        <FormattedMessage\n          defaultMessage=\"Receiving to <b>{wallet}</b>\"\n          id=\"PXQ0z0\"\n          values={{\n            b: b => <b>&quot;{b}&quot;</b>,\n            wallet: wallets.config?.info.alias,\n          }}\n        />\n      </p>\n      <input\n        type=\"text\"\n        placeholder={formatMessage({ defaultMessage: \"Comment\", id: \"LgbKvU\" })}\n        value={comment}\n        onChange={e => setComment(e.target.value)}\n      />\n      <div className=\"flex flex-col\">\n        <small>\n          <FormattedMessage defaultMessage=\"Amount in sats\" />\n        </small>\n        <input type=\"number\" value={amount} onChange={e => setAmount(Number(e.target.value))} />\n      </div>\n      <AsyncButton\n        onClick={async () => {\n          try {\n            if (wallets.wallet) {\n              const inv = await wallets.wallet.createInvoice({\n                amount: amount,\n                memo: comment,\n                expiry: 600,\n              })\n              setInvoice(inv.pr)\n            }\n          } catch (e) {\n            setError((e as Error).message)\n          }\n        }}\n      >\n        <FormattedMessage defaultMessage=\"Generate Invoice\" />\n      </AsyncButton>\n      {error && <b className=\"warning\">{error}</b>}\n      {invoice && (\n        <div className=\"flex flex-col gap-2 items-center\">\n          <QrCode data={invoice} link={`lightning:${invoice}`} />\n          <Copy text={invoice} />\n        </div>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Pages/wallet/send.tsx",
    "content": "import { LNURL } from \"@snort/shared\"\nimport type { WalletInvoice } from \"@snort/wallet\"\nimport { useState } from \"react\"\nimport { FormattedMessage, FormattedNumber, useIntl } from \"react-intl\"\nimport AsyncButton from \"@/Components/Button/AsyncButton\"\nimport Icon from \"@/Components/Icons/Icon\"\nimport { useWallet } from \"@/Wallet\"\n\nexport function WalletSendPage() {\n  const wallets = useWallet()\n  const { formatMessage } = useIntl()\n  const [invoice, setInvoice] = useState(\"\")\n  const [error, setError] = useState(\"\")\n  const [amount, setAmount] = useState(0)\n  const [comment, setComment] = useState(\"\")\n  const [result, setResult] = useState<WalletInvoice>()\n\n  const lnurl = !invoice.startsWith(\"lnbc\")\n\n  return (\n    <div className=\"px-3 py-2 flex flex-col gap-4\">\n      <div className=\"text-2xl font-bold\">\n        <FormattedMessage defaultMessage=\"Send\" />\n      </div>\n      <p>\n        <FormattedMessage\n          defaultMessage=\"Sending from <b>{wallet}</b>\"\n          id=\"Xnimz0\"\n          values={{\n            b: b => <b>&quot;{b}&quot;</b>,\n            wallet: wallets.config?.info.alias,\n          }}\n        />\n      </p>\n      <input\n        type=\"text\"\n        placeholder={formatMessage({ defaultMessage: \"Invoice / Lightning Address\", id: \"EHqHsu\" })}\n        value={invoice}\n        onChange={e => setInvoice(e.target.value)}\n      />\n      {lnurl && (\n        <>\n          <input\n            type=\"text\"\n            placeholder={formatMessage({ defaultMessage: \"Comment\", id: \"LgbKvU\" })}\n            value={comment}\n            onChange={e => setComment(e.target.value)}\n          />\n          <div className=\"flex flex-col\">\n            <small>\n              <FormattedMessage defaultMessage=\"Amount in sats\" />\n            </small>\n            <input type=\"number\" value={amount} onChange={e => setAmount(Number(e.target.value))} />\n          </div>\n        </>\n      )}\n      <AsyncButton\n        onClick={async () => {\n          try {\n            if (wallets.wallet) {\n              if (!lnurl) {\n                const res = await wallets.wallet.payInvoice(invoice)\n                setResult(res)\n              } else {\n                const lnurl = new LNURL(invoice)\n                await lnurl.load()\n                const pr = await lnurl.getInvoice(amount, comment)\n                if (pr.pr) {\n                  const res = await wallets.wallet.payInvoice(pr.pr)\n                  setResult(res)\n                }\n              }\n            }\n          } catch (e) {\n            setError((e as Error).message)\n          }\n        }}\n      >\n        <FormattedMessage defaultMessage=\"Pay\" />\n      </AsyncButton>\n      {error && <b className=\"warning\">{error}</b>}\n      {result && (\n        <div className=\"flex gap-2\">\n          <Icon name=\"check\" className=\"success\" />\n          <FormattedMessage\n            defaultMessage=\"Paid {amount} sats, fee {fee} sats\"\n            id=\"aRex7h\"\n            values={{\n              amount: <FormattedNumber value={result.amount / 1000} />,\n              fee: <FormattedNumber value={result.fees / 1000} />,\n            }}\n          />\n        </div>\n      )}\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/app/src/State/NoteCreator.ts",
    "content": "import { ExternalStore } from \"@snort/shared\"\nimport type { NostrEvent, TaggedNostrEvent } from \"@snort/system\"\nimport type { ZapTarget } from \"@snort/wallet\"\nimport { useSyncExternalStoreWithSelector } from \"use-sync-external-store/with-selector\"\n\nimport type { BlobDescriptor } from \"@/Utils/Upload/blossom\"\n\ninterface NoteCreatorDataSnapshot {\n  show: boolean\n  note: string\n  error: string\n  active: boolean\n  advanced: boolean\n  preview?: NostrEvent\n  replyTo?: TaggedNostrEvent\n  quote?: TaggedNostrEvent\n  selectedCustomRelays?: Array<string>\n  zapSplits?: Array<ZapTarget>\n  sensitive?: string\n  pollOptions?: Array<string>\n  otherEvents?: Array<NostrEvent>\n  attachments?: Record<string, Array<BlobDescriptor>>\n  extraTags?: Array<Array<string>>\n  sending?: Array<NostrEvent>\n  sendStarted: boolean\n  hashTags: Array<string>\n  filePicker: \"hidden\" | \"compact\" | \"wide\"\n  reset: () => void\n  update: (fn: (v: NoteCreatorDataSnapshot) => void) => void\n}\n\nclass NoteCreatorStore extends ExternalStore<NoteCreatorDataSnapshot> {\n  #data: NoteCreatorDataSnapshot\n\n  constructor() {\n    super()\n    this.#data = {\n      show: false,\n      note: \"\",\n      error: \"\",\n      active: false,\n      advanced: false,\n      sendStarted: false,\n      filePicker: \"hidden\",\n      hashTags: [],\n      reset: this.#resetFn,\n      update: this.#updateFn,\n    }\n  }\n\n  #reset(d: NoteCreatorDataSnapshot) {\n    d.show = false\n    d.note = \"\"\n    d.error = \"\"\n    d.active = false\n    d.advanced = false\n    d.sendStarted = false\n    d.preview = undefined\n    d.replyTo = undefined\n    d.quote = undefined\n    d.selectedCustomRelays = undefined\n    d.zapSplits = undefined\n    d.sensitive = undefined\n    d.pollOptions = undefined\n    d.otherEvents = undefined\n    d.sending = undefined\n    d.extraTags = undefined\n    d.hashTags = []\n    d.filePicker = \"hidden\"\n    d.attachments = undefined\n  }\n\n  #resetFn = () => {\n    this.#reset(this.#data)\n    this.notifyChange(this.#data)\n  }\n\n  #updateFn = (fn: (v: NoteCreatorDataSnapshot) => void) => {\n    fn(this.#data)\n    this.notifyChange(this.#data)\n  }\n\n  takeSnapshot(): NoteCreatorDataSnapshot {\n    const sn = {\n      ...this.#data,\n      reset: this.#resetFn,\n      update: this.#updateFn,\n    } as NoteCreatorDataSnapshot\n    return sn\n  }\n}\n\nconst NoteCreatorState = new NoteCreatorStore()\n\nexport function useNoteCreator<T extends object = NoteCreatorDataSnapshot>(\n  selector?: (v: NoteCreatorDataSnapshot) => T,\n) {\n  const defaultSelector = (v: NoteCreatorDataSnapshot) => v as unknown as T\n\n  return useSyncExternalStoreWithSelector<NoteCreatorDataSnapshot, T>(\n    c => NoteCreatorState.hook(c),\n    () => NoteCreatorState.snapshot(),\n    undefined,\n    selector || defaultSelector,\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Utils/Const.ts",
    "content": "/**\n * 1 Hour in seconds\n */\nexport const Hour = 60 * 60\n\n/**\n * 1 Day in seconds\n */\nexport const Day = Hour * 24\n\n/**\n * Day this project started\n */\nexport const Birthday = new Date(2022, 12 - 1, 17)\n\n/**\n * Add-on api for snort features\n */\nexport const ApiHost = \"https://api.snort.social\"\n\n/**\n * Kierans pubkey\n */\nexport const KieranPubKey = \"npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\"\n\n/**\n * Official snort account\n */\nexport const SnortPubKey = \"npub1sn0rtcjcf543gj4wsg7fa59s700d5ztys5ctj0g69g2x6802npjqhjjtws\"\n\n/**\n * Default search relays\n */\nexport const SearchRelays = [\"wss://relay.nostr.band/\", \"wss://search.nos.today/\", \"wss://relay.noswhere.com/\"]\n\n/**\n * Snort imgproxy details\n */\nexport const DefaultImgProxy = {\n  url: \"https://imgproxy.v0l.io\",\n  key: \"a82fcf26aa0ccb55dfc6b4bd6a1c90744d3be0f38429f21a8828b43449ce7cebe6bdc2b09a827311bef37b18ce35cb1e6b1c60387a254541afa9e5b4264ae942\",\n  salt: \"a897770d9abf163de055e9617891214e75a9016d748f8ef865e6ffbcb9ed932295659549773a22a019a5f06d0b440c320be411e3fddfe784e199e4f03d74bd9b\",\n}\n\n/**\n * Blaster relays\n */\nexport const Blasters = []\n\n/**\n * Regex to match email address\n */\nexport const EmailRegex =\n  // eslint-disable-next-line no-useless-escape\n  /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/\n\n/**\n * Regex to match a mnemonic seed\n */\nexport const MnemonicRegex = /(\\w+)/g\n\n/**\n * Extract file extensions regex\n */\n// eslint-disable-next-line no-useless-escape\nexport const FileExtensionRegex = /\\.([\\w]{1,7})$/i\n\n/**\n * Extract note reactions regex\n */\nexport const MentionRegex = /(#\\[\\d+\\])/gi\n\n/**\n * Simple lightning invoice regex\n */\nexport const InvoiceRegex = /(lnbc\\w+)/i\n\n/**\n * YouTube URL regex\n * https://music.youtube.com/watch?v=KyF9hKd-EC4&list=RDTMAK5uy_kset8DisdE7LSD4TNjEVvrKRTmG7a56sY\n */\nexport const YoutubeUrlRegex =\n  /(?:https?:\\/\\/)?(?:www|m\\.)?(?:youtu\\.be\\/|youtube\\.com\\/(?:live\\/|shorts\\/|embed\\/|v\\/|watch\\?v=|watch\\?.+&v=))((\\w|-){11})((?:&list=)(?:(\\w|-)+))?/\n\n/**\n * Hashtag regex\n */\n// eslint-disable-next-line no-useless-escape\nexport const HashtagRegex = /(#[^\\s!@#$%^&*()=+./,[{\\]};:'\"?><]+)/g\n\n/**\n * Tidal share link regex\n */\nexport const TidalRegex = /tidal\\.com\\/(?:browse\\/)?(\\w+)\\/([a-z0-9-]+)/i\n\n/**\n * SoundCloud regex\n */\nexport const SoundCloudRegex = /soundcloud\\.com\\/(?!live)([a-zA-Z0-9]+)\\/([a-zA-Z0-9-]+)/\n\n/**\n * Mixcloud regex\n */\nexport const MixCloudRegex = /mixcloud\\.com\\/(?!live)([a-zA-Z0-9]+)\\/([a-zA-Z0-9-]+)/\n\n/**\n * Spotify embed regex\n */\nexport const SpotifyRegex = /open\\.spotify\\.com\\/(track|album|playlist|episode)\\/([a-zA-Z0-9]+)/\n\n/**\n * Twitch embed regex\n */\nexport const TwitchRegex = /twitch.tv\\/([a-z0-9_]+$)/i\n\n/**\n * Apple Music embed regex\n */\nexport const AppleMusicRegex =\n  /music\\.apple\\.com\\/([a-z]{2}\\/)?(?:album|playlist)\\/[\\w\\d-]+\\/([.a-zA-Z0-9-]+)(?:\\?i=\\d+)?/i\n\n/**\n * Nostr Nests embed regex\n */\nexport const NostrNestsRegex = /nostrnests\\.com\\/[a-zA-Z0-9]+/i\n\n/*\n * Magnet link parser\n */\nexport const MagnetRegex = /(magnet:[\\S]+)/i\n\n/**\n * Wavlake embed regex\n */\nexport const WavlakeRegex =\n  /https?:\\/\\/(?:player\\.|www\\.)?wavlake\\.com\\/(?!top|new|artists|account|activity|login|preferences|feed|profile)(?:(?:track|album)\\/[a-f0-9]{8}(?:-[a-f0-9]{4}){3}-[a-f0-9]{12}|[a-z-]+)/i\n\n/*\n * Regex to match any base64 string\n */\nexport const CashuRegex = /(cashuA[A-Za-z0-9_-]{0,10000}={0,3})/i\n\n/*\n * Max username length - profile/settings\n */\nexport const MaxUsernameLength = 100\n\n/*\n * Max about length - profile/settings\n */\nexport const MaxAboutLength = 1000\n\n/*\n * Snort backend publishes rates\n */\nexport const SnortPubkey = \"npub1sn0rtcjcf543gj4wsg7fa59s700d5ztys5ctj0g69g2x6802npjqhjjtws\"\n\n/**\n * List of relay monitor relays\n */\nexport const MonitorRelays = [\n  \"wss://relaypag.es\",\n  \"wss://relay.nostr.watch\",\n  \"wss://history.nostr.watch\",\n  \"wss://monitorlizard.nostr1.com\",\n]\n"
  },
  {
    "path": "packages/app/src/Utils/Login/Functions.ts",
    "content": "import { bech32ToHex, unixNowMs } from \"@snort/shared\"\nimport {\n  EventPublisher,\n  type KeyStorage,\n  Nip7Signer,\n  Nip46Signer,\n  Nip55Signer,\n  PrivateKeySigner,\n  type RelaySettings,\n  type SystemInterface,\n  type UserMetadata,\n} from \"@snort/system\"\n\nimport { GiftsCache } from \"@/Cache\"\nimport { dedupeById, deleteRefCode, unwrap } from \"@/Utils\"\nimport { Blasters } from \"@/Utils/Const\"\nimport {\n  type LoginSession,\n  LoginSessionType,\n  LoginStore,\n  type SnortAppData,\n  type UserPreferences,\n} from \"@/Utils/Login/index\"\nimport { entropyToPrivateKey, generateBip39Entropy } from \"@/Utils/nip6\"\nimport type { SubscriptionEvent } from \"@/Utils/Subscription\"\n\nimport { Nip7OsSigner } from \"./Nip7OsSigner\"\nimport { bytesToHex } from \"@noble/hashes/utils.js\"\n\nexport function logout(id: string) {\n  LoginStore.removeSession(id)\n  GiftsCache.clear()\n  deleteRefCode()\n  localStorage.clear()\n}\n\nexport function markNotificationsRead(state: LoginSession) {\n  state.readNotifications = unixNowMs()\n  LoginStore.updateSession(state)\n}\n\nexport function clearEntropy(state: LoginSession) {\n  state.generatedEntropy = undefined\n  LoginStore.updateSession(state)\n}\n\n/**\n * Generate a new key\n */\nexport async function generateNewLoginKeys() {\n  const entropy = generateBip39Entropy()\n  const privateKey = await entropyToPrivateKey(entropy)\n  return { entropy, privateKey }\n}\n\n/**\n * Login with newly generated key\n */\nexport async function generateNewLogin(\n  keys: { entropy: Uint8Array; privateKey: string },\n  system: SystemInterface,\n  pin: (key: string) => Promise<KeyStorage>,\n  profile: UserMetadata,\n) {\n  const { entropy, privateKey } = keys\n  const newRelays = {} as Record<string, RelaySettings>\n\n  for (const [k, v] of Object.entries(CONFIG.defaultRelays)) {\n    if (!newRelays[k]) {\n      newRelays[k] = v\n    }\n  }\n\n  // connect to new relays\n  await Promise.all(Object.entries(newRelays).map(([k, v]) => system.ConnectToRelay(k, v)))\n\n  const publisher = EventPublisher.privateKey(privateKey)\n  const publicKey = publisher.pubKey\n\n  // Create new contact list following self and site account\n  const contactList = [publicKey, ...CONFIG.signUp.defaultFollows.map(a => bech32ToHex(a))].map(a => [\"p\", a]) as Array<\n    [string, string]\n  >\n  const ev = await publisher.contactList(contactList, newRelays)\n  system.BroadcastEvent(ev)\n\n  // Create relay metadata event\n  const ev2 = await publisher.relayList(newRelays)\n  system.BroadcastEvent(ev2)\n  Promise.all(Blasters.map(a => system.WriteOnceToRelay(a, ev2)))\n\n  // Publish new profile\n  const ev3 = await publisher.metadata(profile)\n  system.BroadcastEvent(ev3)\n  Promise.all(Blasters.map(a => system.WriteOnceToRelay(a, ev3)))\n\n  LoginStore.loginWithPrivateKey(await pin(privateKey), bytesToHex(entropy), newRelays)\n}\n\nexport function updateSession(id: string, fn: (state: LoginSession) => void) {\n  const session = LoginStore.get(id)\n  if (session) {\n    fn(session)\n    LoginStore.updateSession(session)\n  }\n}\n\nexport function setAppData(state: LoginSession, data: SnortAppData) {\n  state.state.setAppData(data)\n  LoginStore.updateSession(state)\n}\n\nexport function updateAppData(id: string, fn: (data: SnortAppData) => SnortAppData) {\n  const session = LoginStore.get(id)\n  if (session?.state.appdata) {\n    const next = fn(session.state.appdata)\n    setAppData(session, next)\n  }\n}\n\nexport function setPreference(obj: Partial<UserPreferences>) {\n  const { id } = LoginStore.snapshot()\n  const session = LoginStore.get(id)\n  if (!session?.state.appdata) return\n  const p = {\n    preferences: {\n      ...session.state.appdata.preferences,\n      ...obj,\n    },\n  }\n  session.state.setAppData(p)\n}\n\nexport async function saveAppData(id: string) {\n  const session = LoginStore.get(id)\n  if (session?.state.appdata) {\n    await session.state.saveAppData()\n  }\n}\n\nexport function addSubscription(state: LoginSession, ...subs: SubscriptionEvent[]) {\n  const newSubs = dedupeById([...(state.subscriptions || []), ...subs])\n  if (newSubs.length !== state.subscriptions.length) {\n    state.subscriptions = newSubs\n    LoginStore.updateSession(state)\n  }\n}\n\nexport function sessionNeedsPin(l: LoginSession) {\n  return l.privateKeyData?.shouldUnlock()\n}\n\nexport function createPublisher(l: LoginSession) {\n  switch (l.type) {\n    case LoginSessionType.PrivateKey: {\n      return EventPublisher.privateKey(unwrap(l.privateKeyData as KeyStorage).value)\n    }\n    case LoginSessionType.Nip46: {\n      const relayArgs = (l.remoteSignerRelays ?? []).map(a => `relay=${encodeURIComponent(a)}`)\n      const inner = new PrivateKeySigner(unwrap(l.privateKeyData as KeyStorage).value)\n      const nip46 = new Nip46Signer(`bunker://${unwrap(l.publicKey)}?${[...relayArgs].join(\"&\")}`, inner)\n      nip46.on(\"oauth\", url => {\n        window.open(url, CONFIG.appNameCapitalized, \"width=600,height=800,popup=yes\")\n      })\n      return new EventPublisher(nip46, unwrap(l.publicKey))\n    }\n    case LoginSessionType.Nip7os: {\n      return new EventPublisher(new Nip7OsSigner(), unwrap(l.publicKey))\n    }\n    case LoginSessionType.Nip7: {\n      return new EventPublisher(new Nip7Signer(), unwrap(l.publicKey))\n    }\n    case LoginSessionType.Nip55: {\n      return new EventPublisher(new Nip55Signer(), unwrap(l.publicKey))\n    }\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Utils/Login/LoginSession.ts",
    "content": "import type { KeyStorage, UserState } from \"@snort/system\"\n\nimport type { UserPreferences } from \"@/Utils/Login/index\"\nimport type { SubscriptionEvent } from \"@/Utils/Subscription\"\n\n/**\n * Stores latest copy of an item\n */\nexport interface Newest<T> {\n  item: T\n  timestamp: number\n}\n\nexport enum LoginSessionType {\n  PrivateKey = \"private_key\",\n  PublicKey = \"public_key\",\n  Nip7 = \"nip7\",\n  Nip46 = \"nip46\",\n  Nip7os = \"nip7_os\",\n  Nip55 = \"nip55\",\n}\n\nexport interface SnortAppData {\n  preferences: UserPreferences\n}\n\nexport interface LoginSession {\n  /**\n   * Unique ID to identify this session\n   */\n  id: string\n\n  /**\n   * Type of login session\n   */\n  type: LoginSessionType\n\n  /**\n   * Current user private key\n   * @deprecated Moving to pin encrypted storage\n   */\n  privateKey?: string\n\n  /**\n   * If this session cannot sign events\n   */\n  readonly: boolean\n\n  /**\n   * Encrypted private key\n   */\n  privateKeyData?: KeyStorage\n\n  /**\n   * BIP39-generated, hex-encoded entropy\n   */\n  generatedEntropy?: string\n\n  /**\n   * Current users public key\n   */\n  publicKey?: string\n\n  /**\n   * Login state for the current user\n   */\n  state: UserState<SnortAppData>\n\n  /**\n   * Timestamp of last read notification\n   */\n  readNotifications: number\n\n  /**\n   * Snort subscriptions licences\n   */\n  subscriptions: Array<SubscriptionEvent>\n\n  /**\n   * Remote signer relays (NIP-46)\n   */\n  remoteSignerRelays?: Array<string>\n\n  /**\n   * A list of chats which we have joined (NIP-28/NIP-29)\n   */\n  extraChats: Array<string>\n\n  /**\n   * Is login session in stalker mode\n   */\n  stalker: boolean\n}\n"
  },
  {
    "path": "packages/app/src/Utils/Login/MultiAccountStore.ts",
    "content": "import { ExternalStore, getPublicKey, unwrap } from \"@snort/shared\"\nimport {\n  EventKind,\n  EventPublisher,\n  KeyStorage,\n  type RelaySettings,\n  UserState,\n  type UserStateObject,\n} from \"@snort/system\"\nimport { v4 as uuid } from \"uuid\"\n\nimport { createPublisher, type LoginSession, LoginSessionType, type SnortAppData } from \"@/Utils/Login/index\"\n\nimport { DefaultPreferences, type UserPreferences } from \"./Preferences\"\n\nconst AccountStoreKey = \"sessions\"\nconst LoggedOut = {\n  id: \"default\",\n  type: \"public_key\",\n  readonly: true,\n  tags: {\n    item: [],\n    timestamp: 0,\n  },\n  muted: {\n    item: [],\n    timestamp: 0,\n  },\n  blocked: {\n    item: [],\n    timestamp: 0,\n  },\n  bookmarked: {\n    item: [],\n    timestamp: 0,\n  },\n  pinned: {\n    item: [],\n    timestamp: 0,\n  },\n  relays: {\n    item: CONFIG.defaultRelays,\n    timestamp: 0,\n  },\n  latestNotification: 0,\n  readNotifications: 0,\n  subscriptions: [],\n  extraChats: [],\n  stalker: false,\n  state: new UserState<SnortAppData>(\"\", {\n    initAppdata: {\n      preferences: DefaultPreferences,\n    },\n    encryptAppdata: true,\n    appdataId: \"snort\",\n  }),\n} as LoginSession\n\nexport class MultiAccountStore extends ExternalStore<LoginSession> {\n  #activeAccount?: string\n  #saveDebounce?: ReturnType<typeof setTimeout>\n  #accounts: Map<string, LoginSession> = new Map()\n  #publishers = new Map<string, EventPublisher>()\n\n  constructor() {\n    super()\n    if (typeof ServiceWorkerGlobalScope !== \"undefined\" && globalThis instanceof ServiceWorkerGlobalScope) {\n      // return if sw. we might want to use localForage (idb) to share keys between sw and app\n      return\n    }\n    const existing = window.localStorage.getItem(AccountStoreKey)\n    if (existing) {\n      const logins = JSON.parse(existing)\n      this.#accounts = new Map((logins as Array<LoginSession>).map(a => [a.id, a]))\n    } else {\n      this.#accounts = new Map()\n    }\n    this.#migrate()\n    if (!this.#activeAccount) {\n      this.#activeAccount = this.#accounts.keys().next().value\n    }\n    for (const [, v] of this.#accounts) {\n      // reset readonly on load\n      if (v.type === LoginSessionType.PrivateKey && v.readonly) {\n        v.readonly = false\n      }\n      v.extraChats ??= []\n      if (v.privateKeyData) {\n        v.privateKeyData = KeyStorage.fromPayload(v.privateKeyData as object)\n      }\n      const stateObj = v.state as unknown as UserStateObject<SnortAppData> | undefined\n      const stateClass = new UserState<SnortAppData>(\n        v.publicKey!,\n        {\n          initAppdata: stateObj?.appdata ?? {\n            preferences: {\n              ...DefaultPreferences,\n              ...CONFIG.defaultPreferences,\n            },\n          },\n          encryptAppdata: true,\n          appdataId: \"snort\",\n        },\n        stateObj,\n      )\n      MultiAccountStore.enableStandardLists(stateClass)\n      stateClass.on(\"change\", () => this.#save())\n      if (v.state instanceof UserState) {\n        v.state.destroy()\n      }\n      console.debug(\"UserState assign = \", stateClass)\n      v.state = stateClass\n\n      // always activate signer\n      const signer = createPublisher(v)\n      if (signer) {\n        this.#publishers.set(v.id, signer)\n      }\n    }\n  }\n\n  private static enableStandardLists<T>(state: UserState<T>) {\n    state.checkIsStandardList(EventKind.BlossomServerList) // track blossom list\n    state.checkIsStandardList(EventKind.PinList)\n    state.checkIsStandardList(EventKind.BookmarksList)\n  }\n\n  getSessions() {\n    return [...this.#accounts.values()].map(v => ({\n      pubkey: unwrap(v.publicKey),\n      id: v.id,\n    }))\n  }\n\n  get(id: string) {\n    const s = this.#accounts.get(id)\n    if (s) {\n      return { ...s }\n    }\n  }\n\n  allSubscriptions() {\n    return [...this.#accounts.values()].flatMap(a => a.subscriptions)\n  }\n\n  switchAccount(id: string) {\n    if (this.#accounts.has(id)) {\n      this.#activeAccount = id\n      this.#save()\n    }\n  }\n\n  getPublisher(id: string) {\n    return this.#publishers.get(id)\n  }\n\n  setPublisher(id: string, pub: EventPublisher) {\n    this.#publishers.set(id, pub)\n    this.notifyChange()\n  }\n\n  loginWithPubkey(\n    key: string,\n    type: LoginSessionType,\n    relays?: Record<string, RelaySettings>,\n    remoteSignerRelays?: Array<string>,\n    privateKey?: KeyStorage,\n    stalker?: boolean,\n  ) {\n    if (this.#accounts.has(key)) {\n      throw new Error(\"Already logged in with this pubkey\")\n    }\n    const initRelays = this.decideInitRelays(relays)\n    const newSession = {\n      ...LoggedOut,\n      id: uuid(),\n      readonly: type === LoginSessionType.PublicKey,\n      type,\n      publicKey: key,\n      relays: {\n        item: initRelays,\n        timestamp: 1,\n      },\n      state: new UserState<SnortAppData>(key, {\n        initAppdata: {\n          preferences: {\n            ...DefaultPreferences,\n            ...CONFIG.defaultPreferences,\n          },\n        },\n        encryptAppdata: true,\n        appdataId: \"snort\",\n      }),\n      remoteSignerRelays,\n      privateKeyData: privateKey,\n      stalker: stalker ?? false,\n    } as LoginSession\n\n    MultiAccountStore.enableStandardLists(newSession.state)\n    newSession.state?.on(\"change\", () => this.#save())\n    const pub = createPublisher(newSession)\n    if (pub) {\n      this.#publishers.set(newSession.id, pub)\n    }\n    this.#accounts.set(newSession.id, newSession)\n    this.#activeAccount = newSession.id\n    this.#save()\n    return newSession\n  }\n\n  decideInitRelays(relays: Record<string, RelaySettings> | undefined): Record<string, RelaySettings> {\n    if (import.meta.env.VITE_SINGLE_RELAY) return { [import.meta.env.VITE_SINGLE_RELAY]: { read: true, write: true } }\n    if (relays && Object.keys(relays).length > 0) {\n      return relays\n    }\n    return CONFIG.defaultRelays\n  }\n\n  loginWithPrivateKey(key: KeyStorage, entropy?: string, relays?: Record<string, RelaySettings>) {\n    const pubKey = getPublicKey(key.value)\n    if (this.#accounts.has(pubKey)) {\n      throw new Error(\"Already logged in with this pubkey\")\n    }\n    const initRelays = this.decideInitRelays(relays)\n    const newSession = {\n      ...LoggedOut,\n      id: uuid(),\n      type: LoginSessionType.PrivateKey,\n      readonly: false,\n      privateKeyData: key,\n      publicKey: pubKey,\n      generatedEntropy: entropy,\n      relays: {\n        item: initRelays,\n        timestamp: 1,\n      },\n      state: new UserState<SnortAppData>(pubKey, {\n        initAppdata: {\n          preferences: {\n            ...DefaultPreferences,\n            ...CONFIG.defaultPreferences,\n          },\n        },\n        encryptAppdata: true,\n        appdataId: \"snort\",\n      }),\n    } as LoginSession\n    MultiAccountStore.enableStandardLists(newSession.state)\n    newSession.state?.on(\"change\", () => this.#save())\n\n    if (\"nostr_os\" in window && window?.nostr_os) {\n      window?.nostr_os.saveKey(key.value)\n      newSession.type = LoginSessionType.Nip7os\n      newSession.privateKeyData = undefined\n    }\n    const pub = EventPublisher.privateKey(key.value)\n    this.#publishers.set(newSession.id, pub)\n\n    this.#accounts.set(newSession.id, newSession)\n    this.#activeAccount = newSession.id\n    this.#save()\n    return newSession\n  }\n\n  updateSession(s: LoginSession) {\n    if (this.#accounts.has(s.id)) {\n      this.#accounts.set(s.id, s)\n      this.#save()\n    }\n  }\n\n  removeSession(id: string) {\n    if (this.#accounts.delete(id)) {\n      if (this.#activeAccount === id) {\n        this.#activeAccount = undefined\n      }\n      this.#save()\n    }\n  }\n\n  takeSnapshot(): LoginSession {\n    const s = this.#activeAccount ? this.#accounts.get(this.#activeAccount) : undefined\n    if (!s) return LoggedOut\n\n    return { ...s }\n  }\n\n  #migrate() {\n    let didMigrate = false\n\n    // delete some old keys\n    for (const [, acc] of this.#accounts) {\n      if (\"appData\" in acc) {\n        delete acc.appData\n        didMigrate = true\n      }\n      if (\"contacts\" in acc) {\n        delete acc.contacts\n        didMigrate = true\n      }\n      if (\"follows\" in acc) {\n        delete acc.follows\n        didMigrate = true\n      }\n      if (\"relays\" in acc) {\n        delete acc.relays\n        didMigrate = true\n      }\n      if (\"blocked\" in acc) {\n        delete acc.blocked\n        didMigrate = true\n      }\n      if (\"bookmarked\" in acc) {\n        delete acc.bookmarked\n        didMigrate = true\n      }\n      if (\"muted\" in acc) {\n        delete acc.muted\n        didMigrate = true\n      }\n      if (\"pinned\" in acc) {\n        delete acc.pinned\n        didMigrate = true\n      }\n      if (\"tags\" in acc) {\n        delete acc.tags\n        didMigrate = true\n      }\n      if (acc.state?.appdata) {\n        if (\"id\" in acc.state.appdata) {\n          delete acc.state.appdata.id\n          didMigrate = true\n        }\n        if (\"mutedWords\" in acc.state.appdata) {\n          delete acc.state.appdata.mutedWords\n          didMigrate = true\n        }\n        if (\"showContentWarningPosts\" in acc.state.appdata) {\n          delete acc.state.appdata.showContentWarningPosts\n          didMigrate = true\n        }\n\n        if (acc.state.appdata.preferences) {\n          if (!(\"muteWithWoT\" in acc.state.appdata.preferences)) {\n            ;(acc.state.appdata.preferences as UserPreferences).muteWithWoT = true\n            didMigrate = true\n          }\n        }\n      }\n    }\n\n    if (didMigrate) {\n      console.debug(\"Finished migration in MultiAccountStore\")\n      this.#save()\n    }\n  }\n\n  #save() {\n    if (this.#saveDebounce !== undefined) {\n      clearTimeout(this.#saveDebounce)\n    }\n    this.notifyChange()\n    this.#saveDebounce = setTimeout(() => {\n      if (!this.#activeAccount && this.#accounts.size > 0) {\n        this.#activeAccount = this.#accounts.keys().next().value\n      }\n      const toSave = []\n      for (const v of this.#accounts.values()) {\n        if (v.privateKeyData instanceof KeyStorage) {\n          toSave.push({\n            ...v,\n            state: v.state instanceof UserState ? v.state.serialize() : v.state,\n            privateKeyData: v.privateKeyData.toPayload(),\n          })\n        } else {\n          toSave.push({\n            ...v,\n            state: v.state instanceof UserState ? v.state.serialize() : v.state,\n          })\n        }\n      }\n\n      console.debug(\"Trying to save\", toSave)\n      window.localStorage.setItem(AccountStoreKey, JSON.stringify(toSave))\n      this.#saveDebounce = undefined\n    }, 2000)\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Utils/Login/Nip7OsSigner.ts",
    "content": "/* eslint-disable @typescript-eslint/no-unused-vars */\nimport type { EventSigner, NostrEvent } from \"@snort/system\"\n\nimport type { Nip7os } from \"@/Utils/Login/index\"\n\nexport class Nip7OsSigner implements EventSigner {\n  #interface: Nip7os\n\n  constructor() {\n    if (\"nostr_os\" in window && window.nostr_os) {\n      this.#interface = window.nostr_os\n    } else {\n      throw new Error(\"Nost OS extension not available\")\n    }\n  }\n\n  get supports(): string[] {\n    return [\"nip04\"]\n  }\n\n  init(): Promise<void> {\n    return Promise.resolve()\n  }\n\n  getPubKey(): string | Promise<string> {\n    return this.#interface.getPublicKey()\n  }\n\n  nip4Encrypt(content: string, key: string): Promise<string> {\n    return Promise.resolve(this.#interface.nip04_encrypt(content, key))\n  }\n\n  nip4Decrypt(content: string, otherKey: string): Promise<string> {\n    return Promise.resolve(this.#interface.nip04_decrypt(content, otherKey))\n  }\n\n  nip44Encrypt(_content: string, _key: string): Promise<string> {\n    throw new Error(\"Method not implemented.\")\n  }\n\n  nip44Decrypt(_content: string, _otherKey: string): Promise<string> {\n    throw new Error(\"Method not implemented.\")\n  }\n\n  sign(ev: NostrEvent): Promise<NostrEvent> {\n    const ret = this.#interface.signEvent(JSON.stringify(ev))\n    return Promise.resolve(JSON.parse(ret) as NostrEvent)\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Utils/Login/Preferences.ts",
    "content": "import type { ImgProxySettings } from \"@/Hooks/useImgProxy\"\nimport type { RootTabRoutePath } from \"@/Pages/Root/RootTabRoutes\"\nimport { DefaultImgProxy } from \"@/Utils/Const\"\n\nexport interface UserPreferences {\n  /**\n   * User selected language\n   */\n  language?: string\n\n  /**\n   * Enable reactions / reposts / zaps\n   */\n  enableReactions: boolean\n\n  /**\n   * Reaction emoji\n   */\n  reactionEmoji: string\n\n  /**\n   * Automatically load media (show link only) (bandwidth/privacy)\n   */\n  autoLoadMedia: \"none\" | \"follows-only\" | \"all\"\n\n  /**\n   * Select between light/dark theme\n   */\n  theme: \"system\" | \"light\" | \"dark\"\n\n  /**\n   * Ask for confirmation when reposting notes\n   */\n  confirmReposts: boolean\n\n  /**\n   * Automatically show the latests notes\n   */\n  autoShowLatest: boolean\n\n  /**\n   * Show debugging menus to help diagnose issues\n   */\n  showDebugMenus: boolean\n\n  /**\n   * Use imgproxy to optimize images\n   */\n  imgProxyConfig?: ImgProxySettings\n\n  /**\n   * Default page to select on load\n   */\n  defaultRootTab: RootTabRoutePath\n\n  /**\n   * Default zap amount\n   */\n  defaultZapAmount: number\n\n  /**\n   * Auto-zap every post\n   */\n  autoZap: boolean\n\n  /**\n   * Proof-of-Work to apply to all events\n   */\n  pow?: number\n\n  /**\n   * Collect usage metrics\n   */\n  telemetry?: boolean\n\n  /**\n   * Show badges on profiles\n   */\n  showBadges?: boolean\n\n  /**\n   * Show user status messages on profiles\n   */\n  showStatus?: boolean\n\n  /**\n   * Check event signatures\n   */\n  checkSigs: boolean\n\n  /**\n   * Auto-translate when available\n   */\n  autoTranslate?: boolean\n\n  /**\n   * Hides muted notes when selected\n   */\n  hideMutedNotes: boolean\n\n  /**\n   * Show posts with content warning\n   */\n  showContentWarningPosts: boolean\n\n  /**\n   * Mute notes outside your WoT\n   */\n  muteWithWoT: boolean\n\n  /**\n   * Selected DVM provider pubkey for trending notes (kind 5300)\n   */\n  trendingDvmPubkey?: string\n\n  /**\n   * AI Agent service URL\n   */\n  agentUrl?: string\n\n  /**\n   * AI Agent API key\n   */\n  agentKey?: string\n\n  /**\n   * AI Agent model to use\n   */\n  agentModel?: string\n}\n\nexport const DefaultPreferences = {\n  enableReactions: true,\n  reactionEmoji: \"+\",\n  autoLoadMedia: \"all\",\n  theme: \"system\",\n  confirmReposts: false,\n  showDebugMenus: true,\n  autoShowLatest: false,\n  imgProxyConfig: DefaultImgProxy,\n  defaultRootTab: \"following\",\n  defaultZapAmount: 50,\n  autoZap: false,\n  telemetry: true,\n  showBadges: false,\n  showStatus: true,\n  checkSigs: true,\n  autoTranslate: true,\n  hideMutedNotes: false,\n  muteWithWoT: false,\n  showContentWarningPosts: false,\n  trendingDvmPubkey: \"0d9ec486275b70f0c4faec277fc4c63b9f14cb1ca1ec029f7d76210e957e5257\",\n} as UserPreferences\n"
  },
  {
    "path": "packages/app/src/Utils/Login/index.ts",
    "content": "import { MultiAccountStore } from \"./MultiAccountStore\"\n\nexport const LoginStore = new MultiAccountStore()\n\nexport interface Nip7os {\n  getPublicKey: () => string\n  signEvent: (ev: string) => string\n  saveKey: (key: string) => void\n  nip04_encrypt: (content: string, to: string) => string\n  nip04_decrypt: (content: string, from: string) => string\n}\n\ndeclare global {\n  interface Window {\n    nostr_os?: Nip7os\n  }\n}\n\nexport * from \"./Functions\"\nexport * from \"./LoginSession\"\nexport * from \"./Preferences\"\n"
  },
  {
    "path": "packages/app/src/Utils/Nip05/ServiceProvider.ts",
    "content": "import { throwIfOffline } from \"@snort/shared\"\n\nexport type ServiceErrorCode =\n  | \"UNKNOWN_ERROR\"\n  | \"INVALID_BODY\"\n  | \"NO_SUCH_DOMAIN\"\n  | \"TOO_SHORT\"\n  | \"TOO_LONG\"\n  | \"REGEX\"\n  | \"DISALLOWED\"\n  | \"REGISTERED\"\n  | \"NOT_AVAILABLE\"\n  | \"RATE_LIMITED\"\n  | \"NO_TOKEN\"\n  | \"INVALID_TOKEN\"\n  | \"NO_SUCH_PAYMENT\"\n  | \"INTERNAL_PAYMENT_CHECK_ERROR\"\n\nexport interface ServiceError {\n  error: ServiceErrorCode\n  errors: Array<string>\n}\n\nexport interface ServiceConfig {\n  domains: DomainConfig[]\n}\n\nexport type DomainConfig = {\n  name: string\n  default: boolean\n  length: [number, number]\n  regex: [string, string]\n  regexChars: [string, string]\n}\n\nexport type HandleAvailability = {\n  available: boolean\n  why?: ServiceErrorCode\n  reasonTag?: string | null\n  quote?: HandleQuote\n}\n\nexport type HandleQuote = {\n  price: number\n  data: HandleData\n}\n\nexport type HandleData = {\n  type: string | \"premium\" | \"short\"\n}\n\nexport type HandleRegisterResponse = {\n  quote: HandleQuote\n  paymentHash: string\n  invoice: string\n  token: string\n}\n\nexport type CheckRegisterResponse = {\n  available: boolean\n  paid: boolean\n  password: string\n}\n\nexport class ServiceProvider {\n  readonly url: URL | string\n\n  constructor(url: URL | string) {\n    this.url = url\n  }\n\n  async GetConfig(): Promise<ServiceConfig | ServiceError> {\n    return await this.getJson(\"/config.json\")\n  }\n\n  async CheckAvailable(handle: string, domain: string): Promise<HandleAvailability | ServiceError> {\n    return await this.getJson(\"/registration/availability\", \"POST\", {\n      name: handle,\n      domain,\n    })\n  }\n\n  async RegisterHandle(handle: string, domain: string, pubkey: string): Promise<HandleRegisterResponse | ServiceError> {\n    return await this.getJson(\"/registration/register\", \"PUT\", {\n      name: handle,\n      domain,\n      pk: pubkey,\n      ref: \"snort\",\n    })\n  }\n\n  async CheckRegistration(token: string): Promise<CheckRegisterResponse | ServiceError> {\n    return await this.getJson(\"/registration/register/check\", \"POST\", undefined, {\n      authorization: token,\n    })\n  }\n\n  protected async getJson<T>(\n    path: string,\n    method?: \"GET\" | string,\n    body?: unknown,\n    headers?: { [key: string]: string },\n  ): Promise<T | ServiceError> {\n    throwIfOffline()\n    try {\n      const rsp = await fetch(`${this.url}${path}`, {\n        method: method,\n        body: body ? JSON.stringify(body) : undefined,\n        headers: {\n          accept: \"application/json\",\n          ...(body ? { \"content-type\": \"application/json\" } : {}),\n          ...headers,\n        },\n      })\n\n      const obj = await rsp.json()\n      if (\"error\" in obj) {\n        return obj as ServiceError\n      }\n      return obj as T\n    } catch (e) {\n      console.warn(e)\n    }\n    return { error: \"UNKNOWN_ERROR\", errors: [] }\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Utils/Nip05/SnortServiceProvider.ts",
    "content": "import { EventKind, type EventPublisher } from \"@snort/system\"\n\nimport { type ServiceError, ServiceProvider } from \"./ServiceProvider\"\n\nexport interface ManageHandle {\n  id: string\n  handle: string\n  domain: string\n  pubkey: string\n  created: Date\n  lnAddress?: string\n  forwardType?: ForwardType\n}\n\nexport enum ForwardType {\n  Redirect = 0,\n  ProxyDirect = 1,\n  ProxyTrusted = 2,\n}\n\nexport interface PatchHandle {\n  lnAddress?: string\n  forwardType?: ForwardType\n}\n\nexport default class SnortServiceProvider extends ServiceProvider {\n  readonly #publisher: EventPublisher\n\n  constructor(publisher: EventPublisher, url: string | URL) {\n    super(url)\n    this.#publisher = publisher\n  }\n\n  async list() {\n    return this.getJsonAuthd<Array<ManageHandle>>(\"/list\", \"GET\")\n  }\n\n  async transfer(id: string, to: string) {\n    return this.getJsonAuthd<object>(`/${id}/transfer?to=${to}`, \"PATCH\")\n  }\n\n  async patch(id: string, obj: PatchHandle) {\n    return this.getJsonAuthd<object>(`/${id}`, \"PATCH\", obj)\n  }\n\n  async registerForSubscription(handle: string, domain: string, id: string) {\n    return this.getJsonAuthd<object>(`/registration/register/${id}`, \"PUT\", {\n      name: handle,\n      domain,\n      pk: \"\",\n      ref: \"snort\",\n    })\n  }\n\n  async getJsonAuthd<T>(\n    path: string,\n    method?: \"GET\" | string,\n    body?: unknown,\n    headers?: { [key: string]: string },\n  ): Promise<T | ServiceError> {\n    const auth = await this.#publisher.generic(eb => {\n      eb.kind(EventKind.HttpAuthentication)\n      eb.tag([\"url\", `${this.url}${path}`])\n      eb.tag([\"method\", method ?? \"GET\"])\n      return eb\n    })\n    if (!auth) {\n      return {\n        error: \"INVALID_TOKEN\",\n      } as ServiceError\n    }\n\n    return this.getJson<T>(path, method, body, {\n      ...headers,\n      authorization: `Nostr ${window.btoa(JSON.stringify(auth))}`,\n    })\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Utils/Notifications.ts",
    "content": "import { base64 } from \"@scure/base\"\nimport { removeUndefined, unwrap } from \"@snort/shared\"\nimport { type CachedMetadata, EventKind, type EventPublisher, type TaggedNostrEvent } from \"@snort/system\"\n\nimport { ProfilesCache } from \"@/Cache\"\nimport SnortApi from \"@/External/SnortApi\"\nimport { MentionRegex } from \"@/Utils/Const\"\nimport { defaultAvatar, getDisplayName, tagFilterOfTextRepost } from \"@/Utils/index\"\nimport type { LoginSession } from \"@/Utils/Login\"\n\nexport interface NotificationRequest {\n  title: string\n  body: string\n  icon: string\n  timestamp: number\n}\n\nexport async function makeNotification(ev: TaggedNostrEvent): Promise<NotificationRequest | null> {\n  switch (ev.kind) {\n    case EventKind.TextNote: {\n      if (ev.tags.some(tagFilterOfTextRepost(ev))) {\n        return null\n      }\n      const pubkeys = new Set([ev.pubkey, ...ev.tags.filter(a => a[0] === \"p\").map(a => a[1])])\n      await ProfilesCache.buffer([...pubkeys])\n      const allUsers = removeUndefined([...pubkeys].map(a => ProfilesCache.getFromCache(a)))\n      const fromUser = ProfilesCache.getFromCache(ev.pubkey)\n      const name = getDisplayName(fromUser, ev.pubkey)\n      const avatarUrl = fromUser?.picture || defaultAvatar(ev.pubkey)\n      return {\n        title: `Reply from ${name}`,\n        body: replaceTagsWithUser(ev, allUsers).substring(0, 50),\n        icon: avatarUrl,\n        timestamp: ev.created_at * 1000,\n      }\n    }\n  }\n  return null\n}\n\nfunction replaceTagsWithUser(ev: TaggedNostrEvent, users: CachedMetadata[]) {\n  return ev.content\n    .split(MentionRegex)\n    .map(match => {\n      const matchTag = match.match(/#\\[(\\d+)\\]/)\n      if (matchTag && matchTag.length === 2) {\n        const idx = parseInt(matchTag[1], 10)\n        const ref = ev.tags[idx]\n        if (ref && ref[0] === \"p\" && ref.length > 1) {\n          const u = users.find(a => a.pubkey === ref[1])\n          return `@${getDisplayName(u, ref[1])}`\n        }\n      }\n      return match\n    })\n    .join()\n}\n\nexport async function sendNotification(state: LoginSession, req: NotificationRequest) {\n  const hasPermission = \"Notification\" in window && Notification.permission === \"granted\"\n  const shouldShowNotification = hasPermission && req.timestamp > state.readNotifications\n  if (shouldShowNotification) {\n    try {\n      const worker = await navigator.serviceWorker.ready\n      worker.showNotification(req.title, {\n        tag: \"notification\",\n        ...req,\n      })\n    } catch (error) {\n      console.warn(error)\n    }\n  }\n}\n\nexport async function subscribeToNotifications(publisher: EventPublisher) {\n  if (!CONFIG.features.pushNotifications) {\n    return\n  }\n  // request permissions to send notifications\n  if (\"Notification\" in window) {\n    try {\n      if (Notification.permission !== \"granted\") {\n        await Notification.requestPermission()\n      }\n    } catch (e) {\n      console.error(e)\n    }\n  }\n  try {\n    if (\"serviceWorker\" in navigator) {\n      const reg = await navigator.serviceWorker.ready\n      if (reg && publisher) {\n        const api = new SnortApi(undefined, publisher?.signer)\n        const sub = await reg.pushManager.subscribe({\n          userVisibleOnly: true,\n          applicationServerKey: (await api.getPushNotificationInfo()).publicKey,\n        })\n        await api.registerPushNotifications({\n          endpoint: sub.endpoint,\n          p256dh: base64.encode(new Uint8Array(unwrap(sub.getKey(\"p256dh\")))),\n          auth: base64.encode(new Uint8Array(unwrap(sub.getKey(\"auth\")))),\n          scope: `${globalThis.location.protocol}//${globalThis.location.hostname}`,\n        })\n      }\n    }\n  } catch (e) {\n    console.error(e)\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Utils/Number.ts",
    "content": "const intl = new Intl.NumberFormat(\"en\", {\n  minimumFractionDigits: 0,\n  maximumFractionDigits: 2,\n})\n\nexport function formatShort(n: number) {\n  if (n < 2e3) {\n    return n\n  } else if (n < 1e6) {\n    return `${intl.format(n / 1e3)}K`\n  } else if (n < 1e9) {\n    return `${intl.format(n / 1e6)}M`\n  } else {\n    return `${intl.format(n / 1e9)}G`\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Utils/Subscription/index.ts",
    "content": "import { unixNow } from \"@snort/shared\"\n\nexport enum SubscriptionType {\n  Supporter = 0,\n  Premium = 1,\n}\n\nexport enum LockedFeatures {\n  MultiAccount = 1,\n  NostrAddress = 2,\n  Badge = 3,\n  DeepL = 4,\n  RelayRetention = 5,\n  RelayBackup = 6,\n  RelayAccess = 7,\n  LNProxy = 8,\n  EmailBridge = 9,\n}\n\nexport const Plans = [\n  {\n    id: SubscriptionType.Supporter,\n    price: 5_000,\n    disabled: false,\n    unlocks: [\n      LockedFeatures.MultiAccount,\n      LockedFeatures.NostrAddress,\n      LockedFeatures.Badge,\n      LockedFeatures.RelayAccess,\n    ],\n  },\n  {\n    id: SubscriptionType.Premium,\n    price: 20_000,\n    disabled: false,\n    unlocks: [\n      LockedFeatures.DeepL,\n      LockedFeatures.RelayBackup,\n      LockedFeatures.RelayRetention,\n      LockedFeatures.LNProxy,\n      LockedFeatures.EmailBridge,\n    ],\n  },\n]\n\nexport interface SubscriptionEvent {\n  id: string\n  type: SubscriptionType\n  start: number\n  end: number\n}\n\nexport function getActiveSubscriptions(s: Array<SubscriptionEvent>) {\n  const now = unixNow()\n  return [...s].sort((a, b) => b.type - a.type).filter(a => a.start <= now && a.end > now)\n}\n\nexport function getCurrentSubscription(s: Array<SubscriptionEvent>) {\n  return getActiveSubscriptions(s).at(0)\n}\n\nexport function mostRecentSubscription(s: Array<SubscriptionEvent>) {\n  return [...s].sort((a, b) => (b.start > a.start ? -1 : 1)).at(0)\n}\n"
  },
  {
    "path": "packages/app/src/Utils/Thread/ThreadContextWrapper.tsx",
    "content": "\nimport {\n  EventExt,\n  EventKind,\n  type NostrLink,\n  NoteCollection,\n  RequestBuilder,\n  type TaggedNostrEvent,\n} from \"@snort/system\"\nimport { useEventFeed, useRequestBuilder } from \"@snort/system-react\"\nimport { type ReactNode, useMemo, useState } from \"react\"\nimport { useLocation } from \"react-router-dom\"\n\nimport useModeration from \"@/Hooks/useModeration\"\nimport { replyChainKey, ThreadContext } from \".\"\n\n/**\n * Thread context wrapper, which loads threads for a given link\n */\nexport function ThreadContextWrapper({ link, children }: { link: NostrLink; children?: ReactNode }) {\n  const location = useLocation()\n  const [currentId, setCurrentId] = useState(link.tagKey)\n  const primary = useEventFeed(link)\n  const parsedThread = primary ? EventExt.extractThread(primary) : undefined\n\n  const subReplies = useMemo(() => {\n    // top level note of this thread\n    // if primary is loaded and its a root note, use its link as the rootLink\n    const rootLink = parsedThread?.root ?? parsedThread?.replyTo ?? (primary && !parsedThread ? link : undefined)\n    const k = rootLink ? rootLink.tagKey : undefined\n    const sub = new RequestBuilder(`thread-replies:${k}`)\n    if (rootLink) {\n      sub.withFilter().link(rootLink)\n      const f = sub.withFilter().kinds([EventKind.TextNote]).replyToLink([rootLink])\n      if (rootLink.kind && rootLink.kind !== EventKind.TextNote) {\n        f.kinds([EventKind.Comment])\n      }\n    }\n    return sub\n  }, [primary, link, parsedThread])\n\n  const rootReplies = useRequestBuilder(subReplies)\n\n  const ns = new NoteCollection()\n  ns.add(rootReplies)\n  if (primary) {\n    ns.add(primary)\n  }\n\n  const { muted, unmuted, chains } = useFilteredThread(ns.snapshot)\n\n  // Root is the parent of the current note or\n  // the current note if its a root note or\n  // the root of the thread\n  const rootNote = useMemo(() => {\n    const currentNoteRouter =\n      location.state && \"sig\" in location.state ? (location.state as TaggedNostrEvent) : undefined\n    const currentNote = currentNoteRouter ?? unmuted.find(a => EventExt.keyOf(a) === currentId)\n    if (currentNote) {\n      const key = replyChainKey(currentNote)\n      if (key) {\n        return unmuted.find(a => EventExt.keyOf(a) === key)\n      } else {\n        return currentNote\n      }\n    }\n  }, [unmuted, location.state, currentId])\n\n  /// Parent is the replied to note of the root note\n  const parent = useMemo(() => {\n    if (rootNote) {\n      const parentId = replyChainKey(rootNote)\n      return unmuted.find(a => EventExt.keyOf(a) === parentId)\n    }\n  }, [rootNote, unmuted])\n\n  const ctxValue = {\n    thread: parsedThread,\n    current: currentId,\n    root: rootNote,\n    chains,\n    data: unmuted,\n    mutedData: muted,\n    parent,\n    setCurrent: (v: string) => setCurrentId(v),\n  }\n\n  return <ThreadContext.Provider value={ctxValue}>{children}</ThreadContext.Provider>\n}\n\nfunction useFilteredThread(notes: Array<TaggedNostrEvent>) {\n  const { isMuted } = useModeration()\n\n  const unmuted: TaggedNostrEvent[] = []\n  const muted: TaggedNostrEvent[] = []\n\n  notes.forEach(n => {\n    if (isMuted(n.pubkey)) {\n      muted.push(n)\n    } else {\n      unmuted.push(n)\n    }\n  })\n\n  const chains = new Map<string, Array<string>>()\n  unmuted.forEach(v => {\n    const replyTo = replyChainKey(v)\n    if (replyTo) {\n      const vk = EventExt.keyOf(v)\n      if (!chains.has(replyTo)) {\n        chains.set(replyTo, [vk])\n      } else {\n        chains.get(replyTo)?.push(vk)\n      }\n    }\n  })\n\n  return { unmuted, muted, chains }\n}\n"
  },
  {
    "path": "packages/app/src/Utils/Thread/index.ts",
    "content": "import { EventExt, EventKind, type TaggedNostrEvent, type Thread } from \"@snort/system\"\nimport { createContext } from \"react\"\nimport { ThreadContextWrapper } from \"./ThreadContextWrapper\"\n\nexport { ThreadContextWrapper }\n\n/**\n * Get the chain key as a reply event\n *\n * ie. Get the key for which this event is replying to\n */\nexport function replyChainKey(ev: TaggedNostrEvent) {\n  if (ev.kind !== EventKind.Comment) {\n    const t = EventExt.extractThread(ev)\n    const tag = t?.replyTo ?? t?.root\n    return tag?.tagKey\n  } else {\n    const k = ev.tags.find(t => [\"e\", \"a\", \"i\"].includes(t[0]))\n    return k?.[1]\n  }\n}\n\nexport interface ThreadContextState {\n  thread?: Thread\n  current: string\n  root?: TaggedNostrEvent\n  chains: Map<string, Array<string>>\n  data: Array<TaggedNostrEvent>\n  mutedData: Array<TaggedNostrEvent>\n  parent?: TaggedNostrEvent\n  setCurrent: (i: string) => void\n}\n\nexport const ThreadContext = createContext<ThreadContextState | undefined>(undefined)\n"
  },
  {
    "path": "packages/app/src/Utils/Upload/blossom.ts",
    "content": "import { bytesToHex } from \"@noble/hashes/utils.js\"\nimport { base64 } from \"@scure/base\"\nimport { throwIfOffline, unixNow } from \"@snort/shared\"\nimport type { EventKind, EventPublisher } from \"@snort/system\"\n\nexport interface BlobDescriptor {\n  url?: string\n  sha256: string\n  size: number\n  type?: string\n  uploaded?: number\n  nip94?: Array<Array<string>>\n}\n\nexport class Blossom {\n  constructor(\n    readonly url: string,\n    readonly publisher: EventPublisher,\n  ) {\n    this.url = new URL(this.url).toString()\n  }\n\n  async upload(file: File) {\n    const hash = await window.crypto.subtle.digest(\"SHA-256\", await file.arrayBuffer())\n    const tags = [[\"x\", bytesToHex(new Uint8Array(hash))]]\n\n    const rsp = await this.#req(\"upload\", \"PUT\", \"upload\", file, tags)\n    if (rsp.ok) {\n      const json = await rsp.json()\n      if (\"error\" in json && typeof json.error === \"string\") {\n        throw new Error(json.error)\n      }\n      const ret = json as BlobDescriptor\n      this.#fixTags(ret)\n      return ret\n    } else {\n      const text = await rsp.text()\n      throw new Error(text)\n    }\n  }\n\n  async media(file: File) {\n    const hash = await window.crypto.subtle.digest(\"SHA-256\", await file.arrayBuffer())\n    const tags = [[\"x\", bytesToHex(new Uint8Array(hash))]]\n\n    const rsp = await this.#req(\"media\", \"PUT\", \"media\", file, tags)\n    if (rsp.ok) {\n      const ret = (await rsp.json()) as BlobDescriptor\n      this.#fixTags(ret)\n      return ret\n    } else {\n      const text = await rsp.text()\n      throw new Error(text)\n    }\n  }\n\n  async mirror(url: string) {\n    const body = JSON.stringify({ url })\n    const rsp = await this.#req(\n      \"mirror\",\n      \"PUT\",\n      \"mirror\",\n      body,\n      [\n        [\"t\", \"upload\"],\n        [\"t\", \"mirror\"],\n      ],\n      {\n        \"content-type\": \"application/json\",\n        \"content-length\": body.length.toString(),\n      },\n    )\n    if (rsp.ok) {\n      const ret = (await rsp.json()) as BlobDescriptor\n      this.#fixTags(ret)\n      return ret\n    } else {\n      const text = await rsp.text()\n      throw new Error(text)\n    }\n  }\n\n  async list(pk: string) {\n    const rsp = await this.#req(`list/${pk}`, \"GET\", \"list\")\n    if (rsp.ok) {\n      const ret = (await rsp.json()) as Array<BlobDescriptor>\n      ret.forEach(a => this.#fixTags(a))\n      return ret\n    } else {\n      const text = await rsp.text()\n      throw new Error(text)\n    }\n  }\n\n  async delete(id: string) {\n    const tags = [[\"x\", id]]\n\n    const rsp = await this.#req(id, \"DELETE\", \"delete\", undefined, tags)\n    if (!rsp.ok) {\n      const text = await rsp.text()\n      throw new Error(text)\n    }\n  }\n\n  #fixTags(r: BlobDescriptor) {\n    if (!r.nip94) return\n    if (Array.isArray(r.nip94)) return\n    // blossom.band invalid response\n    if (r.nip94 && \"tags\" in r.nip94) {\n      r.nip94 = r.nip94.tags\n      return\n    }\n    r.nip94 = Object.entries(r.nip94 as Record<string, string>)\n  }\n\n  async #req(\n    path: string,\n    method: \"GET\" | \"POST\" | \"DELETE\" | \"PUT\",\n    term: string,\n    body?: BodyInit,\n    tags?: Array<Array<string>>,\n    headers?: Record<string, string>,\n  ) {\n    throwIfOffline()\n\n    const url = `${this.url}${path}`\n    const now = unixNow()\n    const auth = async (url: string, method: string) => {\n      const auth = await this.publisher.generic(eb => {\n        eb.kind(24_242 as EventKind)\n          .tag([\"u\", url])\n          .tag([\"method\", method.toLowerCase()])\n          .tag([\"t\", term])\n          .tag([\"expiration\", (now + 10).toString()])\n        tags?.forEach(t => eb.tag(t))\n        return eb\n      })\n      return `Nostr ${base64.encode(new TextEncoder().encode(JSON.stringify(auth)))}`\n    }\n\n    return await fetch(url, {\n      method,\n      body,\n      headers: {\n        ...headers,\n        accept: \"application/json\",\n        authorization: await auth(url, method),\n      },\n    })\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Utils/Upload/index.ts",
    "content": "import { EventPublisher, type Nip94Tags, type NostrEvent } from \"@snort/system\"\n\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport { useMediaServerList } from \"@/Hooks/useMediaServerList\"\nimport { randomSample } from \"@/Utils\"\nimport { KieranPubKey } from \"@/Utils/Const\"\n\nimport { Blossom } from \"./blossom\"\nimport { bech32ToHex } from \"@snort/shared\"\n\nexport interface UploadResult {\n  url?: string\n  error?: string\n\n  /**\n   * NIP-94 File Header\n   */\n  header?: NostrEvent\n\n  /**\n   * Media metadata\n   */\n  metadata?: Nip94Tags\n}\n\n/**\n * List of supported upload services and their owners on nostr\n */\nexport const UploaderServices = [\n  {\n    name: \"void.cat\",\n    owner: bech32ToHex(KieranPubKey),\n  },\n  {\n    name: \"nostr.build\",\n    owner: bech32ToHex(\"npub1nxy4qpqnld6kmpphjykvx2lqwvxmuxluddwjamm4nc29ds3elyzsm5avr7\"),\n  },\n  {\n    name: \"nostrimg.com\",\n    owner: bech32ToHex(\"npub1xv6axulxcx6mce5mfvfzpsy89r4gee3zuknulm45cqqpmyw7680q5pxea6\"),\n  },\n  {\n    name: \"nostrcheck.me\",\n    owner: bech32ToHex(\"npub138s5hey76qrnm2pmv7p8nnffhfddsm8sqzm285dyc0wy4f8a6qkqtzx624\"),\n  },\n]\n\nexport interface Uploader {\n  upload: (f: File | Blob, filename: string) => Promise<UploadResult>\n  progress: Array<UploadProgress>\n}\n\nexport interface UploadProgress {\n  id: string\n  file: File | Blob\n  progress: number\n  stage: UploadStage\n}\n\nexport type UploadStage = \"starting\" | \"hashing\" | \"uploading\" | \"done\" | undefined\n\nexport default function useFileUpload(privKey?: string) {\n  const { publisher } = useEventPublisher()\n  const { servers } = useMediaServerList()\n\n  const pub = privKey ? EventPublisher.privateKey(privKey) : publisher\n  if (servers.length > 0 && pub) {\n    const sampled = randomSample(servers, 3)\n    const primary = sampled[0]\n    const mirrors = sampled.slice(1)\n    return new MultiServerBlossom(primary, mirrors, pub)\n  } else if (pub) {\n    return new Blossom(\"https://blossom.band\", pub)\n  }\n}\n\nclass MultiServerBlossom {\n  constructor(\n    private primary: string,\n    private mirrors: string[],\n    private publisher: EventPublisher,\n  ) {}\n\n  async upload(file: File | Blob) {\n    const blossom = new Blossom(this.primary, this.publisher)\n    const result = await blossom.upload(file instanceof Blob ? new File([file], \"blob\") : file)\n\n    const mirrorUrls = []\n    for (const server of this.mirrors) {\n      try {\n        if (result.url) {\n          const mirrorResult = await new Blossom(server, this.publisher).mirror(result.url)\n          if (mirrorResult.url) {\n            mirrorUrls.push(mirrorResult.url)\n          }\n        }\n      } catch (e) {\n        console.warn(\"Mirror upload failed for\", server, e)\n      }\n    }\n\n    result.nip94 ??= []\n    for (const url of mirrorUrls) {\n      result.nip94.push([\"fallback\", url])\n    }\n\n    return result\n  }\n}\n"
  },
  {
    "path": "packages/app/src/Utils/ZapPoolController.ts",
    "content": "import { bech32ToHex, ExternalStore, LNURL, unixNow } from \"@snort/shared\"\nimport { type LNWallet, WalletInvoiceState } from \"@snort/wallet\"\nimport debug from \"debug\"\n\nimport { ProfilesCache } from \"@/Cache\"\nimport { Toastore } from \"@/Components/Toaster/Toaster\"\nimport { SnortPubKey } from \"@/Utils/Const\"\nimport { getDisplayName, trackEvent } from \"@/Utils/index\"\nimport { Wallets } from \"@/Wallet\"\n\nexport enum ZapPoolRecipientType {\n  Generic = 0,\n  Relay = 1,\n  FileHost = 2,\n  DataProvider = 3,\n}\n\nexport interface ZapPoolRecipient {\n  type: ZapPoolRecipientType\n  pubkey: string\n  split: number\n  sum: number\n}\n\nclass ZapPool extends ExternalStore<Array<ZapPoolRecipient>> {\n  #log = debug(\"ZapPool\")\n  #store = new Map<string, ZapPoolRecipient>()\n  #isPayoutInProgress = false\n  #lastPayout = 0\n\n  constructor() {\n    super()\n    this.#load()\n    setTimeout(() => this.#autoPayout().catch(console.error), 5_000)\n  }\n\n  async payout(wallet: LNWallet) {\n    if (this.#isPayoutInProgress) {\n      throw new Error(\"Payout already in progress\")\n    }\n    this.#isPayoutInProgress = true\n    this.#lastPayout = unixNow()\n    for (const x of this.#store.values()) {\n      if (x.sum === 0) continue\n      try {\n        const profile = await ProfilesCache.get(x.pubkey)\n        if (!profile) {\n          throw new Error(`Failed to get profile for ${x.pubkey}`)\n        }\n        const svc = new LNURL(profile.lud16 || profile.lud06 || \"\")\n        await svc.load()\n        const amtSend = x.sum\n        const invoice = await svc.getInvoice(amtSend, `SnortZapPool: ${x.split}%`)\n        if (invoice.pr) {\n          const result = await wallet.payInvoice(invoice.pr)\n          this.#log(\"%o %o\", invoice, result)\n          if (result.state === WalletInvoiceState.Paid) {\n            x.sum -= amtSend\n            Toastore.push({\n              element: `Sent ${amtSend.toLocaleString()} sats to ${getDisplayName(\n                profile,\n                x.pubkey,\n              )} from your zap pool`,\n              expire: unixNow() + 10,\n              icon: \"zap\",\n            })\n          } else {\n            throw new Error(`Failed to pay invoice, unknown reason`)\n          }\n        } else {\n          throw new Error(invoice.reason ?? \"Failed to get invoice\")\n        }\n      } catch (e) {\n        console.error(e)\n        if (e instanceof Error) {\n          const profile = ProfilesCache.getFromCache(x.pubkey)\n          Toastore.push({\n            element: `Failed to send sats to ${getDisplayName(profile, x.pubkey)} (${\n              e.message\n            }), please try again later`,\n            expire: unixNow() + 10,\n            icon: \"close\",\n          })\n        }\n      }\n    }\n    this.#save()\n    this.notifyChange()\n    this.#isPayoutInProgress = false\n  }\n\n  calcAllocation(n: number) {\n    let res = 0\n    for (const x of this.#store.values()) {\n      res += Math.ceil(n * (x.split / 100))\n    }\n    return res\n  }\n\n  allocate(n: number) {\n    if (this.#isPayoutInProgress) {\n      throw new Error(\"Payout is in progress, cannot allocate to pool\")\n    }\n    for (const x of this.#store.values()) {\n      x.sum += Math.ceil(n * (x.split / 100))\n    }\n    this.#save()\n    this.notifyChange()\n  }\n\n  getOrDefault(rcpt: ZapPoolRecipient): ZapPoolRecipient {\n    const k = this.#key(rcpt)\n    const existing = this.#store.get(k)\n    if (existing) {\n      return { ...existing }\n    }\n    return rcpt\n  }\n\n  set(rcpt: ZapPoolRecipient) {\n    const k = this.#key(rcpt)\n    // delete entry if split is 0 and sum is 0\n    if (rcpt.split === 0 && rcpt.sum === 0 && this.#store.has(k)) {\n      this.#store.delete(k)\n    } else {\n      this.#store.set(k, rcpt)\n    }\n    this.#save()\n    this.notifyChange()\n  }\n\n  #key(rcpt: ZapPoolRecipient) {\n    return `${rcpt.pubkey}-${rcpt.type}`\n  }\n\n  #save() {\n    globalThis.localStorage.setItem(\"zap-pool\", JSON.stringify(this.takeSnapshot()))\n    globalThis.localStorage.setItem(\"zap-pool-last-payout\", this.#lastPayout.toString())\n  }\n\n  #load() {\n    const existing = globalThis.localStorage.getItem(\"zap-pool\")\n    if (existing) {\n      const arr = JSON.parse(existing) as Array<ZapPoolRecipient>\n      this.#store = new Map(arr.map(a => [`${a.pubkey}-${a.type}`, a]))\n    } else if (CONFIG.defaultZapPoolFee) {\n      this.#store = new Map([\n        [\n          `${bech32ToHex(SnortPubKey)}-${ZapPoolRecipientType.Generic}`,\n          {\n            type: ZapPoolRecipientType.Generic,\n            split: CONFIG.defaultZapPoolFee,\n            pubkey: bech32ToHex(SnortPubKey),\n            sum: 0,\n          },\n        ],\n      ])\n    }\n\n    const lastPayout = globalThis.localStorage.getItem(\"zap-pool-last-payout\")\n    if (lastPayout) {\n      this.#lastPayout = Number(lastPayout)\n    }\n  }\n\n  async #autoPayout() {\n    const payoutInterval = 60 * 60\n    try {\n      if (this.#lastPayout < unixNow() - payoutInterval) {\n        const wallet = Wallets.get()\n        if (wallet) {\n          if (wallet.canAutoLogin()) {\n            await wallet.login()\n          }\n          trackEvent(\"ZapPool\", { automatic: true })\n          await this.payout(wallet)\n        }\n      }\n    } catch (e) {\n      console.error(e)\n    }\n    setTimeout(() => this.#autoPayout().catch(console.error), 60_000)\n  }\n\n  takeSnapshot(): ZapPoolRecipient[] {\n    return [...this.#store.values()]\n  }\n}\n\nexport const ZapPoolController = CONFIG.features.zapPool ? new ZapPool() : undefined\n"
  },
  {
    "path": "packages/app/src/Utils/emoji-search.ts",
    "content": "import { matchSorter } from \"match-sorter\"\n\nexport default async function searchEmoji(key: string) {\n  const emoji = await import(\"emojilib\")\n  /* build proper library with included name of the emoji */\n  const library = Object.entries(emoji.default).map(([emoji, keywords]) => ({\n    name: keywords[0],\n    keywords,\n    char: emoji,\n  }))\n  return matchSorter(library, key, { keys: [\"keywords\"] })\n}\n"
  },
  {
    "path": "packages/app/src/Utils/getEventMedia.ts",
    "content": "import { EventKind, type ParsedFragment, readNip94TagsFromIMeta, type TaggedNostrEvent } from \"@snort/system\"\n\nimport { transformTextCached } from \"@/Hooks/useTextTransformCache\"\n\nexport default function getEventMedia(event: TaggedNostrEvent) {\n  // emulate parsed media from imeta kinds\n  const mediaKinds = [EventKind.Photo, EventKind.Video, EventKind.ShortVideo]\n  if (mediaKinds.includes(event.kind)) {\n    const meta = event.tags.filter(a => a[0] === \"imeta\").map(readNip94TagsFromIMeta)\n    return meta.map(\n      a =>\n        ({\n          type: \"media\",\n          mimeType: a.mimeType,\n          content: a.url,\n        }) as ParsedFragment,\n    )\n  }\n  const parsed = transformTextCached(event.id, event.content, event.tags)\n  return parsed.filter(\n    a => a.type === \"media\" && (a.mimeType?.startsWith(\"image/\") || a.mimeType?.startsWith(\"video/\")),\n  )\n}\n"
  },
  {
    "path": "packages/app/src/Utils/index.ts",
    "content": "import { bytesToHex, hexToBytes } from \"@noble/hashes/utils.js\"\nimport { base32hex } from \"@scure/base\"\nimport { bech32ToHex, encodeTLV, hexToBech32, isOffline, NostrPrefix } from \"@snort/shared\"\nimport type { CachedMetadata, EventKind, NostrEvent, NostrLink, TaggedNostrEvent, UserMetadata } from \"@snort/system\"\n\nimport Nostrich from \"@/assets/img/nostrich.webp\"\nimport AnimalName from \"@/Components/User/AnimalName\"\nimport { Birthday, Day } from \"@/Utils/Const\"\n\nimport TZ from \"../tz.json\"\nimport { LoginStore } from \"./Login\"\n\nexport async function openFile(): Promise<File | undefined> {\n  return new Promise(resolve => {\n    const elm = document.createElement(\"input\")\n    let lock = false\n    elm.type = \"file\"\n    const handleInput = (e: Event) => {\n      lock = true\n      const elm = e.target as HTMLInputElement\n      if ((elm.files?.length ?? 0) > 0) {\n        resolve(elm.files?.[0])\n      } else {\n        resolve(undefined)\n      }\n    }\n\n    elm.onchange = e => handleInput(e)\n    elm.click()\n    window.addEventListener(\n      \"focus\",\n      () => {\n        setTimeout(() => {\n          if (!lock) {\n            resolve(undefined)\n          }\n        }, 300)\n      },\n      { once: true },\n    )\n  })\n}\n\n/**\n * Parse bech32 ids\n * https://github.com/nostr-protocol/nips/blob/master/19.md\n * @param id bech32 id\n */\nexport function parseId(id: string) {\n  const hrp = [\"note\", \"npub\", \"nsec\"]\n  try {\n    if (hrp.some(a => id.startsWith(a))) {\n      return bech32ToHex(id)\n    }\n  } catch (_e) {\n    // Ignore the error.\n  }\n  return id\n}\n\n/**\n * Convert hex note id to bech32 link url\n * @param hex\n * @returns\n */\nexport function eventLink(hex: string, relays?: Array<string> | string) {\n  const encoded = relays\n    ? encodeTLV(NostrPrefix.Event, hexToBytes(hex), Array.isArray(relays) ? relays : [relays])\n    : hexToBech32(NostrPrefix.Note, hex)\n  return `/${encoded}`\n}\n\nexport function getLinkReactions(\n  notes: ReadonlyArray<TaggedNostrEvent> | undefined,\n  link: NostrLink,\n  kind?: EventKind,\n) {\n  return notes?.filter(a => a.kind === (kind ?? a.kind) && link.isReplyToThis(a)) || []\n}\n\nexport function getAllLinkReactions(\n  notes: readonly TaggedNostrEvent[] | undefined,\n  links: Array<NostrLink>,\n  kind?: EventKind,\n) {\n  return notes?.filter(a => a.kind === (kind ?? a.kind) && links.some(b => b.isReplyToThis(a))) || []\n}\n\nexport function deepClone<T>(obj: T) {\n  if (\"structuredClone\" in window) {\n    return structuredClone(obj)\n  } else {\n    return JSON.parse(JSON.stringify(obj))\n  }\n}\n\n/**\n * Simple debounce\n */\nexport function debounce(timeout: number, fn: () => void) {\n  const t = setTimeout(fn, timeout)\n  return () => clearTimeout(t)\n}\n\nexport function dedupeByPubkey(events: TaggedNostrEvent[]) {\n  const deduped = events.reduce(\n    ({ list, seen }: { list: TaggedNostrEvent[]; seen: Set<string> }, ev) => {\n      if (seen.has(ev.pubkey)) {\n        return { list, seen }\n      }\n      seen.add(ev.pubkey)\n      return {\n        seen,\n        list: [...list, ev],\n      }\n    },\n    { list: [], seen: new Set([]) },\n  )\n  return deduped.list as TaggedNostrEvent[]\n}\n\nexport function dedupeById<T extends { id: string }>(events: Array<T>) {\n  const deduped = events.reduce(\n    ({ list, seen }: { list: Array<T>; seen: Set<string> }, ev) => {\n      if (seen.has(ev.id)) {\n        return { list, seen }\n      }\n      seen.add(ev.id)\n      return {\n        seen,\n        list: [...list, ev],\n      }\n    },\n    { list: [], seen: new Set([]) },\n  )\n  return deduped.list as Array<T>\n}\n\n/**\n * Return newest event by pubkey\n * @param events List of all notes to filter from\n * @returns\n */\nexport function getLatestByPubkey(events: TaggedNostrEvent[]): Map<string, TaggedNostrEvent> {\n  const deduped = events.reduce((results: Map<string, TaggedNostrEvent>, ev) => {\n    if (!results.has(ev.pubkey)) {\n      const latest = getNewest(events.filter(a => a.pubkey === ev.pubkey))\n      if (latest) {\n        results.set(ev.pubkey, latest)\n      }\n    }\n    return results\n  }, new Map<string, TaggedNostrEvent>())\n  return deduped\n}\n\nexport function getLatestProfileByPubkey(profiles: CachedMetadata[]): Map<string, CachedMetadata> {\n  const deduped = profiles.reduce((results: Map<string, CachedMetadata>, ev) => {\n    if (!results.has(ev.pubkey)) {\n      const latest = getNewestProfile(profiles.filter(a => a.pubkey === ev.pubkey))\n      if (latest) {\n        results.set(ev.pubkey, latest)\n      }\n    }\n    return results\n  }, new Map<string, CachedMetadata>())\n  return deduped\n}\n\nexport function dedupe<T>(v: Array<T>) {\n  return [...new Set(v)]\n}\n\nexport function appendDedupe<T>(a?: Array<T>, b?: Array<T>) {\n  return dedupe([...(a ?? []), ...(b ?? [])])\n}\n\nexport function unwrap<T>(v: T | undefined | null): T {\n  if (v === undefined || v === null) {\n    throw new Error(\"missing value\")\n  }\n  return v\n}\n\n/**\n * Get a random sample of elements from an array using Fisher-Yates partial shuffle.\n * This is an unbiased O(min(size, length)) algorithm, much better than sort-based approaches.\n * @param coll - The array to sample from\n * @param size - The number of elements to sample (clamped to array length)\n * @returns Array of randomly sampled elements\n */\nexport function randomSample<T>(coll: T[], size: number): T[] {\n  if (coll.length === 0 || size <= 0) {\n    return []\n  }\n\n  const sampleSize = Math.min(size, coll.length)\n  const result = [...coll]\n\n  // Partial Fisher-Yates shuffle: only shuffle the first 'sampleSize' elements\n  for (let i = 0; i < sampleSize; i++) {\n    const j = i + Math.floor(Math.random() * (result.length - i))\n    ;[result[i], result[j]] = [result[j], result[i]]\n  }\n  return result.slice(0, sampleSize)\n}\n\nexport function getNewest(rawNotes: readonly TaggedNostrEvent[]) {\n  const notes = [...rawNotes]\n  notes.sort((a, b) => b.created_at - a.created_at)\n  if (notes.length > 0) {\n    return notes[0]\n  }\n}\n\nexport function getNewestProfile(rawNotes: CachedMetadata[]) {\n  const notes = [...rawNotes]\n  notes.sort((a, b) => b.created - a.created)\n  if (notes.length > 0) {\n    return notes[0]\n  }\n}\n\nexport function getNewestEventTagsByKey(evs: TaggedNostrEvent[], tag: string) {\n  const newest = getNewest(evs)\n  if (newest) {\n    const keys = newest.tags.filter(p => p && p.length === 2 && p[0] === tag).map(p => p[1])\n    return {\n      keys,\n      createdAt: newest.created_at,\n    }\n  }\n}\n\nexport function tagFilterOfTextRepost(note: TaggedNostrEvent, id?: string): (tag: string[], i: number) => boolean {\n  return (tag, i) => tag[0] === \"e\" && tag[3] === \"mention\" && note.content === `#[${i}]` && (id ? tag[1] === id : true)\n}\n\nexport function groupByPubkey(acc: Record<string, CachedMetadata>, user: CachedMetadata) {\n  return { ...acc, [user.pubkey]: user }\n}\n\nexport const delay = (t: number) => {\n  return new Promise(resolve => {\n    setTimeout(resolve, t)\n  })\n}\n\nexport function orderAscending<T>(arr: Array<T & { created_at: number }>) {\n  return arr.sort((a, b) => (b.created_at > a.created_at ? -1 : 1))\n}\n\nexport interface Magnet {\n  dn?: string | string[]\n  tr?: string | string[]\n  xs?: string | string[]\n  as?: string | string[]\n  ws?: string | string[]\n  kt?: string[]\n  ix?: number | number[]\n  xt?: string | string[]\n  infoHash?: string\n  raw?: string\n}\n\n/**\n * Parse a magnet URI and return an object of keys/values\n */\nexport function magnetURIDecode(uri: string): Magnet | undefined {\n  try {\n    const result: Record<string, string | number | number[] | string[] | undefined> = {\n      raw: uri,\n    }\n\n    // Support 'magnet:' and 'stream-magnet:' uris\n    const data = uri.trim().split(\"magnet:?\")[1]\n\n    const params = data && data.length > 0 ? data.split(\"&\") : []\n\n    params.forEach(param => {\n      const split = param.split(\"=\")\n      const key = split[0]\n      const val = decodeURIComponent(split[1])\n\n      if (!result[key]) {\n        result[key] = []\n      }\n\n      switch (key) {\n        case \"dn\": {\n          ;(result[key] as string[]).push(val.replace(/\\+/g, \" \"))\n          break\n        }\n        case \"kt\": {\n          val.split(\"+\").forEach(e => {\n            ;(result[key] as string[]).push(e)\n          })\n          break\n        }\n        case \"ix\": {\n          ;(result[key] as number[]).push(Number(val))\n          break\n        }\n        case \"so\": {\n          // todo: not implemented yet\n          break\n        }\n        default: {\n          ;(result[key] as string[]).push(val)\n          break\n        }\n      }\n    })\n\n    // Convenience properties for parity with `parse-torrent-file` module\n    let m\n    if (result.xt) {\n      const xts = Array.isArray(result.xt) ? result.xt : [result.xt]\n      xts.forEach(xt => {\n        if (typeof xt === \"string\") {\n          if ((m = xt.match(/^urn:btih:(.{40})/))) {\n            result.infoHash = [m[1].toLowerCase()]\n          } else if ((m = xt.match(/^urn:btih:(.{32})/))) {\n            const decodedStr = base32hex.decode(m[1])\n            result.infoHash = [bytesToHex(decodedStr)]\n          } else if ((m = xt.match(/^urn:btmh:1220(.{64})/))) {\n            result.infoHashV2 = [m[1].toLowerCase()]\n          }\n        }\n      })\n    }\n\n    if (result.xs) {\n      const xss = Array.isArray(result.xs) ? result.xs : [result.xs]\n      xss.forEach(xs => {\n        if (typeof xs === \"string\" && (m = xs.match(/^urn:btpk:(.{64})/))) {\n          if (!result.publicKey) {\n            result.publicKey = []\n          }\n          ;(result.publicKey as string[]).push(m[1].toLowerCase())\n        }\n      })\n    }\n\n    for (const [k, v] of Object.entries(result)) {\n      if (Array.isArray(v)) {\n        if (v.length === 1) {\n          result[k] = v[0]\n        } else if (v.length === 0) {\n          result[k] = undefined\n        }\n      }\n    }\n    return result\n  } catch (e) {\n    console.warn(\"Failed to parse magnet link\", e)\n  }\n}\n\nexport function chunks<T>(arr: T[], length: number) {\n  const result = []\n  let idx = 0\n  let n = arr.length / length\n  while (n > 0) {\n    result.push(arr.slice(idx, idx + length))\n    idx += length\n    n -= 1\n  }\n  return result\n}\n\nexport function findTag(e: NostrEvent, tag: string) {\n  const maybeTag = e.tags.find(evTag => {\n    return evTag[0] === tag\n  })\n  return maybeTag?.[1]\n}\n\nexport function getRelayName(url: string) {\n  try {\n    const parsedUrl = new URL(url)\n    return parsedUrl.host + parsedUrl.search\n  } catch {\n    return url\n  }\n}\n\nexport function getUrlHostname(url?: string) {\n  try {\n    return new URL(url ?? \"\").hostname\n  } catch {\n    return url?.match(/(\\S+\\.\\S+)/i)?.[1] ?? url\n  }\n}\n\nexport function sanitizeRelayUrl(url?: string) {\n  if ((url?.length ?? 0) === 0) return\n  try {\n    return new URL(url!).toString()\n  } catch {\n    // ignore\n  }\n}\n\nexport function kvToObject<T>(o: string, sep?: string) {\n  return Object.fromEntries(\n    o.split(sep ?? \",\").map(v => {\n      const match = v.trim().match(/^(\\w+)=\"(.*)\"$/)\n      if (match) {\n        return [match[1], match[2]]\n      }\n      return []\n    }),\n  ) as T\n}\n\nexport function defaultAvatar(input?: string) {\n  if (isOffline()) return Nostrich\n  const key = (input?.length ?? 0) === 0 ? \"missing\" : input\n  return `https://nostr-rs-api.v0l.io/avatar/${isHalloween() ? \"zombies\" : \"cyberpunks\"}/${key}.webp`\n}\n\nexport function isFormElement(target: HTMLElement): boolean {\n  if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) {\n    return true\n  }\n\n  return false\n}\n\nconst ThisYear = new Date().getFullYear()\nconst IsTheSeason = (target: Date, window: number) => {\n  const now = new Date()\n  const days = (target.getTime() - now.getTime()) / (Day * 1000)\n  return (days >= 0 && days <= window) || (now.getDate() === target.getDate() && now.getMonth() === target.getMonth())\n}\n\nexport const isHalloween = () => {\n  const event = new Date(ThisYear, 9, 31)\n  return IsTheSeason(event, 7)\n}\n\nexport const isStPatricksDay = () => {\n  const event = new Date(ThisYear, 2, 17)\n  return IsTheSeason(event, 1)\n}\n\nexport const isChristmas = () => {\n  const event = new Date(ThisYear, 11, 25)\n  return IsTheSeason(event, 7)\n}\n\nexport const isBirthday = () => {\n  const event = new Date(ThisYear, Birthday.getMonth(), Birthday.getDate())\n  return CONFIG.appName === \"Snort\" && IsTheSeason(event, 1)\n}\n\nexport function getDisplayName(user: UserMetadata | undefined, pubkey: string): string {\n  return getDisplayNameOrPlaceHolder(user, pubkey)[0]\n}\n\nexport function getDisplayNameOrPlaceHolder(user: UserMetadata | undefined, pubkey: string): [string, boolean] {\n  if (typeof user?.display_name === \"string\" && user.display_name.length > 0) {\n    return [user.display_name.trim(), false]\n  } else if (typeof user?.name === \"string\" && user.name.length > 0) {\n    return [user.name.trim(), false]\n  } else if (pubkey && CONFIG.animalNamePlaceholders) {\n    return [AnimalName(pubkey), true]\n  }\n\n  return [hexToBech32(NostrPrefix.PublicKey, pubkey).substring(0, 12), false]\n}\n\nexport function getCountry() {\n  const tz = Intl.DateTimeFormat().resolvedOptions()\n  const info = (TZ as Record<string, Array<string> | undefined>)[tz.timeZone]\n  const pos = info?.[1]\n  const sep = Number(pos?.slice(1).search(/[-+]/)) + 1\n  const [lat, lon] = [pos?.slice(0, sep) ?? \"00\", pos?.slice(sep) ?? \"000\"]\n  return {\n    zone: tz.timeZone,\n    country: info?.[0],\n    lat: Number(lat) / 10 ** (lat.length - 3),\n    lon: Number(lon) / 10 ** (lon.length - 4),\n    info,\n  }\n}\n\nexport function calculateDistance(lat1: number, lon1: number, lat2: number, lon2: number): number {\n  const R = 6371000 // Radius of the Earth in meters\n  const dLat = toRadians(lat2 - lat1)\n  const dLon = toRadians(lon2 - lon1)\n\n  const a =\n    Math.sin(dLat / 2) * Math.sin(dLat / 2) +\n    Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2)\n  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))\n  return R * c\n}\n\nfunction toRadians(degrees: number): number {\n  return degrees * (Math.PI / 180)\n}\n\nexport function trackEvent(\n  event: string,\n  props?: Record<string, string | boolean>,\n  e?: { destination?: { url: string } },\n) {\n  if (\n    !import.meta.env.DEV &&\n    CONFIG.features.analytics &&\n    (LoginStore.snapshot().state.appdata?.preferences.telemetry ?? true)\n  ) {\n    fetch(\"https://pa.v0l.io/api/event\", {\n      method: \"POST\",\n      headers: {\n        \"content-type\": \"application/json\",\n      },\n      body: JSON.stringify({\n        d: CONFIG.hostname,\n        n: event,\n        r: document.referrer === window.location.href ? null : document.referrer,\n        p: props,\n        u: e?.destination?.url ?? `${window.location.protocol}//${window.location.host}${window.location.pathname}`,\n      }),\n    })\n  }\n}\n\nexport function storeRefCode() {\n  const ref = getCurrentRefCode()\n  if (ref) {\n    window.localStorage.setItem(\"ref\", ref)\n  }\n}\n\nexport function getCurrentRefCode() {\n  if (window.location.search) {\n    const q = new URLSearchParams(window.location.search)\n    const ref = q.get(\"ref\")\n    if (ref) {\n      return ref\n    }\n  }\n}\n\nexport function getRefCode() {\n  const r = window.localStorage.getItem(\"ref\")\n  if (r) return r\n}\n\nexport function deleteRefCode() {\n  window.localStorage.removeItem(\"ref\")\n}\n"
  },
  {
    "path": "packages/app/src/Utils/nip6.ts",
    "content": "import { bytesToHex, hexToBytes } from \"@noble/hashes/utils.js\"\nimport { HDKey } from \"@scure/bip32\"\nimport * as bip39 from \"@scure/bip39\"\nimport { wordlist } from \"@scure/bip39/wordlists/english.js\"\n\n/**\n * NIP06-defined derivation path for private keys\n */\nexport const DerivationPath = \"m/44'/1237'/0'/0/0\"\n\nexport function generateBip39Entropy(mnemonic?: string) {\n  try {\n    const mn = mnemonic ?? bip39.generateMnemonic(wordlist, 256)\n    return bip39.mnemonicToEntropy(mn, wordlist)\n  } catch (_e) {\n    throw new Error(\"INVALID MNEMONIC PHRASE\")\n  }\n}\n\n/**\n * Convert hex-encoded seed into mnemonic phrase\n */\nexport function seedToMnemonic(hex: string) {\n  const bytes = hexToBytes(hex)\n  return bip39.entropyToMnemonic(bytes, wordlist)\n}\n\n/**\n * Derrive NIP-06 private key from master key\n */\nexport function seedToPrivateKey(seed: Uint8Array) {\n  const masterKey = HDKey.fromMasterSeed(seed)\n  const newKey = masterKey.derive(DerivationPath)\n\n  if (!newKey.privateKey) {\n    throw new Error(\"INVALID KEY DERIVATION\")\n  }\n\n  return bytesToHex(newKey.privateKey)\n}\n\nexport async function entropyToPrivateKey(entropy: Uint8Array) {\n  const mm = bip39.entropyToMnemonic(entropy, wordlist)\n  const seed = await bip39.mnemonicToSeed(mm)\n  const masterKey = HDKey.fromMasterSeed(seed)\n  const newKey = masterKey.derive(DerivationPath)\n\n  if (!newKey.privateKey) {\n    throw new Error(\"INVALID KEY DERIVATION\")\n  }\n\n  return bytesToHex(newKey.privateKey)\n}\n"
  },
  {
    "path": "packages/app/src/Utils/stream.ts",
    "content": "import type { TaggedNostrEvent } from \"@snort/system\"\n\nexport function getHost(ev?: TaggedNostrEvent) {\n  return ev?.tags.find(a => a[0] === \"p\" && a[3] === \"host\")?.[1] ?? ev?.pubkey ?? \"\"\n}\n\nexport type StreamState = \"live\" | \"ended\" | \"planned\"\n\nexport interface StreamInfo {\n  id?: string\n  title?: string\n  summary?: string\n  image?: string\n  thumbnail?: string\n  status?: StreamState\n  stream?: string\n  recording?: string\n  contentWarning?: string\n  tags: Array<string>\n  goal?: string\n  participants?: string\n  starts?: string\n  ends?: string\n  service?: string\n  host?: string\n  gameId?: string\n}\n\nconst gameTagFormat = /^[a-z-]+:[a-z0-9-]+$/i\nexport function extractStreamInfo(ev?: TaggedNostrEvent) {\n  const ret = {\n    host: getHost(ev),\n  } as StreamInfo\n  const matchTag = (tag: Array<string>, k: string, into: (v: string) => void) => {\n    if (tag[0] === k) {\n      into(tag[1])\n    }\n  }\n\n  for (const t of ev?.tags ?? []) {\n    matchTag(t, \"d\", v => (ret.id = v))\n    matchTag(t, \"title\", v => (ret.title = v))\n    matchTag(t, \"summary\", v => (ret.summary = v))\n    matchTag(t, \"image\", v => (ret.image = v))\n    matchTag(t, \"thumbnail\", v => (ret.thumbnail = v))\n    matchTag(t, \"status\", v => (ret.status = v as StreamState))\n    if (t[0] === \"streaming\") {\n      matchTag(t, \"streaming\", v => (ret.stream = v))\n    }\n    matchTag(t, \"recording\", v => (ret.recording = v))\n    matchTag(t, \"url\", v => (ret.recording = v))\n    matchTag(t, \"content-warning\", v => (ret.contentWarning = v))\n    matchTag(t, \"current_participants\", v => (ret.participants = v))\n    matchTag(t, \"goal\", v => (ret.goal = v))\n    matchTag(t, \"starts\", v => (ret.starts = v))\n    matchTag(t, \"ends\", v => (ret.ends = v))\n    matchTag(t, \"service\", v => (ret.service = v))\n  }\n  const { regularTags } = sortStreamTags(ev?.tags ?? [])\n  ret.tags = regularTags\n\n  return ret\n}\n\nexport function sortStreamTags(tags: Array<string | Array<string>>) {\n  const plainTags = tags.filter(a => (Array.isArray(a) ? a[0] === \"t\" : true)).map(a => (Array.isArray(a) ? a[1] : a))\n\n  const regularTags = plainTags.filter(a => !a.match(gameTagFormat)) ?? []\n  const prefixedTags = plainTags.filter(a => !regularTags.includes(a))\n  return { regularTags, prefixedTags }\n}\n"
  },
  {
    "path": "packages/app/src/Utils/wasm.ts",
    "content": "import {\n  EventExt,\n  type FlatReqFilter,\n  type NostrEvent,\n  type Optimizer,\n  type PowMiner,\n  PowWorker,\n  type ReqFilter,\n  type TaggedNostrEvent,\n} from \"@snort/system\"\nimport PowWorkerURL from \"@snort/system/src/pow-worker.ts?worker&url\"\n\nimport { unwrap } from \"@/Utils/index\"\n\nimport {\n  compress,\n  expand_filter,\n  flat_merge,\n  get_diff,\n  pow,\n  schnorr_verify_batch,\n  schnorr_verify_event,\n  default as wasmInit,\n} from \"../../../system-wasm/pkg/system_wasm\"\nimport WasmPath from \"../../../system-wasm/pkg/system_wasm_bg.wasm\"\n\nexport const WasmOptimizer = {\n  expandFilter: (f: ReqFilter) => {\n    return expand_filter(f) as Array<FlatReqFilter>\n  },\n  getDiff: (prev: Array<ReqFilter>, next: Array<ReqFilter>) => {\n    return get_diff(prev, next) as Array<FlatReqFilter>\n  },\n  flatMerge: (all: Array<FlatReqFilter>) => {\n    return flat_merge(all) as Array<ReqFilter>\n  },\n  compress: (all: Array<ReqFilter>) => {\n    return compress(all) as Array<ReqFilter>\n  },\n  schnorrVerify: ev => {\n    if (EventExt.isVerified(ev)) return true\n    const { relays, ...clean } = ev as TaggedNostrEvent\n    const ok = schnorr_verify_event(clean) as boolean\n    if (ok) EventExt.markVerified(ev)\n    return ok\n  },\n  batchVerify: evs => {\n    // Filter to only the events that need verification, preserving their index.\n    const unverified: Array<{ idx: number; ev: NostrEvent }> = []\n    const results = new Array<boolean>(evs.length)\n    for (let i = 0; i < evs.length; i++) {\n      if (EventExt.isVerified(evs[i])) {\n        results[i] = true\n      } else {\n        unverified.push({ idx: i, ev: evs[i] })\n      }\n    }\n    if (unverified.length > 0) {\n      // One JS→WASM call for all unverified events; returns Uint8Array (1=valid, 0=invalid).\n      const raw = schnorr_verify_batch(\n        unverified.map(u => u.ev),\n      ) as Uint8Array\n      for (let j = 0; j < unverified.length; j++) {\n        const ok = raw[j] === 1\n        results[unverified[j].idx] = ok\n        if (ok) EventExt.markVerified(unverified[j].ev)\n      }\n    }\n    return results\n  },\n} as Optimizer\n\nexport class WasmPowWorker implements PowMiner {\n  minePow(ev: NostrEvent, target: number): Promise<NostrEvent> {\n    const res = pow(ev, target)\n    return Promise.resolve(res)\n  }\n}\n\nexport { wasmInit, WasmPath }\nexport const hasWasm = \"WebAssembly\" in globalThis && localStorage.getItem(\"wasm\") !== \"off\"\nconst DefaultPowWorker = hasWasm ? undefined : new PowWorker(PowWorkerURL)\nexport const GetPowWorker = () => (hasWasm ? new WasmPowWorker() : unwrap(DefaultPowWorker))\n"
  },
  {
    "path": "packages/app/src/Wallet/index.ts",
    "content": "import { ExternalStore, unwrap } from \"@snort/shared\"\nimport { type LNWallet, loadWallet, type WalletInfo, WalletKind } from \"@snort/wallet\"\nimport { useEffect, useSyncExternalStore } from \"react\"\n\nexport interface WalletConfig {\n  id: string\n  kind: WalletKind\n  active: boolean\n  info: WalletInfo\n\n  /**\n   * Opaque string for wallet config\n   */\n  data?: string\n}\n\nexport interface WalletStoreSnapshot {\n  configs: Array<WalletConfig>\n  config?: WalletConfig\n  wallet?: LNWallet\n}\n\nexport class WalletStore extends ExternalStore<WalletStoreSnapshot> {\n  #configs: Array<WalletConfig>\n  #instance: Map<string, LNWallet>\n\n  constructor() {\n    super()\n    this.#configs = []\n    this.#instance = new Map()\n    this.load(false)\n    this.notifyChange()\n  }\n\n  list() {\n    return Object.freeze([...this.#configs])\n  }\n\n  get() {\n    const activeConfig = this.#configs.find(a => a.active)\n    if (!activeConfig) {\n      if (this.#configs.length === 0) {\n        return undefined\n      }\n      throw new Error(\"No active wallet config\")\n    }\n    if (this.#instance.has(activeConfig.id)) {\n      return unwrap(this.#instance.get(activeConfig.id))\n    } else {\n      const w = this.#activateWallet(activeConfig)\n      if (w) {\n        if (\"then\" in w) {\n          w.then(async wx => {\n            if (wx) {\n              this.#instance.set(activeConfig.id, wx)\n              this.notifyChange()\n            }\n          })\n          return undefined\n        } else {\n          this.#instance.set(activeConfig.id, w)\n          this.notifyChange()\n        }\n        return w\n      } else {\n        throw new Error(\"Unable to activate wallet config\")\n      }\n    }\n  }\n\n  add(cfg: WalletConfig) {\n    this.#configs.push(cfg)\n    this.save()\n  }\n\n  remove(id: string) {\n    const idx = this.#configs.findIndex(a => a.id === id)\n    if (idx === -1) {\n      throw new Error(\"Wallet not found\")\n    }\n    const [removed] = this.#configs.splice(idx, 1)\n    if (removed.active && this.#configs.length > 0) {\n      this.#configs[0].active = true\n    }\n    this.save()\n  }\n\n  switch(id: string) {\n    this.#configs.forEach(a => (a.active = a.id === id))\n    this.save()\n  }\n\n  save() {\n    const json = JSON.stringify(this.#configs)\n    window.localStorage.setItem(\"wallet-config\", json)\n    this.notifyChange()\n  }\n\n  load(snapshot = true) {\n    const cfg = window.localStorage.getItem(\"wallet-config\")\n    if (cfg) {\n      this.#configs = JSON.parse(cfg)\n    }\n    if (snapshot) {\n      this.notifyChange()\n    }\n  }\n\n  free() {\n    this.#instance.forEach(w => w.close())\n  }\n\n  takeSnapshot(): WalletStoreSnapshot {\n    return {\n      configs: [...this.#configs],\n      config: this.#configs.find(a => a.active),\n      wallet: this.get(),\n    } as WalletStoreSnapshot\n  }\n\n  async #activateWallet(cfg: WalletConfig) {\n    const w = await loadWallet(cfg.kind, cfg.data)\n    if (w) {\n      w.on(\"change\", d => this.#onWalletChange(cfg, d))\n    }\n    return w\n  }\n\n  #onWalletChange(cfg: WalletConfig, data?: string) {\n    if (data) {\n      const activeConfig = this.#configs.find(a => a.id === cfg.id)\n      if (activeConfig) {\n        activeConfig.data = data\n      }\n      this.save()\n    } else {\n      this.notifyChange()\n    }\n  }\n}\n\nexport const Wallets = new WalletStore()\nwindow.document.addEventListener(\"close\", () => {\n  Wallets.free()\n})\n\nexport function useWallet() {\n  const wallet = useSyncExternalStore<WalletStoreSnapshot>(\n    h => Wallets.hook(h),\n    () => Wallets.snapshot(),\n  )\n  useEffect(() => {\n    if (wallet.wallet?.isReady() === false && wallet.wallet.canAutoLogin()) {\n      wallet.wallet.login().catch(console.error)\n    }\n  }, [wallet])\n  return wallet\n}\n\n/**\n * Adds a wallet config for WebLN if detected\n */\nexport function setupWebLNWalletConfig(store: WalletStore) {\n  const wallets = store.list()\n\n  const existing = wallets.find(a => a.kind === WalletKind.WebLN)\n  if (window.webln && !existing) {\n    const newConfig = {\n      id: \"webln\",\n      kind: WalletKind.WebLN,\n      active: wallets.length === 0,\n      info: {\n        alias: \"WebLN\",\n      },\n    } as WalletConfig\n    store.add(newConfig)\n  } else if (existing) {\n    store.remove(existing.id)\n  }\n}\n"
  },
  {
    "path": "packages/app/src/assets/fonts/inter.css",
    "content": "/* cyrillic-ext */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 400;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa2JL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 400;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa0ZL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek-ext */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 400;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa2ZL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+1F00-1FFF;\n}\n/* greek */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 400;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1pL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+0370-03FF;\n}\n/* vietnamese */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 400;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa2pL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range:\n    U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309,\n    U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 400;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa25L7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range:\n    U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F,\n    U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 400;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1ZL7W0Q5nw.woff2) format(\"woff2\");\n  unicode-range:\n    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074,\n    U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* cyrillic-ext */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 500;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa2JL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 500;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa0ZL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek-ext */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 500;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa2ZL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+1F00-1FFF;\n}\n/* greek */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 500;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1pL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+0370-03FF;\n}\n/* vietnamese */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 500;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa2pL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range:\n    U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309,\n    U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 500;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa25L7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range:\n    U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F,\n    U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 500;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1ZL7W0Q5nw.woff2) format(\"woff2\");\n  unicode-range:\n    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074,\n    U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* cyrillic-ext */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 600;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa2JL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 600;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa0ZL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek-ext */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 600;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa2ZL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+1F00-1FFF;\n}\n/* greek */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 600;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1pL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+0370-03FF;\n}\n/* vietnamese */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 600;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa2pL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range:\n    U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309,\n    U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 600;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa25L7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range:\n    U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F,\n    U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 600;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1ZL7W0Q5nw.woff2) format(\"woff2\");\n  unicode-range:\n    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074,\n    U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* cyrillic-ext */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 700;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa2JL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 700;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa0ZL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek-ext */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 700;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa2ZL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+1F00-1FFF;\n}\n/* greek */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 700;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1pL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range: U+0370-03FF;\n}\n/* vietnamese */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 700;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa2pL7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range:\n    U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309,\n    U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 700;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa25L7W0Q5n-wU.woff2) format(\"woff2\");\n  unicode-range:\n    U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F,\n    U+A720-A7FF;\n}\n/* latin */\n@font-face {\n  font-family: \"Inter\";\n  font-style: normal;\n  font-weight: 700;\n  font-display: swap;\n  src: url(UcC73FwrK3iLTeHuS_fvQtMwCp50KnMa1ZL7W0Q5nw.woff2) format(\"woff2\");\n  unicode-range:\n    U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074,\n    U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n"
  },
  {
    "path": "packages/app/src/bench.html",
    "content": "<!doctype html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"utf-8\" />\n    <title>Snort Benchmarks</title>\n  </head>\n  <body>\n    Check console\n  </body>\n</html>\n"
  },
  {
    "path": "packages/app/src/benchmarks.ts",
    "content": "import { bytesToHex } from \"@noble/hashes/utils.js\"\nimport {\n  DefaultQueryOptimizer,\n  EventExt,\n  type FlatReqFilter,\n  type PowMiner,\n  type QueryOptimizer,\n  type ReqFilter,\n} from \"@snort/system\"\nimport { compress, default as wasmInit, expand_filter, flat_merge, get_diff, pow } from \"@snort/system-wasm\"\nimport WasmPath from \"@snort/system-wasm/pkg/system_wasm_bg.wasm\"\n\nconst WasmQueryOptimizer = {\n  expandFilter: (f: ReqFilter) => {\n    return expand_filter(f) as Array<FlatReqFilter>\n  },\n  getDiff: (prev: Array<ReqFilter>, next: Array<ReqFilter>) => {\n    return get_diff(prev, next) as Array<FlatReqFilter>\n  },\n  flatMerge: (all: Array<FlatReqFilter>) => {\n    return flat_merge(all) as Array<ReqFilter>\n  },\n  compress: (all: Array<ReqFilter>) => {\n    return compress(all) as Array<ReqFilter>\n  },\n} as QueryOptimizer\n\nconst makeOnePubkey = () => {\n  const rnd = globalThis.crypto.getRandomValues(new Uint8Array(32))\n  return bytesToHex(rnd)\n}\n\nconst randomPubkeys = (() => {\n  const ret = []\n  for (let x = 0; x < 50; x++) {\n    ret.push(makeOnePubkey())\n  }\n  return ret\n})()\n\nconst testExpand = (q: QueryOptimizer) => {\n  q.expandFilter({\n    kinds: [1, 2, 3],\n    authors: randomPubkeys,\n  })\n}\nconst testGetDiff = (q: QueryOptimizer) => {\n  q.getDiff(\n    [\n      {\n        kinds: [1, 2, 3],\n        authors: randomPubkeys,\n      },\n    ],\n    [\n      {\n        kinds: [1, 2, 3, 4, 5],\n        authors: randomPubkeys,\n      },\n    ],\n  )\n}\nconst testFlatMerge = (q: QueryOptimizer) => {\n  q.flatMerge(\n    q.expandFilter({\n      kinds: [1, 6, 7, 6969],\n      authors: randomPubkeys,\n    }),\n  )\n}\nconst testCompress = (q: QueryOptimizer) => {\n  q.compress([\n    {\n      kinds: [1, 6, 7, 6969],\n      authors: randomPubkeys,\n    },\n    {\n      kinds: [1, 6, 7, 6969],\n      authors: randomPubkeys,\n    },\n    {\n      kinds: [1, 6, 7, 6969],\n      authors: randomPubkeys,\n    },\n    {\n      kinds: [1, 6, 7, 6969],\n      authors: randomPubkeys,\n    },\n    {\n      kinds: [1, 6, 7, 6969],\n      authors: randomPubkeys,\n    },\n  ])\n}\n\nconst runAll = async () => {\n  await wasmInit(WasmPath)\n\n  const tinybench = await import(\"tinybench\")\n\n  const { Bench } = tinybench\n  const wasmSuite = new Bench({ time: 1_000 })\n  const suite = new Bench({ time: 1_000 })\n\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  const addTests = (s: any, q: QueryOptimizer, p: PowMiner) => {\n    s.add(\"expand\", () => testExpand(q))\n    s.add(\"get_diff\", () => testGetDiff(q))\n    s.add(\"flat_merge\", () => testFlatMerge(q))\n    s.add(\"compress\", () => testCompress(q))\n    s.add(\"pow\", () => {\n      const ev = {\n        id: \"\",\n        kind: 1,\n        created_at: 1234567,\n        pubkey: \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\",\n        content: \"test\",\n        sig: \"\",\n        tags: [],\n      }\n      p.minePow(ev, 12)\n    })\n  }\n\n  addTests(suite, DefaultQueryOptimizer, {\n    minePow(ev, target) {\n      return Promise.resolve(EventExt.minePow(ev, target))\n    },\n  })\n  addTests(wasmSuite, WasmQueryOptimizer, {\n    minePow(ev, target) {\n      return Promise.resolve(pow(ev, target))\n    },\n  })\n\n  console.log(\"DefaultQueryOptimizer\")\n  await suite.run()\n  console.table(suite.table())\n  const p0 = document.createElement(\"pre\")\n  p0.innerText = JSON.stringify(suite.table(), undefined, \"  \")\n  document.body.appendChild(p0)\n\n  console.log(\"WasmQueryOptimizer\")\n  await wasmSuite.run()\n  console.table(wasmSuite.table())\n  const p1 = document.createElement(\"pre\")\n  p1.innerText = JSON.stringify(wasmSuite.table(), undefined, \"  \")\n  document.body.appendChild(p1)\n}\nrunAll().catch(console.error)\n"
  },
  {
    "path": "packages/app/src/chat/index.ts",
    "content": "import { encodeTLVEntries, type ExternalStore, type TLVEntry, TLVEntryType, unixNow, unwrap } from \"@snort/shared\"\nimport {\n  EventKind,\n  type EventPublisher,\n  type NostrEvent,\n  type RequestBuilder,\n  type SystemInterface,\n  type TaggedNostrEvent,\n  type UserMetadata,\n} from \"@snort/system\"\nimport { useRequestBuilder } from \"@snort/system-react\"\nimport { useEffect, useMemo, useRef, useSyncExternalStore } from \"react\"\n\nimport useEventPublisher from \"@/Hooks/useEventPublisher\"\nimport useLogin from \"@/Hooks/useLogin\"\nimport useModeration from \"@/Hooks/useModeration\"\nimport { GiftsCache } from \"@/Cache\"\nimport { findTag } from \"@/Utils\"\nimport type { LoginSession } from \"@/Utils/Login\"\n\nimport { Nip17Chats, Nip17ChatSystem } from \"./nip17\"\n\nexport enum ChatType {\n  PublicGroupChat = 2,\n  PrivateGroupChat = 3,\n  PrivateDirectMessage = 4,\n}\n\nexport interface ChatMessage {\n  id: string\n  from: string\n  created_at: number\n  tags: Array<Array<string>>\n  needsDecryption: boolean\n  content: string\n  decrypt: (pub: EventPublisher) => Promise<string>\n}\n\nexport interface ChatParticipant {\n  type: \"pubkey\" | \"generic\"\n  id: string\n  profile?: UserMetadata\n}\n\nexport interface Chat {\n  type: ChatType\n  id: string\n  title?: string\n  unread: number\n  lastMessage: number\n  participants: Array<ChatParticipant>\n  messages: Array<ChatMessage>\n  createMessage(msg: string, pub: EventPublisher): Promise<Array<NostrEvent>>\n  sendMessage(ev: Array<NostrEvent>, system: SystemInterface): void | Promise<void>\n  markRead(id?: string): void\n}\n\nexport interface ChatSystem {\n  subscription(session: LoginSession): RequestBuilder\n  listChats(pk: string, evs: Array<TaggedNostrEvent>): Array<Chat>\n  processEvents(pub: EventPublisher, evs: Array<TaggedNostrEvent>): Promise<void>\n}\n\nexport function chatTo(e: NostrEvent) {\n  if (e.kind === EventKind.DirectMessage) {\n    return unwrap(findTag(e, \"p\"))\n  } else if (e.kind === EventKind.SimpleChatMessage) {\n    const gt = unwrap(e.tags.find(a => a[0] === \"g\"))\n    return `${gt[2]}${gt[1]}`\n  }\n  throw new Error(\"Not a chat message\")\n}\n\nexport function inChatWith(e: NostrEvent, myPk: string) {\n  if (e.pubkey === myPk) {\n    return chatTo(e)\n  } else {\n    return e.pubkey\n  }\n}\n\nexport function selfChat(e: NostrEvent, myPk: string) {\n  return chatTo(e) === myPk && e.pubkey === myPk\n}\n\nexport function lastReadInChat(id: string) {\n  const k = `dm:seen:${id}`\n  return parseInt(window.localStorage.getItem(k) ?? \"0\", 10)\n}\n\nexport function setLastReadIn(id: string, time?: number) {\n  const now = time ?? unixNow()\n  const k = `dm:seen:${id}`\n  const current = lastReadInChat(id)\n  if (current < now) {\n    window.localStorage.setItem(k, now.toString())\n  }\n}\n\nexport function createChatLink(type: ChatType, ...params: Array<string>) {\n  switch (type) {\n    case ChatType.PrivateDirectMessage: {\n      if (params.length > 1) throw new Error(\"Must only contain one pubkey\")\n      return `/messages/${encodeTLVEntries(\"nchat17\", {\n        type: TLVEntryType.Author,\n        length: params[0].length,\n        value: params[0],\n      } as TLVEntry)}`\n    }\n    case ChatType.PrivateGroupChat: {\n      return `/messages/${encodeTLVEntries(\n        \"nchat17\",\n        ...params.map(\n          a =>\n            ({\n              type: TLVEntryType.Author,\n              length: a.length,\n              value: a,\n            }) as TLVEntry,\n        ),\n      )}`\n    }\n  }\n  throw new Error(\"Unknown chat type\")\n}\n\nexport function createEmptyChatObject(id: string) {\n  if (id.startsWith(\"nchat17\")) {\n    return Nip17ChatSystem.createChatObj(id, [], GiftsCache)\n  }\n  throw new Error(\"Cant create new empty chat, unknown id\")\n}\n\nexport function useChatSystem<T extends ChatSystem & ExternalStore<Array<Chat>>>(sys: T) {\n  const login = useLogin()\n  const { publisher } = useEventPublisher()\n  const chat = useSyncExternalStore(\n    s => sys.hook(s),\n    () => sys.snapshot(),\n  )\n  // biome-ignore lint/correctness/useExhaustiveDependencies: sys is a stable singleton\n  const sub = useMemo(() => {\n    return sys.subscription(login)\n  }, [login])\n  const data = useRequestBuilder(sub)\n  const { isMuted } = useModeration()\n\n  const processTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n  const dataRef = useRef(data)\n  dataRef.current = data\n  const loadedPersisted = useRef(false)\n\n  useEffect(() => {\n    if (!publisher || loadedPersisted.current) return\n    loadedPersisted.current = true\n    GiftsCache.loadPersistedAndDecrypt(publisher)\n  }, [publisher])\n\n  // biome-ignore lint/correctness/useExhaustiveDependencies: data is used as trigger, dataRef for latest value\n  useEffect(() => {\n    if (!publisher) return\n    if (processTimerRef.current) clearTimeout(processTimerRef.current)\n    processTimerRef.current = setTimeout(() => {\n      sys.processEvents(publisher, dataRef.current)\n    }, 100)\n    return () => {\n      if (processTimerRef.current) clearTimeout(processTimerRef.current)\n    }\n  }, [data, publisher])\n\n  // biome-ignore lint/correctness/useExhaustiveDependencies: sys is a stable singleton, chat intentionally triggers re-derive\n  return useMemo(() => {\n    if (login.publicKey) {\n      return sys.listChats(\n        login.publicKey,\n        data.filter(a => !isMuted(a.pubkey)),\n      )\n    }\n    return []\n  }, [chat, login, data, isMuted])\n}\n\nexport function useChatSystems() {\n  const nip17 = useChatSystem(Nip17Chats)\n  return nip17\n}\n\nexport function useChat(id: string) {\n  return useChatSystem(Nip17Chats).find(a => a.id === id) ?? createEmptyChatObject(id)\n}\n"
  },
  {
    "path": "packages/app/src/chat/nip17.ts",
    "content": "import { decodeTLV, encodeTLVEntries, ExternalStore, type TLVEntry, TLVEntryType } from \"@snort/shared\"\nimport { EventKind, type EventPublisher, type NostrEvent, RequestBuilder, type TaggedNostrEvent } from \"@snort/system\"\n\nimport { GiftsCache } from \"@/Cache\"\nimport type { GiftWrapCache, UnwrappedGift } from \"@/Cache/GiftWrapCache\"\nimport { getCachedDecryptedContent } from \"@/Cache/GiftWrapCache\"\nimport { type Chat, type ChatSystem, ChatType, lastReadInChat, setLastReadIn } from \"@/chat\"\nimport type { LoginSession } from \"@/Utils/Login\"\nimport { GetPowWorker } from \"@/Utils/wasm\"\n\nfunction computeChatId(u: UnwrappedGift, pk: string): string | undefined {\n  const pTags = [...(u.tags ?? []).filter(a => a[0] === \"p\").map(a => a[1]), u.inner.pubkey]\n    .filter((v, i, a) => a.indexOf(v) === i)\n    .sort()\n    .filter(a => a !== pk)\n\n  if (pTags.length === 0) return\n  return encodeTLVEntries(\n    \"nchat17\",\n    ...pTags.map(\n      v =>\n        ({\n          value: v,\n          type: TLVEntryType.Author,\n          length: v.length,\n        }) as TLVEntry,\n    ),\n  )\n}\n\nexport class Nip17ChatSystem extends ExternalStore<Array<Chat>> implements ChatSystem {\n  #cache: GiftWrapCache\n  #seenEvents: Set<string> = new Set()\n\n  constructor(cache: GiftWrapCache) {\n    super()\n    this.#cache = cache\n    this.#cache.on(\"change\", () => this.notifyChange())\n  }\n\n  subscription(session: LoginSession) {\n    const pk = session.publicKey\n    const rb = new RequestBuilder(`nip17:${pk?.slice(0, 12)}`)\n\n    if (pk && !session.readonly) {\n      rb.withOptions({ useSyncModule: true })\n      rb.withFilter().kinds([EventKind.GiftWrap]).tag(\"p\", [pk])\n    }\n    return rb\n  }\n\n  async processEvents(pub: EventPublisher, evs: Array<TaggedNostrEvent>) {\n    const evsProcess = evs.filter(a => !this.#seenEvents.has(a.id) && !this.#cache.keysOnTable().includes(a.id))\n    await this.#cache.onEvent(evsProcess, \"\", pub)\n    for (const a of evsProcess) {\n      this.#seenEvents.add(a.id)\n    }\n  }\n\n  listChats(pk: string): Chat[] {\n    const evs = this.#nip24Events()\n    const messages = evs.filter(a => a.to === pk)\n\n    const chatMap = new Map<string, UnwrappedGift[]>()\n    for (const m of messages) {\n      const id = computeChatId(m, pk)\n      if (!id) continue\n      const existing = chatMap.get(id)\n      if (existing) {\n        existing.push(m)\n      } else {\n        chatMap.set(id, [m])\n      }\n    }\n\n    return [...chatMap.entries()].map(([id, chatMessages]) => {\n      return Nip17ChatSystem.createChatObj(id, chatMessages, this.#cache)\n    })\n  }\n\n  static createChatObj(id: string, messages: Array<UnwrappedGift>, cache?: GiftWrapCache) {\n    const last = lastReadInChat(id)\n    const participants = decodeTLV(id)\n      .filter(v => v.type === TLVEntryType.Author)\n      .map(v => ({\n        type: \"pubkey\" as const,\n        id: v.value as string,\n      }))\n    let bestTitle: string | undefined\n    let bestTitleTime = 0\n    let unread = 0\n    let lastMessage = 0\n    for (const v of messages) {\n      const sbj = v.tags?.find(a => a[0] === \"subject\")?.[1]\n      if (v.created_at > bestTitleTime && sbj) {\n        bestTitle = sbj\n        bestTitleTime = v.created_at\n      }\n      if (v.inner.created_at > last) unread++\n      if (v.created_at > lastMessage) lastMessage = v.created_at\n    }\n    return {\n      type: ChatType.PrivateDirectMessage,\n      id,\n      title: bestTitle,\n      unread,\n      lastMessage,\n      participants,\n      messages: messages.map(m => {\n        const cached = getCachedDecryptedContent(m.id)\n        return {\n          id: m.id,\n          created_at: m.inner.created_at,\n          from: m.inner.pubkey,\n          tags: m.tags,\n          content: cached ?? \"\",\n          needsDecryption: cached === undefined,\n          decrypt: async (pub: EventPublisher) => {\n            return await pub.decryptDm(m.inner)\n          },\n        }\n      }),\n      createMessage: async (msg: string, pub: EventPublisher) => {\n        const gossip = pub.createUnsigned(EventKind.ChatRumor, msg, eb => {\n          for (const pt of participants) {\n            eb.tag([\"p\", pt.id])\n          }\n          return eb\n        })\n        const outMessages: Array<Promise<NostrEvent>> = []\n        const powTarget = 4 * 4\n        for (const pt of participants) {\n          outMessages.push(pub.giftWrap(await pub.sealRumor(gossip, pt.id), pt.id, powTarget))\n        }\n        outMessages.push(pub.giftWrap(await pub.sealRumor(gossip, pub.pubKey), pub.pubKey, powTarget, GetPowWorker()))\n        const ret = await Promise.all(outMessages)\n        if (cache) {\n          await cache.onEvent(\n            ret.map(a => ({ ...a, relays: [] })),\n            \"\",\n            pub,\n          )\n        }\n        return ret\n      },\n      sendMessage: (ev: Array<NostrEvent>, system: { BroadcastEvent: (e: NostrEvent) => void }) => {\n        for (const a of ev) {\n          system.BroadcastEvent(a)\n        }\n      },\n      markRead: (msgId?: string) => {\n        const msg = messages.find(a => a.id === msgId)\n        setLastReadIn(id, msg?.inner.created_at)\n        Nip17Chats.notifyChange()\n      },\n    } as Chat\n  }\n\n  takeSnapshot(p: string): Chat[] {\n    return this.listChats(p)\n  }\n\n  #nip24Events() {\n    const sn = this.#cache.snapshot()\n    return sn.filter(a => a.inner.kind === EventKind.SealedRumor)\n  }\n}\n\nexport const Nip17Chats = new Nip17ChatSystem(GiftsCache)\n"
  },
  {
    "path": "packages/app/src/hug.json",
    "content": "{\n  \"v\": \"4.8.0\",\n  \"meta\": { \"g\": \"LottieFiles AE 3.1.1\", \"a\": \"\", \"k\": \"\", \"d\": \"\", \"tc\": \"\" },\n  \"fr\": 24,\n  \"ip\": 0,\n  \"op\": 137,\n  \"w\": 1500,\n  \"h\": 1200,\n  \"nm\": \"export\",\n  \"ddd\": 0,\n  \"assets\": [\n    {\n      \"id\": \"comp_0\",\n      \"layers\": [\n        {\n          \"ddd\": 0,\n          \"ind\": 1,\n          \"ty\": 3,\n          \"nm\": \"Null 1\",\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 0, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [2722, 1309, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [0, 0, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [200, 200, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 2,\n          \"ty\": 4,\n          \"nm\": \"cyan4 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 5.76,\n                  \"s\": [-526.339, -133.139, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 53.76,\n                  \"s\": [-522.339, -141.139, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                { \"t\": 107.52, \"s\": [-526.339, -133.139, 0] }\n              ],\n              \"ix\": 2\n            },\n            \"a\": { \"a\": 0, \"k\": [33.675, 33.675, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -18.46], [18.46, 0], [0, 18.461], [-18.46, 0]],\n                      \"o\": [[0, 18.461], [-18.46, 0], [0, -18.46], [18.46, 0]],\n                      \"v\": [[33.425, -0.001], [0, 33.425], [-33.425, -0.001], [0, -33.425]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.426999978458, 0.783999992819, 0.976000019148, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [33.675, 33.676], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 4,\n          \"ty\": 4,\n          \"nm\": \"pink4 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 0,\n                  \"s\": [-372.442, -149.196, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 38.4,\n                  \"s\": [-378.442, -148.196, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 77.76,\n                  \"s\": [-372.442, -149.196, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 102.72,\n                  \"s\": [-375.442, -142.196, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                { \"t\": 129.6, \"s\": [-372.442, -149.196, 0] }\n              ],\n              \"ix\": 2\n            },\n            \"a\": { \"a\": 0, \"k\": [40.025, 40.025, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -21.968], [21.966, 0], [0, 21.967], [-21.967, 0]],\n                      \"o\": [[0, 21.967], [-21.967, 0], [0, -21.968], [21.966, 0]],\n                      \"v\": [[39.775, 0.001], [0.001, 39.775], [-39.775, 0.001], [0.001, -39.775]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.913999968884, 0.2, 0.513999968884, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [40.025, 40.025], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 6,\n          \"ty\": 4,\n          \"nm\": \"yellow4 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-188.747, -211.077, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [39.289, 39.289, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -21.561], [21.56, 0], [0, 21.561], [-21.561, 0]],\n                      \"o\": [[0, 21.561], [-21.561, 0], [0, -21.561], [21.56, 0]],\n                      \"v\": [[39.039, 0], [0, 39.039], [-39.039, 0], [0, -39.039]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.925, 0.8, 0.289999988032, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [39.289, 39.289], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 8,\n          \"ty\": 4,\n          \"nm\": \"orange4 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 0,\n                  \"s\": [-662.191, -265.434, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 48,\n                  \"s\": [-657.191, -269.434, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                { \"t\": 96, \"s\": [-662.191, -265.434, 0] }\n              ],\n              \"ix\": 2\n            },\n            \"a\": { \"a\": 0, \"k\": [40.816, 40.816, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -22.404], [22.403, 0], [0, 22.404], [-22.405, 0]],\n                      \"o\": [[0, 22.404], [-22.405, 0], [0, -22.404], [22.403, 0]],\n                      \"v\": [[40.566, 0], [0.001, 40.566], [-40.566, 0], [0.001, -40.566]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.902000038297, 0.40800000359, 0.231000010173, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [40.816, 40.816], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 10,\n          \"ty\": 4,\n          \"nm\": \"blue4 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-136.554, -320.427, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [29.677, 29.677, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -16.252], [16.252, 0], [0, 16.252], [-16.252, 0]],\n                      \"o\": [[0, 16.252], [-16.252, 0], [0, -16.252], [16.252, 0]],\n                      \"v\": [[29.427, 0], [0, 29.427], [-29.427, 0], [0, -29.427]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.258999992819, 0.176000004189, 0.811999990426, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [29.677, 29.677], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 12,\n          \"ty\": 4,\n          \"nm\": \"white4 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 5.76,\n                  \"s\": [-683.178, -211.118, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 41.28,\n                  \"s\": [-668.178, -221.118, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 75.84,\n                  \"s\": [-683.178, -211.118, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 103.68,\n                  \"s\": [-668.178, -221.118, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                { \"t\": 131.52, \"s\": [-683.178, -211.118, 0] }\n              ],\n              \"ix\": 2\n            },\n            \"a\": { \"a\": 0, \"k\": [36.072, 36.071, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -19.784], [19.784, 0], [0, 19.783], [-19.783, 0]],\n                      \"o\": [[0, 19.783], [-19.783, 0], [0, -19.784], [19.784, 0]],\n                      \"v\": [[35.822, 0.001], [0, 35.822], [-35.822, 0.001], [0, -35.822]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [1, 1, 1, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [36.072, 36.071], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 14,\n          \"ty\": 4,\n          \"nm\": \"cyan3 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-559.337, -174.471, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [26.87, 16.808, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [0, 0], [2.006, 3.203]],\n                      \"o\": [[0, 0], [-3.204, 2.006], [0, 0]],\n                      \"v\": [[4.717, 0.081], [4.717, 0.081], [-4.717, -2.088]],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": { \"a\": 0, \"k\": [0, 0, 0, 1], \"ix\": 3 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 4 },\n                  \"w\": { \"a\": 0, \"k\": 5, \"ix\": 5 },\n                  \"lc\": 2,\n                  \"lj\": 2,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [17.217, 14.588], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [0, 0], [2.006, 3.204]],\n                      \"o\": [[0, 0], [-3.204, 2.006], [0, 0]],\n                      \"v\": [[4.717, 0.082], [4.717, 0.082], [-4.717, -2.088]],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": { \"a\": 0, \"k\": [0, 0, 0, 1], \"ix\": 3 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 4 },\n                  \"w\": { \"a\": 0, \"k\": 5, \"ix\": 5 },\n                  \"lc\": 2,\n                  \"lj\": 2,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [36.523, 19.029], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 2\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 2,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 16,\n          \"ty\": 4,\n          \"nm\": \"cyan2 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-577.398, -249.283, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [46.926, 40.417, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-32.361, 8.389], [9.77, -15.399], [-10.343, -7.383]],\n                      \"o\": [[0, 0], [17.653, -4.577], [-11.197, 17.652], [0, 0]],\n                      \"v\": [[-46.676, -3.611], [14.919, -35.59], [36.906, -5.453], [26.512, 40.167]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.426999978458, 0.783999992819, 0.976000019148, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [46.926, 40.417], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 18,\n          \"ty\": 4,\n          \"nm\": \"cyan1 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-606.09, -167.869, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [101.992, 101.992, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -56.19], [56.19, 0], [0, 56.19], [-56.191, 0]],\n                      \"o\": [[0, 56.19], [-56.191, 0], [0, -56.19], [56.19, 0]],\n                      \"v\": [[101.742, 0], [0, 101.742], [-101.742, 0], [0, -101.742]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.426999978458, 0.783999992819, 0.976000019148, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [101.992, 101.992], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 20,\n          \"ty\": 4,\n          \"nm\": \"black3 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 1.92,\n                  \"s\": [-470.376, -171.715, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 40.32,\n                  \"s\": [-467.876, -176.215, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                { \"t\": 79.68, \"s\": [-470.376, -171.715, 0] }\n              ],\n              \"ix\": 2\n            },\n            \"a\": { \"a\": 0, \"k\": [11.35, 3.401, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 1,\n                    \"k\": [\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 1.92,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.001, 3.151], [-3.151, 0], [0.001, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 4.8,\n                        \"s\": [\n                          {\n                            \"i\": [[-0.431, -0.431], [1.74, 0], [0.012, 1.74], [-1.741, 0]],\n                            \"o\": [[-0.089, 1.738], [-1.741, 0], [-0.467, -0.467], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.026, 0.526], [-3.151, 0], [0.077, -0.651]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 7.68,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.001, 3.151], [-3.151, 0], [0.001, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 26.88,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.001, 3.151], [-3.151, 0], [0.001, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 29.76,\n                        \"s\": [\n                          {\n                            \"i\": [[-0.431, -0.431], [1.74, 0], [0.012, 1.74], [-1.741, 0]],\n                            \"o\": [[-0.089, 1.738], [-1.741, 0], [-0.467, -0.467], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.026, 0.526], [-3.151, 0], [0.077, -0.651]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 32.64,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.001, 3.151], [-3.151, 0], [0.001, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 34.56,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.001, 3.151], [-3.151, 0], [0.001, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 37.44,\n                        \"s\": [\n                          {\n                            \"i\": [[-0.431, -0.431], [1.74, 0], [0.012, 1.74], [-1.741, 0]],\n                            \"o\": [[-0.089, 1.738], [-1.741, 0], [-0.467, -0.467], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.026, 0.526], [-3.151, 0], [0.077, -0.651]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 40.32,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.001, 3.151], [-3.151, 0], [0.001, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 106.56,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.001, 3.151], [-3.151, 0], [0.001, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 109.44,\n                        \"s\": [\n                          {\n                            \"i\": [[-0.431, -0.431], [1.74, 0], [0.012, 1.74], [-1.741, 0]],\n                            \"o\": [[-0.089, 1.738], [-1.741, 0], [-0.467, -0.467], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.026, 0.526], [-3.151, 0], [0.077, -0.651]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"t\": 112.32,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.001, 3.151], [-3.151, 0], [0.001, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      }\n                    ],\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.423999980852, 0.779999976065, 0.976000019148, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [3.401, 3.401], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 1,\n                    \"k\": [\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 1.92,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0, 3.151], [-3.151, 0], [0, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 4.8,\n                        \"s\": [\n                          {\n                            \"i\": [[-0.225, -0.91], [1.74, 0], [0.08, 1.738], [-1.741, 0]],\n                            \"o\": [[0.369, 1.7], [-1.741, 0], [-0.048, -0.66], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.024, 0.651], [-3.151, 0], [0.024, -0.651]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 7.68,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0, 3.151], [-3.151, 0], [0, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 26.88,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0, 3.151], [-3.151, 0], [0, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 29.76,\n                        \"s\": [\n                          {\n                            \"i\": [[-0.225, -0.91], [1.74, 0], [0.08, 1.738], [-1.741, 0]],\n                            \"o\": [[0.369, 1.7], [-1.741, 0], [-0.048, -0.66], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.024, 0.651], [-3.151, 0], [0.024, -0.651]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 32.64,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0, 3.151], [-3.151, 0], [0, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 34.56,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0, 3.151], [-3.151, 0], [0, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 37.44,\n                        \"s\": [\n                          {\n                            \"i\": [[-0.225, -0.91], [1.74, 0], [0.08, 1.738], [-1.741, 0]],\n                            \"o\": [[0.369, 1.7], [-1.741, 0], [-0.048, -0.66], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.024, 0.651], [-3.151, 0], [0.024, -0.651]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 40.32,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0, 3.151], [-3.151, 0], [0, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 106.56,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0, 3.151], [-3.151, 0], [0, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 0.833 },\n                        \"o\": { \"x\": 0.167, \"y\": 0.167 },\n                        \"t\": 109.44,\n                        \"s\": [\n                          {\n                            \"i\": [[-0.225, -0.91], [1.74, 0], [0.08, 1.738], [-1.741, 0]],\n                            \"o\": [[0.369, 1.7], [-1.741, 0], [-0.048, -0.66], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0.024, 0.651], [-3.151, 0], [0.024, -0.651]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"t\": 112.32,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -1.74], [1.74, 0], [0, 1.74], [-1.741, 0]],\n                            \"o\": [[0, 1.74], [-1.741, 0], [0, -1.74], [1.74, 0]],\n                            \"v\": [[3.151, 0], [0, 3.151], [-3.151, 0], [0, -3.151]],\n                            \"c\": true\n                          }\n                        ]\n                      }\n                    ],\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.423999980852, 0.779999976065, 0.976000019148, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [19.299, 3.401], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 2\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 2,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 22,\n          \"ty\": 4,\n          \"nm\": \"black2 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-426.208, -190.428, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [32.117, 27.673, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-22.093, 5.728], [6.669, -10.513], [-7.062, -5.041]],\n                      \"o\": [[0, 0], [12.051, -3.124], [-7.645, 12.052], [0, 0]],\n                      \"v\": [[-31.866, -2.465], [10.186, -24.298], [25.197, -3.723], [18.1, 27.423]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.078000005086, 0.090000002992, 0.102000000898, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [32.116, 27.673], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 24,\n          \"ty\": 4,\n          \"nm\": \"black1 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-444.842, -132.665, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [78.8, 72.955, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0.835, -10.445], [10.446, 0.836], [-0.836, 10.445], [-10.446, -0.836]],\n                      \"o\": [[-0.836, 10.445], [-10.445, -0.836], [0.836, -10.446], [10.445, 0.836]],\n                      \"v\": [[18.914, 1.513], [-1.513, 18.913], [-18.913, -1.512], [1.514, -18.913]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.078000005086, 0.090000002992, 0.102000000898, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [19.998, 66.858], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -40.153], [40.154, 0], [0, 40.154], [-40.153, 0]],\n                      \"o\": [[0, 40.154], [-40.153, 0], [0, -40.153], [40.154, 0]],\n                      \"v\": [[72.704, 0], [-0.001, 72.705], [-72.704, 0], [-0.001, -72.705]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.078000005086, 0.090000002992, 0.102000000898, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [84.646, 72.955], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 2\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 2,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 26,\n          \"ty\": 4,\n          \"nm\": \"pink3 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 7.68,\n                  \"s\": [-362.562, -206.245, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 39.36,\n                  \"s\": [-362.562, -192.245, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.167, \"y\": 0 },\n                  \"t\": 76.8,\n                  \"s\": [-362.562, -206.245, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 104.64,\n                  \"s\": [-362.562, -192.245, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                { \"t\": 133.44, \"s\": [-362.562, -206.245, 0] }\n              ],\n              \"ix\": 2\n            },\n            \"a\": { \"a\": 0, \"k\": [27.245, 13.837, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [0, 0], [2.673, 2.673]],\n                      \"o\": [[0, 0], [-2.673, 2.673], [0, 0]],\n                      \"v\": [[4.84, -1.337], [4.84, -1.337], [-4.84, -1.337]],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": { \"a\": 0, \"k\": [0, 0, 0, 1], \"ix\": 3 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 4 },\n                  \"w\": { \"a\": 0, \"k\": 5, \"ix\": 5 },\n                  \"lc\": 2,\n                  \"lj\": 2,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [17.34, 13.837], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [0, 0], [2.673, 2.673]],\n                      \"o\": [[0, 0], [-2.673, 2.673], [0, 0]],\n                      \"v\": [[4.84, -1.337], [4.84, -1.337], [-4.84, -1.337]],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": { \"a\": 0, \"k\": [0, 0, 0, 1], \"ix\": 3 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 4 },\n                  \"w\": { \"a\": 0, \"k\": 5, \"ix\": 5 },\n                  \"lc\": 2,\n                  \"lj\": 2,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [37.151, 13.837], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 2\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 2,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 28,\n          \"ty\": 4,\n          \"nm\": \"pink2 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-319.44, -294.264, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [42.688, 38.502, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-21.036, 25.982], [-1.298, -18.19], [-12.708, 0.212]],\n                      \"o\": [[0, 0], [11.476, -14.173], [1.488, 20.851], [0, 0]],\n                      \"v\": [[-42.438, 38.252], [-11.917, -24.079], [23.679, -12.914], [42.438, 29.949]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.913999968884, 0.2, 0.513999968884, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [42.688, 38.502], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 30,\n          \"ty\": 4,\n          \"nm\": \"pink1 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-289.703, -175.687, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [115.772, 115.772, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -63.801], [63.8, 0], [0, 63.801], [-63.802, 0]],\n                      \"o\": [[0, 63.801], [-63.802, 0], [0, -63.801], [63.8, 0]],\n                      \"v\": [[115.522, -0.001], [0.001, 115.521], [-115.522, -0.001], [0.001, -115.521]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.913999968884, 0.2, 0.513999968884, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [115.772, 115.772], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 32,\n          \"ty\": 4,\n          \"nm\": \"yellow3 Outlines 2\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-252.053, -313.182, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [16.451, 7.128, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 1,\n                    \"k\": [\n                      {\n                        \"i\": { \"x\": 0.667, \"y\": 1 },\n                        \"o\": { \"x\": 0.333, \"y\": 0 },\n                        \"t\": 10.56,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -2.511], [2.512, 0], [0, 2.512], [-2.512, 0]],\n                            \"o\": [[0, 2.512], [-2.512, 0], [0, -2.511], [2.512, 0]],\n                            \"v\": [[4.548, -0.001], [0, 4.548], [-4.548, -0.001], [0, -4.548]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.667, \"y\": 1 },\n                        \"o\": { \"x\": 0.333, \"y\": 0 },\n                        \"t\": 12.48,\n                        \"s\": [\n                          {\n                            \"i\": [[-0.389, -2.481], [2.512, 0], [0.254, 0.513], [-2.512, 0]],\n                            \"o\": [[0.159, 0.763], [-2.512, 0], [-0.01, -2.511], [2.512, 0]],\n                            \"v\": [[4.548, -0.001], [0.5, 0.048], [-4.548, -0.001], [0.5, -2.298]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 1 },\n                        \"o\": { \"x\": 0.167, \"y\": 0 },\n                        \"t\": 14.4,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -2.511], [2.512, 0], [0, 2.512], [-2.512, 0]],\n                            \"o\": [[0, 2.512], [-2.512, 0], [0, -2.511], [2.512, 0]],\n                            \"v\": [[4.548, -0.001], [0, 4.548], [-4.548, -0.001], [0, -4.548]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.667, \"y\": 1 },\n                        \"o\": { \"x\": 0.333, \"y\": 0 },\n                        \"t\": 91.2,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -2.511], [2.512, 0], [0, 2.512], [-2.512, 0]],\n                            \"o\": [[0, 2.512], [-2.512, 0], [0, -2.511], [2.512, 0]],\n                            \"v\": [[4.548, -0.001], [0, 4.548], [-4.548, -0.001], [0, -4.548]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.667, \"y\": 1 },\n                        \"o\": { \"x\": 0.333, \"y\": 0 },\n                        \"t\": 93.12,\n                        \"s\": [\n                          {\n                            \"i\": [[-0.389, -2.481], [2.512, 0], [0.254, 0.513], [-2.512, 0]],\n                            \"o\": [[0.159, 0.763], [-2.512, 0], [-0.01, -2.511], [2.512, 0]],\n                            \"v\": [[4.548, -0.001], [0.5, 0.048], [-4.548, -0.001], [0.5, -2.298]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"t\": 95.04,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -2.511], [2.512, 0], [0, 2.512], [-2.512, 0]],\n                            \"o\": [[0, 2.512], [-2.512, 0], [0, -2.511], [2.512, 0]],\n                            \"v\": [[4.548, -0.001], [0, 4.548], [-4.548, -0.001], [0, -4.548]],\n                            \"c\": true\n                          }\n                        ]\n                      }\n                    ],\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.337000020345, 0.497999991623, 0.866999966491, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [4.797, 4.798], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 1,\n                    \"k\": [\n                      {\n                        \"i\": { \"x\": 0.667, \"y\": 1 },\n                        \"o\": { \"x\": 0.333, \"y\": 0 },\n                        \"t\": 10.56,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -2.512], [2.512, 0], [0, 2.511], [-2.512, 0]],\n                            \"o\": [[0, 2.511], [-2.512, 0], [0, -2.512], [2.512, 0]],\n                            \"v\": [[4.547, 0], [0, 4.548], [-4.547, 0], [0, -4.548]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.667, \"y\": 1 },\n                        \"o\": { \"x\": 0.333, \"y\": 0 },\n                        \"t\": 12.48,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -2.512], [2.512, 0], [0, 2.511], [-2.512, 0]],\n                            \"o\": [[0, 2.511], [-2.512, 0], [0, -2.512], [2.512, 0]],\n                            \"v\": [[4.547, -2.75], [0.5, -2.452], [-4.547, -3.5], [0, -4.548]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.833, \"y\": 1 },\n                        \"o\": { \"x\": 0.167, \"y\": 0 },\n                        \"t\": 14.4,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -2.512], [2.512, 0], [0, 2.511], [-2.512, 0]],\n                            \"o\": [[0, 2.511], [-2.512, 0], [0, -2.512], [2.512, 0]],\n                            \"v\": [[4.547, 0], [0, 4.548], [-4.547, 0], [0, -4.548]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.667, \"y\": 1 },\n                        \"o\": { \"x\": 0.333, \"y\": 0 },\n                        \"t\": 91.2,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -2.512], [2.512, 0], [0, 2.511], [-2.512, 0]],\n                            \"o\": [[0, 2.511], [-2.512, 0], [0, -2.512], [2.512, 0]],\n                            \"v\": [[4.547, 0], [0, 4.548], [-4.547, 0], [0, -4.548]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"i\": { \"x\": 0.667, \"y\": 1 },\n                        \"o\": { \"x\": 0.333, \"y\": 0 },\n                        \"t\": 93.12,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -2.512], [2.512, 0], [0, 2.511], [-2.512, 0]],\n                            \"o\": [[0, 2.511], [-2.512, 0], [0, -2.512], [2.512, 0]],\n                            \"v\": [[4.547, -2.75], [0.5, -2.452], [-4.547, -3.5], [0, -4.548]],\n                            \"c\": true\n                          }\n                        ]\n                      },\n                      {\n                        \"t\": 95.04,\n                        \"s\": [\n                          {\n                            \"i\": [[0, -2.512], [2.512, 0], [0, 2.511], [-2.512, 0]],\n                            \"o\": [[0, 2.511], [-2.512, 0], [0, -2.512], [2.512, 0]],\n                            \"v\": [[4.547, 0], [0, 4.548], [-4.547, 0], [0, -4.548]],\n                            \"c\": true\n                          }\n                        ]\n                      }\n                    ],\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.337000020345, 0.497999991623, 0.866999966491, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [28.105, 9.459], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 2\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 2,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 33,\n          \"ty\": 4,\n          \"nm\": \"yellow3 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-252.053, -313.182, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [16.451, 7.128, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -2.511], [2.512, 0], [0, 2.512], [-2.512, 0]],\n                      \"o\": [[0, 2.512], [-2.512, 0], [0, -2.511], [2.512, 0]],\n                      \"v\": [[4.548, -0.001], [0, 4.548], [-4.548, -0.001], [0, -4.548]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.337000020345, 0.497999991623, 0.866999966491, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [4.797, 4.798], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -2.512], [2.512, 0], [0, 2.511], [-2.512, 0]],\n                      \"o\": [[0, 2.511], [-2.512, 0], [0, -2.512], [2.512, 0]],\n                      \"v\": [[4.547, 0], [0, 4.548], [-4.547, 0], [0, -4.548]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.337000020345, 0.497999991623, 0.866999966491, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [28.105, 9.459], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 2\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 2,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 35,\n          \"ty\": 4,\n          \"nm\": \"yellow2 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-98.155, -292.363, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [43.974, 40.469, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-31.64, -10.79], [16.629, -7.49], [-4.578, -11.857]],\n                      \"o\": [[0, 0], [17.261, 5.887], [-19.059, 8.584], [0, 0]],\n                      \"v\": [[-43.724, -36.594], [25.306, -29.429], [27.095, 7.835], [-6.675, 40.219]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.925, 0.8, 0.289999988032, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [43.975, 40.469], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 37,\n          \"ty\": 4,\n          \"nm\": \"yellow1 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-207.393, -208.747, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [149.996, 149.996, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -82.703], [82.702, 0], [0, 82.702], [-82.702, 0]],\n                      \"o\": [[0, 82.702], [-82.702, 0], [0, -82.703], [82.702, 0]],\n                      \"v\": [[149.746, 0.001], [0, 149.747], [-149.746, 0.001], [0, -149.746]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.925, 0.8, 0.289999988032, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [149.996, 149.996], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 39,\n          \"ty\": 4,\n          \"nm\": \"white3 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 6.72,\n                  \"s\": [-487.561, -286.832, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 66.24,\n                  \"s\": [-477.561, -262.832, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                { \"t\": 126.72, \"s\": [-487.561, -286.832, 0] }\n              ],\n              \"ix\": 2\n            },\n            \"a\": { \"a\": 0, \"k\": [27.245, 13.837, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [0, 0], [-2.673, -2.673]],\n                      \"o\": [[0, 0], [2.673, -2.673], [0, 0]],\n                      \"v\": [[-4.839, 1.336], [-4.839, 1.336], [4.839, 1.336]],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": { \"a\": 0, \"k\": [0, 0, 0, 1], \"ix\": 3 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 4 },\n                  \"w\": { \"a\": 0, \"k\": 5, \"ix\": 5 },\n                  \"lc\": 2,\n                  \"lj\": 2,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [37.151, 13.837], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [0, 0], [-2.673, -2.673]],\n                      \"o\": [[0, 0], [2.673, -2.673], [0, 0]],\n                      \"v\": [[-4.84, 1.336], [-4.84, 1.336], [4.84, 1.336]],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": { \"a\": 0, \"k\": [0, 0, 0, 1], \"ix\": 3 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 4 },\n                  \"w\": { \"a\": 0, \"k\": 5, \"ix\": 5 },\n                  \"lc\": 2,\n                  \"lj\": 2,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [17.34, 13.837], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 2\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 2,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 41,\n          \"ty\": 4,\n          \"nm\": \"white2 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                { \"i\": { \"x\": [0.667], \"y\": [1] }, \"o\": { \"x\": [0.333], \"y\": [0] }, \"t\": 11.52, \"s\": [15] },\n                { \"i\": { \"x\": [0.667], \"y\": [1] }, \"o\": { \"x\": [0.333], \"y\": [0] }, \"t\": 76.8, \"s\": [27] },\n                { \"t\": 135.36, \"s\": [15] }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 11.52,\n                  \"s\": [-570.907, -353.765, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 76.8,\n                  \"s\": [-551.907, -350.765, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                { \"t\": 135.36, \"s\": [-570.907, -353.765, 0] }\n              ],\n              \"ix\": 2\n            },\n            \"a\": { \"a\": 0, \"k\": [31.99, 37.47, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-19.036, 25.162], [1.558, -17.898], [-9.362, -0.015]],\n                      \"o\": [[0, 0], [10.383, -13.727], [-1.785, 20.514], [0, 0]],\n                      \"v\": [[-31.739, 37.22], [-0.72, -23.493], [23.879, -11.898], [31.739, 30.549]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [1, 1, 1, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [31.989, 37.47], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 43,\n          \"ty\": 4,\n          \"nm\": \"white1 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                { \"i\": { \"x\": [0.667], \"y\": [1] }, \"o\": { \"x\": [0.333], \"y\": [0] }, \"t\": 0, \"s\": [0] },\n                { \"i\": { \"x\": [0.667], \"y\": [1] }, \"o\": { \"x\": [0.333], \"y\": [0] }, \"t\": 51.84, \"s\": [-5] },\n                { \"t\": 107.52, \"s\": [0] }\n              ],\n              \"ix\": 10\n            },\n            \"p\": { \"a\": 0, \"k\": [-523.973, -207.871, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [149.604, 141.775, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -14.732], [14.733, 0], [0, 14.733], [-14.733, 0]],\n                      \"o\": [[0, 14.733], [-14.733, 0], [0, -14.732], [14.733, 0]],\n                      \"v\": [[26.677, -0.001], [0, 26.676], [-26.676, -0.001], [0, -26.676]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [1, 1, 1, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [272.281, 120.799], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -78.162], [78.161, 0], [0, 78.161], [-78.163, 0]],\n                      \"o\": [[0, 78.161], [-78.163, 0], [0, -78.162], [78.161, 0]],\n                      \"v\": [[141.525, 0], [0, 141.525], [-141.524, 0], [0, -141.524]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [1, 1, 1, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [141.775, 141.775], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 2\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 2,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 45,\n          \"ty\": 4,\n          \"nm\": \"blue3 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 11.52,\n                  \"s\": [-357.735, -352.728, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 62.4,\n                  \"s\": [-352.735, -363.728, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                { \"t\": 117.12, \"s\": [-357.735, -352.728, 0] }\n              ],\n              \"ix\": 2\n            },\n            \"a\": { \"a\": 0, \"k\": [14.703, 10.041, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -2.512], [2.512, 0], [0, 2.511], [-2.512, 0]],\n                      \"o\": [[0, 2.511], [-2.512, 0], [0, -2.512], [2.512, 0]],\n                      \"v\": [[4.548, 0], [-0.001, 4.547], [-4.548, 0], [-0.001, -4.547]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.925, 0.8, 0.289999988032, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [4.798, 4.797], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -2.511], [2.512, 0], [0, 2.512], [-2.511, 0]],\n                      \"o\": [[0, 2.512], [-2.511, 0], [0, -2.511], [2.512, 0]],\n                      \"v\": [[4.548, 0], [-0.001, 4.547], [-4.548, 0], [-0.001, -4.547]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.925, 0.8, 0.289999988032, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [24.608, 15.285], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 2\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 2,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 47,\n          \"ty\": 4,\n          \"nm\": \"blue2 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": {\n              \"a\": 1,\n              \"k\": [\n                { \"i\": { \"x\": [0.667], \"y\": [1] }, \"o\": { \"x\": [0.333], \"y\": [0] }, \"t\": 20.16, \"s\": [0] },\n                { \"i\": { \"x\": [0.667], \"y\": [1] }, \"o\": { \"x\": [0.333], \"y\": [0] }, \"t\": 70.08, \"s\": [19] },\n                { \"t\": 124.8, \"s\": [0] }\n              ],\n              \"ix\": 10\n            },\n            \"p\": {\n              \"a\": 1,\n              \"k\": [\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 20.16,\n                  \"s\": [-219.232, -444.809, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                {\n                  \"i\": { \"x\": 0.667, \"y\": 1 },\n                  \"o\": { \"x\": 0.333, \"y\": 0 },\n                  \"t\": 70.08,\n                  \"s\": [-216.232, -428.809, 0],\n                  \"to\": [0, 0, 0],\n                  \"ti\": [0, 0, 0]\n                },\n                { \"t\": 124.8, \"s\": [-219.232, -444.809, 0] }\n              ],\n              \"ix\": 2\n            },\n            \"a\": { \"a\": 0, \"k\": [44.87, 40.367, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-30.538, 13.603], [7.1, -16.797], [-11.418, -5.58]],\n                      \"o\": [[0, 0], [16.658, -7.42], [-8.14, 19.254], [0, 0]],\n                      \"v\": [[-44.62, 8.988], [10.87, -32.697], [37.52, -6.591], [34.777, 40.117]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.258999992819, 0.176000004189, 0.811999990426, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [44.87, 40.367], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 49,\n          \"ty\": 4,\n          \"nm\": \"blue1 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-262.436, -276.095, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [161.891, 161.891, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -89.272], [89.272, 0], [0, 89.271], [-89.272, 0]],\n                      \"o\": [[0, 89.271], [-89.272, 0], [0, -89.272], [89.272, 0]],\n                      \"v\": [[161.641, 0], [0, 161.641], [-161.641, 0], [0, -161.641]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.258999992819, 0.176000004189, 0.811999990426, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [161.891, 161.891], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 51,\n          \"ty\": 4,\n          \"nm\": \"orange3 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-482.836, -394.807, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [18.781, 17.111, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [0, 0], [2.673, 2.673]],\n                      \"o\": [[0, 0], [-2.673, 2.673], [0, 0]],\n                      \"v\": [[4.84, -1.337], [4.84, -1.337], [-4.84, -1.337]],\n                      \"c\": false\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"st\",\n                  \"c\": { \"a\": 0, \"k\": [1, 1, 1, 1], \"ix\": 3 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 4 },\n                  \"w\": { \"a\": 0, \"k\": 5, \"ix\": 5 },\n                  \"lc\": 2,\n                  \"lj\": 2,\n                  \"bm\": 0,\n                  \"nm\": \"Stroke 1\",\n                  \"mn\": \"ADBE Vector Graphic - Stroke\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [19.988, 20.386], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -2.512], [2.511, 0], [0, 2.511], [-2.512, 0]],\n                      \"o\": [[0, 2.511], [-2.512, 0], [0, -2.512], [2.511, 0]],\n                      \"v\": [[4.548, 0], [0, 4.547], [-4.548, 0], [0, -4.547]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [1, 1, 1, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [32.765, 4.797], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 2\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 2,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -2.512], [2.512, 0], [0, 2.511], [-2.511, 0]],\n                      \"o\": [[0, 2.511], [-2.511, 0], [0, -2.512], [2.512, 0]],\n                      \"v\": [[4.548, 0], [-0.001, 4.547], [-4.548, 0], [-0.001, -4.547]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [1, 1, 1, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [4.797, 4.797], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 3\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 3,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 53,\n          \"ty\": 4,\n          \"nm\": \"orange2 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 15, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-544.483, -534.152, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [63.718, 68.41, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-18.484, 49.442], [-11.055, -26.588], [-18.922, 6.681]],\n                      \"o\": [[0, 0], [10.083, -26.971], [12.672, 30.476], [0, 0]],\n                      \"v\": [[-59.466, 68.16], [-44.984, -40.461], [13.909, -41.572], [63.468, 13.215]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.902000038297, 0.40800000359, 0.231000010173, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [63.718, 68.41], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 55,\n          \"ty\": 4,\n          \"nm\": \"orange1 Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-486.287, -309.136, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [221.177, 221.177, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, -122.015], [122.015, 0], [0, 122.015], [-122.014, 0]],\n                      \"o\": [[0, 122.015], [-122.014, 0], [0, -122.015], [122.015, 0]],\n                      \"v\": [[220.927, 0], [0, 220.927], [-220.927, 0], [0, -220.927]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.902000038297, 0.40800000359, 0.231000010173, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [221.177, 221.177], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        },\n        {\n          \"ddd\": 0,\n          \"ind\": 57,\n          \"ty\": 4,\n          \"nm\": \"feet Outlines\",\n          \"parent\": 1,\n          \"sr\": 1,\n          \"ks\": {\n            \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n            \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n            \"p\": { \"a\": 0, \"k\": [-392.775, -89.025, 0], \"ix\": 2 },\n            \"a\": { \"a\": 0, \"k\": [271.5, 38.275, 0], \"ix\": 1 },\n            \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n          },\n          \"ao\": 0,\n          \"shapes\": [\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-32.344, 0], [0, 0]],\n                      \"o\": [[0, 0], [32.343, 0], [0, 0]],\n                      \"v\": [[-23.583, 16.943], [0, -16.943], [26.279, 16.943]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.913999968884, 0.2, 0.513999968884, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [345.398, 59.357], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 1\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 1,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-32.343, 0], [0, 0]],\n                      \"o\": [[0, 0], [32.344, 0], [0, 0]],\n                      \"v\": [[-23.583, 15.5], [-0.001, -15.5], [26.279, 15.5]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.913999968884, 0.2, 0.513999968884, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [405.545, 60.8], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 2\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 2,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-24.817, 0], [0, 0]],\n                      \"o\": [[0, 0], [24.817, 0], [0, 0]],\n                      \"v\": [[-18.096, 13], [0, -13], [20.164, 13]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.078000005086, 0.090000002992, 0.102000000898, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [201.659, 63.3], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 3\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 3,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-24.818, 0], [0, 0]],\n                      \"o\": [[0, 0], [24.816, 0], [0, 0]],\n                      \"v\": [[-18.095, 13], [0.001, -13], [20.164, 13]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.078000005086, 0.090000002992, 0.102000000898, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [247.808, 63.3], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 4\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 4,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-29.589, 0], [0, 0]],\n                      \"o\": [[0, 0], [29.59, 0], [0, 0]],\n                      \"v\": [[-21.575, 15.5], [-0.001, -15.5], [24.041, 15.5]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.426999978458, 0.783999992819, 0.976000019148, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [29.839, 60.8], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 5\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 5,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-29.589, 0], [0, 0]],\n                      \"o\": [[0, 0], [29.589, 0], [0, 0]],\n                      \"v\": [[-21.575, 15.5], [0, -15.5], [24.041, 15.5]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.426999978458, 0.783999992819, 0.976000019148, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [84.864, 60.8], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 6\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 6,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-33.938, 0], [0, 0]],\n                      \"o\": [[0, 0], [33.939, 0], [0, 0]],\n                      \"v\": [[-24.747, 17.779], [-0.001, -17.779], [27.574, 17.779]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [1, 1, 1, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [109.157, 58.522], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 7\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 7,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-33.938, 0], [0, 0]],\n                      \"o\": [[0, 0], [33.939, 0], [0, 0]],\n                      \"v\": [[-24.747, 17.779], [-0.001, -17.779], [27.574, 17.779]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [1, 1, 1, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [172.27, 58.522], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 8\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 8,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-43.072, 0], [0, 0]],\n                      \"o\": [[0, 0], [43.072, 0], [0, 0]],\n                      \"v\": [[-31.407, 22.563], [0, -22.563], [34.996, 22.563]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.925, 0.8, 0.289999988032, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [418.58, 53.737], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 9\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 9,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-43.072, 0], [0, 0]],\n                      \"o\": [[0, 0], [43.072, 0], [0, 0]],\n                      \"v\": [[-31.407, 22.563], [0, -22.563], [34.996, 22.563]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.925, 0.8, 0.289999988032, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [499.678, 53.737], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 10\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 10,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-47.554, 0], [0, 0]],\n                      \"o\": [[0, 0], [47.554, 0], [0, 0]],\n                      \"v\": [[-34.675, 24.911], [0, -24.911], [38.638, 24.911]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.258999992819, 0.176000004189, 0.811999990426, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [323.539, 51.39], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 11\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 11,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-47.554, 0], [0, 0]],\n                      \"o\": [[0, 0], [47.554, 0], [0, 0]],\n                      \"v\": [[-34.675, 24.911], [0, -24.911], [38.638, 24.911]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.258999992819, 0.176000004189, 0.811999990426, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [437.973, 51.39], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 12\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 12,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-71.634, 0], [0, 0]],\n                      \"o\": [[0, 0], [71.634, 0], [0, 0]],\n                      \"v\": [[-52.234, 37.525], [0, -37.525], [58.203, 37.525]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.902000038297, 0.40800000359, 0.231000010173, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [104.903, 37.775], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 13\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 13,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            },\n            {\n              \"ty\": \"gr\",\n              \"it\": [\n                {\n                  \"ind\": 0,\n                  \"ty\": \"sh\",\n                  \"ix\": 1,\n                  \"ks\": {\n                    \"a\": 0,\n                    \"k\": {\n                      \"i\": [[0, 0], [-71.634, 0], [0, 0]],\n                      \"o\": [[0, 0], [71.635, 0], [0, 0]],\n                      \"v\": [[-52.234, 37.525], [-0.001, -37.525], [58.203, 37.525]],\n                      \"c\": true\n                    },\n                    \"ix\": 2\n                  },\n                  \"nm\": \"Path 1\",\n                  \"mn\": \"ADBE Vector Shape - Group\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"fl\",\n                  \"c\": { \"a\": 0, \"k\": [0.902000038297, 0.40800000359, 0.231000010173, 1], \"ix\": 4 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 5 },\n                  \"r\": 1,\n                  \"bm\": 0,\n                  \"nm\": \"Fill 1\",\n                  \"mn\": \"ADBE Vector Graphic - Fill\",\n                  \"hd\": false\n                },\n                {\n                  \"ty\": \"tr\",\n                  \"p\": { \"a\": 0, \"k\": [250.117, 37.775], \"ix\": 2 },\n                  \"a\": { \"a\": 0, \"k\": [0, 0], \"ix\": 1 },\n                  \"s\": { \"a\": 0, \"k\": [100, 100], \"ix\": 3 },\n                  \"r\": { \"a\": 0, \"k\": 0, \"ix\": 6 },\n                  \"o\": { \"a\": 0, \"k\": 100, \"ix\": 7 },\n                  \"sk\": { \"a\": 0, \"k\": 0, \"ix\": 4 },\n                  \"sa\": { \"a\": 0, \"k\": 0, \"ix\": 5 },\n                  \"nm\": \"Transform\"\n                }\n              ],\n              \"nm\": \"Group 14\",\n              \"np\": 2,\n              \"cix\": 2,\n              \"bm\": 0,\n              \"ix\": 14,\n              \"mn\": \"ADBE Vector Group\",\n              \"hd\": false\n            }\n          ],\n          \"ip\": 0,\n          \"op\": 487.68,\n          \"st\": 0,\n          \"bm\": 0\n        }\n      ]\n    }\n  ],\n  \"layers\": [\n    {\n      \"ddd\": 0,\n      \"ind\": 1,\n      \"ty\": 0,\n      \"nm\": \"web_anim02\",\n      \"refId\": \"comp_0\",\n      \"sr\": 1,\n      \"ks\": {\n        \"o\": { \"a\": 0, \"k\": 100, \"ix\": 11 },\n        \"r\": { \"a\": 0, \"k\": 0, \"ix\": 10 },\n        \"p\": { \"a\": 0, \"k\": [130, 652, 0], \"ix\": 2 },\n        \"a\": { \"a\": 0, \"k\": [1366, 661, 0], \"ix\": 1 },\n        \"s\": { \"a\": 0, \"k\": [100, 100, 100], \"ix\": 6 }\n      },\n      \"ao\": 0,\n      \"w\": 2732,\n      \"h\": 1322,\n      \"ip\": 0,\n      \"op\": 487.68,\n      \"st\": 0,\n      \"bm\": 0\n    }\n  ],\n  \"markers\": []\n}\n"
  },
  {
    "path": "packages/app/src/index.css",
    "content": "@import \"tailwindcss\";\n\n@custom-variant dark (&:where(.dark, .dark *));\n@custom-variant light (&:where(.light, .light *));\n\n@theme {\n  --bg-color: #000;\n  --header-bg-color: rgba(0, 0, 0, 0.3);\n  --nearly-bg-color: #090909;\n  --font-color: #fff;\n  --font-secondary-color: #a7a7a7;\n  --font-size: 15px;\n  --font-size-small: 13px;\n  --font-size-tiny: 11px;\n\n  /* Highlight colors */\n  --primary: #ff3f15;\n  --highlight: #ac88ff;\n  --error: #ff6053;\n  --success: #2ad544;\n  --warning: #ff8800;\n  --live: #f83838;\n  --heart: #ef4444;\n  --zap: #ff710a;\n  --mention: #961ee1;\n  --repost: #1ecbe1;\n  --pro: #ffdd65;\n  --free: #1a5aff;\n\n  --gray-gradient: linear-gradient(\n    to bottom right,\n    var(--color-neutral-700),\n    var(--color-neutral-700),\n    var(--color-neutral-100)\n  );\n  --snort-gradient: linear-gradient(90deg, #a178ff 0%, #ff6baf 100%);\n  --dm-gradient: linear-gradient(90deg, #5722d2 0%, #db1771 100%);\n  --invoice-gradient: linear-gradient(\n    45deg,\n    var(--color-neutral-800) 50%,\n    rgba(161, 120, 255, 0.2),\n    rgba(255, 107, 175, 0.2) 108.33%\n  );\n\n  /* Tailwind color mappings */\n  --color-highlight: var(--highlight);\n  --color-error: var(--error);\n  --color-success: var(--success);\n  --color-warning: var(--warning);\n  --color-heart: var(--heart);\n  --color-zap: var(--zap);\n  --color-mention: var(--mention);\n  --color-repost: var(--repost);\n  --color-primary: var(--primary);\n  --color-pro: var(--pro);\n  --color-free: var(--free);\n\n  --color-layer-1: var(--color-neutral-900);\n  --color-layer-2: var(--color-neutral-800);\n  --color-layer-3: var(--color-neutral-700);\n}\n\n* {\n  @apply border-neutral-800 light:border-neutral-400;\n}\n\n@utility layer-1 {\n  @apply bg-layer-1 rounded-lg border px-3 py-2;\n}\n\n@utility layer-1-hover {\n  @apply layer-1 hover:bg-layer-2 cursor-pointer;\n}\n\n@utility layer-2 {\n  @apply bg-layer-2 rounded-lg border px-3 py-2;\n}\n\n@utility layer-2-hover {\n  @apply layer-2 hover:bg-layer-3 cursor-pointer;\n}\n\n::-webkit-scrollbar {\n  width: 8px;\n  height: 8px;\n}\n\n::-webkit-scrollbar-track {\n  background-color: var(--color-neutral-800);\n  border-radius: 100px;\n}\n\n::-webkit-scrollbar-thumb {\n  background-color: var(--color-neutral-700);\n  border-radius: 100px;\n}\n\n::-webkit-scrollbar-thumb:hover {\n  background-color: var(--color-neutral-600);\n}\n\nhtml {\n  -webkit-tap-highlight-color: transparent;\n}\n\nhtml.light {\n  --bg-color: #fff;\n  --header-bg-color: rgba(255, 255, 255, 0.3);\n  --nearly-bg-color: #f9f9f9;\n  --font-color: #0f0f0f;\n  --font-secondary-color: #5c6c92;\n  --highlight: #7139f1;\n  --gray: #dee1e8;\n  --dm-gradient: #dee1e8;\n  --invoice-gradient: linear-gradient(45deg, #f0f0f0 50%, #f7b73333, #fc4a1a33);\n  --paid-invoice-gradient: linear-gradient(45deg, #f0f0f0 50%, #f7b73399, #fc4a1a99);\n  --bg-secondary: #f5f5f5;\n  --primary: #ff3f15;\n\n  --color-layer-1: var(--color-neutral-200);\n  --color-layer-2: var(--color-neutral-300);\n  --color-layer-3: var(--color-neutral-400);\n}\n\nbody {\n  margin: 0;\n  font-family: \"Inter\", sans-serif;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  background-color: var(--bg-color);\n  color: var(--font-color);\n  font-size: var(--font-size);\n  overflow-x: hidden;\n  overflow-y: scroll;\n}\n\ncode {\n  font-family: source-code-pro, Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\n\nul {\n  padding-inline-start: 2rem;\n}\n\na {\n  text-decoration: none;\n  overflow-wrap: break-word;\n}\n\na:hover {\n  text-decoration: underline;\n}\n\nsmall {\n  @apply text-neutral-300 leading-6 font-medium light:text-neutral-500;\n}\n\n/* Custom utilities that don't exist in Tailwind */\n@utility text-snort-gradient {\n  background: var(--snort-gradient);\n  background-clip: text;\n  -webkit-background-clip: text;\n  -webkit-text-fill-color: transparent;\n}\n\n@utility text-primary-gradient {\n  background: var(--primary);\n  background-clip: text;\n  -webkit-background-clip: text;\n  -webkit-text-fill-color: transparent;\n}\n\n@utility text-outline {\n  -webkit-text-stroke: 1px black;\n}\n\n/* Deck layout styling */\n.deck-layout {\n  display: flex;\n  height: 100vh;\n  overflow-y: hidden;\n}\n\n.deck-layout .deck-cols {\n  display: flex;\n  height: 100vh;\n  overflow-y: hidden;\n  overflow-x: auto;\n}\n\n.deck-layout .deck-cols .deck-col-header {\n  padding: 8px 16px;\n  border: 1px solid var(--color-neutral-800);\n  border-collapse: collapse;\n  font-size: 20px;\n  font-weight: 700;\n  min-height: 40px;\n  max-height: 40px;\n}\n\n.deck-layout .deck-cols .deck-col-header:not(:last-of-type) {\n  border-right: 0;\n}\n\n.deck-layout .deck-cols > div {\n  display: flex;\n  flex-direction: column;\n  height: 100vh;\n  width: 550px;\n  min-width: 550px;\n}\n\n.deck-layout .deck-cols > div > div:not(:first-of-type) {\n  overflow-y: scroll;\n}\n\n@utility button {\n  position: relative;\n  cursor: pointer;\n  padding: 10px 16px;\n  font-weight: 600;\n  color: black;\n  font-size: var(--font-size);\n  background-color: white;\n  border: none;\n  border-radius: 100px;\n  outline: none;\n}\n\n.button {\n  @apply button;\n}\n\nbutton,\nbutton[type=\"reset\"],\nbutton[type=\"submit\"] {\n  @apply button;\n  user-select: none;\n}\n\n.btn,\ninput,\nselect {\n  @apply rounded-full;\n}\n\nbutton.primary {\n  background: rgb(239, 150, 68);\n  background: var(--primary);\n  color: #fff;\n  border: none;\n}\n\nbutton.primary:hover {\n  box-shadow: 0px 0px 10px var(--primary);\n  background: var(--primary);\n}\n\nbutton:disabled {\n  opacity: 0.3;\n  cursor: not-allowed;\n}\n\nbutton.secondary:disabled {\n  color: var(--font-secondary-color);\n  cursor: not-allowed;\n}\n\nbutton:disabled:hover {\n  cursor: not-allowed;\n  color: var(--font-color);\n  border-color: var(--color-neutral-800);\n}\n\n.light button.transparent {\n  color: var(--font-color);\n}\n\n.light button:disabled {\n  color: var(--font-color);\n}\n\nbutton:hover {\n  background-color: var(--color-neutral-100);\n}\n\nbutton.secondary {\n  color: var(--font-color);\n  background-color: var(--color-neutral-700);\n}\n\nbutton.transparent {\n  font-weight: 400;\n  color: var(--font-secondary-color);\n  background-color: transparent;\n  border: 1px solid var(--color-neutral-800);\n}\n\nbutton.secondary:hover {\n  border: none;\n  color: var(--font-color);\n  background-color: var(--color-neutral-800);\n}\n\nbutton.transparent:hover {\n  color: var(--bg-color);\n  background-color: var(--font-color);\n}\n\nbutton.icon {\n  border: none;\n  background: var(--bg-secondary);\n  color: var(--font-color);\n  width: 40px;\n  height: 40px;\n  padding: 10px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\nbutton.icon:hover {\n  color: var(--highlight);\n}\n\n.button-icon-sm {\n  padding: 4px;\n  border-radius: 8px;\n  display: flex;\n  align-items: center;\n  cursor: pointer;\n}\n\n.button-icon-sm.active {\n  background: rgba(255, 255, 255, 0.1);\n}\n\n.btn {\n  padding: 10px;\n  border-radius: 5px;\n  cursor: pointer;\n  color: var(--font-color);\n  user-select: none;\n  background: none;\n  border: none;\n  display: inline-flex;\n}\n\n.light .btn {\n  color: #64748b;\n}\n\n.btn-warn {\n  border-color: var(--error);\n}\n\n.btn-success {\n  border-color: var(--success);\n}\n\n.btn.active {\n  color: var(--font-color);\n  font-weight: 700;\n}\n\n.btn.disabled {\n  opacity: 0.3;\n}\n\n.btn:hover {\n  color: var(--highlight);\n}\n\n.btn-sm {\n  padding: 5px;\n}\n\ntextarea {\n  font: inherit;\n}\n\np {\n  margin-top: 1em;\n  margin-bottom: 1em;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6 {\n  padding: 0;\n  font-weight: 600;\n}\n\nh1 {\n  font-size: 32px;\n  line-height: 42px;\n}\n\nh2 {\n  font-size: 26px;\n  line-height: 36px;\n}\n\nh3 {\n  font-size: 20px;\n  line-height: 30px;\n}\n\nh4 {\n  font-size: 18px;\n  line-height: 28px;\n}\n\ninput[type],\nselect,\ntextarea {\n  padding: 8px 12px;\n  color: var(--font-color);\n  background: transparent;\n  border: 2px solid rgba(255, 255, 255, 0.1);\n  border-radius: 12px;\n  outline: none;\n  font-size: 15px;\n  line-height: 24px;\n  /* 150% */\n}\n\n.light input[type],\n.light select,\n.light textarea {\n  border: 2px solid var(--color-neutral-400);\n}\n\noption,\noptgroup {\n  background-color: var(--bg-color);\n}\n\ninput::placeholder,\ntextarea::placeholder {\n  @apply text-neutral-500;\n}\n\ninput[type=\"checkbox\"] {\n  width: 20px;\n  height: 20px;\n}\n\ninput:disabled {\n  color: var(--color-neutral-800);\n  cursor: not-allowed;\n}\n\n/* Custom utilities for special width behavior */\n@utility w-stretch {\n  width: 100%;\n  width: stretch;\n  width: -webkit-fill-available;\n  width: -moz-available;\n}\n\n@utility max-w-stretch {\n  max-width: 100%;\n  max-width: stretch;\n  max-width: -webkit-fill-available;\n  max-width: -moz-available;\n}\n\n.scroll-lock {\n  overflow: hidden;\n  height: 100vh;\n}\n\n@media (max-width: 720px) {\n  div.form {\n    grid-auto-flow: dense;\n  }\n\n  div.form-group {\n    flex-direction: column;\n    align-items: flex-start;\n  }\n}\n\nbutton.tall {\n  height: 40px;\n}\n\n.action-heading {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  justify-content: space-between;\n}\n\n.action-heading button {\n  min-width: 98px;\n}\n\nsvg.heart-solid {\n  color: var(--heart);\n}\n\nsvg.zap-solid {\n  color: var(--zap);\n}\n\nsvg.repeat {\n  color: var(--repost);\n}\n\n.light button.icon {\n  border: 1px solid var(--color-neutral-800);\n  box-shadow: rgba(0, 0, 0, 0.08) 0 1px 1px;\n}\n\n.light button.icon:hover {\n  box-shadow: rgba(0, 0, 0, 0.2) 0 1px 3px;\n}\n\n.light button,\n.light button.secondary {\n  color: #4b5c83;\n  background-color: #fff;\n  border: 1px solid var(--color-neutral-800);\n  box-shadow: rgba(0, 0, 0, 0.08) 0 1px 1px;\n}\n\n.light button.primary {\n  background: var(--primary);\n  color: #fff;\n  border: none;\n  box-shadow: rgba(0, 0, 0, 0.08) 0 1px 1px;\n}\n\n.light button:hover,\n.light button.secondary:hover {\n  box-shadow: rgba(0, 0, 0, 0.2) 0 1px 3px;\n}\n\n.light button.primary:hover {\n  box-shadow: 0px 0px 10px var(--primary);\n}\n\n.light .modal button.secondary:hover {\n  background: #fff;\n}\n\n@utility hide-scrollbar {\n  scrollbar-width: none;\n  -ms-overflow-style: none;\n\n  &::-webkit-scrollbar {\n    display: none;\n  }\n}\n\n@utility pb-safe-area {\n  padding-bottom: env(safe-area-inset-bottom);\n}\n\n@utility sm-hide-scrollbar {\n  @media (max-width: 768px) {\n    scrollbar-width: none;\n    -ms-overflow-style: none;\n\n    &::-webkit-scrollbar {\n      display: none;\n    }\n  }\n}\n\n@utility pb-safe-area-plus-footer {\n  @media (max-width: 768px) {\n    padding-bottom: calc(env(safe-area-inset-bottom) + 56px);\n  }\n}\n\n.active > .icon-outline {\n  display: none;\n}\n\n.active > .icon-solid {\n  display: inline-block;\n}\n\n.icon-solid {\n  display: none;\n}\n\n@media (min-width: 768px) {\n  .rt-border {\n    border-right-width: 1px;\n    border-right-color: var(--color-neutral-800);\n  }\n}\n"
  },
  {
    "path": "packages/app/src/index.tsx",
    "content": "import \"./index.css\"\nimport \"@/assets/fonts/inter.css\"\n\nimport { unixNow, unixNowMs } from \"@snort/shared\"\nimport { EventBuilder } from \"@snort/system\"\nimport { SnortContext } from \"@snort/system-react\"\nimport { StrictMode } from \"react\"\nimport * as ReactDOM from \"react-dom/client\"\nimport { createBrowserRouter, type RouteObject, RouterProvider } from \"react-router-dom\"\n\nimport { initRelayWorker, ProfilesCache, preload, Relay } from \"@/Cache\"\nimport { IntlProvider } from \"@/Components/IntlProvider/IntlProvider\"\nimport { addCachedMetadataToFuzzySearch } from \"@/Db/FuzzySearch\"\nimport ErrorPage from \"@/Pages/ErrorPage\"\nimport { OnboardingRoutes } from \"@/Pages/onboarding/routes\"\nimport { RootRoutes } from \"@/Pages/Root/RootRoutes\"\nimport SettingsRoutes from \"@/Pages/settings/Routes\"\nimport { System } from \"@/system\"\nimport { storeRefCode, unwrap } from \"@/Utils\"\nimport { hasWasm, WasmPath, wasmInit } from \"@/Utils/wasm\"\nimport { setupWebLNWalletConfig, Wallets } from \"@/Wallet\"\nimport { SpotlightContextWrapper } from \"./Components/Spotlight/context\"\nimport { Day } from \"./Utils/Const\"\nimport { LoginStore } from \"./Utils/Login\"\n\nasync function initSite() {\n  EventBuilder.ClientTag = [\n    \"client\",\n    CONFIG.appNameCapitalized,\n    \"31990:84de35e2584d2b144aae823c9ed0b0f3deda09648530b93d1a2a146d1dea9864:app-profile\",\n  ]\n  storeRefCode()\n  if (hasWasm) {\n    await wasmInit(WasmPath)\n    await initRelayWorker()\n  }\n\n  setupWebLNWalletConfig(Wallets)\n\n  const login = LoginStore.snapshot()\n  preload(login.state.follows).then(async () => {\n    queueMicrotask(async () => {\n      const start = unixNowMs()\n      await System.PreloadSocialGraph(login.state.follows, login.publicKey)\n      console.debug(\n        `Social graph loaded in ${(unixNowMs() - start).toFixed(3)}ms`,\n        System.config.socialGraphInstance.size(),\n      )\n    })\n\n    for (const ev of ProfilesCache.snapshot()) {\n      try {\n        addCachedMetadataToFuzzySearch(ev)\n      } catch (e) {\n        console.error(\"Failed to handle metadata event from sql db\", e)\n      }\n    }\n  })\n\n  // cleanup\n  Relay?.delete([\"REQ\", \"cleanup\", { kinds: [1, 6, 7, 9735], until: unixNow() - Day * 30 }])\n\n  return null\n}\n\nlet didInit = false\nconst mainRoutes = [\n  ...RootRoutes,\n  {\n    path: \"/cache-debug\",\n    async lazy() {\n      const { DebugPage } = await import(\"@/Pages/CacheDebug\")\n      return { Component: DebugPage }\n    },\n  },\n  {\n    path: \"/help\",\n    async lazy() {\n      const { default: HelpPage } = await import(\"@/Pages/HelpPage\")\n      return { Component: HelpPage }\n    },\n  },\n  {\n    path: \"/e/:id\",\n    async lazy() {\n      const { ThreadRoute } = await import(\"@/Components/Event/Thread/ThreadRoute\")\n      return { Component: ThreadRoute }\n    },\n  },\n  {\n    path: \"/p/:id\",\n    async lazy() {\n      const { default: ProfilePage } = await import(\"@/Pages/Profile/ProfilePage\")\n      return { Component: ProfilePage }\n    },\n  },\n  {\n    path: \"/notifications\",\n    async lazy() {\n      const { default: NotificationsPage } = await import(\"@/Pages/Notifications/Notifications\")\n      return { Component: NotificationsPage }\n    },\n  },\n  {\n    path: \"/free-nostr-address\",\n    async lazy() {\n      const { default: FreeNostrAddressPage } = await import(\"@/Pages/FreeNostrAddressPage\")\n      return { Component: FreeNostrAddressPage }\n    },\n  },\n  {\n    path: \"/nostr-address\",\n    async lazy() {\n      const { default: NostrAddressPage } = await import(\"@/Pages/NostrAddressPage\")\n      return { Component: NostrAddressPage }\n    },\n  },\n  {\n    path: \"/messages/:id?\",\n    async lazy() {\n      const { default: MessagesPage } = await import(\"@/Pages/Messages/MessagesPage\")\n      return { Component: MessagesPage }\n    },\n  },\n  {\n    path: \"/about\",\n    async lazy() {\n      const { default: DonatePage } = await import(\"@/Pages/Donate/DonatePage\")\n      return { Component: DonatePage }\n    },\n  },\n  {\n    path: \"/search/:keyword?\",\n    async lazy() {\n      const { default: SearchPage } = await import(\"@/Pages/SearchPage\")\n      return { Component: SearchPage }\n    },\n  },\n  {\n    path: \"/list-feed/:id\",\n    async lazy() {\n      const { ListFeedPage } = await import(\"@/Pages/ListFeedPage\")\n      return { Component: ListFeedPage }\n    },\n  },\n  {\n    path: \"/changelog\",\n    async lazy() {\n      const { AboutPage } = await import(\"@/Pages/About\")\n      return { Component: AboutPage }\n    },\n  },\n  {\n    path: \"/wallet\",\n    async lazy() {\n      const { default: WalletPage } = await import(\"@/Pages/wallet\")\n      const WalletPageWrapper = () => (\n        <div className=\"px-3 py-2\">\n          <WalletPage showHistory={true} />\n        </div>\n      )\n      return { Component: WalletPageWrapper }\n    },\n  },\n  {\n    path: \"/wallet/send\",\n    async lazy() {\n      const { WalletSendPage } = await import(\"@/Pages/wallet/send\")\n      return { Component: WalletSendPage }\n    },\n  },\n  {\n    path: \"/wallet/receive\",\n    async lazy() {\n      const { WalletReceivePage } = await import(\"@/Pages/wallet/receive\")\n      return { Component: WalletReceivePage }\n    },\n  },\n  OnboardingRoutes,\n  ...SettingsRoutes,\n] as Array<RouteObject>\n\nif (CONFIG.features.zapPool) {\n  mainRoutes.push({\n    path: \"/zap-pool\",\n    async lazy() {\n      const { default: ZapPoolPage } = await import(\"@/Pages/ZapPool/ZapPool\")\n      return { Component: ZapPoolPage }\n    },\n  })\n}\n\nif (CONFIG.features.subscriptions) {\n  mainRoutes.push({\n    path: \"/subscribe\",\n    async lazy() {\n      const { SubscribePage } = await import(\"@/Pages/subscribe\")\n      return { Component: SubscribePage }\n    },\n  })\n  mainRoutes.push({\n    path: \"/subscribe/manage\",\n    async lazy() {\n      const { default: ManageSubscriptionPage } = await import(\"@/Pages/subscribe/ManageSubscription\")\n      return { Component: ManageSubscriptionPage }\n    },\n  })\n}\n\n// add catch all route\nmainRoutes.push({\n  path: \"/:link\",\n  async lazy() {\n    const { default: NostrLinkHandler } = await import(\"@/Pages/NostrLinkHandler\")\n    return { Component: NostrLinkHandler }\n  },\n})\n\nconst routes = [\n  {\n    async lazy() {\n      const { default: Layout } = await import(\"@/Pages/Layout\")\n      return { Component: Layout }\n    },\n    errorElement: <ErrorPage />,\n    loader: async () => {\n      if (!didInit) {\n        didInit = true\n        return await initSite()\n      }\n      return null\n    },\n    children: mainRoutes,\n  },\n  {\n    path: \"/component-debug\",\n    loader: async () => {\n      if (!didInit) {\n        didInit = true\n        return await initSite()\n      }\n      return null\n    },\n    async lazy() {\n      const { default: ComponentDebugPage } = await import(\"@/Pages/ComponentDebug\")\n      return { Component: ComponentDebugPage }\n    },\n  },\n] as Array<RouteObject>\n\nconst router = createBrowserRouter(routes)\n\nconst root = ReactDOM.createRoot(unwrap(document.getElementById(\"root\")))\nroot.render(\n  <StrictMode>\n    <IntlProvider>\n      <SnortContext.Provider value={System}>\n        <SpotlightContextWrapper>\n          <RouterProvider router={router} />\n        </SpotlightContextWrapper>\n      </SnortContext.Provider>\n    </IntlProvider>\n  </StrictMode>,\n)\n\n// Use react-helmet instead?\ndocument.title = CONFIG.appTitle\n"
  },
  {
    "path": "packages/app/src/lang.json",
    "content": "{\n  \"+D82kt\": {\n    \"defaultMessage\": \"Are you sure you want to repost: {id}\"\n  },\n  \"+PzQ9Y\": {\n    \"defaultMessage\": \"Payout Now\"\n  },\n  \"+QM0PJ\": {\n    \"defaultMessage\": \"Sync all events for your profile into local cache\"\n  },\n  \"+UjDmN\": {\n    \"defaultMessage\": \"Logged in with write access\"\n  },\n  \"+Vxixo\": {\n    \"defaultMessage\": \"Secret Group Chat\"\n  },\n  \"+W+Kof\": {\n    \"defaultMessage\": \"Cashu Wallet History\"\n  },\n  \"+mO9i4\": {\n    \"defaultMessage\": \"Code Snippet\"\n  },\n  \"+sDqqq\": {\n    \"defaultMessage\": \"Peer-to-peer Order events\"\n  },\n  \"+tShPg\": {\n    \"defaultMessage\": \"following\"\n  },\n  \"+vA//S\": {\n    \"defaultMessage\": \"Logins\"\n  },\n  \"+vIQlC\": {\n    \"defaultMessage\": \"Please make sure to save the following password in order to manage your handle in the future\"\n  },\n  \"+vVZ/G\": {\n    \"defaultMessage\": \"Connect\"\n  },\n  \"+vj0U3\": {\n    \"defaultMessage\": \"edit\"\n  },\n  \"+xliwN\": {\n    \"defaultMessage\": \"{name} reposted\"\n  },\n  \"/B8zwF\": {\n    \"defaultMessage\": \"Your space the way you want it 😌\"\n  },\n  \"/GCoTA\": {\n    \"defaultMessage\": \"Clear\"\n  },\n  \"/JE/X+\": {\n    \"defaultMessage\": \"Account Support\"\n  },\n  \"/T7HId\": {\n    \"defaultMessage\": \"HTTP File Storage Integration\"\n  },\n  \"/Xf4UW\": {\n    \"defaultMessage\": \"Send anonymous usage metrics\"\n  },\n  \"/d6vEc\": {\n    \"defaultMessage\": \"Make your profile easier to find and share\"\n  },\n  \"/ioUrF\": {\n    \"defaultMessage\": \"From File\"\n  },\n  \"/n5KSF\": {\n    \"defaultMessage\": \"{n} ms\"\n  },\n  \"00LcfG\": {\n    \"defaultMessage\": \"Load more\"\n  },\n  \"01iNut\": {\n    \"defaultMessage\": \"Nostr address does not belong to you\"\n  },\n  \"08zn6O\": {\n    \"defaultMessage\": \"Export Keys\"\n  },\n  \"0Azlrb\": {\n    \"defaultMessage\": \"Manage\"\n  },\n  \"0BUTMv\": {\n    \"defaultMessage\": \"Search...\"\n  },\n  \"0MndVW\": {\n    \"defaultMessage\": \"Generic LNDHub wallet (BTCPayServer / Alby / LNBits)\"\n  },\n  \"0PtoZq\": {\n    \"defaultMessage\": \"URL for AI Agent service\"\n  },\n  \"0jOEtS\": {\n    \"defaultMessage\": \"Invalid LNURL\"\n  },\n  \"0kOBMu\": {\n    \"defaultMessage\": \"Handling Mentions\"\n  },\n  \"0mch2Y\": {\n    \"defaultMessage\": \"name has disallowed characters\"\n  },\n  \"0oMk/p\": {\n    \"defaultMessage\": \"Other Chats\"\n  },\n  \"0siT4z\": {\n    \"defaultMessage\": \"Politics\"\n  },\n  \"0uoY11\": {\n    \"defaultMessage\": \"Show Status\"\n  },\n  \"0yO7wF\": {\n    \"defaultMessage\": \"{n} secs\"\n  },\n  \"0zASjL\": {\n    \"defaultMessage\": \"Go\",\n    \"description\": \"Button text after entering username in quick signup\"\n  },\n  \"1/BFEj\": {\n    \"defaultMessage\": \"git stuff\"\n  },\n  \"1A6QoL\": {\n    \"defaultMessage\": \"Author-Derived Servers ({count})\"\n  },\n  \"1GvBMj\": {\n    \"defaultMessage\": \"internal reference\"\n  },\n  \"1Ia8qN\": {\n    \"defaultMessage\": \"Processing\"\n  },\n  \"1Mo59U\": {\n    \"defaultMessage\": \"Are you sure you want to remove this note from bookmarks?\"\n  },\n  \"1R43+L\": {\n    \"defaultMessage\": \"Enter Nostr Wallet Connect config\"\n  },\n  \"1UWegE\": {\n    \"defaultMessage\": \"Be sure to back up your keys!\"\n  },\n  \"1nYUGC\": {\n    \"defaultMessage\": \"{n} Following\"\n  },\n  \"1o2BgB\": {\n    \"defaultMessage\": \"Check Signatures\"\n  },\n  \"1ozeyg\": {\n    \"defaultMessage\": \"Nature\"\n  },\n  \"1sawgR\": {\n    \"defaultMessage\": \"Page {current} of {total} ({count} items)\"\n  },\n  \"1udzha\": {\n    \"defaultMessage\": \"Conversations\"\n  },\n  \"2/2yg+\": {\n    \"defaultMessage\": \"Add\"\n  },\n  \"25V4l1\": {\n    \"defaultMessage\": \"Banner\"\n  },\n  \"25WwxF\": {\n    \"defaultMessage\": \"Don't have an account?\"\n  },\n  \"28oKbu\": {\n    \"defaultMessage\": \"Moderated Communities\"\n  },\n  \"29sHFE\": {\n    \"defaultMessage\": \"Wallet Connect\"\n  },\n  \"2BBGxX\": {\n    \"defaultMessage\": \"Subject tag in text events\"\n  },\n  \"2HIqeO\": {\n    \"defaultMessage\": \"User emoji list\"\n  },\n  \"2IFGap\": {\n    \"defaultMessage\": \"Donate\"\n  },\n  \"2Npgrt\": {\n    \"defaultMessage\": \"Has imeta tags for images, but no r tags\"\n  },\n  \"2O2sfp\": {\n    \"defaultMessage\": \"Finish\"\n  },\n  \"2Qsf9/\": {\n    \"defaultMessage\": \"Generic lists\"\n  },\n  \"2YxhJx\": {\n    \"defaultMessage\": \"Reserved Cashu Wallet Tokens\"\n  },\n  \"2a2YiP\": {\n    \"defaultMessage\": \"{n} Bookmarks\"\n  },\n  \"2k0Cv+\": {\n    \"defaultMessage\": \"Dislikes ({n})\"\n  },\n  \"2mcwT8\": {\n    \"defaultMessage\": \"New Note\"\n  },\n  \"2oCF7O\": {\n    \"defaultMessage\": \"Followed by friends of friends\"\n  },\n  \"2raFAu\": {\n    \"defaultMessage\": \"Application-specific data\"\n  },\n  \"2ukA4d\": {\n    \"defaultMessage\": \"{n} hours\"\n  },\n  \"2xzTkL\": {\n    \"defaultMessage\": \"Curated lists of people to follow.\"\n  },\n  \"2z7Kky\": {\n    \"defaultMessage\": \"Latest Articles\"\n  },\n  \"2zJXeA\": {\n    \"defaultMessage\": \"Profiles\"\n  },\n  \"3/w0Mr\": {\n    \"defaultMessage\": \"Post Event\"\n  },\n  \"39AHJm\": {\n    \"defaultMessage\": \"Sign Up\"\n  },\n  \"3GWu6/\": {\n    \"defaultMessage\": \"User Statuses\"\n  },\n  \"3KNMbJ\": {\n    \"defaultMessage\": \"Articles\"\n  },\n  \"3MKdAw\": {\n    \"defaultMessage\": \"Blobs stored on mediaservers\"\n  },\n  \"3QwfJR\": {\n    \"defaultMessage\": \"~{amount}\"\n  },\n  \"3VI9mt\": {\n    \"defaultMessage\": \"Save Changes\"\n  },\n  \"3adEeb\": {\n    \"defaultMessage\": \"{n} viewers\"\n  },\n  \"3cc4Ct\": {\n    \"defaultMessage\": \"Light\"\n  },\n  \"3gOsZq\": {\n    \"defaultMessage\": \"Translators\"\n  },\n  \"3qnJlS\": {\n    \"defaultMessage\": \"You are voting with {amount} sats\"\n  },\n  \"3t3kok\": {\n    \"defaultMessage\": \"{n,plural,=1{{n} new note} other{{n} new notes}}\"\n  },\n  \"3tVy+Z\": {\n    \"defaultMessage\": \"{n} Followers\"\n  },\n  \"3yk8fB\": {\n    \"defaultMessage\": \"Wallet\"\n  },\n  \"40VR6s\": {\n    \"defaultMessage\": \"Nostr Connect\"\n  },\n  \"450Fty\": {\n    \"defaultMessage\": \"None\"\n  },\n  \"47E53q\": {\n    \"defaultMessage\": \"Wiki\"\n  },\n  \"47FYwb\": {\n    \"defaultMessage\": \"Cancel\"\n  },\n  \"48zn4v\": {\n    \"defaultMessage\": \"Bid\"\n  },\n  \"4L2vUY\": {\n    \"defaultMessage\": \"Your new NIP-05 handle is:\"\n  },\n  \"4MjsHk\": {\n    \"defaultMessage\": \"Life\"\n  },\n  \"4OB335\": {\n    \"defaultMessage\": \"Dislike\"\n  },\n  \"4OQuna\": {\n    \"defaultMessage\": \"Draft Event\"\n  },\n  \"4P/kKm\": {\n    \"defaultMessage\": \"Private Key Encryption\"\n  },\n  \"4Vmpt4\": {\n    \"defaultMessage\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n  },\n  \"4Z3t5i\": {\n    \"defaultMessage\": \"Use imgproxy to compress images\"\n  },\n  \"4emo2p\": {\n    \"defaultMessage\": \"Missing Relays\"\n  },\n  \"4oPRxH\": {\n    \"defaultMessage\": \"Supported Kinds:\"\n  },\n  \"4rYCjn\": {\n    \"defaultMessage\": \"Note to Self\"\n  },\n  \"4rxi5n\": {\n    \"defaultMessage\": \"hardcopy reference\"\n  },\n  \"4tKMJS\": {\n    \"defaultMessage\": \"Software Application\"\n  },\n  \"4wgYpI\": {\n    \"defaultMessage\": \"Recommended Application Handlers\"\n  },\n  \"5BVs2e\": {\n    \"defaultMessage\": \"zap\"\n  },\n  \"5CB6zB\": {\n    \"defaultMessage\": \"Zap Splits\"\n  },\n  \"5PRWs7\": {\n    \"defaultMessage\": \"Notifications API Enabled\"\n  },\n  \"5dfmvv\": {\n    \"defaultMessage\": \"Zap Goal\"\n  },\n  \"5h6Dks\": {\n    \"defaultMessage\": \"Ask me anything about Nostr or {appName}\"\n  },\n  \"5qEWCr\": {\n    \"defaultMessage\": \"File Metadata\"\n  },\n  \"5tgBVG\": {\n    \"defaultMessage\": \"You have unsaved changes to your profile, contacts, relays, or settings.\"\n  },\n  \"5u6iEc\": {\n    \"defaultMessage\": \"Transfer to Pubkey\"\n  },\n  \"5vMmmR\": {\n    \"defaultMessage\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n  },\n  \"5ykRmX\": {\n    \"defaultMessage\": \"Send zap\"\n  },\n  \"6/hB3S\": {\n    \"defaultMessage\": \"Watch Replay\"\n  },\n  \"60kEE3\": {\n    \"defaultMessage\": \"Mute list\"\n  },\n  \"62nsdy\": {\n    \"defaultMessage\": \"Retry\"\n  },\n  \"6559gb\": {\n    \"defaultMessage\": \"New follow list length {length}\"\n  },\n  \"65BmHb\": {\n    \"defaultMessage\": \"Failed to proxy image from {host}, click here to load directly\"\n  },\n  \"6D4Hhn\": {\n    \"defaultMessage\": \"Recommend Relay\"\n  },\n  \"6KGebm\": {\n    \"defaultMessage\": \"Seal\"\n  },\n  \"6OSOXl\": {\n    \"defaultMessage\": \"Reason: <i>{reason}</i>\"\n  },\n  \"6Z3bDG\": {\n    \"defaultMessage\": \"Cashu Wallet Event\"\n  },\n  \"6bgpn+\": {\n    \"defaultMessage\": \"Not all clients support this, you may still receive some zaps as if zap splits was not configured\"\n  },\n  \"6dmn4m\": {\n    \"defaultMessage\": \"Thread\"\n  },\n  \"6ewQqw\": {\n    \"defaultMessage\": \"Likes ({n})\"\n  },\n  \"6m1Zkw\": {\n    \"defaultMessage\": \"Relay Monitor Announcement\"\n  },\n  \"6mr8WU\": {\n    \"defaultMessage\": \"Followed by\"\n  },\n  \"6pdxsi\": {\n    \"defaultMessage\": \"Extra metadata fields and tags\"\n  },\n  \"6uMqL1\": {\n    \"defaultMessage\": \"Unpaid\"\n  },\n  \"6xNr8c\": {\n    \"defaultMessage\": \"Switch accounts\"\n  },\n  \"6xap9L\": {\n    \"defaultMessage\": \"Good\"\n  },\n  \"7+Domh\": {\n    \"defaultMessage\": \"Notes\"\n  },\n  \"712i26\": {\n    \"defaultMessage\": \"Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node\"\n  },\n  \"753yX5\": {\n    \"defaultMessage\": \"Label\"\n  },\n  \"769A8p\": {\n    \"defaultMessage\": \"Wiki article\"\n  },\n  \"77nkEO\": {\n    \"defaultMessage\": \"Relay Information Document\"\n  },\n  \"7LFU8U\": {\n    \"defaultMessage\": \"Search Capability\"\n  },\n  \"7UOvbT\": {\n    \"defaultMessage\": \"Offline\"\n  },\n  \"7YkSA2\": {\n    \"defaultMessage\": \"Community Leader\"\n  },\n  \"7aCUzE\": {\n    \"defaultMessage\": \"Choose a DVM (Data Vending Machine) to provide content.\"\n  },\n  \"7gMmSL\": {\n    \"defaultMessage\": \"Reaction\"\n  },\n  \"7hp70g\": {\n    \"defaultMessage\": \"NIP-05\"\n  },\n  \"7mC9+e\": {\n    \"defaultMessage\": \"Has images but no imeta tags\"\n  },\n  \"7nAz/z\": {\n    \"defaultMessage\": \"Mute notes from people who are outside your web of trust\"\n  },\n  \"7pFGAQ\": {\n    \"defaultMessage\": \"Close Relays\"\n  },\n  \"8/vBbP\": {\n    \"defaultMessage\": \"Reposts ({n})\"\n  },\n  \"89q5wc\": {\n    \"defaultMessage\": \"Confirm Reposts\"\n  },\n  \"8BDFvJ\": {\n    \"defaultMessage\": \"Conventions for clients' use of e and p tags in text events\"\n  },\n  \"8Cw1Fj\": {\n    \"defaultMessage\": \"Link Set\"\n  },\n  \"8ED/4u\": {\n    \"defaultMessage\": \"Reply To\"\n  },\n  \"8HJxXG\": {\n    \"defaultMessage\": \"Sign up\"\n  },\n  \"8QDesP\": {\n    \"defaultMessage\": \"Zap {n} sats\"\n  },\n  \"8Rkoyb\": {\n    \"defaultMessage\": \"Recipient\"\n  },\n  \"8Y6bZQ\": {\n    \"defaultMessage\": \"Invalid zap split: {input}\"\n  },\n  \"8g2vyB\": {\n    \"defaultMessage\": \"name too long\"\n  },\n  \"8jmwT8\": {\n    \"defaultMessage\": \"bech32-encoded entities\"\n  },\n  \"8xdDLn\": {\n    \"defaultMessage\": \"Follow sets\"\n  },\n  \"8za9Pq\": {\n    \"defaultMessage\": \"Draft Classified Listing\"\n  },\n  \"9+Ddtu\": {\n    \"defaultMessage\": \"Next\"\n  },\n  \"90OuKH\": {\n    \"defaultMessage\": \"Sign in with Nostr Connect\"\n  },\n  \"92gdbw\": {\n    \"defaultMessage\": \"Relay Discovery\"\n  },\n  \"9HU8vw\": {\n    \"defaultMessage\": \"Reply\"\n  },\n  \"9O+VX8\": {\n    \"defaultMessage\": \"Partial\"\n  },\n  \"9RNiUn\": {\n    \"defaultMessage\": \"View Feed\"\n  },\n  \"9SvQep\": {\n    \"defaultMessage\": \"Follows {n}\"\n  },\n  \"9V0wg3\": {\n    \"defaultMessage\": \"Calendar Event RSVP\"\n  },\n  \"9WRlF4\": {\n    \"defaultMessage\": \"Send\"\n  },\n  \"9WTAKy\": {\n    \"defaultMessage\": \"Search sets..\"\n  },\n  \"9kO0VQ\": {\n    \"defaultMessage\": \"Hide muted notes\"\n  },\n  \"9kSari\": {\n    \"defaultMessage\": \"Retry publishing\"\n  },\n  \"9pMqYs\": {\n    \"defaultMessage\": \"Nostr Address\"\n  },\n  \"9qtLJC\": {\n    \"defaultMessage\": \"Payment Required\"\n  },\n  \"9wO4wJ\": {\n    \"defaultMessage\": \"Lightning Invoice\"\n  },\n  \"9zaOuc\": {\n    \"defaultMessage\": \"Suggestions by\"\n  },\n  \"A86fJ+\": {\n    \"defaultMessage\": \"Generic Repost\"\n  },\n  \"ADmfQT\": {\n    \"defaultMessage\": \"Parent\",\n    \"description\": \"Link to parent note in thread\"\n  },\n  \"AKrsKF\": {\n    \"defaultMessage\": \"API key for AI Agent service\"\n  },\n  \"AN0Z7Q\": {\n    \"defaultMessage\": \"Muted Words\"\n  },\n  \"ASRK0S\": {\n    \"defaultMessage\": \"This author has been muted\"\n  },\n  \"AedFVZ\": {\n    \"defaultMessage\": \"Create or update a product\"\n  },\n  \"AgentKey1\": {\n    \"defaultMessage\": \"Agent Key\"\n  },\n  \"AgentUrl1\": {\n    \"defaultMessage\": \"Agent URL\"\n  },\n  \"AkCxS/\": {\n    \"defaultMessage\": \"Reason\"\n  },\n  \"AktAk2\": {\n    \"defaultMessage\": \"Great\"\n  },\n  \"Am8glJ\": {\n    \"defaultMessage\": \"Game\"\n  },\n  \"AqGfF4\": {\n    \"defaultMessage\": \"Channel Creation\"\n  },\n  \"Aujn2T\": {\n    \"defaultMessage\": \"Count\"\n  },\n  \"Awq32I\": {\n    \"defaultMessage\": \"Push notifications\"\n  },\n  \"AxDOiG\": {\n    \"defaultMessage\": \"Months\"\n  },\n  \"AyGauy\": {\n    \"defaultMessage\": \"Login\"\n  },\n  \"Ayx8rG\": {\n    \"defaultMessage\": \"Curated Publication Index\"\n  },\n  \"B2Cjgu\": {\n    \"defaultMessage\": \"Buy Nostr Address\"\n  },\n  \"B4C47Y\": {\n    \"defaultMessage\": \"name too short\"\n  },\n  \"B6+XJy\": {\n    \"defaultMessage\": \"zapped\"\n  },\n  \"B6H7eJ\": {\n    \"defaultMessage\": \"nsec, npub, nip-05, hex\"\n  },\n  \"B7wvUM\": {\n    \"defaultMessage\": \"You can add a single or multiple relays, one per line.\"\n  },\n  \"BGGacK\": {\n    \"defaultMessage\": \"AI Embeddings / Vector lists\"\n  },\n  \"BQW4gi\": {\n    \"defaultMessage\": \"Relay-based Groups\"\n  },\n  \"BWpuKl\": {\n    \"defaultMessage\": \"Update\"\n  },\n  \"Bb19fh\": {\n    \"defaultMessage\": \"Posts by users that you are not following directly, but your follows are following them.\"\n  },\n  \"BfuAQ5\": {\n    \"defaultMessage\": \"Marketplace UI/UX\"\n  },\n  \"Blxcdx\": {\n    \"defaultMessage\": \"Relay\",\n    \"description\": \"Relay name (URL)\"\n  },\n  \"Bo+O//\": {\n    \"defaultMessage\": \"HTTP Auth\"\n  },\n  \"C1LjMx\": {\n    \"defaultMessage\": \"Lightning Donation\"\n  },\n  \"C6Lhhp\": {\n    \"defaultMessage\": \"Live Event\"\n  },\n  \"C7642/\": {\n    \"defaultMessage\": \"Quote Repost\"\n  },\n  \"C81/uG\": {\n    \"defaultMessage\": \"Logout\"\n  },\n  \"C8FsOr\": {\n    \"defaultMessage\": \"Popular Servers\"\n  },\n  \"C8HhVE\": {\n    \"defaultMessage\": \"Suggested Follows\"\n  },\n  \"CA1efg\": {\n    \"defaultMessage\": \"Video sets\"\n  },\n  \"CHTbO3\": {\n    \"defaultMessage\": \"Failed to load invoice\"\n  },\n  \"CI0LCO\": {\n    \"defaultMessage\": \"Has images but no r tags\"\n  },\n  \"CJ0biq\": {\n    \"defaultMessage\": \"Poll Response\"\n  },\n  \"CJx5Nd\": {\n    \"defaultMessage\": \"Profile Zaps\"\n  },\n  \"CM+Cfj\": {\n    \"defaultMessage\": \"Follow List\"\n  },\n  \"CM0k0d\": {\n    \"defaultMessage\": \"Prune follow list\"\n  },\n  \"CSOaM+\": {\n    \"defaultMessage\": \"{note_type} by {name}{title}\"\n  },\n  \"CVWeJ6\": {\n    \"defaultMessage\": \"Trending People\"\n  },\n  \"CYkOCI\": {\n    \"defaultMessage\": \"and {count} others you follow\"\n  },\n  \"CaZ1xw\": {\n    \"defaultMessage\": \"Alt tag starts with \\\"A short note: \\\"\"\n  },\n  \"CcqOwX\": {\n    \"defaultMessage\": \"Follow Lists\"\n  },\n  \"Cdxwi0\": {\n    \"defaultMessage\": \"Repository announcements\"\n  },\n  \"CmZ9ls\": {\n    \"defaultMessage\": \"{n} Muted\"\n  },\n  \"Coy6SH\": {\n    \"defaultMessage\": \"Calendar\"\n  },\n  \"CsCUYo\": {\n    \"defaultMessage\": \"{n} sats\"\n  },\n  \"Cu/K85\": {\n    \"defaultMessage\": \"Translated from {lang}\"\n  },\n  \"CzHZoc\": {\n    \"defaultMessage\": \"Social Graph\"\n  },\n  \"D++Njw\": {\n    \"defaultMessage\": \"Text Note References\"\n  },\n  \"D+KzKd\": {\n    \"defaultMessage\": \"Automatically zap every note when loaded\"\n  },\n  \"D09wbg\": {\n    \"defaultMessage\": \"Badge Definition\"\n  },\n  \"D3idYv\": {\n    \"defaultMessage\": \"Settings\"\n  },\n  \"D9xTLE\": {\n    \"defaultMessage\": \"Channel Hide Message\"\n  },\n  \"DBiVK1\": {\n    \"defaultMessage\": \"Cache\"\n  },\n  \"DKnriN\": {\n    \"defaultMessage\": \"Send sats\"\n  },\n  \"DZzCem\": {\n    \"defaultMessage\": \"Show latest {n} notes\"\n  },\n  \"Dh3hbq\": {\n    \"defaultMessage\": \"Auto Zap\"\n  },\n  \"Dn82AL\": {\n    \"defaultMessage\": \"Live\"\n  },\n  \"DqUmXt\": {\n    \"defaultMessage\": \"Product sold as an auction\"\n  },\n  \"DrZqav\": {\n    \"defaultMessage\": \"About must be less than {limit} characters\"\n  },\n  \"DtYelJ\": {\n    \"defaultMessage\": \"Transfer\"\n  },\n  \"Dx4ey3\": {\n    \"defaultMessage\": \"Toggle all\"\n  },\n  \"E3oB+t\": {\n    \"defaultMessage\": \"Browser\"\n  },\n  \"E5ZIPD\": {\n    \"defaultMessage\": \"<big>{amount}</big> <small>sats</small>\"\n  },\n  \"EHqHsu\": {\n    \"defaultMessage\": \"Invoice / Lightning Address\"\n  },\n  \"EJbFi7\": {\n    \"defaultMessage\": \"Search notes\"\n  },\n  \"ELbg9p\": {\n    \"defaultMessage\": \"Data Providers\"\n  },\n  \"EQKRE4\": {\n    \"defaultMessage\": \"Show badges on profile pages\"\n  },\n  \"EW5L+2\": {\n    \"defaultMessage\": \"Select Provider\"\n  },\n  \"EWeVrH\": {\n    \"defaultMessage\": \"Reaction to a website\"\n  },\n  \"EWyQH5\": {\n    \"defaultMessage\": \"Global\"\n  },\n  \"Ebl/B2\": {\n    \"defaultMessage\": \"Translate to {lang}\"\n  },\n  \"Ec+xLY\": {\n    \"defaultMessage\": \"Curation sets\"\n  },\n  \"EcZF24\": {\n    \"defaultMessage\": \"Custom Relays\"\n  },\n  \"EcglP9\": {\n    \"defaultMessage\": \"Key\"\n  },\n  \"EjFyoR\": {\n    \"defaultMessage\": \"On-chain Donation Address\"\n  },\n  \"EnCOBJ\": {\n    \"defaultMessage\": \"Buy\"\n  },\n  \"EsHX35\": {\n    \"defaultMessage\": \"Sorry, we dont understand this event kind ({name}), please try one of the following apps instead!\"\n  },\n  \"F/6VqP\": {\n    \"defaultMessage\": \"Server\"\n  },\n  \"F3l7xL\": {\n    \"defaultMessage\": \"Add Account\"\n  },\n  \"F4eJ/3\": {\n    \"defaultMessage\": \"Classified Listings\"\n  },\n  \"FDguSC\": {\n    \"defaultMessage\": \"{n} Zaps\"\n  },\n  \"FHWpHC\": {\n    \"defaultMessage\": \"Wallet Response\"\n  },\n  \"FHvSk3\": {\n    \"defaultMessage\": \"Authentication of clients to relays\"\n  },\n  \"FMfjrl\": {\n    \"defaultMessage\": \"Show status messages on profile pages\"\n  },\n  \"FSYL8G\": {\n    \"defaultMessage\": \"Trending Users\"\n  },\n  \"FWJR1B\": {\n    \"defaultMessage\": \"User groups\"\n  },\n  \"FcNSft\": {\n    \"defaultMessage\": \"Redirect issues HTTP redirect to the supplied lightning address\"\n  },\n  \"FdhSU2\": {\n    \"defaultMessage\": \"Claim Now\"\n  },\n  \"FfYsOb\": {\n    \"defaultMessage\": \"An error has occured!\"\n  },\n  \"FmXUJg\": {\n    \"defaultMessage\": \"follows you\"\n  },\n  \"FvanT6\": {\n    \"defaultMessage\": \"Accounts\"\n  },\n  \"FvzcUF\": {\n    \"defaultMessage\": \"👋 Welcome to AI Chat!\"\n  },\n  \"FzbSGg\": {\n    \"defaultMessage\": \"You dont have any media servers, try adding some.\"\n  },\n  \"G/yZLu\": {\n    \"defaultMessage\": \"Remove\"\n  },\n  \"G1BGCg\": {\n    \"defaultMessage\": \"Select Wallet\"\n  },\n  \"G3A56c\": {\n    \"defaultMessage\": \"Subscribed to Push\"\n  },\n  \"GFOoEE\": {\n    \"defaultMessage\": \"Salt\"\n  },\n  \"GIqktu\": {\n    \"defaultMessage\": \"Supported NIPs\"\n  },\n  \"GL8aXW\": {\n    \"defaultMessage\": \"Bookmarks ({n})\"\n  },\n  \"GLdw/8\": {\n    \"defaultMessage\": \"File Message\"\n  },\n  \"GQo+OV\": {\n    \"defaultMessage\": \"prompt reference\"\n  },\n  \"GSye7T\": {\n    \"defaultMessage\": \"Lightning Address\"\n  },\n  \"Gcn9NQ\": {\n    \"defaultMessage\": \"Magnet Link\"\n  },\n  \"GpkNYn\": {\n    \"defaultMessage\": \"Torrent\"\n  },\n  \"GqKcVm\": {\n    \"defaultMessage\": \"App curation sets\"\n  },\n  \"GqQeu/\": {\n    \"defaultMessage\": \"Invalid Lightning Address\"\n  },\n  \"GrDnue\": {\n    \"defaultMessage\": \"Nutzap Mint Recommendation\"\n  },\n  \"GspYR7\": {\n    \"defaultMessage\": \"{n} Dislike\"\n  },\n  \"GtIxzZ\": {\n    \"defaultMessage\": \"via {client}\",\n    \"description\": \"via {client name} tag\"\n  },\n  \"Gxcr08\": {\n    \"defaultMessage\": \"Broadcast Event\"\n  },\n  \"H+vHiz\": {\n    \"defaultMessage\": \"Hex Key..\",\n    \"description\": \"Hexidecimal 'key' input for improxy\"\n  },\n  \"H/oroO\": {\n    \"defaultMessage\": \"Dealing with Unknown Events\"\n  },\n  \"H0JBH6\": {\n    \"defaultMessage\": \"Log Out\"\n  },\n  \"H0OG3T\": {\n    \"defaultMessage\": \"Leader Info\"\n  },\n  \"H1GTaC\": {\n    \"defaultMessage\": \"Bookmark list\"\n  },\n  \"H6/kLh\": {\n    \"defaultMessage\": \"Order Paid!\"\n  },\n  \"HAlOn1\": {\n    \"defaultMessage\": \"Name\"\n  },\n  \"HCUGGO\": {\n    \"defaultMessage\": \"DVM suggested users to follow.\"\n  },\n  \"HFls6j\": {\n    \"defaultMessage\": \"name will be available later\"\n  },\n  \"HOzFdo\": {\n    \"defaultMessage\": \"Muted\"\n  },\n  \"HWbkEK\": {\n    \"defaultMessage\": \"Clear cache and reload\"\n  },\n  \"HbefNb\": {\n    \"defaultMessage\": \"Open Wallet\"\n  },\n  \"HhcAVH\": {\n    \"defaultMessage\": \"You don't follow this person, click here to load media from <i>{link}</i>, or update <a><i>your preferences</i></a> to always load media from everybody.\"\n  },\n  \"HirEqa\": {\n    \"defaultMessage\": \"Leave empty to use default model from agent service\"\n  },\n  \"HpAmQZ\": {\n    \"defaultMessage\": \"Relay reviews\"\n  },\n  \"HqOhtW\": {\n    \"defaultMessage\": \"No DVM providers found\"\n  },\n  \"HqRNN8\": {\n    \"defaultMessage\": \"Support\"\n  },\n  \"Hqo/rL\": {\n    \"defaultMessage\": \"Curated Publication Content\"\n  },\n  \"HzSFeV\": {\n    \"defaultMessage\": \"Expiration Timestamp\"\n  },\n  \"I0tYZf\": {\n    \"defaultMessage\": \"Create or update a stall\"\n  },\n  \"I1AoOu\": {\n    \"defaultMessage\": \"Last post {time}\"\n  },\n  \"IEwZvs\": {\n    \"defaultMessage\": \"Are you sure you want to unpin this note?\"\n  },\n  \"IIOul1\": {\n    \"defaultMessage\": \"Account Data\"\n  },\n  \"IKKHqV\": {\n    \"defaultMessage\": \"Follows\"\n  },\n  \"IOu4Xh\": {\n    \"defaultMessage\": \"You must be a {tier} subscriber to access {app} deck\"\n  },\n  \"IVbtTS\": {\n    \"defaultMessage\": \"Zap all {n} sats\"\n  },\n  \"IWz1ta\": {\n    \"defaultMessage\": \"Auto Translate\"\n  },\n  \"Ig9/a1\": {\n    \"defaultMessage\": \"Sent {n} sats to {name}\"\n  },\n  \"IgsWFG\": {\n    \"defaultMessage\": \"Not followed by anyone you follow\"\n  },\n  \"IoQq+a\": {\n    \"defaultMessage\": \"Click here to load anyway\"\n  },\n  \"IvjoDS\": {\n    \"defaultMessage\": \"Connected\"\n  },\n  \"Ix8l+B\": {\n    \"defaultMessage\": \"Trending Notes\"\n  },\n  \"J+dIsA\": {\n    \"defaultMessage\": \"Subscriptions\"\n  },\n  \"J1iLmb\": {\n    \"defaultMessage\": \"Notifications Not Allowed\"\n  },\n  \"J2HeQ+\": {\n    \"defaultMessage\": \"Use commas to separate words e.g. word1, word2, word3\"\n  },\n  \"J2Q92B\": {\n    \"defaultMessage\": \"Emoji sets\"\n  },\n  \"JCOqRK\": {\n    \"defaultMessage\": \"P-tag with non-standard marker (nickname)\"\n  },\n  \"JGrt9q\": {\n    \"defaultMessage\": \"Send sats to {name}\"\n  },\n  \"JHEHCk\": {\n    \"defaultMessage\": \"Zaps ({n})\"\n  },\n  \"JIVWWA\": {\n    \"defaultMessage\": \"Sport\"\n  },\n  \"JJNc3c\": {\n    \"defaultMessage\": \"Previous\"\n  },\n  \"JPFYIM\": {\n    \"defaultMessage\": \"No lightning address\"\n  },\n  \"JSx7y9\": {\n    \"defaultMessage\": \"Subscribe to {site_name} {plan} for {price} and receive the following rewards\"\n  },\n  \"JeoS4y\": {\n    \"defaultMessage\": \"Repost\"\n  },\n  \"Jh5zKH\": {\n    \"defaultMessage\": \"Search relays list\"\n  },\n  \"JjGgXI\": {\n    \"defaultMessage\": \"Search users\"\n  },\n  \"JkLHGw\": {\n    \"defaultMessage\": \"Website\"\n  },\n  \"JmcxzF\": {\n    \"defaultMessage\": \"Relays are servers you connect to for sending and receiving events. Aim for 4-8 relays.\"\n  },\n  \"JymXbw\": {\n    \"defaultMessage\": \"Private Key\"\n  },\n  \"K3r6DQ\": {\n    \"defaultMessage\": \"Delete\"\n  },\n  \"K7AkdL\": {\n    \"defaultMessage\": \"Show\"\n  },\n  \"K9zklU\": {\n    \"defaultMessage\": \"External Content IDs\"\n  },\n  \"KAhAcM\": {\n    \"defaultMessage\": \"Enter LNDHub config\"\n  },\n  \"KGmQjH\": {\n    \"defaultMessage\": \"Highlights\"\n  },\n  \"KJryGq\": {\n    \"defaultMessage\": \"Live Chat Message\"\n  },\n  \"KN7zKn\": {\n    \"defaultMessage\": \"Error\"\n  },\n  \"KQvWvD\": {\n    \"defaultMessage\": \"Deleted\"\n  },\n  \"KT9nox\": {\n    \"defaultMessage\": \"Protected Events\"\n  },\n  \"KahimY\": {\n    \"defaultMessage\": \"Unknown event kind: {kind}\"\n  },\n  \"KipVeG\": {\n    \"defaultMessage\": \"Mapping Nostr keys to DNS-based internet identifiers\"\n  },\n  \"KtsyO0\": {\n    \"defaultMessage\": \"Enter Pin\"\n  },\n  \"KyRp/q\": {\n    \"defaultMessage\": \"Wallet Request\"\n  },\n  \"LBAnc7\": {\n    \"defaultMessage\": \"View as user?\"\n  },\n  \"LEmxc8\": {\n    \"defaultMessage\": \"Zap Goals\"\n  },\n  \"LKw/ue\": {\n    \"defaultMessage\": \"Check out the code {link}\"\n  },\n  \"LPw/EW\": {\n    \"defaultMessage\": \"Nostr address' use the <a>NIP-05</a> specification which is a DNS based verification spec which helps to validate you as a real user.\"\n  },\n  \"LR1XjT\": {\n    \"defaultMessage\": \"Pin too short\"\n  },\n  \"LXxsbk\": {\n    \"defaultMessage\": \"Anonymous\"\n  },\n  \"LgbKvU\": {\n    \"defaultMessage\": \"Comment\"\n  },\n  \"LhLvRx\": {\n    \"defaultMessage\": \"Name must be between 8 and 15 characters\"\n  },\n  \"LmdPXO\": {\n    \"defaultMessage\": \"Cannot verify Nostr Address\"\n  },\n  \"Lu5/Bj\": {\n    \"defaultMessage\": \"Open on Zapstr\"\n  },\n  \"LuDBLj\": {\n    \"defaultMessage\": \"Torrents\"\n  },\n  \"Lw+I+J\": {\n    \"defaultMessage\": \"{n,plural,=0{{name} zapped} other{{name} & {n} others zapped}}\"\n  },\n  \"LwYmVi\": {\n    \"defaultMessage\": \"Zaps on this note will be split to the following users.\"\n  },\n  \"M3Oirc\": {\n    \"defaultMessage\": \"Debug Menus\"\n  },\n  \"M6C/px\": {\n    \"defaultMessage\": \"Become a leader\"\n  },\n  \"MBAYRO\": {\n    \"defaultMessage\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n  },\n  \"MF9ke5\": {\n    \"defaultMessage\": \"{size} bytes ({kb} KB)\"\n  },\n  \"MI2jkA\": {\n    \"defaultMessage\": \"Not available:\"\n  },\n  \"MKDHEa\": {\n    \"defaultMessage\": \"Join Room\"\n  },\n  \"MP54GY\": {\n    \"defaultMessage\": \"Wallet password\",\n    \"description\": \"Wallet password input placeholder\"\n  },\n  \"MWTx65\": {\n    \"defaultMessage\": \"Default Page\"\n  },\n  \"MYBYdJ\": {\n    \"defaultMessage\": \"Short Text Note\"\n  },\n  \"MYUBaG\": {\n    \"defaultMessage\": \"Client Authentication\"\n  },\n  \"MkQ4FX\": {\n    \"defaultMessage\": \"Proxy Tags\"\n  },\n  \"Ml7+RS\": {\n    \"defaultMessage\": \"Send this link to your friends and share the magic of the nostr.\"\n  },\n  \"Mrpkot\": {\n    \"defaultMessage\": \"Pay for subscription\"\n  },\n  \"MuVeKe\": {\n    \"defaultMessage\": \"Buy nostr address\"\n  },\n  \"Muhna4\": {\n    \"defaultMessage\": \"Counting results\"\n  },\n  \"MzRYWH\": {\n    \"defaultMessage\": \"Buying {item}\"\n  },\n  \"N2IrpM\": {\n    \"defaultMessage\": \"Confirm\"\n  },\n  \"NAidKb\": {\n    \"defaultMessage\": \"Notifications\"\n  },\n  \"NAuFNH\": {\n    \"defaultMessage\": \"You already have a subscription of this type, please renew or pay\"\n  },\n  \"NDTFsp\": {\n    \"defaultMessage\": \"Job Feedback\"\n  },\n  \"NepkXH\": {\n    \"defaultMessage\": \"Can't vote with {amount} sats, please set a different default zap amount\"\n  },\n  \"NndBJE\": {\n    \"defaultMessage\": \"New users page\"\n  },\n  \"Nr9Yyx\": {\n    \"defaultMessage\": \"Reposts\"\n  },\n  \"Nw1A4y\": {\n    \"defaultMessage\": \"Content ends with double newline\"\n  },\n  \"NxzeNU\": {\n    \"defaultMessage\": \"Dead\"\n  },\n  \"O3Jz4E\": {\n    \"defaultMessage\": \"Use your invite code to earn sats!\"\n  },\n  \"OEW7yJ\": {\n    \"defaultMessage\": \"Zaps\"\n  },\n  \"OIqnZN\": {\n    \"defaultMessage\": \"OpenTimestamps Attestations for Events\"\n  },\n  \"OJHKIL\": {\n    \"defaultMessage\": \"Gift Wrap\"\n  },\n  \"OKhRC6\": {\n    \"defaultMessage\": \"Share\"\n  },\n  \"OLEm6z\": {\n    \"defaultMessage\": \"Unknown login error\"\n  },\n  \"OQSOJF\": {\n    \"defaultMessage\": \"Get a free nostr address\"\n  },\n  \"OQXnew\": {\n    \"defaultMessage\": \"You subscription is still active, you can't renew yet\"\n  },\n  \"ORGv1Q\": {\n    \"defaultMessage\": \"Created\"\n  },\n  \"ORa81+\": {\n    \"defaultMessage\": \"Merge Requests\"\n  },\n  \"OuProE\": {\n    \"defaultMessage\": \"Long-form Content\"\n  },\n  \"OxPdQ0\": {\n    \"defaultMessage\": \"Scanning {date}\"\n  },\n  \"P2o+ZZ\": {\n    \"defaultMessage\": \"Invalid Nostr Address\"\n  },\n  \"P61BTu\": {\n    \"defaultMessage\": \"Copy Event JSON\"\n  },\n  \"P7FD0F\": {\n    \"defaultMessage\": \"System (Default)\"\n  },\n  \"P7nJT9\": {\n    \"defaultMessage\": \"Total today (UTC): {amount} sats\"\n  },\n  \"P8JC58\": {\n    \"defaultMessage\": \"Distance\"\n  },\n  \"P8zI6H\": {\n    \"defaultMessage\": \"Slide Set\"\n  },\n  \"PCSt5T\": {\n    \"defaultMessage\": \"Preferences\"\n  },\n  \"PJLVAh\": {\n    \"defaultMessage\": \"Invalid cashu token\"\n  },\n  \"PXQ0z0\": {\n    \"defaultMessage\": \"Receiving to <b>{wallet}</b>\"\n  },\n  \"PYo9HP\": {\n    \"defaultMessage\": \"Events Breakdown\"\n  },\n  \"PamNxw\": {\n    \"defaultMessage\": \"Unknown file header: {name}\"\n  },\n  \"Pe0ogR\": {\n    \"defaultMessage\": \"Theme\"\n  },\n  \"PlfdcA\": {\n    \"defaultMessage\": \"Ask {appName} AI\"\n  },\n  \"PrsIg7\": {\n    \"defaultMessage\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n  },\n  \"QDFTjG\": {\n    \"defaultMessage\": \"{n} Relays\"\n  },\n  \"QGVI63\": {\n    \"defaultMessage\": \"Agent\"\n  },\n  \"QJfhKt\": {\n    \"defaultMessage\": \"The private key is like a password, but it cannot be reset. Guard it carefully and never show it to anyone. Once someone has your private key, they will have access to your account forever.\"\n  },\n  \"QW5bRH\": {\n    \"defaultMessage\": \"Blossom Blob Debug Info\"\n  },\n  \"QWhotP\": {\n    \"defaultMessage\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n  },\n  \"QpaLA3\": {\n    \"defaultMessage\": \"Channel Message\"\n  },\n  \"Qxv0B2\": {\n    \"defaultMessage\": \"You currently have {number} sats in your zap pool.\"\n  },\n  \"Qy6/Ft\": {\n    \"defaultMessage\": \"Private Direct Messages\"\n  },\n  \"R/6nsx\": {\n    \"defaultMessage\": \"Subscription\"\n  },\n  \"R7x0mX\": {\n    \"defaultMessage\": \"Chat Message\"\n  },\n  \"R81upa\": {\n    \"defaultMessage\": \"People you follow\"\n  },\n  \"RDha9y\": {\n    \"defaultMessage\": \"Service Worker Not Running\"\n  },\n  \"RRz1cA\": {\n    \"defaultMessage\": \"Repository state announcements\"\n  },\n  \"RSr2uB\": {\n    \"defaultMessage\": \"Username must only contain lowercase letters and numbers\"\n  },\n  \"RahCRH\": {\n    \"defaultMessage\": \"Expired\"\n  },\n  \"RefZpK\": {\n    \"defaultMessage\": \"Short-form Portrait Video Event\"\n  },\n  \"RfhLwC\": {\n    \"defaultMessage\": \"By: {author}\"\n  },\n  \"RgEsTx\": {\n    \"defaultMessage\": \"Write access to {app} relay, with 1 year of event retention\"\n  },\n  \"RhDAoS\": {\n    \"defaultMessage\": \"Are you sure you want to delete {id}\"\n  },\n  \"RmxSZo\": {\n    \"defaultMessage\": \"Data Vending Machines\"\n  },\n  \"RoOyAh\": {\n    \"defaultMessage\": \"Relays\"\n  },\n  \"RrUIfX\": {\n    \"defaultMessage\": \"Downloadable backups from {app} relay\"\n  },\n  \"Rs4kCE\": {\n    \"defaultMessage\": \"Bookmark\"\n  },\n  \"S/NV2G\": {\n    \"defaultMessage\": \"Loading note: {id}\"\n  },\n  \"SFuk1v\": {\n    \"defaultMessage\": \"Permissions\"\n  },\n  \"SLZGPn\": {\n    \"defaultMessage\": \"Enter a pin to encrypt your private key, you must enter this pin every time you open {site}.\"\n  },\n  \"SOqbe9\": {\n    \"defaultMessage\": \"Update Lightning Address\"\n  },\n  \"SP0+yi\": {\n    \"defaultMessage\": \"Buy Subscription\"\n  },\n  \"SW3TFA\": {\n    \"defaultMessage\": \"Popular relays used by people you follow.\"\n  },\n  \"SYQtZ7\": {\n    \"defaultMessage\": \"LN Address Proxy\"\n  },\n  \"Sd0PKc\": {\n    \"defaultMessage\": \"Relay sets\"\n  },\n  \"SfwSIm\": {\n    \"defaultMessage\": \"Problem Tracker\"\n  },\n  \"ShdEie\": {\n    \"defaultMessage\": \"Mark all read\"\n  },\n  \"Sjo1P4\": {\n    \"defaultMessage\": \"Custom\"\n  },\n  \"SmuYUd\": {\n    \"defaultMessage\": \"What should we call you?\"\n  },\n  \"So+Y+A\": {\n    \"defaultMessage\": \"Nutzap\"\n  },\n  \"SopQOK\": {\n    \"defaultMessage\": \"Web bookmarks\"\n  },\n  \"Ss0sWu\": {\n    \"defaultMessage\": \"Pay Now\"\n  },\n  \"SsUQnC\": {\n    \"defaultMessage\": \"Application-specific Data\"\n  },\n  \"StKzTE\": {\n    \"defaultMessage\": \"The author has marked this note as a <i>sensitive topic</i>\"\n  },\n  \"T83nqf\": {\n    \"defaultMessage\": \"Relays close to your geographic location.\"\n  },\n  \"TDR5ge\": {\n    \"defaultMessage\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n  },\n  \"TGc5nI\": {\n    \"defaultMessage\": \"Handler information\"\n  },\n  \"TH1fFo\": {\n    \"defaultMessage\": \"Telegram\"\n  },\n  \"TJo5E6\": {\n    \"defaultMessage\": \"Preview\"\n  },\n  \"TOG64f\": {\n    \"defaultMessage\": \"Use Local Relay\"\n  },\n  \"TP/cMX\": {\n    \"defaultMessage\": \"Ended\"\n  },\n  \"TaeBqw\": {\n    \"defaultMessage\": \"Sign in with Nostr Extension\"\n  },\n  \"TdTXXf\": {\n    \"defaultMessage\": \"Learn more\"\n  },\n  \"TdtZQ5\": {\n    \"defaultMessage\": \"Crypto\"\n  },\n  \"Tdv6NY\": {\n    \"defaultMessage\": \"Interest sets\"\n  },\n  \"TgDKhI\": {\n    \"defaultMessage\": \"Calendar Events\"\n  },\n  \"TpgeGw\": {\n    \"defaultMessage\": \"Hex Salt..\",\n    \"description\": \"Hexidecimal 'salt' input for imgproxy\"\n  },\n  \"Tpy00S\": {\n    \"defaultMessage\": \"People\"\n  },\n  \"TvwmZr\": {\n    \"defaultMessage\": \"Hash\"\n  },\n  \"TwyMau\": {\n    \"defaultMessage\": \"Account\"\n  },\n  \"TzA+w1\": {\n    \"defaultMessage\": \"Followed By Friends\"\n  },\n  \"U/fbvs\": {\n    \"defaultMessage\": \"Git Replies (deprecated)\"\n  },\n  \"U1aPPi\": {\n    \"defaultMessage\": \"Stop listening\"\n  },\n  \"U30H69\": {\n    \"defaultMessage\": \"Community Definition\"\n  },\n  \"U3P+36\": {\n    \"defaultMessage\": \"Has both r tags and imeta tags for images\"\n  },\n  \"UJTWqI\": {\n    \"defaultMessage\": \"Remove from my relays\"\n  },\n  \"ULXFfP\": {\n    \"defaultMessage\": \"Receive\"\n  },\n  \"ULsJTk\": {\n    \"defaultMessage\": \"Published by\"\n  },\n  \"UNjfWJ\": {\n    \"defaultMessage\": \"Check all event signatures received from relays\"\n  },\n  \"UT7Nkj\": {\n    \"defaultMessage\": \"New Chat\"\n  },\n  \"UUPFlt\": {\n    \"defaultMessage\": \"Users must accept the content warning to show the content of your note.\"\n  },\n  \"UaCh1c\": {\n    \"defaultMessage\": \"Add Server\"\n  },\n  \"Ub+AGc\": {\n    \"defaultMessage\": \"Sign In\"\n  },\n  \"Up5U7K\": {\n    \"defaultMessage\": \"Block\"\n  },\n  \"Ups2/p\": {\n    \"defaultMessage\": \"Your application is pending\"\n  },\n  \"UsCzPc\": {\n    \"defaultMessage\": \"Share a personalized invitation with friends!\"\n  },\n  \"UxgyeY\": {\n    \"defaultMessage\": \"Your referral code is {code}\"\n  },\n  \"UxkETt\": {\n    \"defaultMessage\": \"Show Thread Data\"\n  },\n  \"V20Og0\": {\n    \"defaultMessage\": \"Labeling\"\n  },\n  \"V2dZY9\": {\n    \"defaultMessage\": \"{n,plural,=1{& {n} other} other{& {n} others}}\"\n  },\n  \"V93INS\": {\n    \"defaultMessage\": \"<dark>Created by</dark> {name}\"\n  },\n  \"VOjC1i\": {\n    \"defaultMessage\": \"Pick which upload service you want to upload attachments to\"\n  },\n  \"VR5eHw\": {\n    \"defaultMessage\": \"Public key (npub/nprofile)\"\n  },\n  \"VZzKYK\": {\n    \"defaultMessage\": \"Client Fingerprint\"\n  },\n  \"VfhYxG\": {\n    \"defaultMessage\": \"To see a full list of changes you can view the changelog {here}\"\n  },\n  \"VlJkSk\": {\n    \"defaultMessage\": \"{n} muted\"\n  },\n  \"VnXp8Z\": {\n    \"defaultMessage\": \"Avatar\"\n  },\n  \"W1yoZY\": {\n    \"defaultMessage\": \"It looks like you dont have any subscriptions, you can get one {link}\"\n  },\n  \"W2PiAr\": {\n    \"defaultMessage\": \"{n} Blocked\"\n  },\n  \"W4SaxY\": {\n    \"defaultMessage\": \"Local\"\n  },\n  \"W9355R\": {\n    \"defaultMessage\": \"Unmute\"\n  },\n  \"WTrOy3\": {\n    \"defaultMessage\": \"Chat\"\n  },\n  \"WeLEuL\": {\n    \"defaultMessage\": \"From Server\"\n  },\n  \"WfYjW2\": {\n    \"defaultMessage\": \"Upload Banner\"\n  },\n  \"Wj5TbN\": {\n    \"defaultMessage\": \"Issues\"\n  },\n  \"WmZhfL\": {\n    \"defaultMessage\": \"Automatically translate notes to your local language\"\n  },\n  \"WvGmZT\": {\n    \"defaultMessage\": \"npub / nprofile / nostr address\"\n  },\n  \"X1TTm3\": {\n    \"defaultMessage\": \"Single newline only before image URLs\"\n  },\n  \"X6tipZ\": {\n    \"defaultMessage\": \"Sign in with key\"\n  },\n  \"X7xU8J\": {\n    \"defaultMessage\": \"nsec, npub, nip-05, hex, mnemonic\"\n  },\n  \"XECMfW\": {\n    \"defaultMessage\": \"Send usage metrics\"\n  },\n  \"XICsE8\": {\n    \"defaultMessage\": \"File hosts\"\n  },\n  \"XPB8VV\": {\n    \"defaultMessage\": \"Alby wallet connection\"\n  },\n  \"XQiFEl\": {\n    \"defaultMessage\": \"Follows Relay Health\"\n  },\n  \"XSdWHA\": {\n    \"defaultMessage\": \"Redeem\"\n  },\n  \"XXm7jJ\": {\n    \"defaultMessage\": \"Trending Hashtags\"\n  },\n  \"XgWvGA\": {\n    \"defaultMessage\": \"Reactions\"\n  },\n  \"Xnimz0\": {\n    \"defaultMessage\": \"Sending from <b>{wallet}</b>\"\n  },\n  \"Xopqkl\": {\n    \"defaultMessage\": \"Your default zap amount is {number} sats, example values are calculated from this.\"\n  },\n  \"YDMrKK\": {\n    \"defaultMessage\": \"Users\"\n  },\n  \"YDURw6\": {\n    \"defaultMessage\": \"Service URL\"\n  },\n  \"YH2RKk\": {\n    \"defaultMessage\": \"Popular media servers.\"\n  },\n  \"YLGfQn\": {\n    \"defaultMessage\": \"Write message\"\n  },\n  \"YQZY/S\": {\n    \"defaultMessage\": \"It looks like you dont follow enough people, take a look at {newUsersPage} to discover people to follow!\"\n  },\n  \"YR2I9M\": {\n    \"defaultMessage\": \"No keys, no {app}, There is no way to reset it if you don't back up. It only takes a minute.\"\n  },\n  \"YU7ZYp\": {\n    \"defaultMessage\": \"Public Chat\"\n  },\n  \"YXA3AH\": {\n    \"defaultMessage\": \"Enable reactions\"\n  },\n  \"YYUgme\": {\n    \"defaultMessage\": \"Badge Info\"\n  },\n  \"Yf3DwC\": {\n    \"defaultMessage\": \"Connect a wallet to send instant payments\"\n  },\n  \"YuoEb9\": {\n    \"defaultMessage\": \"Try another relay\"\n  },\n  \"Z48UEo\": {\n    \"defaultMessage\": \"Channel Metadata\"\n  },\n  \"Z7kkeJ\": {\n    \"defaultMessage\": \"Delegated Event Signing\"\n  },\n  \"ZFe9tl\": {\n    \"defaultMessage\": \"Compose a note\"\n  },\n  \"ZKORll\": {\n    \"defaultMessage\": \"Activate Now\"\n  },\n  \"ZLmyG9\": {\n    \"defaultMessage\": \"Contributors\"\n  },\n  \"ZS+jRE\": {\n    \"defaultMessage\": \"Send zap splits to\"\n  },\n  \"ZT17bG\": {\n    \"defaultMessage\": \"Cashu Wallet Tokens\"\n  },\n  \"ZlIh4/\": {\n    \"defaultMessage\": \"Encrypted Direct Messages\"\n  },\n  \"ZlmK/p\": {\n    \"defaultMessage\": \"{name} invited you to {app}\"\n  },\n  \"a1x4gD\": {\n    \"defaultMessage\": \"Media servers store media which you can share in notes as images and videos\"\n  },\n  \"a5UPxh\": {\n    \"defaultMessage\": \"Fund developers and platforms providing NIP-05 verification services\"\n  },\n  \"a7TDNm\": {\n    \"defaultMessage\": \"Notes will stream in real time into global and notes tab\"\n  },\n  \"aHje0o\": {\n    \"defaultMessage\": \"Name or nym\"\n  },\n  \"aMaLBK\": {\n    \"defaultMessage\": \"Supported Extensions\"\n  },\n  \"aRex7h\": {\n    \"defaultMessage\": \"Paid {amount} sats, fee {fee} sats\"\n  },\n  \"aWpBzj\": {\n    \"defaultMessage\": \"Show more\"\n  },\n  \"aYJIC7\": {\n    \"defaultMessage\": \"Zap Type:\"\n  },\n  \"abbGKq\": {\n    \"defaultMessage\": \"{n} km\"\n  },\n  \"af6Oxx\": {\n    \"defaultMessage\": \"Authors ({count})\"\n  },\n  \"agOXPD\": {\n    \"defaultMessage\": \"Size\"\n  },\n  \"ak3MTf\": {\n    \"defaultMessage\": \"Invite Friends\"\n  },\n  \"b12Goz\": {\n    \"defaultMessage\": \"Mnemonic\"\n  },\n  \"b5vAk0\": {\n    \"defaultMessage\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n  },\n  \"bF1MYT\": {\n    \"defaultMessage\": \"You are a community leader and are earning <b>{percent}</b> of referred users subscriptions!\"\n  },\n  \"bG00/W\": {\n    \"defaultMessage\": \"Service Worker Running\"\n  },\n  \"bJ+wrA\": {\n    \"defaultMessage\": \"Compute prune list\"\n  },\n  \"bLZL5a\": {\n    \"defaultMessage\": \"Get Address\"\n  },\n  \"bMphls\": {\n    \"defaultMessage\": \"Logged in with read-only access\"\n  },\n  \"bQdA2k\": {\n    \"defaultMessage\": \"Sensitive Content\"\n  },\n  \"bep9C3\": {\n    \"defaultMessage\": \"Public Key\"\n  },\n  \"bfvyfs\": {\n    \"defaultMessage\": \"Anon\"\n  },\n  \"bxv59V\": {\n    \"defaultMessage\": \"Just now\"\n  },\n  \"c+1p0i\": {\n    \"defaultMessage\": \"Kind mute sets\"\n  },\n  \"c2T+1B\": {\n    \"defaultMessage\": \"Redirects\"\n  },\n  \"c35bj2\": {\n    \"defaultMessage\": \"If you have an enquiry about your NIP-05 order please DM {link}\"\n  },\n  \"c3LlRO\": {\n    \"defaultMessage\": \"{n}KiB\"\n  },\n  \"c3g2hL\": {\n    \"defaultMessage\": \"Broadcast Again\"\n  },\n  \"c6BMLV\": {\n    \"defaultMessage\": \"Starter Pack\"\n  },\n  \"cE4Hfw\": {\n    \"defaultMessage\": \"Discover\"\n  },\n  \"cF3ruj\": {\n    \"defaultMessage\": \"Follow All\"\n  },\n  \"cFbU1B\": {\n    \"defaultMessage\": \"Using Alby? Go to {link} to get your NWC config!\"\n  },\n  \"cG/bKQ\": {\n    \"defaultMessage\": \"Native nostr wallet connection\"\n  },\n  \"cHCwbF\": {\n    \"defaultMessage\": \"Photography\"\n  },\n  \"cKbMRX\": {\n    \"defaultMessage\": \"Direct Message\"\n  },\n  \"cPIKU2\": {\n    \"defaultMessage\": \"Following\"\n  },\n  \"cQfLWb\": {\n    \"defaultMessage\": \"URL..\",\n    \"description\": \"Placeholder text for imgproxy url textbox\"\n  },\n  \"cVcgLJ\": {\n    \"defaultMessage\": \"Media Servers\"\n  },\n  \"cWx9t8\": {\n    \"defaultMessage\": \"Mute all\"\n  },\n  \"cg1VJ2\": {\n    \"defaultMessage\": \"Connect Wallet\"\n  },\n  \"cnwHgH\": {\n    \"defaultMessage\": \"OpenTimestamps\"\n  },\n  \"ctXnlV\": {\n    \"defaultMessage\": \"Zap amount:\"\n  },\n  \"cuP16y\": {\n    \"defaultMessage\": \"Multi account support\"\n  },\n  \"cuV2gK\": {\n    \"defaultMessage\": \"name is registered\"\n  },\n  \"cw1Ftc\": {\n    \"defaultMessage\": \"Live Activities\"\n  },\n  \"cyR7Kh\": {\n    \"defaultMessage\": \"Back\"\n  },\n  \"d+6YsV\": {\n    \"defaultMessage\": \"Lists to mute:\"\n  },\n  \"d0qim7\": {\n    \"defaultMessage\": \"WoT Filter\"\n  },\n  \"d2ebEu\": {\n    \"defaultMessage\": \"Not Subscribed to Push\"\n  },\n  \"d7d0/x\": {\n    \"defaultMessage\": \"LN Address\"\n  },\n  \"dK2CcV\": {\n    \"defaultMessage\": \"The public key is like your username, you can share it with anyone.\"\n  },\n  \"dOQCL8\": {\n    \"defaultMessage\": \"Display name\"\n  },\n  \"ddd3JX\": {\n    \"defaultMessage\": \"Popular Hashtags\"\n  },\n  \"djLctd\": {\n    \"defaultMessage\": \"Amount in sats\"\n  },\n  \"dmcsBA\": {\n    \"defaultMessage\": \"Classified Listing\"\n  },\n  \"dmsiLv\": {\n    \"defaultMessage\": \"A default Zap Pool split of {n} has been configured for {site} developers, you can disable it at any time in {link}\"\n  },\n  \"do3Om+\": {\n    \"defaultMessage\": \"Ask me anything...\"\n  },\n  \"e5x8FT\": {\n    \"defaultMessage\": \"Kind\"\n  },\n  \"e61Jf3\": {\n    \"defaultMessage\": \"Coming soon\"\n  },\n  \"e7VmYP\": {\n    \"defaultMessage\": \"Enter pin to unlock your private key\"\n  },\n  \"e7qqly\": {\n    \"defaultMessage\": \"Mark All Read\"\n  },\n  \"eF0Re7\": {\n    \"defaultMessage\": \"Use a nostr signer extension to sign in\"\n  },\n  \"eHAneD\": {\n    \"defaultMessage\": \"Reaction emoji\"\n  },\n  \"eJj8HD\": {\n    \"defaultMessage\": \"Get Verified\"\n  },\n  \"eSzf2G\": {\n    \"defaultMessage\": \"A single zap of {nIn} sats will allocate {nOut} sats to the zap pool.\"\n  },\n  \"eW/Bj9\": {\n    \"defaultMessage\": \"Feed\"\n  },\n  \"eXT2QQ\": {\n    \"defaultMessage\": \"Group Chat\"\n  },\n  \"eZtOxB\": {\n    \"defaultMessage\": \"window.nostr capability for web browsers\"\n  },\n  \"egib+2\": {\n    \"defaultMessage\": \"{n,plural,=1{& {n} other} other{& {n} others}}\"\n  },\n  \"ejEGdx\": {\n    \"defaultMessage\": \"Home\"\n  },\n  \"eoV49s\": {\n    \"defaultMessage\": \"Poor\"\n  },\n  \"f0Mcqr\": {\n    \"defaultMessage\": \"Double newlines before image URLs\"\n  },\n  \"f1OxTe\": {\n    \"defaultMessage\": \"Community leaders are individuals who grow the nostr ecosystem by being active in their local communities and helping onboard new users. Anyone can become a community leader, but few hold the current honorary title.\"\n  },\n  \"f2CAxA\": {\n    \"defaultMessage\": \"Dump\"\n  },\n  \"fB8U26\": {\n    \"defaultMessage\": \"{app} is an open source project built by passionate people in their free time, your donations are greatly appreciated\"\n  },\n  \"fBI91o\": {\n    \"defaultMessage\": \"Zap\"\n  },\n  \"fBlba3\": {\n    \"defaultMessage\": \"Thanks for using {site}, please consider donating if you can.\"\n  },\n  \"fOksnD\": {\n    \"defaultMessage\": \"Can't vote because LNURL service does not support zaps\"\n  },\n  \"fQN+tq\": {\n    \"defaultMessage\": \"Show posts that have a content warning tag\"\n  },\n  \"fWZYP5\": {\n    \"defaultMessage\": \"Pinned\"\n  },\n  \"fX5RYm\": {\n    \"defaultMessage\": \"Pick a few topics of interest\"\n  },\n  \"filwqD\": {\n    \"defaultMessage\": \"Read\"\n  },\n  \"fjAcWo\": {\n    \"defaultMessage\": \"Gift Wraps\"\n  },\n  \"flnGvv\": {\n    \"defaultMessage\": \"What's on your mind?\"\n  },\n  \"fqwcJ1\": {\n    \"defaultMessage\": \"On-chain Donation\"\n  },\n  \"fr+XYA\": {\n    \"defaultMessage\": \"Lightning Pub RPC\"\n  },\n  \"fsB/4p\": {\n    \"defaultMessage\": \"Saved\"\n  },\n  \"fucxlm\": {\n    \"defaultMessage\": \"Attach Media\"\n  },\n  \"furjvW\": {\n    \"defaultMessage\": \"Watch Stream\"\n  },\n  \"g5pX+a\": {\n    \"defaultMessage\": \"About\"\n  },\n  \"g985Wp\": {\n    \"defaultMessage\": \"Failed to send vote\"\n  },\n  \"gDzDRs\": {\n    \"defaultMessage\": \"Emoji to send when reactiong to a note\"\n  },\n  \"gPxSgn\": {\n    \"defaultMessage\": \"Follow Sets\"\n  },\n  \"gQP3HJ\": {\n    \"defaultMessage\": \"Found {n} events!\"\n  },\n  \"gSqFQf\": {\n    \"defaultMessage\": \"Double newlines before quoted notes\"\n  },\n  \"gWDnbF\": {\n    \"defaultMessage\": \"Recent content that people you follow have reacted to.\"\n  },\n  \"gXgY3+\": {\n    \"defaultMessage\": \"Not all clients support this yet\"\n  },\n  \"gczcC5\": {\n    \"defaultMessage\": \"Subscribe\"\n  },\n  \"geppt8\": {\n    \"defaultMessage\": \"{count} ({count2} in memory)\"\n  },\n  \"gib7iq\": {\n    \"defaultMessage\": \"No handles found\"\n  },\n  \"gjBiyj\": {\n    \"defaultMessage\": \"Loading...\"\n  },\n  \"gkMmvC\": {\n    \"defaultMessage\": \"Android Signer Application\"\n  },\n  \"gl1NeW\": {\n    \"defaultMessage\": \"Lists\"\n  },\n  \"go2/QF\": {\n    \"defaultMessage\": \"User server list\"\n  },\n  \"grQ+mI\": {\n    \"defaultMessage\": \"Proof of Work\"\n  },\n  \"grRQTM\": {\n    \"defaultMessage\": \"{n} people\"\n  },\n  \"gtNjNP\": {\n    \"defaultMessage\": \"Basic protocol flow description\"\n  },\n  \"h1gtUi\": {\n    \"defaultMessage\": \"Poll\"\n  },\n  \"h3FJTU\": {\n    \"defaultMessage\": \"Not a thread!\"\n  },\n  \"h7jvCs\": {\n    \"defaultMessage\": \"{site} is more fun together!\"\n  },\n  \"h8XMJL\": {\n    \"defaultMessage\": \"Badges\"\n  },\n  \"h9M0rW\": {\n    \"defaultMessage\": \"User Metadata\"\n  },\n  \"hF6IN2\": {\n    \"defaultMessage\": \"Prune Follow List\"\n  },\n  \"hMQmIw\": {\n    \"defaultMessage\": \"Sync Account\"\n  },\n  \"hMzcSq\": {\n    \"defaultMessage\": \"Messages\"\n  },\n  \"hRTfTR\": {\n    \"defaultMessage\": \"PRO\"\n  },\n  \"hY4lzx\": {\n    \"defaultMessage\": \"Supports\"\n  },\n  \"hYOE+U\": {\n    \"defaultMessage\": \"Invite\"\n  },\n  \"hicxcO\": {\n    \"defaultMessage\": \"Show replies\"\n  },\n  \"hmZ3Bz\": {\n    \"defaultMessage\": \"Media\"\n  },\n  \"hniz8Z\": {\n    \"defaultMessage\": \"here\"\n  },\n  \"hv/eRj\": {\n    \"defaultMessage\": \"Blocked relays list\"\n  },\n  \"hvFRBo\": {\n    \"defaultMessage\": \"Interaction\"\n  },\n  \"i/dBAR\": {\n    \"defaultMessage\": \"Zap Pool\"\n  },\n  \"i5gBFz\": {\n    \"defaultMessage\": \"Your sent and received payments will show up here.\"\n  },\n  \"i8CwA4\": {\n    \"defaultMessage\": \"Extension\"\n  },\n  \"iCqGww\": {\n    \"defaultMessage\": \"Reactions ({n})\"\n  },\n  \"iEoXYx\": {\n    \"defaultMessage\": \"DeepL translations\"\n  },\n  \"iGT1eE\": {\n    \"defaultMessage\": \"Prevent fake accounts from imitating you\"\n  },\n  \"iHN12u\": {\n    \"defaultMessage\": \"Admin\"\n  },\n  \"iICVoL\": {\n    \"defaultMessage\": \"{x} follows ({y} duplicates)\"\n  },\n  \"iNWbVV\": {\n    \"defaultMessage\": \"Handle\"\n  },\n  \"iYc3Ld\": {\n    \"defaultMessage\": \"Payments\"\n  },\n  \"icCxlA\": {\n    \"defaultMessage\": \"new users page\"\n  },\n  \"ieGrWo\": {\n    \"defaultMessage\": \"Follow\"\n  },\n  \"igUUst\": {\n    \"defaultMessage\": \"Group Chat Threaded Reply\"\n  },\n  \"ipHVx5\": {\n    \"defaultMessage\": \"Generate Invoice\"\n  },\n  \"itPgxd\": {\n    \"defaultMessage\": \"Profile\"\n  },\n  \"ixpzZx\": {\n    \"defaultMessage\": \"{name} liked\"\n  },\n  \"izWS4J\": {\n    \"defaultMessage\": \"Unfollow\"\n  },\n  \"j9xbzF\": {\n    \"defaultMessage\": \"Already backed up\"\n  },\n  \"jA3OE/\": {\n    \"defaultMessage\": \"{n,plural,=1{{n} sat} other{{n} sats}}\"\n  },\n  \"jAmfGl\": {\n    \"defaultMessage\": \"Your {site_name} subscription is expired\"\n  },\n  \"jHa/ko\": {\n    \"defaultMessage\": \"Clean up your feed\"\n  },\n  \"jMzO1S\": {\n    \"defaultMessage\": \"Internal error: {msg}\"\n  },\n  \"jiAVXu\": {\n    \"defaultMessage\": \"Video Event\"\n  },\n  \"jvC7xj\": {\n    \"defaultMessage\": \"Ask me to post, reply, search, or help you navigate {appName}\"\n  },\n  \"jvo0vs\": {\n    \"defaultMessage\": \"Save\"\n  },\n  \"jzgQ2z\": {\n    \"defaultMessage\": \"{n} Reactions\"\n  },\n  \"k0kCJp\": {\n    \"defaultMessage\": \"Apply Now\"\n  },\n  \"k2veDA\": {\n    \"defaultMessage\": \"Write\"\n  },\n  \"k7sKNy\": {\n    \"defaultMessage\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n  },\n  \"kJYo0u\": {\n    \"defaultMessage\": \"{n,plural,=0{{name} reposted} other{{name} & {n} others reposted}}\"\n  },\n  \"kKC9ya\": {\n    \"defaultMessage\": \"Wallet Info\"\n  },\n  \"kNd2FL\": {\n    \"defaultMessage\": \"Tidal login\"\n  },\n  \"kQAf2d\": {\n    \"defaultMessage\": \"Select\"\n  },\n  \"kaaf1E\": {\n    \"defaultMessage\": \"now\"\n  },\n  \"kc79d3\": {\n    \"defaultMessage\": \"Topics\"\n  },\n  \"klCm96\": {\n    \"defaultMessage\": \"Community Post Approval\"\n  },\n  \"kqPQJD\": {\n    \"defaultMessage\": \"Configure zap pool\"\n  },\n  \"kuPHYE\": {\n    \"defaultMessage\": \"{n,plural,=0{{name} liked} other{{name} & {n} others liked}}\"\n  },\n  \"l+ikU1\": {\n    \"defaultMessage\": \"Everything in {plan}\"\n  },\n  \"l3H1EK\": {\n    \"defaultMessage\": \"Invite your friends\"\n  },\n  \"l3nTjd\": {\n    \"defaultMessage\": \"Basic key derivation from mnemonic seed phrase\"\n  },\n  \"lCILNz\": {\n    \"defaultMessage\": \"Buy Now\"\n  },\n  \"lD3+8a\": {\n    \"defaultMessage\": \"Pay\"\n  },\n  \"lEnclp\": {\n    \"defaultMessage\": \"My events: {n}\"\n  },\n  \"lbr3Lq\": {\n    \"defaultMessage\": \"Copy link\"\n  },\n  \"lfOesV\": {\n    \"defaultMessage\": \"Non-Zap\"\n  },\n  \"lgg1KN\": {\n    \"defaultMessage\": \"account page\"\n  },\n  \"ll3xBp\": {\n    \"defaultMessage\": \"Image proxy service\"\n  },\n  \"lnaT9F\": {\n    \"defaultMessage\": \"Following {n}\"\n  },\n  \"lsNFM1\": {\n    \"defaultMessage\": \"Click to load content from {link}\"\n  },\n  \"lvlPhZ\": {\n    \"defaultMessage\": \"Pay Invoice\"\n  },\n  \"m/59y2\": {\n    \"defaultMessage\": \"Zap Request\"\n  },\n  \"m6h2Eg\": {\n    \"defaultMessage\": \"Handler recommendation\"\n  },\n  \"mCEKiZ\": {\n    \"defaultMessage\": \"{n} notes have been muted\"\n  },\n  \"mFtdYh\": {\n    \"defaultMessage\": \"{type} Worker Relay\"\n  },\n  \"mKAr6h\": {\n    \"defaultMessage\": \"Follow all\"\n  },\n  \"mKh2HS\": {\n    \"defaultMessage\": \"File upload service\"\n  },\n  \"mKhgP9\": {\n    \"defaultMessage\": \"{n,plural,=0{} =1{zapped} other{zapped}}\"\n  },\n  \"mOFG3K\": {\n    \"defaultMessage\": \"Start\"\n  },\n  \"mfe8RW\": {\n    \"defaultMessage\": \"Option: {n}\"\n  },\n  \"mmPSWH\": {\n    \"defaultMessage\": \"Read Only\"\n  },\n  \"n19OA3\": {\n    \"defaultMessage\": \"Agent Model\"\n  },\n  \"n1Whvj\": {\n    \"defaultMessage\": \"Switch\"\n  },\n  \"n5l7tP\": {\n    \"defaultMessage\": \"Time-Based Calendar Event\"\n  },\n  \"n8k1SG\": {\n    \"defaultMessage\": \"{n}MiB\"\n  },\n  \"nD4frR\": {\n    \"defaultMessage\": \"Bid confirmation\"\n  },\n  \"nDejmx\": {\n    \"defaultMessage\": \"Unblock\"\n  },\n  \"nGBrvw\": {\n    \"defaultMessage\": \"Bookmarks\"\n  },\n  \"nGGDsi\": {\n    \"defaultMessage\": \"Notifications Allowed\"\n  },\n  \"nIchMQ\": {\n    \"defaultMessage\": \"Searching for account activity ({progress})\"\n  },\n  \"nPHrqp\": {\n    \"defaultMessage\": \"Coinjoin Pool\"\n  },\n  \"nUT0Lv\": {\n    \"defaultMessage\": \"Tools\"\n  },\n  \"nWQFic\": {\n    \"defaultMessage\": \"Renew\"\n  },\n  \"nihgfo\": {\n    \"defaultMessage\": \"Listen to this article\"\n  },\n  \"nwZXeh\": {\n    \"defaultMessage\": \"{n} blocked\"\n  },\n  \"o/gK53\": {\n    \"defaultMessage\": \"Deck\"\n  },\n  \"o7e+nJ\": {\n    \"defaultMessage\": \"{n} followers\"\n  },\n  \"oEyQP6\": {\n    \"defaultMessage\": \"Unlimited note retention on {app} relay\"\n  },\n  \"oHPB8Q\": {\n    \"defaultMessage\": \"Zap {name}\"\n  },\n  \"oJ+JJN\": {\n    \"defaultMessage\": \"Nothing found :/\"\n  },\n  \"odFwjL\": {\n    \"defaultMessage\": \"Follows only\"\n  },\n  \"ojzbwv\": {\n    \"defaultMessage\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out {link}\"\n  },\n  \"opNVQC\": {\n    \"defaultMessage\": \"Unpin\"\n  },\n  \"ozZ2Cj\": {\n    \"defaultMessage\": \"Badge Award\"\n  },\n  \"p9Ps2l\": {\n    \"defaultMessage\": \"{x}/{y} have relays ({percent})\"\n  },\n  \"pEQAGA\": {\n    \"defaultMessage\": \"Root e-tag is last in tags array (with multiple e-tags)\"\n  },\n  \"pRess9\": {\n    \"defaultMessage\": \"ZapPool\"\n  },\n  \"plOM0t\": {\n    \"defaultMessage\": \"Custom Emoji\"\n  },\n  \"plg2Ua\": {\n    \"defaultMessage\": \"Channel Mute User\"\n  },\n  \"puLNUJ\": {\n    \"defaultMessage\": \"Pin\"\n  },\n  \"pxF+t0\": {\n    \"defaultMessage\": \"Popular\"\n  },\n  \"pyjJ5f\": {\n    \"defaultMessage\": \"Nostr Marketplace (for resilient marketplaces)\"\n  },\n  \"pzTOmv\": {\n    \"defaultMessage\": \"Followers\"\n  },\n  \"q3OuMw\": {\n    \"defaultMessage\": \"Torrent Comment\"\n  },\n  \"qAY40L\": {\n    \"defaultMessage\": \"Date-Based Calendar Event\"\n  },\n  \"qBYNMb\": {\n    \"defaultMessage\": \"Group Thread Reply\"\n  },\n  \"qDwvZ4\": {\n    \"defaultMessage\": \"Unknown error\"\n  },\n  \"qFIVx4\": {\n    \"defaultMessage\": \"Profile Badges\"\n  },\n  \"qMePPG\": {\n    \"defaultMessage\": \"Note\"\n  },\n  \"qMx1sA\": {\n    \"defaultMessage\": \"Default Zap amount\"\n  },\n  \"qUJTsT\": {\n    \"defaultMessage\": \"Blocked\"\n  },\n  \"qXCbgZ\": {\n    \"defaultMessage\": \"Unlock\"\n  },\n  \"qZsKBR\": {\n    \"defaultMessage\": \"Renew {tier}\"\n  },\n  \"qcJFEJ\": {\n    \"defaultMessage\": \"Notifications API Disabled\"\n  },\n  \"qdGuQo\": {\n    \"defaultMessage\": \"Your Private Key Is (do not share this with anyone)\"\n  },\n  \"qfmMQh\": {\n    \"defaultMessage\": \"This note has been muted\"\n  },\n  \"qkvYUb\": {\n    \"defaultMessage\": \"Add to Profile\"\n  },\n  \"qmJ8kD\": {\n    \"defaultMessage\": \"Translation failed\"\n  },\n  \"qtWLmt\": {\n    \"defaultMessage\": \"Like\"\n  },\n  \"qx+v3H\": {\n    \"defaultMessage\": \"Request to Vanish\"\n  },\n  \"qyJtWy\": {\n    \"defaultMessage\": \"Show less\"\n  },\n  \"qydxOd\": {\n    \"defaultMessage\": \"Science\"\n  },\n  \"qz9fty\": {\n    \"defaultMessage\": \"Incorrect pin\"\n  },\n  \"r3C4x/\": {\n    \"defaultMessage\": \"Software\"\n  },\n  \"r5srDR\": {\n    \"defaultMessage\": \"Enter wallet password\"\n  },\n  \"rAQG0X\": {\n    \"defaultMessage\": \"Relay List Metadata\"\n  },\n  \"rIsVe+\": {\n    \"defaultMessage\": \"Public chats list\"\n  },\n  \"rMgF34\": {\n    \"defaultMessage\": \"Back up now\"\n  },\n  \"rRRXtB\": {\n    \"defaultMessage\": \"Lightning Zaps\"\n  },\n  \"rT14Ow\": {\n    \"defaultMessage\": \"Add Relays\"\n  },\n  \"reFEEC\": {\n    \"defaultMessage\": \"Reporting\"\n  },\n  \"rfuMjE\": {\n    \"defaultMessage\": \"(Default)\"\n  },\n  \"rhSI1/\": {\n    \"defaultMessage\": \"Model\"\n  },\n  \"rkM7l8\": {\n    \"defaultMessage\": \"Encrypted Direct Message\"\n  },\n  \"rmdsT4\": {\n    \"defaultMessage\": \"{n} days\"\n  },\n  \"rn52n9\": {\n    \"defaultMessage\": \"Public Chat Channels\"\n  },\n  \"sFUkSN\": {\n    \"defaultMessage\": \"Bookmark sets\"\n  },\n  \"sKDn4e\": {\n    \"defaultMessage\": \"Show Badges\"\n  },\n  \"sUNhQE\": {\n    \"defaultMessage\": \"user\"\n  },\n  \"sV1+m+\": {\n    \"defaultMessage\": \"Loading context...\"\n  },\n  \"sXNv9b\": {\n    \"defaultMessage\": \"Invalid notification context\"\n  },\n  \"sZQzjQ\": {\n    \"defaultMessage\": \"Failed to parse zap split: {input}\"\n  },\n  \"saInmO\": {\n    \"defaultMessage\": \"The relay name shown is not the same as the full URL entered.\"\n  },\n  \"saorw+\": {\n    \"defaultMessage\": \"Event Deletion Request\"\n  },\n  \"sbSCT3\": {\n    \"defaultMessage\": \"Private event relay list\"\n  },\n  \"sfL/O+\": {\n    \"defaultMessage\": \"Muted notes will not be shown\"\n  },\n  \"t+iuoN\": {\n    \"defaultMessage\": \"Claim your included {app} nostr address\"\n  },\n  \"tDDiRL\": {\n    \"defaultMessage\": \"Interests list\"\n  },\n  \"tFpT/O\": {\n    \"defaultMessage\": \"Release artifact sets\"\n  },\n  \"tO0JqG\": {\n    \"defaultMessage\": \"Source Code\"\n  },\n  \"tO1oq9\": {\n    \"defaultMessage\": \"Video Events\"\n  },\n  \"tOdNiY\": {\n    \"defaultMessage\": \"Dark\"\n  },\n  \"tRGdV1\": {\n    \"defaultMessage\": \"Versioned Encryption\"\n  },\n  \"tU0ADf\": {\n    \"defaultMessage\": \"Unknown NIP-{x}\"\n  },\n  \"tf1lIh\": {\n    \"defaultMessage\": \"Free\"\n  },\n  \"th5lxp\": {\n    \"defaultMessage\": \"Send note to a subset of your write relays\"\n  },\n  \"thnRpU\": {\n    \"defaultMessage\": \"Getting NIP-05 verified can help:\"\n  },\n  \"tj6kdX\": {\n    \"defaultMessage\": \"{sign} {amount} sats\"\n  },\n  \"ttxS0b\": {\n    \"defaultMessage\": \"Supporter Badge\"\n  },\n  \"tzMNF3\": {\n    \"defaultMessage\": \"Status\"\n  },\n  \"u/vOPu\": {\n    \"defaultMessage\": \"Paid\"\n  },\n  \"u4I8q8\": {\n    \"defaultMessage\": \"Pin list\"\n  },\n  \"u81G9+\": {\n    \"defaultMessage\": \"Uptime\"\n  },\n  \"u9NoC1\": {\n    \"defaultMessage\": \"Name must be less than {limit} characters\"\n  },\n  \"uBjtbB\": {\n    \"defaultMessage\": \"Try: Summarize my timeline\"\n  },\n  \"uCk8r+\": {\n    \"defaultMessage\": \"Already have an account?\"\n  },\n  \"uD7Els\": {\n    \"defaultMessage\": \"External Identities in Profiles\"\n  },\n  \"uJaMkO\": {\n    \"defaultMessage\": \"Relay list to receive DMs\"\n  },\n  \"uSV4Ti\": {\n    \"defaultMessage\": \"Reposts need to be manually confirmed\"\n  },\n  \"uc0din\": {\n    \"defaultMessage\": \"Send sats splits to\"\n  },\n  \"uex/ui\": {\n    \"defaultMessage\": \"external web reference\"\n  },\n  \"ufvXH1\": {\n    \"defaultMessage\": \"Found {n} events\"\n  },\n  \"uhu5aG\": {\n    \"defaultMessage\": \"Public\"\n  },\n  \"un1nGw\": {\n    \"defaultMessage\": \"{n} notes\"\n  },\n  \"usAvMr\": {\n    \"defaultMessage\": \"Edit Profile\"\n  },\n  \"v8lolG\": {\n    \"defaultMessage\": \"Start chat\"\n  },\n  \"vB3oQ/\": {\n    \"defaultMessage\": \"Must be a contact list or pubkey list\"\n  },\n  \"vBsZhD\": {\n    \"defaultMessage\": \"Communities list\"\n  },\n  \"vN5UH8\": {\n    \"defaultMessage\": \"Profile Image\"\n  },\n  \"vU/Q5i\": {\n    \"defaultMessage\": \"This tool will search for the last event published by all of your follows and remove those who have not posted in 6 months\"\n  },\n  \"vZ4quW\": {\n    \"defaultMessage\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n  },\n  \"vhlWFg\": {\n    \"defaultMessage\": \"Poll Options\"\n  },\n  \"voxBKC\": {\n    \"defaultMessage\": \"Followed by friends\"\n  },\n  \"vuMG+5\": {\n    \"defaultMessage\": \"Looking for:\"\n  },\n  \"vxwnbh\": {\n    \"defaultMessage\": \"Amount of work to apply to all published events\"\n  },\n  \"w1Fanr\": {\n    \"defaultMessage\": \"Business\"\n  },\n  \"w6qrwX\": {\n    \"defaultMessage\": \"NSFW\"\n  },\n  \"wEQDC6\": {\n    \"defaultMessage\": \"Edit\"\n  },\n  \"wIr5EQ\": {\n    \"defaultMessage\": \"Explicit Servers ({count})\"\n  },\n  \"wOyDTB\": {\n    \"defaultMessage\": \"File storage server list\"\n  },\n  \"wSZR47\": {\n    \"defaultMessage\": \"Submit\"\n  },\n  \"wc9st7\": {\n    \"defaultMessage\": \"Media Attachments\"\n  },\n  \"wih7iJ\": {\n    \"defaultMessage\": \"name is blocked\"\n  },\n  \"wlWMuh\": {\n    \"defaultMessage\": \"Patches\"\n  },\n  \"wofVHy\": {\n    \"defaultMessage\": \"Moderation\"\n  },\n  \"wqyN/i\": {\n    \"defaultMessage\": \"Find out more info about {service} at {link}\"\n  },\n  \"wtLjP6\": {\n    \"defaultMessage\": \"Copy ID\"\n  },\n  \"wvoA3H\": {\n    \"defaultMessage\": \"Picture\"\n  },\n  \"wyAr3x\": {\n    \"defaultMessage\": \"Results:\"\n  },\n  \"x+3fl6\": {\n    \"defaultMessage\": \"My Relays\"\n  },\n  \"x/Fx2P\": {\n    \"defaultMessage\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n  },\n  \"x82IOl\": {\n    \"defaultMessage\": \"Mute\"\n  },\n  \"xEjBS7\": {\n    \"defaultMessage\": \"For you\"\n  },\n  \"xIcAOU\": {\n    \"defaultMessage\": \"Votes by {type}\"\n  },\n  \"xIoGG9\": {\n    \"defaultMessage\": \"Go to\"\n  },\n  \"xPCyu+\": {\n    \"defaultMessage\": \"nostr: URI scheme\"\n  },\n  \"xbVgIm\": {\n    \"defaultMessage\": \"Automatically load media\"\n  },\n  \"xhQMeQ\": {\n    \"defaultMessage\": \"Expires\"\n  },\n  \"xl4s/X\": {\n    \"defaultMessage\": \"Additional Terms:\"\n  },\n  \"xmcVZ0\": {\n    \"defaultMessage\": \"Search\"\n  },\n  \"xrKHS6\": {\n    \"defaultMessage\": \"Success\"\n  },\n  \"xybOUv\": {\n    \"defaultMessage\": \"FAN\"\n  },\n  \"y/bmsG\": {\n    \"defaultMessage\": \"Allow\"\n  },\n  \"y1Z3or\": {\n    \"defaultMessage\": \"Language\"\n  },\n  \"yAztTU\": {\n    \"defaultMessage\": \"{n} eSats\"\n  },\n  \"yCLnBC\": {\n    \"defaultMessage\": \"LNURL or Lightning Address\"\n  },\n  \"yLzgxH\": {\n    \"defaultMessage\": \"Popular Relays\"\n  },\n  \"yeX8yA\": {\n    \"defaultMessage\": \"Native App\"\n  },\n  \"ymVhDw\": {\n    \"defaultMessage\": \"Email <> DM bridge for your {app} nostr address\"\n  },\n  \"ynNi3b\": {\n    \"defaultMessage\": \"Active URLs ({active}/{max})\"\n  },\n  \"ywyVQg\": {\n    \"defaultMessage\": \"{app} nostr address\"\n  },\n  \"z3UjXR\": {\n    \"defaultMessage\": \"Debug\"\n  },\n  \"z3Ukvq\": {\n    \"defaultMessage\": \"Draft Long-form Content\"\n  },\n  \"zCb8fX\": {\n    \"defaultMessage\": \"Weight\"\n  },\n  \"zFegDD\": {\n    \"defaultMessage\": \"Contact\"\n  },\n  \"zINlao\": {\n    \"defaultMessage\": \"Owner\"\n  },\n  \"zQvVDJ\": {\n    \"defaultMessage\": \"All\"\n  },\n  \"zi9MdS\": {\n    \"defaultMessage\": \"Chess (PGN)\"\n  },\n  \"zm6qS1\": {\n    \"defaultMessage\": \"{n} mins to read\"\n  },\n  \"zonsdq\": {\n    \"defaultMessage\": \"Failed to load LNURL service\"\n  },\n  \"zvCDao\": {\n    \"defaultMessage\": \"Automatically show latest notes\"\n  },\n  \"zx0myy\": {\n    \"defaultMessage\": \"Participants\"\n  }\n}\n"
  },
  {
    "path": "packages/app/src/service-worker.ts",
    "content": "/// <reference lib=\"webworker\" />\nimport { hexToBytes } from \"@noble/hashes/utils.js\"\nimport { bech32 } from \"@scure/base\"\nimport { encodeTLVEntries, NostrPrefix, TLVEntryType } from \"@snort/shared\"\nimport { NostrLink, tryParseNostrLink } from \"@snort/system/dist/nostr-link\"\nimport { CacheableResponsePlugin } from \"workbox-cacheable-response\"\nimport { clientsClaim } from \"workbox-core\"\nimport { ExpirationPlugin } from \"workbox-expiration\"\nimport { precacheAndRoute, type PrecacheEntry } from \"workbox-precaching\"\nimport { registerRoute } from \"workbox-routing\"\nimport { CacheFirst, StaleWhileRevalidate } from \"workbox-strategies\"\n\ndeclare const self: ServiceWorkerGlobalScope & {\n  __WB_MANIFEST: (string | PrecacheEntry)[]\n}\n\nprecacheAndRoute(self.__WB_MANIFEST)\nclientsClaim()\n\n// cache everything in current domain /assets because precache doesn't seem to include everything\nregisterRoute(\n  ({ url }) => url.origin === self.location.origin && url.pathname.startsWith(\"/assets\"),\n  new StaleWhileRevalidate({\n    cacheName: \"assets-cache\",\n    plugins: [\n      new ExpirationPlugin({\n        maxEntries: 200,\n        matchOptions: {\n          ignoreVary: true,\n        },\n      }),\n    ],\n  }),\n)\n\nregisterRoute(\n  ({ url }) => url.pathname.endsWith(\"/.well-known/nostr.json\"),\n  new StaleWhileRevalidate({\n    cacheName: \"nostr-json-cache\",\n    plugins: [new ExpirationPlugin({ maxAgeSeconds: 4 * 60 * 60 })],\n  }),\n)\n\n// Avatars\nregisterRoute(\n  ({ request, url }) => {\n    return (\n      request.destination === \"image\" &&\n      url.href.startsWith(\"https://imgproxy.v0l.io/\") &&\n      (url.pathname.includes(\"rs:fit:32:32\") || url.pathname.includes(\"rs:fit:120:120\"))\n    )\n  },\n  new CacheFirst({\n    cacheName: \"avatar-cache\",\n    plugins: [\n      new ExpirationPlugin({\n        maxEntries: 200, // gif avatars can still be large\n        matchOptions: {\n          ignoreVary: true,\n        },\n      }),\n      new CacheableResponsePlugin({\n        statuses: [0, 200],\n      }),\n    ],\n  }),\n)\n\n// Cache images from any domain\nregisterRoute(\n  // match images except gif\n  ({ request, url }) => request.destination === \"image\" && !url.pathname.endsWith(\".gif\"),\n  new CacheFirst({\n    cacheName: \"image-cache\",\n    plugins: [\n      new ExpirationPlugin({\n        maxEntries: 100,\n        matchOptions: {\n          ignoreVary: true,\n        },\n      }),\n      new CacheableResponsePlugin({\n        statuses: [0, 200],\n      }),\n    ],\n  }),\n)\n\nregisterRoute(\n  ({ url }) => url.origin === \"https://nostr-api.v0l.io\" && url.pathname.startsWith(\"/api/v1/preview\"),\n  new CacheFirst({\n    cacheName: \"preview-cache\",\n    plugins: [\n      new ExpirationPlugin({ maxAgeSeconds: 24 * 60 * 60 }),\n      new CacheableResponsePlugin({ statuses: [0, 200] }),\n    ],\n  }),\n)\n\nregisterRoute(\n  ({ url }) => url.origin === \"https://api.snort.social\" && url.pathname.startsWith(\"/api/v1/translate\"),\n  new CacheFirst({\n    cacheName: \"translate-cache\",\n    plugins: [\n      new ExpirationPlugin({ maxEntries: 1000 }),\n      new CacheableResponsePlugin({\n        statuses: [0, 200, 204],\n      }),\n    ],\n  }),\n)\n\nself.addEventListener(\"message\", event => {\n  if (event.data && event.data.type === \"SKIP_WAITING\") {\n    self.skipWaiting()\n  }\n})\nself.addEventListener(\"install\", event => {\n  // delete all cache on install\n  event.waitUntil(\n    caches.keys().then(cacheNames => {\n      return Promise.all(\n        cacheNames.map(cacheName => {\n          console.debug(\"Deleting cache: \", cacheName)\n          return caches.delete(cacheName)\n        }),\n      )\n    }),\n  )\n  // always skip waiting\n  self.skipWaiting()\n})\n\nenum PushType {\n  Mention = 1,\n  Reaction = 2,\n  Zap = 3,\n  Repost = 4,\n  DirectMessage = 5,\n}\n\ninterface PushNotification {\n  type: PushType\n  data: object\n}\n\ninterface CompactMention {\n  id: string\n  created_at: number\n  content: string\n  author: CompactProfile\n  mentions: Array<CompactProfile>\n}\n\ninterface CompactReaction {\n  id: string\n  created_at: number\n  content: string\n  author: CompactProfile\n  event?: string\n  amount?: number\n}\n\ninterface CompactProfile {\n  pubkey: string\n  name?: string\n  avatar?: string\n}\n\nself.addEventListener(\"notificationclick\", event => {\n  const id = event.notification.tag as string\n  const ev = JSON.parse(event.notification.data) as PushNotification\n\n  event.waitUntil(\n    (async () => {\n      const windows = await self.clients.matchAll({ type: \"window\" })\n      const url = () => {\n        if (ev.type === PushType.Zap || ev.type === PushType.Reaction) {\n          const mention = ev.data as CompactReaction\n          if (mention.event) {\n            return `/${new NostrLink(NostrPrefix.Note, mention.event).encode()}`\n          }\n        } else if (ev.type === PushType.DirectMessage) {\n          const reaction = ev.data as CompactReaction\n          return `/messages/${encodeTLVEntries(\"nchat17\", {\n            type: TLVEntryType.Author,\n            value: reaction.author.pubkey,\n            length: 32,\n          })}`\n        }\n        return `/${new NostrLink(NostrPrefix.Note, id).encode()}`\n      }\n      for (const client of windows) {\n        if (client.url === url() && \"focus\" in client) return client.focus()\n      }\n      if (self.clients.openWindow) return self.clients.openWindow(url())\n    })(),\n  )\n})\n\nself.addEventListener(\"push\", async e => {\n  console.debug(e)\n  const data = e.data?.json() as PushNotification | undefined\n  console.debug(data)\n  if (data) {\n    switch (data.type) {\n      case PushType.Mention: {\n        const evx = data.data as CompactMention\n        await self.registration.showNotification(`${displayNameOrDefault(evx.author)} replied`, makeNotification(data))\n        break\n      }\n      case PushType.Reaction: {\n        const evx = data.data as CompactReaction\n        await self.registration.showNotification(`${displayNameOrDefault(evx.author)} reacted`, makeNotification(data))\n        break\n      }\n      case PushType.Zap: {\n        const evx = data.data as CompactReaction\n        await self.registration.showNotification(\n          `${displayNameOrDefault(evx.author)} zapped${evx.amount ? ` ${formatShort(evx.amount)} sats` : \"\"}`,\n          makeNotification(data),\n        )\n        break\n      }\n      case PushType.Repost: {\n        const evx = data.data as CompactReaction\n        await self.registration.showNotification(`${displayNameOrDefault(evx.author)} reposted`, makeNotification(data))\n        break\n      }\n      case PushType.DirectMessage: {\n        const evx = data.data as CompactReaction\n        await self.registration.showNotification(\n          `${displayNameOrDefault(evx.author)} sent you a DM`,\n          makeNotification(data),\n        )\n        break\n      }\n    }\n  }\n})\n\nconst MentionNostrEntityRegex = /(nostr:n(?:pub|profile|event|ote|addr)1[acdefghjklmnpqrstuvwxyz023456789]+)/g\n\nfunction replaceMentions(content: string, profiles: Array<CompactProfile>) {\n  return content\n    .split(MentionNostrEntityRegex)\n    .map(i => {\n      if (MentionNostrEntityRegex.test(i)) {\n        const link = tryParseNostrLink(i)\n        if (link && (link.type === NostrPrefix.PublicKey || link.type === NostrPrefix.Profile)) {\n          const px = profiles.find(a => a.pubkey === link.id)\n          return `@${displayNameOrDefault(px ?? { pubkey: link.id })}`\n        }\n      }\n      return i\n    })\n    .join(\"\")\n}\n\nfunction displayNameOrDefault(p: CompactProfile) {\n  if ((p.name?.length ?? 0) > 0) {\n    return p.name\n  }\n  return bech32.encode(\"npub\", bech32.toWords(hexToBytes(p.pubkey))).slice(0, 12)\n}\n\nfunction makeNotification(n: PushNotification) {\n  const evx = n.data as CompactMention | CompactReaction\n\n  const body = () => {\n    if (n.type === PushType.Mention) {\n      return (\"mentions\" in evx ? replaceMentions(evx.content, evx.mentions) : evx.content).substring(0, 250)\n    } else if (n.type === PushType.Reaction) {\n      if (evx.content === \"+\") return \"💜\"\n      if (evx.content === \"-\") return \"👎\"\n      return evx.content\n    } else if (n.type === PushType.DirectMessage) {\n      return \"\"\n    } else if (n.type === PushType.Repost) {\n      return \"\"\n    }\n    return evx.content.substring(0, 250)\n  }\n  const ret = {\n    body: body(),\n    icon: evx.author.avatar ?? `https://nostr-rs-api.v0l.io/avatar/robots/${evx.author.pubkey}.webp`,\n    timestamp: evx.created_at * 1000,\n    tag: evx.id,\n    data: JSON.stringify(n),\n  }\n  console.debug(ret)\n  return ret\n}\n\nfunction formatShort(n: number) {\n  if (n > 1000) {\n    return (n / 1000).toFixed(1)\n  } else {\n    return n.toFixed(0)\n  }\n}\n"
  },
  {
    "path": "packages/app/src/setupTests.ts",
    "content": "import { TextDecoder, TextEncoder } from \"node:util\"\n\nObject.assign(global, { TextDecoder, TextEncoder })\n"
  },
  {
    "path": "packages/app/src/system.ts",
    "content": "import { NostrSystem } from \"@snort/system\"\n\nimport { Relay, ProfilesCache, UserFollows, UserRelays } from \"@/Cache\"\nimport { addEventToFuzzySearch } from \"@/Db/FuzzySearch\"\nimport { LoginStore } from \"@/Utils/Login\"\nimport { hasWasm, WasmOptimizer } from \"@/Utils/wasm\"\n\n/**\n * Singleton nostr system\n */\nexport const System = new NostrSystem({\n  relays: UserRelays,\n  profiles: ProfilesCache,\n  cachingRelay: Relay,\n  contactLists: UserFollows,\n  optimizer: hasWasm ? WasmOptimizer : undefined,\n  buildFollowGraph: true,\n  automaticOutboxModel: true,\n})\n\nSystem.on(\"auth\", async (c, r, cb) => {\n  const { id } = LoginStore.snapshot()\n  const pub = LoginStore.getPublisher(id)\n  if (pub) {\n    cb(await pub.nip42Auth(c, r))\n  }\n})\n\nSystem.pool.on(\"event\", (_relay, _sub, ev) => {\n  if (ev.kind === 0) {\n    if (\"discover\" in ProfilesCache) {\n      ProfilesCache.discover(ev)\n    }\n    addEventToFuzzySearch(ev)\n  }\n})\n"
  },
  {
    "path": "packages/app/src/translations/af_ZA.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/ar_SA.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"هل أنت متأكد من إعادة النشر: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"دفع الآن\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"مزامنة جميع الأحداث الخاصة بملفك الشخصي في ذاكرة التخزين المؤقت المحلية\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"إحصائيات الترحيل\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"تسجيل الدخول بصلاحيات كتابة\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"دردشة المجموعة السرية\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"تخصيص الومضة\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"متابعة\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"تسجيل الدخول\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"يرجى التأكد من حفظ كلمة المرور لتتمكن من إدارة المعرّف الخاص بك في المستقبل\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"اتصال\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"تحرير\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعادة نشر \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"مساحتك بالطريقة التي تريدها لها 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"مسح\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"دعم الحساب\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"تكامل تخزين ملفات HTTP\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"إرسال مقاييس الاستخدام المجهولة\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"رسالة دردشة جماعية\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"اجعل ملفك الشخصي أسهل في العثور عليه ومشاركته\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"من الملف\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" مللي ثانية\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"تحميل المزيد\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"عنوان Nostr غير مملوك لك\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"مفاتيح التصدير\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"إدارة\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"بحث...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"محفظة LNDHub عامة (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"عنوان LNURL غير صالح\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"التعامل مع الإشارات\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"الاسم يحتوي على أحرف غير مسموح بها\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"السياسة\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"إظهار الحالة\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ثانية\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"اذهب\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"أشياء git\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"هل أنت متأكد من حذف هذا المنشور من المنشورات المرجعية؟\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"أدخل تكوين اتصال محفظة Nostr\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"تأكد من نسخ مفاتيحك احتياطيًا!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"متصل بـ: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 0,\n      \"value\": \"المتابَعون \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"التحقق من التوقيعات\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"الطبيعة\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"المحادثات\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"اضافة\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"الخلفية\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"ليس لديك حساب؟\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"المجتمعات الخاضعة للإشراف\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"اتصال المحفظة\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"علامة الموضوع في الأحداث النصية\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة الرموز التعبيرية للمستخدم\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"تبرع\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"أدخل كلمة المرور\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"إنهاء\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"القوائم العامة\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 0,\n      \"value\": \"المنشورات المرجعية \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"الاستهجان (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"ملاحظة جديدة\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"متابعة من أصدقاء الأصدقاء\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"البيانات الخاصة بالتطبيق\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ساعات\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"أحدث المقالات\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"الردود\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"تسجيل الدخول\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"حالات المستخدم\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"مقالات\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"النقط المخزنة على خوادم الوسائط\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" المشاهدون\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"فاتح\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"المترجمون\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"بدون عنوان\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"أنت تصوت بـ \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ساتوشي\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" منشور جديد\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" منشورات جديدة\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"المتابِعون \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"المحفظة\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"نوستر كونكت\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"إجمالي الأحداث:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"لا أحد\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"ويكي\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"الغاء\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"العطاءات\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"المطورون الأساسيون\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"معرف NIP-05 الجديد الخاص بك هو:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"الحياة\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"استهجان\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"تشفير المفتاح الخاص\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs هي من أوائل مزودي NIP-05 وتقدم مجموعة من المعرفات بأسعار معقولة\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"استخدم imgproxy لضغط الصور\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"روابط مفقودة\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"ملاحظة خاصة\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"معالجات التطبيقات الموصى بها\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Splits\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"تم تمكين واجهة برمجة تطبيقات الإشعارات\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"هدف الانطلاق\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"شراء معرف\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"البيانات الوصفية للملف\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"تحويل الى عنوان عام\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"أسماء المستخدمين ليست فريدة على Nostr. عنوان النف هو عنوانك الفريد القابل للقراءة للإنسان والذي هو فريد لك عند التسجيل.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"أرسل ومضة\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"شاهد إعادة العرض\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة كتم الصوت\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعادة المحاولة\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"فشل الاتصال:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"طول قائمة المتابعة الجديدة \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"فشلت الصورة الوكيل من \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"، انقر هنا للتحميل مباشرة\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"يوصى بالترحيل\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"ختم\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"السبب: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"نبحث عن: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"ليس كل العملاء يدعمون هذا، قد لا تزال تتلقى بعض الزبابيك كما لو أن تقسيم الزلاب لم يتم تكوينه\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"الإعجابات (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"متبوعة بـ\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"حقول البيانات الوصفية والعلامات الإضافية\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"غير مدفوع\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"تبديل الحسابات\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"جيد\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"منشورات\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"يستخدم البروكسي فواتير HODL لإرسال الدفع، الذي يخفي حوض العقدة الخاصة بك\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"التسمية\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"مقالة ويكي\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"وثيقة معلومات الترحيل\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"إمكانية البحث\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"غير متصل\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائد المجتمع\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"رد الفعل\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"محتوى المقال المعياري\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"كتم الملاحظات من الأشخاص الذين هم خارج شبكة ثقتك\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"إغلاق المرحلات\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعادة النشر (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"تأكيد إعادة النشر\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"اصطلاحات استخدام العملاء للعلامات e و p في الأحداث النصية\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"الرد على\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"التسجيل\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"أومض \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ساتوشي\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"المستلم\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"تقسيم زاق غير صالح: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"خيط المجموعة\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"الاسم طويل جدا\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"الكيانات المرمزة bech32\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"عبارة الاقتران\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"اتبع المجموعات\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"مسودة القائمة المبوبة\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"التالي\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"رد\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"يتابع \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"الرد على حدث التقويم\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"ارسال\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"إخفاء الملاحظات الصامتة\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعادة محاولة النشر\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"عنوان نوستر\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"فاتورة البرق\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعادة النشر العام\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"السياق\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"ملاحظة من \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"كلمات مكتومة\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"تم كتم هذا المستخدم\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"إنشاء منتج أو تحديثه\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"ابقاء المنشورات لمدة غير محدودة في موصل سنورت\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"السبب\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"رائع\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"المباراة\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"إنشاء القناة\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"العد\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"الإشعارات الفورية\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"شهور\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"تسجيل الدخول\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"الاسم قصير جدا\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"وميض\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"يمكنك إضافة مرحلات مفردة أو متعددة، واحدة لكل سطر.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"كتابة الوصول إلى Snort ، مع احتفاظ الحدث لمدة سنة واحدة\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"تضمينات الذكاء الاصطناعي / قوائم المتجهات\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"المجموعات القائمة على الترحيل\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"تحديث\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"واجهة المستخدم/تجربة المستخدم في السوق\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"عنوان Nostr (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"الترحيل\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"مصادقة HTTP\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"التبرع بالبرق\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"حدث مباشر\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعادة عرض الأسعار\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"تسجيل الخروج\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"الخوادم المشهورة\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"المتابعة المقترحة\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"مجموعات الفيديو\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"فشل تحميل البرقية\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"الملف الشخصي Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة المتابعة\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"تقليم قائمة المتابعة\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"الأشخاص المتظاهرون\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"و \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" الآخرين الذين تتابعهم\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعلانات المستودع\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 0,\n      \"value\": \"المكتومون \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"التقويم\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ساتس\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"مترجم من \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"الرسم البياني الاجتماعي\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"مراجع الملاحظات النصية\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"ومّض أي منشور يتم تحميله بشكل تلقائي\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"تعريف الشارة\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعدادات\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"إخفاء رسالة إخفاء القناة\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"مخبئ\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"إرسال الساتوشي\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"عرض أحدث منشورات \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"الومض التلقائي\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"مباشر\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"المنتج المباع بالمزاد العلني\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"يجب أن يكون حول أقل من \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" حرف\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"تحويل\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"تبديل الكل\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"المتصفح\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"ساتس\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"الفاتورة / عنوان البرق\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"البحث في الملاحظات\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"مزودي البيانات\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"إظهار الشارات على صفحات الملف الشخصي\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"رد فعل على موقع الويب\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"عام\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"ترجمة إلى \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"مجموعات التنسيق\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"علاقات مخصصة\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"اسم المستخدم متاح\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"مفتاح\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"عنوان التبرع في السلسلة\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"شراء\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"عذرًا، نحن لا نفهم هذا النوع من الأحداث (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")، يرجى تجربة أحد التطبيقات التالية بدلاً من ذلك!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"الخادم\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"إضافة حساب\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"القوائم المبوبة\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 0,\n      \"value\": \"وميض \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"استجابة المحفظة\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"مصادقة العملاء على المرحلات\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"إظهار رسائل الحالة على صفحات الملف الشخصي\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"المستخدمين المتداولين\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"مجموعات المستخدمين\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعادة توجيه المشكلات HTTP إعادة توجيهها إلى عنوان الإضاءة المقدم\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"احجز الان\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"حدث خطأ!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"متابع لك\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"الحسابات\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"ليس لديك أي خوادم وسائط، حاول إضافة بعضها.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"حذف\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"اختر محفظة\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"الاشتراك في الدفع\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"ملح\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"خطط التنفيذ الوطنية المدعومة\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"المنشورات المرجعية (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"عنوان البرق\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"احصل على عنوانك لسنورت\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"رابط مغناطيسي\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"التورنت\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"عنوان البرق غير صالح\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" استهجان\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"حدث البث\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"مفتاح بصيغة سداسية عشرية ..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"التعامل مع الأحداث المجهولة\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"تسجيل الخروج\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"معلومات القائد\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة الإشارات المرجعية\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"الطلب مدفوع!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"اسم المستخدم\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"سيكون الاسم متاحًا لاحقًا\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"كتم\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"مسح ذاكرة التخزين المؤقت وإعادة التحميل\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"افتح المحفظة\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"أنت لا تتبع هذا الشخص، انقر هنا لتحميل الوسائط من \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"، أو قم بتحديث \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"تفضيلاتك\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" لتحميل الوسائط دائما من الجميع.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"مراجعات الترحيل\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"الدعم\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"الطابع الزمني لانتهاء الصلاحية\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"إنشاء أو تحديث كشك\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"آخر منشور \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"هل أنت متأكد من ازالة تثبيت هذا المنشور؟\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"بيانات الحساب\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"يتبع\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"يجب أن تكون مشتركاً في الموقع الإلكتروني \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" للوصول إلى مجموعة \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"اجعلوا كل الجلسات \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"ترجمة تلقائية\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"آخر مرة شوهد فيها\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"أرسل \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" جلوس إلى \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"لا يتبعه أي شخص تتبعه\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"انقر هنا للتحميل على أي حال\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"متصل\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"ملاحظات شائعة\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"الإشتراكات\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"الإشعارات غير مسموح بها\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"استخدام فواصل لفصل الكلمات على سبيل المثال الكلمات 1 و 2 و 3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"مجموعات الرموز التعبيرية\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"اسم المستخدم\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"إرسال الجلوس إلى \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"وميض (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"الرياضة\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"لا يوجد عنوان للإضاءة\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"اشترك في \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ل \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" و استلم المكافآت التالية\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعادة\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة مرحلات البحث\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"البحث عن المستخدمين\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"موقع إلكتروني\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"المرحلات هي خوادم تتصل بها لإرسال الأحداث واستقبالها. استهدف 4-8 مرحلات.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"المفتاح الخاص\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"متوسط وقت الاستجابة:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"مسح\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"عرض\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"معرّفات المحتوى الخارجي\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"أدخل معلومات التهيئة لـ LNDHub\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"أبرز الملامح\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"رسالة الدردشة المباشرة\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"تم الحذف\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"الأحداث المحمية\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"نوع الحدث غير معروف: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"تعيين مفاتيح Nostr إلى معرّفات الإنترنت المستندة إلى DNS\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"أدخل رقم التعريف\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"طلب المحفظة\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"عرض كمستخدم؟\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"أهداف Zap Goals\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"تحقق من الرمز \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"تثبيت قصير جداً\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"هوية مخفية\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"تعليق\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"يجب أن يتراوح الاسم بين 8 و15 حرفاً\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"لا يمكن التحقق من عنوان Nostr\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"فتح على زابستر\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"السيول\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" عثر على\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" و ! \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" عثر آخرون على\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"سيتم تقسيم الزجاج على هذه الملاحظة إلى المستخدمين التاليين.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"قوائم التصحيح\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"كن قائداً\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"عرض خيار \\\"نسخ المعرف\\\" و \\\"النسخ بصيغة JSON\\\" في قائمة الخيارات المنسدلة لكل منشور\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"غير متاح:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"غرفة الانضمام\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"كلمة مرور المحفظة\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"العرض الافتراضي\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ملاحظة نصية قصيرة\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"مصادقة العميل\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"تعيين كعنوان نوستر الأساسي (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"علامات التوكيل\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"أرسل هذا الرابط إلى أصدقائك وشاركهم سحر النوستر.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"الدفع للاشتراك\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"اشتري عنوان التنفير\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"عد النتائج\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"شراء \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"حساب Iris.to\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"تأكيد\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"الإشعارات\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"لديك فعلا اشتراك من هذا النوع، يرجى التجديد أو الدفع\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"الملاحظات الوظيفية\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"لا يمكن التصويت بـ \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ساتوشي، يرجى تعيين مبلغ افتراضي مختلف\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"صفحة المستخدمين الجدد\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعادة النشر\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"ميت\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"استخدم كود الدعوة الخاص بك لكسب ساتس!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"وميض\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"تصديقات الطوابع الزمنية المفتوحة للأحداث\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"غلاف الهدايا\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"مشاركة\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"خطأ غير معروف أثناء تسجيل الدخول\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"احصل على عنوان مجاني\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"اشتراكك لا يزال نشطا، لا يمكنك التجديد الآن\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"تم الإنشاء\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"طلبات الدمج\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"فشل التحديث، يرجى المحاولة مرة أخرى\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"المحتوى المطول\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"المسح \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"عنوان Nostr غير صالح\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"نسخ بصيغة JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"مطابق لاعدادات جهازك\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"الإجمالي اليوم (بالتوقيت العالمي ): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ساتوشي\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"المسافة\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"التفضيلات\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"الاستلام إلى \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"عنوان الملف غير معروف: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"الثيم\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"سيتم عرض ردود الفعل في كل صفحة ، إذا تم تعطيلها فلن تظهر أي ردود فعل\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 0,\n      \"value\": \"الموصّلات \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"المفتاح الخاص مثل كلمة المرور، ولكن لا يمكن إعادة تعيينه. احرص عليه بعناية ولا تظهره لأي شخص. بمجرد حصول شخص ما على مفتاحك الخاص، سيتمكن من الوصول إلى حسابك إلى الأبد.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"زاب بوول يعمل فقط إذا كنت تستخدم أحد اتصالات المحفظة المدعومة (اتصال WebLN، LNC، LNDHub أو Nostr Wallet)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"رسالة القناة\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"لديك حاليا \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" جلوس في بركة زاب.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"الرسائل الخاصة المباشرة\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"الاشتراك\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"الأشخاص الذين تتابعهم\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"عامل الخدمة لا يعمل\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعلانات حالة المستودع\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"اسم المستخدم يجب أن يحتوي فقط على أحرف وأرقام صغيرة\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"منتهي الصلاحية\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"فعالية الفيديو القصير للصور الشخصية القصيرة\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"لـ: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"هل أنت متأكد أنك تريد حذف \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"ماكينات بيع البيانات\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"موصّلات\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"المنشورات المرجعية\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"ملاحظة التحميل: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"الأذونات\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"أدخل دبوس لتشفير المفتاح الخاص، يجب عليك إدخال هذا الدبوس في كل مرة تفتح فيها \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"إرسال زاب إلى \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"تحديث عنوان البرق\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"شراء الاشتراك\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"المرحلات الشائعة التي يستخدمها الأشخاص الذين تتابعهم.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"وكيل عنوان LN\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"مجموعات الترحيل\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"متتبع المشكلات\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"وضع علامة للكل مقروء\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"مخصص\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"ماذا يجب أن نسميك؟\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"ادفع الآن\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"البيانات الخاصة بالتطبيق\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"وضع المؤلف علامة على هذه المذكرة كموضوع حساس \"\n    },\n    {\n      \"children\": [],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"المرحلات القريبة من موقعك الجغرافي.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"الوسائط في الملاحظات ستظهر تلقائياً للأشخاص المختارين، وإلا فإن الرابط فقط سيظهر\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"معلومات المعالج\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"برقية\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"معاينة\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"استخدام الترحيل المحلي\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"انتهت\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"تسجيل الدخول باستخدام ملحق Nostr\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"اعرف المزيد\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crypto\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"مجموعات الفوائد\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"أحداث التقويم\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"الناس\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"أعجبني\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"الحساب\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"إيقاف الإستماع\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"تعريف المجتمع\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"إزالة من مرحلتي\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"استلم\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"تحقق من جميع توقيعات الأحداث المتلقاة من الترحيل\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"دردشة جديدة\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"سيضطر المستخدمون على قبول التحذير المعروض على منشورك قبل عرضه.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"إضافة خادم\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"تسجيل الدخول\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"حظر\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"طلبك معلق\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"لديك حساب iris.to نشط\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"شارك دعوة مخصصة مع الأصدقاء!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"رمز الإحالة الخاص بك هو \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"وضع العلامات\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"اختر خدمة التحميل التي تريد رفع المرفقات إليها\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"مفتاح عام (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"نعم من فضلك\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"للاطلاع على قائمة كاملة بالتغييرات يمكنك عرض سجل التغييرات \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 0,\n      \"value\": \"تم كتم \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"صورة الحساب \"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"يبدو أنك غير مشترك، يمكنك الاشتراك من هنا \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 0,\n      \"value\": \"المحظورون \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"محلي\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"رفع الكتم\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"من الخادم\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"المشكلات\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"ترجمة الملاحظات إلى لغتك المحلية تلقائياً\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / nostr\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"تسجيل الدخول باستخدام المفتاح\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"إرسال مقاييس الاستخدام\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"مضيفي الملفات\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"اتصال محفظة ألبي\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"يتبع صحة التتابع\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"استرداد\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"الهاشتاغات الرائجة\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"تفاعل\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"الإرسال من \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"مبلغ زابي الافتراضي الخاص بك هو \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" جلسة، على سبيل المثال يتم حساب القيم من هذا.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"المستخدمون\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"رابط الخدمة\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"خوادم الوسائط الشائعة.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"يبدو أنك لا تتابع عددًا كافيًا من الأشخاص، ألقِ نظرة على \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" لاكتشاف الأشخاص الذين يمكنك متابعتهم!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"لا توجد مفاتيح، لا \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"، لا توجد طريقة لإعادة ضبطه إذا لم تقم بعمل نسخة احتياطية. يستغرق الأمر دقيقة واحدة فقط.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"الدردشة العامة\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"تمكين التفاعل\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"قم بتوصيل محفظة لإرسال مدفوعات فورية\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"جرب مرحل آخر\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"البيانات الوصفية للقناة\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"أدخل عبارة الاقتران\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"توقيع الحدث المفوض\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"تأليف ملاحظة\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"نشط الآن\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"المساهمون\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"إرسال تقسيم زاف إلى\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"اسم المستخدم iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" محجوز لك!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"الرسائل المباشرة المشفرة\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" دعوتك إلى \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"تخزن خوادم الوسائط الوسائط التي يمكنك مشاركتها في الملاحظات كصور ومقاطع فيديو\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"ادعم المطورين والمنصات التي تقدم خدمات التحقق من NIP-05\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"سيتم بث الملاحظات في الوقت الحقيقي إلى علامة التبويب العالمية والملاحظات\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"الاسم أو اللاسم\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"الإضافات المدعومة\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"مدفوعة \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ساتس، الرسوم \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ساتس\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"الاتصال بعقدة LND الخاصة بك باستخدام Lightning Node Connect\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"عرض المزيد\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" كم\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"دعوة الأصدقاء\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"سماعة\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"سيكون معرفك بمثابة عنوان برق وستتم اعادة التوجيه الى عنوان البرق أو LNURL الذي تختاره\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"أنت قائد المجتمع وتكسب \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" من اشتراكات المستخدمين المحالين!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"تشغيل عامل الخدمة\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"حساب قائمة التقليم\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"الحصول على العنوان\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"تسجيل الدخول للقراءة فقط\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"محتوى حساس\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"المفتاح العام\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"الأنون\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"الآن\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"أطقم كتم الصوت لطيف مجموعات كتم الصوت\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"لا شكراً\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"عمليات إعادة التوجيه\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"إذا كان لديك استفسار حول طلب NIP-05 الخاص بك ، فيرجى مراسلة \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" على الخاص\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"كيلوبايت\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"بث مرة أخرى\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"باستخدام ألبي؟ انتقل إلى \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" للحصول على تكوين NWC الخاص بك!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"اتصال محفظة نوستر الأصلية\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"التصوير\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"رسالة مباشرة\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"المتابَعون\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL ..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"خوادم الوسائط\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"كتم الكل\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"ربط المحفظة\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"طوابع زمنية مفتوحة\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"دعم الحسابات المتعددة\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"الاسم مسجل\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"أنشطة حية\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"الخلف\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"قوائم لكتم الصوت:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"فلتر WoT\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"غير مشترك في الدفع\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"عنوان البرق\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"المفتاح العام مثل اسم المستخدم الخاص بك، يمكنك مشاركته مع أي شخص.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"اسم العرض\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"رأس المقال المعياري\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"الهاشتاغات الشائعة\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"تسجيل\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"المبلغ في ساتس\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"القائمة المبوبة\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"تم تكوين تقسيم مخزن زاب افتراضي من \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" لمطوري \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ، يمكنك تعطيله في أي وقت في \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"نوع\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"قريباً\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"أدخل دبوس لفتح المفتاح الخاص بك\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"تمت قراءة الكل\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"استخدم ملحق الموقِّع غير المرغوب لتسجيل الدخول\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"رد فعل تعبيري\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"توثيق الحساب\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"سيخصص جزء واحد من جلسات \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" جلسات \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" لبركة الباب.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"الخلاصة\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"دردشة جماعية\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"إمكانية استخدام نافذة.nostr لمتصفحات الويب\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"و \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" أخرى\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"و \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" أخرى\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"الصفحة الرئيسية\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"فقير\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"قادة المجتمع هم الأفراد الذين ينمون نظام nostr البيئي من خلال نشاطهم في مجتمعاتهم المحلية والمساعدة في ضم مستخدمين جدد. يمكن لأي شخص أن يصبح قائد مجتمع، ولكن القليل منهم يحمل اللقب الفخري الحالي.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"تفريغ\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"شكرا لاستخدامك \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"، يرجى النظر في التبرع إذا استطعت.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort هو مشروع مفتوح المصدر أنشأه أشخاص متحمسون في أوقات فراغهم، وتبرعاتكم محل تقدير كبير\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"لا يمكن التصويت لأن خدمة LNURL لا تدعم الوميض\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"إظهار المنشورات التي تحتوي على علامة تحذير المحتوى\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"مثبّت\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"اختيار بعض المواضيع المثيرة للاهتمام\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"يقرأ\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"تغليف الهدايا\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"ما الذي يدور في ذهنك؟\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"التبرع في السلسلة\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"حانة البرق RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"تم الحفظ\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"إرفاق الوسائط\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"مشاهدة البث\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"نبذة\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"فشل إرسال الصوت\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"يتم إرسال الرموز التعبيرية للتفاعل مع منشور\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"قد لا يدعم بعض عملاء نوستر هذه الخاصية\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"اشتراك\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" في الذاكرة)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"تحميل...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"تطبيق موقّع أندرويد\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"القوائم\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة خادم المستخدم\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"دليل العمل\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"وصف تدفق البروتوكول الأساسي\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" أكثر متعة معًا!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"الأوسمة\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"بيانات المستخدم الوصفية\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة متابعة التقليم\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"حساب المزامنة\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"رسائل\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"يدعم\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"دعوة\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"عرض الردود\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"الوسائط\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"هنا\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة المرحلات المحظورة\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"التفاعل\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"مخزن زابل\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"ستظهر مدفوعاتك المرسلة والمستلمة هنا.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"التفاعل (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"ترجمة DeepL\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"منع الحسابات المزيفة من انتحال حسابك\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"المسؤول\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" يتبع (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" مكرر)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"معرف\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"لا يمكن تسجيل الدخول باستخدام المفتاح الخاص خلال اتصال غير آمن، الرجاء استخدم إضافة مدير مفاتيح نوستر بدلاً من ذلك\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"المدفوعات\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"صفحة المستخدمين الجدد\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"متابعة\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"الرد المترابط للمحادثة الجماعية\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"إنشاء فاتورة\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"الملف التعريفي\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"الغاء المتابعة\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"تم النسخ الاحتياطي بالفعل\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" ساتوشي\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" ساتوشي\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"إنتهت صلاحية اشتراكك \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"تنظيف موجز الويب الخاص بك\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"خطأ داخلي: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"حدث الفيديو\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"حفظ\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 0,\n      \"value\": \"التفاعل \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"قدم طلبك الآن\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"يكتب\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"تساعد خدمة التوثيق NIP-05 الخاصة بنا في دعم تطوير هذا الموقع والحصول على شارة خاصة لامعة على موقعنا!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"المرحلات التي قمت بتوصيلها من قبل ويبدو أنها موثوقة.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"تسجيل اسم مستخدم Iris\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" أعد نشر\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" و ! \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" آخرين أعاد نشر\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"معلومات المحفظة\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"تسجيل الدخول إلى المد والجزر\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"اختر\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"الآن\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"المواضيع\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"الموافقة على وظيفة المجتمع\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"تكوين تجمع zap\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" أحب\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" و ! \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" أُعجب آخرون\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"جميع ما في \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"قم بدعوة أصدقائك\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"اشتقاق المفتاح الأساسي من العبارة الأولية الذاكرية\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"اشتر الآن\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"دفع\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"أحداثي \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"عنوان سنورت لنوستر\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"كلمة مرور المحفظة\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"نسخ الرابط\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"غير زاب\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"صفحة الحساب\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"خدمة وكيل الصور\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"المتابَعون \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"انقر لتحميل المحتوى من \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"دفع البرقية\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"طلب Zap\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"توصية المعالج\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" تم كتم صوت الملاحظات\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"يبدو أنك لا تملك واحد، تحقق من \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" للشراء!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ترحيل العمال\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"تابع الكل\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"خدمة تحميل الملفات\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"ومّض\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"ومّض\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"ابدأ\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"خيار: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"للقراءة فقط\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"تبديل\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"حدث التقويم الزمني\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"ميغابايت\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"تأكيد العطاء\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"رفع الحظر\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"المنشورات المرجعية\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"الإشعارات المسموح بها\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"البحث عن نشاط الحساب (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"مجمع كوينوينجوين\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"الأدوات\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"التجديد\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"الاستماع إلى هذه المقالة\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 0,\n      \"value\": \"محظور \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"سطح السفينة\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" المتابِعون\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"لم يتم العثور على شيء\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"المتابعون فقط\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"مهلا، يبدو أنك لا تملك عنوان نوستر بعد، يجب أن تحصل على واحدة! تحقق من \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"جائزة الشارة\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"تحميل\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" لها مرحلات (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"مرحلات موثوقة\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"نسخ احتياطية قابلة للتنزيل من موصل سنورت\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"زاب بول\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"الرموز التعبيرية المخصصة\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"مستخدم كتم صوت القناة\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"تثبيت\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"سوق نوستر (للأسواق المرنة)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"المتابِعون\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"تعليق تورنت\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"حدث التقويم القائم على التاريخ\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"الرد على موضوع المجموعة\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"البريد الإلكتروني <> جسر DM لعنوان Snort الخاص بك\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"خطأ غير معروف\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"شارات الملف الشخصي\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"ملاحظة\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"قيمة الومضة الافتراضية\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"محظور\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"فتح القفل\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"تجديد \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"تم تعطيل واجهة برمجة تطبيقات الإشعارات\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"مفتاحك الخاص هو (لا تشارك هذا مع أي شخص)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"تم كتم هذه الملاحظة\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"أضف إلى الملف الشخصي\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"فشلت الترجمة\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعجاب\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"اعرض أقل\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"العلوم\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"دبوس غير صحيح\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"برنامج\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"أدخل كلمة مرور المحفظة\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"البيانات الوصفية لقائمة الترحيل\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة الدردشات العامة\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"النسخ الاحتياطي الآن\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"صواعق البرق\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"إضافة موصّلات\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعداد التقارير\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(افتراضي)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"رسالة مباشرة مشفرة\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" أيام\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"قنوات الدردشة العامة\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"رابط قصير\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"مجموعات الإشارات المرجعية\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"إظهار الشارات\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"مستخدم\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"فشل تحليل تقسيم zap: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"اسم الترحيل المعروض ليس هو نفسه عنوان URL الكامل الذي تم إدخاله.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"طلب حذف الحدث\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"لن يتم عرض الملاحظات الصامتة\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"نجاح الاتصال:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة الاهتمامات\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"إطلاق مجموعات القطع الأثرية\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"أحداث الفيديو\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"داكن\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"تشفير الإصدار\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"غير معروف NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"حدث عرض الفيديو\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"مجاناً\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"إرسال ملاحظة إلى مجموعة فرعية من مرحلات الكتابة الخاصة بك\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"يمكن أن يساعد الحصول على معرف التوثيق NIP-05 في:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ساتس\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"مقاييس الترحيل\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"وسام الداعم\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"الحالة\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"مدفوع\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة الدبابيس\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"وقت التشغيل\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"يجب أن يكون الاسم أقل من \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" حرف\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"لديك حساب بالفعل؟\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"الهويات الخارجية في الملفات الشخصية\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة الترحيل لتلقي الرسائل المباشرة\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"إعادة النشر تحتاج إلى تأكيد يدويًا\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"إرسال انقسام الجلوس إلى\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"تم العثور على \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"عام\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" الملاحظات\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"تعديل الملف الشخصي\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"بدء الدردشة\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"يجب أن تكون قائمة جهات اتصال أو قائمة حلاقة\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة المجتمعات\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"صورة الملف الشخصي\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"ستقوم هذه الأداة بالبحث عن آخر حدث نشره جميع متابعيك وإزالة أولئك الذين لم ينشروا خلال 6 أشهر\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 هو أحد طرق التحقق المستندة إلى DNS والتي تساعد في التحقق من هويتك كمستخدم حقيقي.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"خيارات الاستطلاع\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"احصل على واحد مجاني\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"يتبعه الأصدقاء\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"مقدار العمل المراد تطبيقه على جميع الأحداث المنشورة\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"الأعمال\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"تحرير\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"قائمة خوادم تخزين الملفات\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"إرسال\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"مرفقات الوسائط\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"الدردشة العامة\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"الاسم محظور\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"الرقع\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"الاعتدال\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"اكتشف المزيد من المعلومات حول \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" على \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"نسخ المعرف\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"مرحلاتي\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"قم بتمويل الخدمات التي تستخدمها من خلال تقسيم جزء من كل الحدائق الخاصة بك إلى مجموعة من الأموال!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"كتم\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"من أجلك\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"الأصوات بواسطة \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"اذهب إلى\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"نوستر مخطط URI\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"موفر\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"تحميل الوسائط تلقائيًا\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ينتهي\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"شروط إضافية:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"البحث\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"المروحة\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"السماح\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"اللغة\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" إي ساتس\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL أو عنوان برق\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"المرحلات الشائعة\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"تطبيق أصلي\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"التصحيح\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"مسودة المحتوى الطويل\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"الوزن\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"تواصل\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"مالك\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"الكل\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"ومّض ساتوشي\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"الشطرنج (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" دقائق للقراءة\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"فشل تحميل خدمة LNURL\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"تظهر تلقائيا أحدث الملاحظات\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"المشاركون\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/az_AZ.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Yenidən dərc etmək istədiyinizə əminsiniz: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"İndi Ödəniş Edin\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gizli qrup söhbəti\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Növü\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"following\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Girişlər\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gələcəkdə hesabınızı idarə etmək üçün aşağıdakı parolu yadda saxladığınızdan əmin olun\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Qoşul\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"edit\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" repost etdi\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your space the way you want it 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hesab Dəstəyi\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"İctimai\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send anonymous usage metrics\"\n    }\n  ],\n  \"/clOBU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weekly\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profilinizi tapmağı və paylaşmağı asanlaşdırın\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daha çox\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"İdarə et\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Axtar...\"\n    }\n  ],\n  \"0HFX0T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use Exact Location\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Yanlış LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"adda icazə verilməyən simvollar var\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Politics\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show Status\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" saniyə\"\n    }\n  ],\n  \"1H4Keq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" users\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bu qeydi əlfəcinlərdən silmək istədiyinizə əminsiniz?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Wallet Connect konfiqurasiyasını daxil edin\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Be sure to back up your keys!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Qoşuldu: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" İzləyir\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check Signatures\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nature\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Söhbətlər\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Əlavə et\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Don't have an account?\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"İanə et\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Şifrə daxil edin\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Finish\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Əlfəcinlər\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bəyənməyənlər (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Note\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" saat\"\n    }\n  ],\n  \"2zJXeA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profiles\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign Up\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Articles\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"İşıq\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tərcüməçilər\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Siz \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats ilə səs verirsiniz\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" İzləyicilər\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Heç biri\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ləğv et\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Əsas Tərtibatçılar\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4MBtMa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name must be between 1 and 32 characters\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Life\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bəyənmə\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs məkanda ilk NIP-05 provayderlərindən biridir və münasib qiymətlərlə yaxşı domen kolleksiyası təklif edir\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Şəkilləri sıxmaq üçün imgproxy istifadə edin\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Özünə Qeyd\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Splits\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pubkey-ə köçürün\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"İstifadəçi adları Nostr-da unikal deyil. Nostr ünvanı qeydiyyatdan keçdiyiniz zaman sizin üçün unikal olan, insan tərəfindən oxuna bilən unikal ünvanınızdır.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap göndər\"\n    }\n  ],\n  \"6/SF6e\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"n\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"h1\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Cashu sats\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Replay\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retry\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" proksi şəklini yükləmək alınmadı, birbaşa yükləmək üçün bura klikləyin\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6TfgXX\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this, you may still receive some zaps as if zap splits was not configured\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bəyənmələr (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6k7xfM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending notes\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed by\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ödənilməmiş\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Qeydlər\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offline\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repostlar (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repostları təsdiqlə\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply To\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign up\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recipient\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid zap split: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"ad çox uzun\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Növbəti\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cavabla\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" izləyir\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Göndər\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retry publishing\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Ünvanı\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning fakturası\"\n    }\n  ],\n  \"ABAQyo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chats\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Valideyn\"\n    }\n  ],\n  \"AIgmDy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add up to 4 hashtags\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted Words\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort relayında limitsiz qeyd saxlama\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Səbəb\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Game\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Months\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daxil ol\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"ad çox qısa\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Yenilə\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr address (nip05)\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quote Repost\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Çıxış\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"and \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" others you follow\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Social Graph\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cache\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle all\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search notes\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show badges on profile pages\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username is available\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain Donation Address\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show status messages on profile pages\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirect issues HTTP redirect to the supplied lightning address\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GQPtfk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Join Stream\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Event\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You don't follow this person, click here to load media from \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", or update \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"your preferences\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to always load media from everybody.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap all \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Translate\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click here to load anyway\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use commas to separate words e.g. word1, word2, word3\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sport\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KHK8B9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Pin\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin too short\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps on this note will be split to the following users.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set as primary Nostr address (nip05)\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.to account\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O8Z8t9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show More\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free nostr address\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PJeJFc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Summary\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username must only contain lowercase letters and numbers\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter a pin to encrypt your private key, you must enter this pin every time you open \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"What should we call you?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"The author has marked this note as a \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sensitive topic\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ended\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Nostr Extension\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crypto\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stop listening\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove from my relays\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check all event signatures received from relays\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign In\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"You have an active iris.to account\"\n    }\n  ],\n  \"VL900k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recommended Relays\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Yes please\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"To see a full list of changes you can view the changelog \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically translate notes to your local language\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / nostr address\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with key\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send usage metrics\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Hashtags\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"No keys, no \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", There is no way to reset it if you don't back up. It only takes a minute.\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap splits to\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" is reserved for you!\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name or nym\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supported Extensions\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"No thanks\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Photography\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lists to mute:\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"d8gpCh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Try to use less than 5 hashtags to stay on topic 🙏\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Hashtags\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Register\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"A default Zap Pool split of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" has been configured for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" developers, you can disable it at any time in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pin to unlock your private key\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use a nostr signer extension to sign in\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", please consider donating if you can.\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show posts that have a content warning tag\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a few topics of interest\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gift Wraps\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain Donation\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" in memory)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" is more fun together!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"ha8JKG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show graph\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payments\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Already backed up\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" subscription is expired\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clean up your feed\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jTrbGf\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km - \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"location\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Register an Iris username\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Topics\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listen to this article\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" i̇zləyicilər\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Heç nə tapılmadı :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Yalnız izləyicilər\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Yüklə\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aktiv Abunəliklər\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort relayindən endirilə bilən ehtiyat nüsxələri\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"İzləyicilər\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Naməlum xəta\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bloklanıb\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been muted\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show less\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Science\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Incorrect pin\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back up now\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"rbrahO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Close\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Short link\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show Badges\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to parse zap split: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"tGXF0Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Lists\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Metrics\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u+LyXc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interactions\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Already have an account?\"\n    }\n  ],\n  \"uKqSN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows Feed\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats splits to\"\n    }\n  ],\n  \"ugyJnE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sending notes and other stuff\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Must be a contact list or pubkey list\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Image\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Business\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Düzəliş et\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Submit\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ad bloklanıb\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderation\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ünvanında \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" haqqında ətraflı məlumat əldə edin\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"ID-ni kopyala\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bütün zaplarınızın bir hissəsini vəsait hovuzuna bölməklə istifadə etdiyiniz xidmətləri maliyyələşdirin!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Səssiz\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kilidi aç\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provayder\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Medianı avtomatik yükləyin\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Müddəti bitir\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Additional Terms:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Axtar\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dil\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL və ya Lightning Ünvanı\"\n    }\n  ],\n  \"yNBPJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weight\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Əlaqə\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sahibi\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hamısı\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sats'larda Zap məbləği\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" mins to read\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL xidmətini yükləmək alınmadı\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ən son qeydləri avtomatik göstərin\"\n    }\n  ],\n  \"zwb6LR\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Mint:\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"zxvhnE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daily\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/ca_ES.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/cs_CZ.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/da_DK.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/de_DE.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bist du sicher, dass du \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" teilen möchtest?\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jetzt auszahlen\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alle Events für dein Profil in den lokalen Cache synchronisieren\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Staffel-Statistiken\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eingeloggt mit Schreibzugriff\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Geheimer Gruppenchat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Typ\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"folgen\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anmeldungen\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bitte sichere dir das folgende Passwort, um dein Handle in Zukunft verwalten zu können\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verbinden\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bearbeiten\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hat gerepostet\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dein Raum, so wie du ihn dir wünschst 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leeren\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konto Hilfe\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"Integration der HTTP-Dateispeicherung\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonyme Nutzungsmetriken senden\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gruppenchat-Nachricht\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mach dein Profil leichter zu finden und zu teilen\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Von Datei\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mehr laden\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-Adresse gehört nicht zu dir\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Schlüssel exportieren\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verwalten\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suche...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generische LNDHub-Wallet (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ungültige LNURL\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Umgang mit Erwähnungen\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Der Name enthält unerlaubte Zeichen\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Politik\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Status anzeigen\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Sek.\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Los\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trottelkram\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bist du sicher, dass du diese Note aus deinen Lesezeichen entfernen möchtest?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Wallet Connect Konfiguration eingeben\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stelle sicher, dass du deine Schlüssel absicherst!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verbunden mit: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Folgen\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Signaturen prüfen\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Natur\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unterhaltungen\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hinzufügen\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du hast noch kein Konto?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderierte Gemeinschaften\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Connect\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betreff-Tag in Text-Ereignissen\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutzer-Emoji-Liste\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Spenden\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Passwort eingeben\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abschließen\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Allgemeine Listen\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Lesezeichen\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gefällt nicht (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Neue Note\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gefolgt von Freunden von Freunden\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anwendungsspezifische Daten\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Stunden\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Neueste Artikel\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Antworten\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registrieren\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutzer-Status\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Artikel\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auf Medienservern gespeicherte Blobs\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Betrachter\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hell\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Übersetzer\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unbenannt\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du stimmst mit \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats ab\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" neues Event\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" neue Events\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Follower\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Verbinden\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ereignisse insgesamt:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Keine\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abbrechen\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Angebot\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primäre Entwickler\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dein neuer NIP-05-Handle ist:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leben\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gefällt nicht\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Schlüsselverschlüsselung\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs ist einer der ersten NIP-05 Anbieter und bietet eine gute Auswahl von Domains zu fairen Preisen\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verwende imgproxy um Bilder zu komprimieren\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fehlende Relais\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notiz an mich selbst\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Empfohlene Anwendungsbetreuer\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-Aufteilungen\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benachrichtigungs-API aktiviert\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-Ziel\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle kaufen\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Datei-Metadaten\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"An öffentlichen Schlüssel übertragen\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutzernamen sind auf Nostr nicht einzigartig. Die Nostr-Adresse ist deine eindeutige, menschenlesbare Adresse, die dir bei der Registrierung eindeutig zugeordnet ist.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap senden\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiederholung anschauen\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stummschaltungsliste\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erneut versuchen\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verbindung fehlgeschlagen:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Neue Länge der Follow-Liste \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bild von \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" konnte nicht durch Proxy geladen werden, klicke hier, um es direkt zu laden\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay empfehlen\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Siegel\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grund: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gesucht: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nicht alle Clients unterstützen dies, deshalb kann es sein, dass du immer noch einige Zaps erhältst, als ob Zap-Aufteilungen nicht konfiguriert wäre\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gefällt (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gefolgt von\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zusätzliche Metadatenfelder und Tags\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nicht bezahlt\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konten wechseln\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gut\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy verwendet HODL-Rechnungen, um die Zahlung weiterzuleiten, wodurch der öffentliche Schlüssel deiner Node verborgen bleibt\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Etikett\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki-Artikel\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Informationsdokument für Relais\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suchfunktion\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offline\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community-Anführer\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaktion\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modularer Artikelinhalt\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stummschalten von Notizen von Personen, die nicht zu Ihrem Vertrauensbereich gehören\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais schließen\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts bestätigen\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konventionen für die Verwendung von e- und p-Tags in Textereignissen durch die Kunden\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Antwort auf\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registrieren\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats zappen\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Empfänger\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ungültige Zap-Aufteilung: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gruppen-Thread\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name ist zu lang\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"bech32-kodierte Entitäten\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verbindungsphrase\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sets folgen\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Entwurf eines Rubrikenangebots\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weiter\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Antworten\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Folgt \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kalender Veranstaltung RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Senden\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stummgeschaltete Notes verbergen\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Veröffentlichen wiederholen\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-Adresse\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Zahlungsanforderung\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic Repost\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vorherige\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note von \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stummgeschaltete Wörter\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dieser Autor wurde stummgeschalten\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ein Produkt erstellen oder aktualisieren\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unbegrenzte Note Speicherung auf Snort Relais\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grund\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Großartig\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Spiel\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erstellung von Kanälen\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anzahl\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Push-Benachrichtigungen\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Monate\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anmelden\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name ist zu kurz\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"hat gezappt\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sie können ein einzelnes oder mehrere Relais hinzufügen, eines pro Zeile.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Schreibzugriff auf Snort Relais, mit 1 Jahr Speicherung von Events\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AI-Einbettungen / Vektorlisten\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais-basierte Gruppen\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aktualisieren\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marktplatz UI/UX\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-Adresse (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP-Authentifizierung\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Spende\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live-Veranstaltung\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zitat-Repost\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abmelden\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beliebte Server\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vorgeschlagene Follows\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video-Sets\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Zahlungsanforderung konnte nicht geladen werden\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil Zappen\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow-Liste\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow-Liste kürzen\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Angesagte Personen\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"und \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" anderen, denen du folgst\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repository-Ankündigungen\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Stummgeschaltet\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kalender\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Übersetzt von \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sozialer Graph\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Text Anmerkung Referenzen\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatisch jede Note beim Laden zappen\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abzeichen Definition\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Einstellungen\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kanal Nachricht ausblenden\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zwischenspeicher\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sats senden\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Neueste \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Notes anzeigen\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Als Auktion verkauftes Produkt\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"\\\"Über\\\" muss weniger als \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zeichen enthalten\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transferieren\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alle umschalten\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Browser\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Sats\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rechnung / Lightning-Adresse\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes suchen\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Datenanbieter\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abzeichen auf Profilseiten anzeigen\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaktion auf eine Website\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auf \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Übersetzen\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kurationssets\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutzerdefinierte Relais\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutzername ist verfügbar\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Schlüssel\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain Spendenadresse\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kaufen\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sorry, wir verstehen diese Art von Veranstaltung nicht (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), bitte versuchen Sie stattdessen eine der folgenden Anwendungen!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konto hinzufügen\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klassifizierte Inserate\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Brieftasche Antwort\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Authentifizierung von Clients gegenüber Relais\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Statusnachrichten auf Profilseiten anzeigen\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Angesagte Benutzer\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutzergruppen\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weiterleitung erstellt eine HTTP-Weiterleitung an die angegebene Lightning-Adresse\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jetzt abholen\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ein Fehler ist aufgetreten!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Folgt dir\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konten\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du hast keine Medienserver; versuche, welche hinzuzufügen.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Entfernen\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet auswählen\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Push abonniert\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unterstützte NIPs\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lesezeichen (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning-Adresse\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beanspruche deine enthaltene Snort Nostr-Adresse\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ungültige Lightning-Adresse\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Gefällt nicht\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Event verbreiten\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex-Schlüssel...\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Umgang mit unbekannten Ereignissen\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abmelden\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anführer-Infos\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lesezeichen-Liste\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bestellung bezahlt!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name wird später verfügbar sein\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stummgeschaltet\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cache leeren und neu laden\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet öffnen\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du folgst dieser Person nicht, klicke hier, um Medien von \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"zu laden, oder aktualisiere \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"deine Einstellungen\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", um Medien immer von allen zu laden.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relaiskritiken\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unterstützung\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zeitstempel des Verfalls\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Einen Verkaufsstand erstellen oder aktualisieren\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Letzter Beitrag \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sind sie sicher, dass sie diese Notiz entpinnen möchten?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kontodaten\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Folgt\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du musst ein \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Abonnent sein, um auf \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Deck zugreifen zu können\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Allen \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats zappen\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatische Übersetzung\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zuletzt gesehen:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sende \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats an \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Von keinem gefolgt, dem du folgst\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klicke hier, um trotzdem zu laden\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verbunden\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Angesagte Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnements\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benachrichtigungen nicht erlaubt\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutze Kommas um Wörter zu trennen, z.B. Wort1, Wort2, Wort3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji-Sets\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutzername\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sats an \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" senden\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sport\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Keine Lightning-Adresse\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonniere \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" für \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" und erhalte folgende Prämien\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suche in der Relaisliste\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nutzer suchen\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Webseite\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais sind Server, an die Sie sich zum Senden und Empfangen von Ereignissen anschließen. Streben Sie 4-8 Relais an.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Privater Schlüssel\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Durchschnittliche Latenzzeit:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Löschen\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anzeigen\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Externe Inhalts-IDs\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNDHub Konfiguration eingeben\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Höhepunkte\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live-Chat-Nachricht\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gelöscht\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Geschützte Ereignisse\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unbekannte Event-Art: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zuordnung von Nostr-Schlüsseln zu DNS-basierten Internet-Kennungen\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"PIN eingeben\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Brieftasche anfordern\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Als Benutzer ansehen?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-Ziele\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sieh dir den Code an \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"PIN zu kurz\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonym\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kommentar\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name muss zwischen 8 und 15 Zeichen lang sein\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-Adresse kann nicht verifiziert werden\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"In Zapstr öffnen\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrents\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zappte\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" andere zappten\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps auf diese Note werden an die folgenden Nutzer aufgeteilt.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menüs\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anführer werden\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zeigt \\\"ID kopieren\\\" und \\\"Event JSON kopieren\\\" im Kontextmenu jeder Nachricht an\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nicht verfügbar:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Raum verbinden\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Passwort\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Standardseite\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kurze Textnotiz\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Client-Authentifizierung\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Als primäre Nostr-Adresse (nip05) festlegen\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy-Tags\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Schicke diesen Link an deine Freunde und teile den Zauber des Nostr.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnement bezahlen\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-Adresse kaufen\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zählergebnisse\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" kaufen\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.to Konto\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bestätigen\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benachrichtigungen\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du hast bereits ein Abonnement dieser Art, bitte erneuern oder bezahlen\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Job-Feedback\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kann nicht mit \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats abstimmen. Bitte einen anderen Standard-Zap-Betrag festlegen\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Neue Benutzer Seite\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tot\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutze deinen Einladungscode, um Sats zu verdienen!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps Bescheinigungen für Ereignisse\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Geschenkverpackungen\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Teilen\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unbekannter Anmeldefehler\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kostenlose Nostr-Adresse erhalten\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dein Abonnement ist noch aktiv, du kannst es noch nicht erneuern\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erstellt\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zusammenführen von Anträgen\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update fehlgeschlagen, bitte versuche es erneut\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Langform-Inhalt\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scanne \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ungültige Nostr-Adresse\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Event JSON kopieren\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Standard)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gesamt heute (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Entfernung\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Einstellungen\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auf \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" empfangen\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unbekannter Datei-Header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erscheinungsbild\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaktionen werden auf jeder Seite angezeigt, wenn Reaktionen deaktiviert sind, werden sie nicht angezeigt\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relais\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Der private Schlüssel ist wie ein Passwort, kann aber nicht zurückgesetzt werden. Hüte ihn sorgfältig und zeige ihn niemandem. Sobald jemand deinen privaten Schlüssel hat, hat er für immer Zugang zu deinem Konto.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool funktioniert nur, wenn du eine der unterstützten Wallet-Verbindungen verwenden (WebLN, LNC, LNDHub oder Nostr Wallet Connect)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kanal-Nachricht\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du hast aktuell \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in deinem Zap Pool.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Direktnachrichten\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnement\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personen, denen du folgst\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service-Worker läuft nicht\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ankündigungen des Repository-Status\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutzername darf nur Kleinbuchstaben und Ziffern enthalten\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abgelaufen\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kurzporträt-Video-Event\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Von: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sind sie sicher, dass sie \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" löschen möchten?\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daten-Automaten\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lesezeichen\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ladehinweis: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berechtigungen\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gib eine PIN ein, um deinen privaten Schlüssel zu verschlüsseln. Du musst diese PIN jedes Mal eingeben, wenn du \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" öffnest.\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap an \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" senden\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning-Adresse aktualisieren\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnement kaufen\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beliebte Relais, die von Personen verwendet werden, denen Sie folgen.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN-Adressen-Proxy\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relaissätze\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Problem Tracker\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alle als gelesen markieren\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutzerdefiniert\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wie sollen wir dich nennen?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jetzt bezahlen\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anwendungsspezifische Daten\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Der Autor hat diese Note als ein \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sensibles Thema\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" markiert\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais in der Nähe Ihres geografischen Standorts.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Medien in Notes werden für ausgewählte Personen automatisch angezeigt, ansonsten wird nur der Link angezeigt\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Informationen zum Handler\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vorschau\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lokales Relais verwenden\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beendet\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anmeldung mit Nostr-Erweiterung\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mehr erfahren\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Krypto\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zinssätze\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kalender Ereignisse\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personen\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"gefällt\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konto\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abspielen beenden\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Definition der Gemeinschaft\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aus meinen Relais entfernen\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Empfangen\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alle von Relais erhaltenen Event-Signaturen überprüfen\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Neuer Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nutzer müssen die Inhaltswarnung akzeptieren, um den Inhalt deiner Note anzuzeigen.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server hinzufügen\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anmelden\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blockieren\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deine Bewerbung ist ausstehend\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du hast ein aktives iris.to Konto\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Teilen Sie eine personalisierte Einladung mit Freunden!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dein Empfehlungscode ist \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kennzeichnung\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wähle einen Upload-Dienst für deine Anhänge\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Öffentlicher Schlüssel (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ja, bitte\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eine vollständige Liste der Änderungen findest du im Changelog \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" stummgeschaltet\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profilbild\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Es sieht so aus, als hättest du keine Abonnements, du kannst eines \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" erhalten\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blockiert\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lokales\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stummschaltung aufheben\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vom Server\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ausgaben\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes automatisch in deine Landessprache übersetzen\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / Nostr-Adresse\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mit Schlüssel anmelden\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nutzungsmetriken senden\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Datei-Hosts\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verbindung zur Alby-Wallet\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Folgt-Relais-Gesundheit\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Einlösen\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Angesagte Hashtags\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaktionen\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Von \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" senden\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dein standardmäßiger Zap-Betrag ist \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, Beispielwerte werden daraus berechnet.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutzer\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL des Dienstes\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beliebte Medienserver.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Es sieht so aus, als würdest du nicht genug Leuten folgen. Schau dir \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" an, um Leute zu entdecken, denen du folgen kannst!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"Keine Schlüssel, kein \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \". Es gibt keine Möglichkeit, sie zurückzusetzen, wenn du keine Sicherungskopie gemacht hast. Es dauert nur eine Minute.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Öffentlicher Chat\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaktionen aktivieren\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verbinde eine Wallet, um sofortige Zahlungen zu senden\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Versuchen Sie ein anderes Relais\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kanal-Metadaten\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verbindungs-Passphrase eingeben\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delegierte Ereignisunterzeichnung\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verfassen einer Notiz\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jetzt aktivieren\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mitwirkende\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sende Zap-Aufteilungen an\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutzername iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ist reserviert für dich!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verschlüsselte Direktnachrichten\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hat dich zu \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eingeladen\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Medienserver speichern Medien, die du in Notes als Bilder und Videos teilen kannst\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Finanziere Entwickler und Plattformen, die NIP-05-Verifizierungsdienste anbieten\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes werden in Echtzeit in Global- und Notes-Tab gestreamt\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name oder Nym\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unterstützte Erweiterungen\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Sats bezahlt, \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Sats Gebühr\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verbindung zu deiner eigenen LND-Node mit Lightning-Node-Connect\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mehr anzeigen\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Freunde einladen\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonik\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dein Handle ist wie eine Lightning-Adresse und leitet dich zu deiner gewählten LNURL oder Lightning-Adresse weiter\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du bist ein Community-Anführer und verdienst \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" an den Abonnements der angeworbenen Nutzer!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service-Worker läuft\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kürzungsliste berechnen\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adresse erhalten\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eingeloggt mit schreibgeschütztem Zugriff\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Empfindlicher Inhalt\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Öffentlicher Schlüssel\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gerade eben\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Freundliche Stummschaltungen\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nein, danke\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leitet  um.\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wenn du eine Anfrage zu deiner NIP-05-Bestellung hast, schreibe bitte eine DM an \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erneut verbreiten\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du benutzt Alby? Gehe zu \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" um deine NWC Konfiguration zu erhalten!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Native Nostr-Wallet-Verbindung\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fotografie\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Direkte Nachricht\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Folge ich\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Medienserver\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alle stummschalten\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet verbinden\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unterstützung für mehrere Konten\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name ist registriert\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live-Aktivitäten\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zurück\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listen zum Stummschalten:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"WoT-Filter\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Push nicht abonniert\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN-Adresse\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Der öffentliche Schlüssel ist wie dein Benutzername, du kannst ihn mit jedem teilen.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anzeigename\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modulare Artikelüberschrift\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beliebte Hashtags\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registrieren\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betrag in Sats\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klassifiziertes Inserat\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eine Standard-Zap-Pool-Aufteilung von \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" wurde für \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Entwickler konfiguriert, du kannst sie jederzeit unter \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" deaktivieren\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Typ (kind)\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kommt bald\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"PIN eingeben, um deinen privaten Schlüssel zu entsperren\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alle als gelesen markieren\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verwende eine Nostr-Signier-Erweiterung um dich anzumelden\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaktions-Emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verifiziert werden\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ein einzelner Zap von \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats wird \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats dem Zap Pool zuweisen.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Futtermittel\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gruppenchat\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"window.nostr-Fähigkeit für Webbrowser\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" anderer\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" andere\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Startseite\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Schlecht\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community-Anführer sind Personen, die das Nostr-Ökosystem verstärken, indem sie in ihren lokalen Gemeinschaften aktiv sind und dabei helfen, neue Nutzer zu gewinnen. Jeder kann ein Community-Anführer werden, aber nur wenige tragen diesen aktuellen Ehrentitel.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ausgeben\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vielen Dank, dass du \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" verwendest. Wenn du die Möglichkeit hast, hilf uns gerne mit einer Spende.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort ist ein Open-Source-Projekt, das von passionierten Menschen in ihrer Freizeit entwickelt wird. Eure Spenden werden sehr geschätzt.\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abstimmung nicht möglich, da der LNURL-Dienst keine Zaps unterstützt\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beiträge anzeigen, die mit einer Inhaltswarnung versehen sind\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Angeheftet\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wähle ein paar Themen von Interesse\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lesen\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gift Wraps\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Was ist gerade los?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-Chain Spende\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gespeichert\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Medien anhängen\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stream ansehen\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Über\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stimmabgabe fehlgeschlagen\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji, das gesendet werden soll, wenn auf eine Note reagiert wird\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nicht alle Clients unterstützen das\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnieren\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" im Speicher)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lädt...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Android Signer-Anwendung\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verzeichnisse\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste der Benutzerserver\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Arbeitsnachweis\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beschreibung des grundlegenden Protokollablaufs\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" macht gemeinsam mehr Spaß!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auszeichnungen\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutzer-Metadaten\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow-Liste kürzen\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konto synchronisieren\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nachrichten\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unterstützt\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Einladung\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Antworten anzeigen\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Medien\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"hier\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste der gesperrten Relais\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interaktion\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deine gesendeten und empfangenen Zahlungen werden hier angezeigt.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaktionen (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL Übersetzungen\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verhindere, dass gefälschte Konten dich imitieren\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verwaltung\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" folgt (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Duplikate)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anmeldung mit privatem Schlüssel bei einer unsicheren Verbindung nicht möglich, bitte verwenden Sie stattdessen eine Nostr Schlüssel Manager Erweiterung\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zahlungen\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seite für neue Benutzer\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Folgen\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gruppenchat Threaded Reply\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rechnung erstellen\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Entfolgen\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bereits gesichert\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dein \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Abonnement ist abgelaufen\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Räume deinen Feed auf\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interner Fehler: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video-Veranstaltung\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Speichern\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reaktionen\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jetzt bewerben\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Schreiben\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unser eigener NIP-05-Verifizierungsdienst unterstützt die Entwicklung dieser Website. Unterstütze uns und erhalte ein Abzeichen auf unserer Seite!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais, an die Sie schon einmal angeschlossen haben und die Ihnen zuverlässig zu sein scheinen.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris-Benutzernamen registrieren\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" hat gerepostet\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" andere haben gerepostet\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Brieftaschen-Infos\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidal-Anmeldung\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wählen Sie\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"eben\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Themen\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Genehmigung des Gemeinschaftspostens\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-Pool konfigurieren\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" gefällt das\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" anderen gefällt das\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alles aus \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lade deine Freunde ein\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grundlegende Ableitung des Schlüssels aus der mnemonischen Seed-Phrase\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jetzt kaufen\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bezahlen\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meine Events: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort Nostr-Adresse\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Passwort\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Link kopieren\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nicht-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kontoseite\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bildproxy-Dienst\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Folgt \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klicken, um Inhalt von \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" zu laden\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Zahlungsanforderung bezahlen\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-Anfrage\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Empfehlung für Handler\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" die Noten sind stummgeschaltet\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"Es sieht so aus, als hättest du keine, checke \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" um eine zu kaufen!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Arbeiter-Relais\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Allen folgen\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Datei-Upload-Dienst\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"hat gezappt\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"haben gezappt\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Starten\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nur lesen\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wechseln\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zeitbasiertes Kalenderereignis\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bestätigung des Angebots\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Freigeben\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lesezeichen\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benachrichtigungen erlaubt\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suche nach Kontoaktivität (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coinjoin-Pool\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tools\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erneuern\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Diesen Artikel anhören\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blockiert\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deck\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Follower\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Keine Treffer :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nur für Folgende\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, es sieht so aus, als hättest du noch keine Nostr-Adresse, du solltest eine anlegen! Sieh dir \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" mal an\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abzeichen-Auszeichnung\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hochladen\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" haben Relais (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zuverlässige Relais\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Herunterladbare Backups vom Snort Relais\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-Pool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benutzerdefinierte Emoji\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kanal Stummschaltung Benutzer\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anheften\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (für widerstandsfähige Marktplätze)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follower\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent-Kommentar\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Datumsbasiertes Kalenderereignis\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gruppe Thread Antwort\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"E-Mail <> DM Brücke für deine Snort Nostr-Adresse\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unbekannter Fehler\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profilabzeichen\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Standard Zap Betrag\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blockiert\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Entsperren\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" erneuern\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Benachrichtigungs-API deaktiviert\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dein privater Schlüssel ist (Teile diesen mit niemanden!)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Diese Note wurde stummgeschaltet\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zum Profil hinzufügen\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Übersetzung fehlgeschlagen\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gefällt mir\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weniger anzeigen\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wissenschaft\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Falsche PIN\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Passwort eingeben\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadaten der Relaisliste\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste der öffentlichen Chats\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jetzt sichern\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blitzschläge\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais hinzufügen\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berichterstattung\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Standard)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verschlüsselte Direktnachricht\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Tage\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Öffentliche Chat-Kanäle\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kurzlink\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lesezeichen-Sets\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abzeichen anzeigen\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nutzer\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fehler beim Parsen der Zap-Aufteilung: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Der angezeigte Relay-Name stimmt nicht mit der eingegebenen vollständigen URL überein.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Antrag auf Löschung eines Ereignisses\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stummgeschaltete Notes werden nicht angezeigt\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erfolgreiche Verbindung:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste der Interessen\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Artefaktsets freigeben\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video-Veranstaltungen\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dunkel\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Versionierte Verschlüsselung\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unbekannt NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Videoansicht Ereignis\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kostenlos\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sende Note zu einer Untergruppe deiner Schreib-Relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eine NIP-05 Verifizierung kann helfen:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Sats\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais Metriken\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unterstützer-Abzeichen\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Status\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bezahlt\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin-Liste\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betriebszeit\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name muss weniger als \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zeichen enthalten\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hast du bereits ein Konto?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"Externe Identitäten in Profilen\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay-Liste zum Empfang von DMs\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts müssen manuell bestätigt werden\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sende Sats-Aufteilungen an\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Events gefunden\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Öffentlich\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Notes\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil anpassen\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat starten\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muss eine Kontaktliste oder Pubkey-Liste sein\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste der Gemeinschaften\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profilbild\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dieses Tool sucht nach dem letzten Event, das von allen deinen Follows veröffentlicht wurde, und entfernt diejenigen, die in den letzten 6 Monaten nichts veröffentlicht haben.\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 ist eine DNS-basierte Verifizierungsspezifikation, die dabei hilft, dich als echten Benutzer zu validieren.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Umfrageoptionen\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eine kostenlos erhalten\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Von Freunden gefolgt\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maß an Arbeit, die auf alle veröffentlichte Events angewendet werden soll\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Business\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anpassen\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dateiablage-Server-Liste\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Absenden\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Medienanhänge\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Öffentlicher Nostr-Chat\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name ist blockiert\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aufnäher\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderation\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erfahre mehr über \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" auf \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"ID kopieren\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meine Relais\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unterstütze die von dir genutzten Dienste, indem du einen Teil deiner Zaps in einen Spendenpool einzahlst!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stummschalten\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Für dich\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stimmen nach \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gehe zu\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: URI-Schema\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anbieter\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Medien automatisch laden\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Läuft aus\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zusätzliche Bedingungen:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suche\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"FAN\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erlauben\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sprache\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL oder Lightning-Adresse\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beliebte Relais\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Native App\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debuggen\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Entwurf von Langform-Inhalten\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gewichtung\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kontakt\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eigentümer\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alle\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Betrag in Sats\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Schach (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Minuten zum Lesen\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fehler beim Laden des LNURL-Dienstes\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Neueste Notes automatisch anzeigen\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Teilnehmer\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/el_GR.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/en.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sync all events for your profile into local cache\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logged in with write access\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+W+Kof\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu Wallet History\"\n    }\n  ],\n  \"+mO9i4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Code Snippet\"\n    }\n  ],\n  \"+sDqqq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Peer-to-peer Order events\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"following\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"edit\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your space the way you want it 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP File Storage Integration\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send anonymous usage metrics\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"From File\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr address does not belong to you\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic LNDHub wallet (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0PtoZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL for AI Agent service\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handling Mentions\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0oMk/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Chats\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Politics\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show Status\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"git stuff\"\n    }\n  ],\n  \"1A6QoL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Author-Derived Servers (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"1GvBMj\": [\n    {\n      \"type\": 0,\n      \"value\": \"internal reference\"\n    }\n  ],\n  \"1Ia8qN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Processing\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Be sure to back up your keys!\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check Signatures\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nature\"\n    }\n  ],\n  \"1sawgR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Page \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"current\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"total\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" items)\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Don't have an account?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderated Communities\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Connect\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subject tag in text events\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"User emoji list\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2Npgrt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Has imeta tags for images, but no r tags\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Finish\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic lists\"\n    }\n  ],\n  \"2YxhJx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reserved Cashu Wallet Tokens\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Note\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed by friends of friends\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Application-specific data\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"2xzTkL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Curated lists of people to follow.\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Latest Articles\"\n    }\n  ],\n  \"2zJXeA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profiles\"\n    }\n  ],\n  \"3/w0Mr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Post Event\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign Up\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"User Statuses\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Articles\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blobs stored on mediaservers\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3VI9mt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save Changes\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" viewers\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bid\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Life\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4OQuna\": [\n    {\n      \"type\": 0,\n      \"value\": \"Draft Event\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key Encryption\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Missing Relays\"\n    }\n  ],\n  \"4oPRxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supported Kinds:\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"4rxi5n\": [\n    {\n      \"type\": 0,\n      \"value\": \"hardcopy reference\"\n    }\n  ],\n  \"4tKMJS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software Application\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recommended Application Handlers\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Splits\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications API Enabled\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Goal\"\n    }\n  ],\n  \"5h6Dks\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ask me anything about Nostr or \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"appName\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"File Metadata\"\n    }\n  ],\n  \"5tgBVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"You have unsaved changes to your profile, contacts, relays, or settings.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Replay\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute list\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retry\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"New follow list length \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recommend Relay\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seal\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6Z3bDG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu Wallet Event\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this, you may still receive some zaps as if zap splits was not configured\"\n    }\n  ],\n  \"6dmn4m\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thread\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6m1Zkw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Monitor Announcement\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed by\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Extra metadata fields and tags\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch accounts\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Good\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Label\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki article\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Information Document\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search Capability\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offline\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Leader\"\n    }\n  ],\n  \"7aCUzE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Choose a DVM (Data Vending Machine) to provide content.\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7mC9+e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Has images but no imeta tags\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute notes from people who are outside your web of trust\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Close Relays\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conventions for clients' use of e and p tags in text events\"\n    }\n  ],\n  \"8Cw1Fj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Link Set\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply To\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign up\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recipient\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid zap split: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"bech32-encoded entities\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow sets\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Draft Classified Listing\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"90OuKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Nostr Connect\"\n    }\n  ],\n  \"92gdbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Discovery\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9O+VX8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Partial\"\n    }\n  ],\n  \"9RNiUn\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Feed\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar Event RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9WTAKy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search sets..\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hide muted notes\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retry publishing\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9qtLJC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payment Required\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"9zaOuc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggestions by\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic Repost\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AKrsKF\": [\n    {\n      \"type\": 0,\n      \"value\": \"API key for AI Agent service\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted Words\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create or update a product\"\n    }\n  ],\n  \"AgentKey1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Agent Key\"\n    }\n  ],\n  \"AgentUrl1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Agent URL\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Great\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Game\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Creation\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Count\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Push notifications\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Months\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"Ayx8rG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Curated Publication Index\"\n    }\n  ],\n  \"B2Cjgu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Nostr Address\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can add a single or multiple relays, one per line.\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AI Embeddings / Vector lists\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay-based Groups\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"Bb19fh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Posts by users that you are not following directly, but your follows are following them.\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marketplace UI/UX\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP Auth\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Event\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quote Repost\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Servers\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video sets\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CI0LCO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Has images but no r tags\"\n    }\n  ],\n  \"CJ0biq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Response\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow List\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prune follow list\"\n    }\n  ],\n  \"CSOaM+\": [\n    {\n      \"type\": 1,\n      \"value\": \"note_type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"title\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"and \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" others you follow\"\n    }\n  ],\n  \"CaZ1xw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alt tag starts with \\\"A short note: \\\"\"\n    }\n  ],\n  \"CcqOwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow Lists\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repository announcements\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Social Graph\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Text Note References\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge Definition\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Hide Message\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cache\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Product sold as an auction\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"About must be less than \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" characters\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle all\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Browser\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sats\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invoice / Lightning Address\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search notes\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show badges on profile pages\"\n    }\n  ],\n  \"EW5L+2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Provider\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction to a website\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Curation sets\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain Donation Address\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sorry, we dont understand this event kind (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), please try one of the following apps instead!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Classified Listings\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Response\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Authentication of clients to relays\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show status messages on profile pages\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"User groups\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirect issues HTTP redirect to the supplied lightning address\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accounts\"\n    }\n  ],\n  \"FvzcUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"👋 Welcome to AI Chat!\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"You dont have any media servers, try adding some.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribed to Push\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supported NIPs\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GLdw/8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File Message\"\n    }\n  ],\n  \"GQo+OV\": [\n    {\n      \"type\": 0,\n      \"value\": \"prompt reference\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent\"\n    }\n  ],\n  \"GqKcVm\": [\n    {\n      \"type\": 0,\n      \"value\": \"App curation sets\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid Lightning Address\"\n    }\n  ],\n  \"GrDnue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nutzap Mint Recommendation\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"GtIxzZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"via \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"client\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Event\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dealing with Unknown Events\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leader Info\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark list\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HCUGGO\": [\n    {\n      \"type\": 0,\n      \"value\": \"DVM suggested users to follow.\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You don't follow this person, click here to load media from \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", or update \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"your preferences\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to always load media from everybody.\"\n    }\n  ],\n  \"HirEqa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leave empty to use default model from agent service\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay reviews\"\n    }\n  ],\n  \"HqOhtW\": [\n    {\n      \"type\": 0,\n      \"value\": \"No DVM providers found\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Support\"\n    }\n  ],\n  \"Hqo/rL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Curated Publication Content\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expiration Timestamp\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create or update a stall\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Last post \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Data\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"You must be a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" subscriber to access \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" deck\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap all \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Translate\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not followed by anyone you follow\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click here to load anyway\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications Not Allowed\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use commas to separate words e.g. word1, word2, word3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji sets\"\n    }\n  ],\n  \"JCOqRK\": [\n    {\n      \"type\": 0,\n      \"value\": \"P-tag with non-standard marker (nickname)\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sport\"\n    }\n  ],\n  \"JJNc3c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Previous\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search relays list\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays are servers you connect to for sending and receiving events. Aim for 4-8 relays.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"External Content IDs\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Highlights\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Chat Message\"\n    }\n  ],\n  \"KN7zKn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Error\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Protected Events\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mapping Nostr keys to DNS-based internet identifiers\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Pin\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Request\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"View as user?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Goals\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LPw/EW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr address' use the \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"NIP-05\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" specification which is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin too short\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name must be between 8 and 15 characters\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cannot verify Nostr Address\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrents\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps on this note will be split to the following users.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Become a leader\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MF9ke5\": [\n    {\n      \"type\": 1,\n      \"value\": \"size\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bytes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kb\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" KB)\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Join Room\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Short Text Note\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Client Authentication\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy Tags\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send this link to your friends and share the magic of the nostr.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Counting results\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Job Feedback\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts\"\n    }\n  ],\n  \"Nw1A4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Content ends with double newline\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dead\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use your invite code to earn sats!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps Attestations for Events\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gift Wrap\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free nostr address\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Merge Requests\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Long-form Content\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scanning \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid Nostr Address\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distance\"\n    }\n  ],\n  \"P8zI6H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Slide Set\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PJLVAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid cashu token\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Receiving to \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PYo9HP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Events Breakdown\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PlfdcA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ask \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"appName\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" AI\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QGVI63\": [\n    {\n      \"type\": 0,\n      \"value\": \"Agent\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"The private key is like a password, but it cannot be reset. Guard it carefully and never show it to anyone. Once someone has your private key, they will have access to your account forever.\"\n    }\n  ],\n  \"QW5bRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blossom Blob Debug Info\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Message\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Direct Messages\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R7x0mX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat Message\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker Not Running\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repository state announcements\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username must only contain lowercase letters and numbers\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Short-form Portrait Video Event\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RgEsTx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" relay, with 1 year of event retention\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Vending Machines\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"RrUIfX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" relay\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading note: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permissions\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter a pin to encrypt your private key, you must enter this pin every time you open \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular relays used by people you follow.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay sets\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Problem Tracker\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"What should we call you?\"\n    }\n  ],\n  \"So+Y+A\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nutzap\"\n    }\n  ],\n  \"SopQOK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Web bookmarks\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Application-specific Data\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"The author has marked this note as a \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sensitive topic\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays close to your geographic location.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handler information\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use Local Relay\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ended\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Nostr Extension\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Learn more\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crypto\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interest sets\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar Events\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"TvwmZr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hash\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account\"\n    }\n  ],\n  \"TzA+w1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed By Friends\"\n    }\n  ],\n  \"U/fbvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Git Replies (deprecated)\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stop listening\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Definition\"\n    }\n  ],\n  \"U3P+36\": [\n    {\n      \"type\": 0,\n      \"value\": \"Has both r tags and imeta tags for images\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove from my relays\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Receive\"\n    }\n  ],\n  \"ULsJTk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Published by\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check all event signatures received from relays\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Server\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign In\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your application is pending\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share a personalized invitation with friends!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your referral code is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"UxkETt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show Thread Data\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Labeling\"\n    }\n  ],\n  \"V2dZY9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"V93INS\": [\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"Created by\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"dark\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VZzKYK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Client Fingerprint\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"To see a full list of changes you can view the changelog \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Local\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WTrOy3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"From Server\"\n    }\n  ],\n  \"WfYjW2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload Banner\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Issues\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically translate notes to your local language\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / nostr address\"\n    }\n  ],\n  \"X1TTm3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Single newline only before image URLs\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with key\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send usage metrics\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alby wallet connection\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows Relay Health\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Hashtags\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sending from \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular media servers.\"\n    }\n  ],\n  \"YLGfQn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write message\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont follow enough people, take a look at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to discover people to follow!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"No keys, no \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", There is no way to reset it if you don't back up. It only takes a minute.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Chat\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"YYUgme\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge Info\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect a wallet to send instant payments\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Try another relay\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Metadata\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delegated Event Signing\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compose a note\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap splits to\"\n    }\n  ],\n  \"ZT17bG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu Wallet Tokens\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encrypted Direct Messages\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" invited you to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media servers store media which you can share in notes as images and videos\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name or nym\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supported Extensions\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, fee \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"aYJIC7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type:\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"af6Oxx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Authors (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"agOXPD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Size\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite Friends\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are a community leader and are earning \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" of referred users subscriptions!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker Running\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compute prune list\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Address\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logged in with read-only access\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kind mute sets\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirects\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"c6BMLV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Starter Pack\"\n    }\n  ],\n  \"cE4Hfw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Discover\"\n    }\n  ],\n  \"cF3ruj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow All\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Native nostr wallet connection\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Photography\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Direct Message\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media Servers\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"ctXnlV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount:\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Activities\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lists to mute:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"WoT Filter\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not Subscribed to Push\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"The public key is like your username, you can share it with anyone.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Hashtags\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount in sats\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Classified Listing\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"A default Zap Pool split of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" has been configured for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" developers, you can disable it at any time in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"do3Om+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ask me anything...\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kind\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pin to unlock your private key\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use a nostr signer extension to sign in\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Feed\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"window.nostr capability for web browsers\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Home\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poor\"\n    }\n  ],\n  \"f0Mcqr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Double newlines before image URLs\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community leaders are individuals who grow the nostr ecosystem by being active in their local communities and helping onboard new users. Anyone can become a community leader, but few hold the current honorary title.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dump\"\n    }\n  ],\n  \"fB8U26\": [\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" is an open source project built by passionate people in their free time, your donations are greatly appreciated\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", please consider donating if you can.\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show posts that have a content warning tag\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a few topics of interest\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gift Wraps\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain Donation\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Attach Media\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Stream\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gPxSgn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow Sets\"\n    }\n  ],\n  \"gQP3HJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Found \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" events!\"\n    }\n  ],\n  \"gSqFQf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Double newlines before quoted notes\"\n    }\n  ],\n  \"gWDnbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent content that people you follow have reacted to.\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" in memory)\"\n    }\n  ],\n  \"gib7iq\": [\n    {\n      \"type\": 0,\n      \"value\": \"No handles found\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Android Signer Application\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lists\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"User server list\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"grRQTM\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" people\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Basic protocol flow description\"\n    }\n  ],\n  \"h1gtUi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll\"\n    }\n  ],\n  \"h3FJTU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not a thread!\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" is more fun together!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"User Metadata\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prune Follow List\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sync Account\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked relays list\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interaction\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your sent and received payments will show up here.\"\n    }\n  ],\n  \"i8CwA4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Extension\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Admin\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" follows (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" duplicates)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payments\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"new users page\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat Threaded Reply\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generate Invoice\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"ixpzZx\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" liked\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Already backed up\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" subscription is expired\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clean up your feed\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video Event\"\n    }\n  ],\n  \"jvC7xj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ask me to post, reply, search, or help you navigate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"appName\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apply Now\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Info\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidal login\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Topics\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Post Approval\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Configure zap pool\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite your friends\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Basic key derivation from mnemonic seed phrase\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"My events: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy link\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Request\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handler recommendation\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes have been muted\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Worker Relay\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n          ]\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read Only\"\n    }\n  ],\n  \"n19OA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Agent Model\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Time-Based Calendar Event\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bid confirmation\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications Allowed\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Searching for account activity (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coinjoin Pool\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tools\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listen to this article\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deck\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oEyQP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" relay\"\n    }\n  ],\n  \"oHPB8Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"opNVQC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpin\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge Award\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" have relays (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEQAGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Root e-tag is last in tags array (with multiple e-tags)\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Emoji\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Mute User\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pxF+t0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (for resilient marketplaces)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent Comment\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Date-Based Calendar Event\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Thread Reply\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Badges\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications API Disabled\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been muted\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"qx+v3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Request to Vanish\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show less\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Science\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Incorrect pin\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay List Metadata\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public chats list\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back up now\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Zaps\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reporting\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rhSI1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Model\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encrypted Direct Message\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Chat Channels\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark sets\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show Badges\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sV1+m+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading context...\"\n    }\n  ],\n  \"sXNv9b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid notification context\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to parse zap split: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"The relay name shown is not the same as the full URL entered.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Event Deletion Request\"\n    }\n  ],\n  \"sbSCT3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private event relay list\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted notes will not be shown\"\n    }\n  ],\n  \"t+iuoN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" nostr address\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interests list\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Release artifact sets\"\n    }\n  ],\n  \"tO0JqG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Source Code\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video Events\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Versioned Encryption\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Free\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Status\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin list\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uptime\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name must be less than \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" characters\"\n    }\n  ],\n  \"uBjtbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Try: Summarize my timeline\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Already have an account?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"External Identities in Profiles\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay list to receive DMs\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats splits to\"\n    }\n  ],\n  \"uex/ui\": [\n    {\n      \"type\": 0,\n      \"value\": \"external web reference\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Found \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" events\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Must be a contact list or pubkey list\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Communities list\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Image\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"This tool will search for the last event published by all of your follows and remove those who have not posted in 6 months\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed by friends\"\n    }\n  ],\n  \"vuMG+5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Looking for:\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Business\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wIr5EQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Explicit Servers (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"File storage server list\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Submit\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media Attachments\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Patches\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderation\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"wvoA3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Picture\"\n    }\n  ],\n  \"wyAr3x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Results:\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"My Relays\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"For you\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: URI scheme\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Additional Terms:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"xrKHS6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Success\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"FAN\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Allow\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Relays\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Native App\"\n    }\n  ],\n  \"ymVhDw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" nostr address\"\n    }\n  ],\n  \"ynNi3b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active URLs (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"active\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"max\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"ywyVQg\": [\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" nostr address\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Draft Long-form Content\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weight\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chess (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" mins to read\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Participants\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/es_ES.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"¿Estás seguro de que quieres republicar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pago inmediato\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sincroniza todos los eventos de tu perfil en la caché local\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Estadísticas de relevos\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conectado con acceso de escritura\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat de grupo secreto\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tipo de Zap\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"siguiente\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingresos\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Asegúrate de guardar ésta contraseña para gestionar tu NIP-05 en el futuro\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conectar\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"editar\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reenviado\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tu espacio como tú quieras 😌.\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claro\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Soporte de Cuenta\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"Integración de almacenamiento de archivos HTTP\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar métricas de uso anónimas\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensaje de chat en grupo\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Haz tu perfil más fácil de encontrar y compartir\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"De archivo\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Más información\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"La dirección Nostr no le pertenece\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claves de exportación\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gestionar\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buscar...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cartera genérica LNDHub (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL inválida\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tratamiento de las menciones\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"el nombre tiene caracteres inválidos\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Política\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar estado\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" seg\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vaya a\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"git cosas\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"¿Estás seguro de que quieres eliminar esta nota de tus favoritos?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Introduzca la configuración de Nostr Wallet Connect\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Asegúrate de hacer una copia de seguridad de tus llaves.\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conectado a: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Siguiendo\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Firmas de cheques\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Naturaleza\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversaciones\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Añadir\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"¿No tiene cuenta?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comunidades moderadas\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Billetera Connect\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Etiqueta de asunto en eventos de texto\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de emoji de usuario\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donar\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Introduce la contraseña\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acabado\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listas genéricas\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Marcadores\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"No me gusta (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nueva Nota\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguidos por amigos de amigos\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Datos específicos de la aplicación\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" horas\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Últimos artículos\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Respuestas\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inscribirse\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Estados de usuario\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Artículos\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blobs almacenados en servidores\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" telespectadores\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claro\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"traductores\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sin título\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Estás votando con \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" nueva nota\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" nuevas notas\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Seguidores\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cartera\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total de eventos:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ninguno\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancelar\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Oferta\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Desarrolladores principales\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tu nuevo NIP-05 es:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vida\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"No me gusta\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cifrado de clave privada\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plbes es uno de los primeros proveedores de NIP-05 y ofrece una buena colección de dominios a precios razonables.\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usar imgproxy para comprimir imágenes\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés ausentes\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensajes guardados\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manipuladores de aplicaciones recomendados\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Splits\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"API de notificaciones activada\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Objetivo Zap\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comprar Handle\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadatos de archivos\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transferir a Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Los nombres de usuario no son únicos en Nostr. La dirección nostr es su dirección única legible por humanos que es única para usted al registrarse.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar zap\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ver la repetición\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de silencio\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reintentar\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conexión fallida:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nueva longitud de la lista de seguimiento \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fallo al enviar la imagen desde \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", haga clic aquí para cargarla directamente.\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recomendar relé\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sello\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Razón: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buscando: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"No todos los clientes lo soportan, puede que aún reciba algunos zaps como si zap splits no estuviera configurado\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Me gusta (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguido de\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Campos de metadatos y etiquetas adicionales\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"No pagado\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cambiar de cuenta\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bien\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notas\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"El proxy utiliza facturas HODL para remitir el pago, lo que oculta la pubkey de tu nodo\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Etiqueta\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Artículo Wiki\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Documento de información sobre el relé\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Capacidad de búsqueda\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fuera de línea\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Líder comunitario\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reacción\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contenido modular de los artículos\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Silencia las notas de personas que están fuera de tu red de confianza\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cerrar Relés\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirmar reposts\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Convenciones para el uso por los clientes de las etiquetas e y p en los eventos de texto\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Responder a\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inscríbete\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zapear \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Destinatario\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Split zap no válido: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hilo de grupo\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"el nombre es demasiado largo\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"entidades codificadas con bech32\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Frase de emparejado\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Siga los juegos\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Borrador de anuncios clasificados\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Siguiente\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Responder\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Siguiendo a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendario Evento RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ocultar notas silenciadas\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reintentar la publicación\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dirección Nostr\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Factura Lightning\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traspaso genérico\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pariente\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Palabras mudas\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Este autor ha sido silenciado\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crear o actualizar un producto\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retención de nota ilimitada en relé Snort\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Razón\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Genial\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Juego\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Creación de canales\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cuenta\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notificaciones push\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meses\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acceso\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"el nombre es demasiado corto\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapeó\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Puede añadir uno o varios relés, uno por línea.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Escriba el acceso al relé Snort, con 1 año de retención de eventos\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AI Embeddings / Listas vectoriales\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grupos basados en relés\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Actualización\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marketplace UI/UX\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dirección nostr (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relé\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"Autenticación HTTP\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donación relámpago\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento en directo\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Volver a citar\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salir\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Servidores populares\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sugerencias\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conjuntos de vídeo\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Error al cargar factura\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Perfil Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de seguimiento\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Podar lista de seguimiento\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personas de moda\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"y \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" otros a los que sigues\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anuncios de repositorios\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Silenciados\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendario\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traducido de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gráfico social\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Texto Nota Referencias\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap automático al cargar cada nota\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Definición de insignia\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Configuración\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Canal Ocultar mensaje\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Caché\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar últimas \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notas\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"En directo\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Producto vendido en subasta\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acerca de debe tener menos de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" caracteres\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transferir\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cambiar todo\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Navegador\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sats\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Factura / Dirección del rayo\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notas de búsqueda\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proveedores de datos\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar insignias en las páginas de perfil\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reacción a un sitio web\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traducir a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conjuntos de conservación\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés personalizados\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nombre de usuario disponible\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clave\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dirección de donación en cadena\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comprar\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"¡Lo sentimos, no entendemos este tipo de evento (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), por favor pruebe una de las siguientes aplicaciones en su lugar!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Servidor\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Añadir Cuenta\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anuncios clasificados\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Respuesta de la cartera\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Autenticación de clientes ante los repetidores\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar mensajes de estado en las páginas de perfil\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usuarios en tendencia\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grupos de usuarios\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirección emite una redirección HTTP a la dirección de rayos suministrada\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reclama Ahora\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"¡Ha ocurrido un error!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"te sigue\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cuentas\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"No tienes ningún servidor multimedia, prueba a añadir alguno.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eliminar\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seleccionar cartera\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suscrito a Push\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"PIN subvencionados\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marcadores (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dirección del rayo\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reclama tu dirección de Snort nostr incluida\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enlace magnet\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrente\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dirección de rayos no válida\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" No me gusta\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento de difusión\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Llave hexagonal..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afrontar acontecimientos desconocidos\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salir\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Información\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de favoritos\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Orden pagada!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nombre\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"el nombre estará disponible más tarde\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Silenciados\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Borrar caché y recargar\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abrir Wallet\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Si no sigues a esta persona, haz clic aquí para cargar medios de \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", o actualiza \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"tus preferencias\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" para cargar siempre medios de todo el mundo.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Revisiones de relés\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ayuda\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fecha de caducidad\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crear o actualizar un puesto\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Último mensaje \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"¿Estás seguro de que quieres desmarcar esta nota?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Datos de la cuenta\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sigue\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debe estar abonado a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" para acceder a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" deck\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap todos \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traducción automática\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visto por última vez:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviado \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"No te sigue nadie\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Haga clic aquí para cargar de todos modos\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conectado\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notas de tendencia\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suscripciones\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notificaciones no permitidas\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utiliza comas para separar palabras, por ejemplo: palabra1, palabra2, palabra3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conjuntos de emoji\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usuario\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar saturación a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deporte\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No hay dirección del rayo\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suscríbase a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" para \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" y reciba las siguientes recompensas\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buscar en la lista de relés\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buscar usuarios\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Web\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Los relés son servidores a los que te conectas para enviar y recibir eventos. Intenta tener entre 4 y 8 relés.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Llave Privada\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Latencia media:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eliminar\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Identificadores de contenido externos\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Introducir configuración de LNDHub\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Destacados\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensaje de chat en directo\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eliminado\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eventos protegidos\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento de tipo desconocido \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Asignación de claves Nostr a identificadores de Internet basados en DNS\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Introducir Pin\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Solicitud de monedero\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"¿Ver como usuario?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Objetivos Zap\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Consulte el código \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alfiler demasiado corto\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anónimo\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comentario\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"El nombre debe tener entre 8 y 15 caracteres\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"No se puede verificar la dirección Nostr\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abrir en Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrentes\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" otros zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps en esta nota se dividirá a los siguientes usuarios.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menús de desarrolladores\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conviértete en líder\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se mostrarán opciones adicionales para desarrolladores en el menú de las notas\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"No disponible:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unirse a la sala\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contraseña de la cartera\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Página por defecto\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota de texto breve\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Autenticación de clientes\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Establecer como dirección Nostr primaria (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Etiquetas proxy\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envía este enlace a tus amigos y comparte la magia del nostr.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagar por suscripción\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comprar nuestra dirección\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Resultados del recuento\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comprando \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.a cuenta\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirmar\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notificaciones\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ya tiene una suscripción de este tipo, por favor renueve o pague\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comentarios sobre el trabajo\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"No se puede votar con \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, por favor establezca una cantidad de zap por defecto diferente\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Página de nuevos usuarios\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muerto\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"¡Usa tu código de invitación para ganar sats!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Certificados OpenTimestamps para eventos\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Papel de regalo\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compartir\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Error de inicio de sesión\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obtener una dirección nostr gratuita\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tu suscripción todavía está activa, aún no puedes renovarla\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Creado\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fusionar solicitudes\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"No se ha podido actualizar, inténtelo de nuevo\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contenido de formato largo\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Escaneado \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dirección Nostr inválida\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copiar JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sistema (por defecto)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total hoy (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sáb\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distancia\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferencias\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recepción a \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encabezado de archivo desconocido: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tema\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se mostrarán las reacciones a las notas\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"La clave privada es como una contraseña, pero no se puede restablecer. Guárdala con cuidado y no se la enseñes nunca a nadie. Una vez que alguien tenga tu clave privada, tendrá acceso a tu cuenta para siempre.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool sólo funciona si utilizas una de las conexiones de monedero compatibles (WebLN, LNC, LNDHub o Nostr Wallet Connect).\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensaje del canal\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Actualmente tienes \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats en tu reserva de zap.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensajes directos privados\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suscripción\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personas a las que sigues\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker no funciona\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anuncios del estado del repositorio\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"El nombre de usuario sólo debe contener letras minúsculas y números\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Caducada\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retrato breve en vídeo Evento\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Por: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"¿Estás seguro de que quieres eliminar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"?\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Máquinas expendedoras de datos\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Favorito\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota de carga: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permisos\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Introduce un pin para encriptar tu clave privada, debes introducir este pin cada vez que abras \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar zap a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Actualizar la dirección de relámpago\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comprar suscripción\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés populares utilizados por las personas a las que sigues.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Dirección Proxy\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conjuntos de relés\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rastreador de problemas\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marcar todo lo leído\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personalizar\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"¿Cómo deberíamos llamarle?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paga Ahora\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Datos específicos de la aplicación\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"El autor ha marcado esta nota como tema sensible \"\n    },\n    {\n      \"children\": [],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés cercanos a su ubicación geográfica.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Los medios de comunicación en las notas se mostrarán automáticamente para las personas seleccionadas, de lo contrario sólo se mostrará el enlace\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Información sobre el manipulador\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegrama\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vista previa\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utilizar el relé local\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Finalizado\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iniciar sesión con la extensión Nostr\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Más información\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cripto\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conjuntos de interés\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendario de eventos\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"sal hexagonal..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personas\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"le gusta\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cuenta\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deja de escuchar\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Definición de Comunidad\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quitar de mis relés\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reciba\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comprobar todas las firmas de eventos recibidas de los relevos\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nuevo chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Los usuarios deben aceptar la advertencia de contenido para mostrar el contenido de tu nota.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Añadir servidor\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iniciar sesión\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bloquear\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Su solicitud está pendiente\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tienes una cuenta activa en iris.to\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comparte una invitación personalizada con tus amigos\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Su código de referencia es \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Etiquetado\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elige qué servicio de subida de ficheros quieres utilizar\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clave pública (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sí, por favor.\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Para ver la lista completa de cambios puede consultar el registro de cambios \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" silenciados\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parece que no tienes ninguna suscripción, puedes obtener una \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bloqueados\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Local\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Desilenciar\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Del servidor\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cuestiones\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traduce automáticamente las notas a tu idioma\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / dirección nostr\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iniciar sesión con la clave\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemónico\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar métricas de uso\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alojamientos de archivos\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conexión del monedero Alby\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sigue Relé Salud\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Canjear\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hashtags de moda\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reacciones\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envío desde \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tu cantidad de zap por defecto es \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, los valores de ejemplo se calculan a partir de esto.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usuarios\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL del Servicio\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Servidores multimedia populares.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parece que no sigues a suficiente gente, echa un vistazo a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" para descubrir gente a la que seguir.\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"No hay llaves, no \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", No hay manera de reiniciarlo si no haces una copia de seguridad. Sólo se tarda un minuto.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat público\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activar reacciones\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conectar un monedero para enviar pagos instantáneos\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pruebe con otro relé\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadatos del canal\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Introduce la frase de emparejamiento\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Firma delegada de actos\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redactar una nota\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activar Ahora\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Colaboradores\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar zap splits a\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"El nombre de usuario iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" está reservado para ti.\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensajes directos cifrados\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" le invitó a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Los servidores multimedia almacenan medios que puedes compartir en notas como imágenes y vídeos\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apoya a las plataformas y desarrolladores que proporcionan servicios de verificación\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Las notas se transmitirán en tiempo real a la pestaña global y de notas\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nombre o apodo\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Extensiones compatibles\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"De pago \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, de pago \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conéctate a tu propio nodo LND con Lightning Node Connect\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar más\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invitar a amigos\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemotécnico\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tu usuario actuará como una dirección de relámpago y redirigirá a tu LNURL o dirección de relámpago seleccionada\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usted es un líder de la comunidad y está ganando \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" de las suscripciones de los usuarios recomendados.\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trabajador de servicios en marcha\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calcular lista de poda\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obtener dirección\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conectado con acceso de sólo lectura\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contenido sensible\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Llave pública\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Justo ahora\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Juegos de sordina\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"No, gracias.\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirecciona\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Si tiene una consulta sobre su pedido de NIP-05, envíe un mensaje privado \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Volver a emitir\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"¿Usas Alby? Visita \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" para obtener tu configuración NWC.\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conexión nativa del monedero nostr\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fotografía\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensaje directo\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Siguiendo\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Servidores multimedia\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Silenciar todos\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conectar cartera\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Soporte multicuenta\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"el nombre ya está registrado\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Actividades en directo\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Atrás\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listas para silenciar:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Filtro WoT\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"No suscrito a Push\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dirección Lightning\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"La clave pública es como tu nombre de usuario, puedes compartirla con cualquiera.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nombre\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cabecera de artículo modular\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hashtags populares\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Regístrese en\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cantidad en saturaciones\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listado clasificado\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se ha configurado una división Zap Pool predeterminada de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" para los desarrolladores de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" , puede desactivarla en cualquier momento en \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amable\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Disponible próximamente\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Introduce el pin para desbloquear tu clave privada\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marcar todo como leído\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utilice una extensión de firmante nostr para iniciar sesión\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji de reacción\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verifica tu perfil\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Un único zap de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats asignará \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats a la reserva de zap.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alimentar\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat en grupo\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"window.nostr para navegadores web\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" otros\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" otros\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inicio\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pobre\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Los líderes de la comunidad son personas que hacen crecer el ecosistema nostr participando activamente en sus comunidades locales y ayudando a incorporar nuevos usuarios. Cualquiera puede convertirse en líder de la comunidad, pero son pocos los que ostentan este título honorífico.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vertedero\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gracias por usar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", por favor considere donar si puede.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort es un proyecto de código abierto construido por personas apasionadas en su tiempo libre, sus donaciones son muy apreciadas.\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"No se puede votar porque el servicio LNURL no soporta zaps\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar los mensajes que tienen una etiqueta de advertencia de contenido\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fijado\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elija algunos temas de interés\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leer\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Papel de regalo\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"¿Qué tienes en mente?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donación en cadena\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Guardado\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adjuntar medios\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ver Stream\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sobre ti\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"No se pudo enviar el voto\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji que se utilizará al reaccionar a una nota\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"No todos los clientes soportan esto\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suscribir\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" en la memoria)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cargando...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aplicación Android Signer\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listas\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de servidores de usuarios\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prueba de trabajo\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Descripción básica del flujo del protocolo\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ¡es más divertido juntos!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Medallas\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadatos de usuario\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Podar lista de seguimiento\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sincronizar cuenta\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensajes\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Soporta\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite a\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar respuestas\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Medios de comunicación\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"aquí\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de relés bloqueados\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interacción\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Piscina Zap\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aquí aparecerán los pagos enviados y recibidos.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reacciones (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traducción de DeepL\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evita que cuentas falsas se hagan pasar por ti\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Admin\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sigue (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" duplicados)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usuario\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"No se puede iniciar sesión con la clave privada en una conexión insegura, por favor utilice una extensión gestora de claves de Nostr\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagos\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"página de nuevos usuarios\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguir\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat de grupo Respuesta hilvanada\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generar factura\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Perfil\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"No seguir\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ya hay copia de seguridad\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Su suscripción a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ha caducado\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Limpie su alimentación\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Error interno: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vídeo del evento\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Guardar\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reacciones\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Solicitar ahora\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Escribir\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nuestro servicio de verificación NIP-05, apoya el desarrollo de este proyecto y obtén una apariencia especial en nuestra web!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés a los que se haya conectado antes y parezcan fiables.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registrar un nombre de usuario Iris\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reenviado\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" otros reenviados\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Información sobre la cartera\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inicio de sesión en Tidal\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seleccione\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"ahora\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Temas\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aprobación del puesto comunitario\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Configurar zap pool\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" me gusta\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" a otros les gustó\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Todo en \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invita a tus amigos\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Derivación de la clave básica a partir de la frase semilla mnemotécnica\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comprar\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagar\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mis eventos: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dirección nostr de Snort\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contraseña de la cartera\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copiar enlace\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"No-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"página de perfil\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy de imágines\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Siguiendo \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clic para cargar contenido de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagar Factura\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Solicitud de Zap\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recomendación del manipulador\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" las notas se han silenciado\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parece que no tienes ninguno, ¡revisa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" para comprar uno!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relevo de trabajadores\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguir todos\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subida de ficheros\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapeó\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapearon\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inicio\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opción: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sólo lectura\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cambia\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento de calendario temporal\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirmación de la oferta\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Desbloquear\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Favoritos\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notificaciones permitidas\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Búsqueda de la actividad de la cuenta (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coinjoin Pool\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Herramientas\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renovar\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Escuche este artículo\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bloqueados\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cubierta\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" seguidores\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"No se ha encontrado nada\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sólo seguidos\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Oye, parece que aún no tienes una dirección Nostr, ¡deberías conseguir una! Echa un vistazo a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premio insignia\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cargar\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" tienen relés (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés fiables\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copias de seguridad descargables desde relé Snort\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji personalizado\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Canal Mute Usuario\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (para mercados resistentes)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguidores\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comentario de Torrent\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento de calendario basado en una fecha\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hilo de respuestas del grupo\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Correo electrónico <> PM puente para su dirección Snort nostr\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Error desconocido\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Insignias de perfil\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Importe por defecto\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bloqueados\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Desbloquear\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renovar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"API de notificaciones desactivada\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tu Clave Privada (no la compartas con nadie) es\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Esta nota ha sido silenciada\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Añadir a tu perfil\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traducción fallida\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Como\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar menos\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ciencia\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clavija incorrecta\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Introducir contraseña de cartera\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadatos de la lista de retransmisión\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de chats públicos\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retrocede ahora\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rayos\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Añadir Relays\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Informes\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Por defecto)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensaje directo cifrado\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" días\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Canales de chat públicos\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enlace corto\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Juegos de marcapáginas\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar insignias\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"usuario\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fallo al parsear zap split: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"El nombre del relé mostrado no coincide con la URL completa introducida.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Solicitud de supresión de eventos\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Las notas silenciadas no se mostrarán\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conexión con éxito:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de intereses\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Publicar conjuntos de artefactos\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eventos en vídeo\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Oscuro\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cifrado por versiones\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Desconocido PIN-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vídeo Ver Evento\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gratis\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar nota a un subconjunto de sus relés de escritura\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obtener un NIP-05 ayuda a:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Métricas de relés\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Insignia de Apoyo\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Estado\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagado\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de pins\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tiempo de actividad\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"El nombre debe tener menos de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" caracteres\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"¿Ya tiene una cuenta?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"Identidades externas en los perfiles\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de retransmisión para recibir DMs\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Los reposts necesitarán ser confirmados\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar splits de saturación a\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encontrado \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eventos\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Público\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notas\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Editar Perfil\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iniciar chat\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debe ser una lista de contactos o una lista pubkey\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de comunidades\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imagen de perfil\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Esta herramienta buscará el último evento publicado por todos tus seguidores y eliminará aquellos que no hayan publicado en 6 meses.\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 es un sistema de verification basado en DNS que permite verificarte como un usuario real.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opciones de encuesta\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Consigue uno gratis\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguidos por amigos\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cantidad de trabajo para aplicar a todos los eventos publicados\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Empresas\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Editar\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de servidores de almacenamiento de archivos\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Archivos adjuntos\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat público de Nostr\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"el nombre no está permitido\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parches\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderación\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aprende más sobre \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" en \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copiar ID\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mis relés\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Financia los servicios que utilizas repartiendo una parte de todos tus zaps en un fondo común.\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Silenciar\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Para ti\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votos por \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ir a\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: Esquema URI\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proveedor\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cargar medios automáticamente\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expira\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Condiciones adicionales:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Búsqueda\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"ABANICO\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permitir\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Idioma\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL o dirección lightning\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés populares\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aplicación nativa\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Depurar\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Borrador de contenido de formato largo\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Peso\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contacto\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dueño\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Todos\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cantidad en sats\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ajedrez (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" minutos para leer\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Error al contactar con el servicio LNURL\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar notas nuevas automáticamente\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Participantes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/fa_IR.json",
    "content": "{\n  \"+D82kt\": \"مطمئنید می خواهید بازنشر کنید: {id}\",\n  \"+PzQ9Y\": \"اکنون بپردازید\",\n  \"+QM0PJ\": \"تمام اطلاعات پروفایل شما با کش داخلی برابر شدند\",\n  \"+QMdsy\": \"اطلاعات رله\",\n  \"+UjDmN\": \"با حق نوشتن وارد شدید\",\n  \"+Vxixo\": \"گپ گروهی خصوصی\",\n  \"+aZY2h\": \"نوع زپ\",\n  \"+tShPg\": \"دنبال می کند\",\n  \"+vA//S\": \"ورود\",\n  \"+vIQlC\": \"لطفا از ذخیره پسورد روبرو به منظور مدیرت شناسه کاربریتان در آینده اطمینان حاصل کنید\",\n  \"+vVZ/G\": \"وصل شدن\",\n  \"+vj0U3\": \"ویرایش\",\n  \"+xliwN\": \"{name} بازنشر کرد\",\n  \"/B8zwF\": \"فضای شما مطابق میلتان 😌\",\n  \"/GCoTA\": \"پاک کردن\",\n  \"/JE/X+\": \"پشتیبانی حساب کاربری\",\n  \"/T7HId\": \"ادغام فضای ذخیره فایل HTTP \",\n  \"/Xf4UW\": \"ارسال مقدار مصرف ناشناس\",\n  \"/b1IHW\": \"پیام گپ گروهی\",\n  \"/d6vEc\": \"یافتن و اشتراک گذاری نمایه خود را آسان تر کنید\",\n  \"/ioUrF\": \"از فایل\",\n  \"/n5KSF\": \"{n} میلی ثانیه\",\n  \"00LcfG\": \"بارگیری بیشتر\",\n  \"01iNut\": \"این آدرس ناستر برای شما نیست\",\n  \"08zn6O\": \"استخراج کلیدها\",\n  \"0Azlrb\": \"مدیریت\",\n  \"0BUTMv\": \"جستجو...\",\n  \"0MndVW\": \"کیف پول کلی LNDHub (BTCPayServer / Alby / LNBits)\",\n  \"0jOEtS\": \"LNURL نامعتبر\",\n  \"0kOBMu\": \"مدیریت اشاره ها\",\n  \"0mch2Y\": \"نام دارای کاراکتر غیرمجاز است\",\n  \"0siT4z\": \"سیاست\",\n  \"0uoY11\": \"نمایش وضعیت\",\n  \"0yO7wF\": \"{n} ثانیه\",\n  \"0zASjL\": \"برو\",\n  \"1/BFEj\": \"چیزهای مربوط به گیت\",\n  \"1Mo59U\": \"مطمئنید می خواهید این یادداشت را از نشانک ها خارج کنید؟\",\n  \"1R43+L\": \"پیکربندی اتصال ناستر به کیف پول\",\n  \"1UWegE\": \"حتما از کلیدهای خود کپی پشتیبان بگیرید!\",\n  \"1c4YST\": \"متصل به:{node}🎉\",\n  \"1nYUGC\": \"{n} دنبال شونده\",\n  \"1o2BgB\": \"بررسی امضا\",\n  \"1ozeyg\": \"طبیعت\",\n  \"1udzha\": \"گفتگوها\",\n  \"2/2yg+\": \"افزودن\",\n  \"25V4l1\": \"بنر\",\n  \"25WwxF\": \"حساب کاربری ندارید؟\",\n  \"28oKbu\": \"انجمن های نظارت شده\",\n  \"29sHFE\": \"اتصال کیف پول\",\n  \"2BBGxX\": \"تگ موضوع در رویداد متنی\",\n  \"2HIqeO\": \"اموجی های کاربر\",\n  \"2IFGap\": \"کمک مالی\",\n  \"2LbrkB\": \"گذرواژه را وارد کنید\",\n  \"2O2sfp\": \"پايان\",\n  \"2Qsf9/\": \"لیست های کلی\",\n  \"2a2YiP\": \"{n} نشانک\",\n  \"2k0Cv+\": \"({n}) ناپسند\",\n  \"2mcwT8\": \"یادداشت جدید\",\n  \"2oCF7O\": \"دنبال شده توسط دوست، دوستان شما\",\n  \"2raFAu\": \"داده های مختص اپلیکیشن\",\n  \"2ukA4d\": \"{n} ساعت\",\n  \"2z7Kky\": \"آخرین مقاله‌ها\",\n  \"3/onCd\": \"پاسخ ها\",\n  \"39AHJm\": \"ثبت نام\",\n  \"3GWu6/\": \"وضعیت کاربر\",\n  \"3KNMbJ\": \"مقالات\",\n  \"3MKdAw\": \"بلاب های ذخیره شده در سرورهای رسانه\",\n  \"3QwfJR\": \"~{amount}\",\n  \"3adEeb\": \"{n} بازدید کننده\",\n  \"3cc4Ct\": \"روشن\",\n  \"3gOsZq\": \"مترجمان\",\n  \"3kbIhS\": \"بی‌عنوان\",\n  \"3qnJlS\": \"با {amount} ساتوشی رای می دهید\",\n  \"3t3kok\": \"{n,plural,one {}=1{{n} یادداشت جدید} other{{n} یادداشت جدید}}\",\n  \"3tVy+Z\": \"{n} دنبال کننده\",\n  \"3yk8fB\": \"کیف پول\",\n  \"40VR6s\": \"اتصال ناستر\",\n  \"41BSaT\": \"تعداد کل رویدادها:\",\n  \"450Fty\": \"هیچ‌کدام\",\n  \"47E53q\": \"ویکی\",\n  \"47FYwb\": \"لغو\",\n  \"48zn4v\": \"پیشنهاد قیمت\",\n  \"4IPzdn\": \"توسعه دهندگان اصلی\",\n  \"4L2vUY\": \"شناسه NIP-0 جدید شما:\",\n  \"4MjsHk\": \"زندگانی\",\n  \"4OB335\": \"ناپسند\",\n  \"4P/kKm\": \"رمزنگاری کلید خصوصی\",\n  \"4Vmpt4\": \"Nostr Plebs یکی از اولین فراهم کنندگان NIP-05 در این محیط است و مجموعه خوبی از دامین ها را با قیمت مناسب ارائه می کند\",\n  \"4Z3t5i\": \"از imgproxy برای فشرده سازی تصویر استفاده کنید\",\n  \"4emo2p\": \"رله های غایب\",\n  \"4rYCjn\": \"یادداشت برای خود\",\n  \"4wgYpI\": \"هندل های توصیه شده اپلیکیشن\",\n  \"5BVs2e\": \"زَپ\",\n  \"5CB6zB\": \"تقسیم زپ\",\n  \"5PRWs7\": \"API اعلان ها فعال است\",\n  \"5dfmvv\": \"هدف زپ\",\n  \"5oTnfy\": \"خرید شناسه\",\n  \"5qEWCr\": \"فراداده فایل\",\n  \"5u6iEc\": \"انتقال به کلید عمومی\",\n  \"5vMmmR\": \"نام کاربری در ناستر یکتا نیست. آدرس ناستر، آدرس یکتای قابل خواندن توسط انسان است که پس از ثبت مختص شما است.\",\n  \"5ykRmX\": \"ارسال زپ\",\n  \"6/hB3S\": \"تماشای بازپخش\",\n  \"60kEE3\": \"لیست خموش\",\n  \"62nsdy\": \"تلاش دوباره\",\n  \"634VVz\": \"اتصال برقرار نشد:\",\n  \"6559gb\": \"طول لیست جدید دنبال ها {length}\",\n  \"65BmHb\": \"تصویر از {host} آورده نشد، اینجا کلیک کنید تا مستقیم بارگیری شود\",\n  \"6D4Hhn\": \"توصیه رله\",\n  \"6KGebm\": \"مهر\",\n  \"6OSOXl\": \"دلیل: <i>{reason}</i>\",\n  \"6WWD34\": \"جستجوی: {noteId}\",\n  \"6bgpn+\": \"همه کلاینت ها از این امکان پشتیبانی نمی کنند. ممکن است همچنان زپ دریافت کنید به صورتی که انگار تقسیم زپ وجود ندارد.\",\n  \"6ewQqw\": \"({n}) لایک\",\n  \"6mr8WU\": \"دنبال شده توسط\",\n  \"6pdxsi\": \"بخش فراداده و تگ های اضافی\",\n  \"6uMqL1\": \"پرداخت نشده\",\n  \"6xNr8c\": \"تعویض حساب‌کاربری\",\n  \"6xap9L\": \"خوب\",\n  \"7+Domh\": \"یادداشت ها\",\n  \"712i26\": \"این پراکسی از صورتحساب برای بازارسال پرداخت ها استفاده می کند، که کلید عمومی گره شما را پنهان می کند.\",\n  \"753yX5\": \"برچسب\",\n  \"769A8p\": \"مقاله ویکی\",\n  \"77nkEO\": \"اسناد اطلاعات رله\",\n  \"7LFU8U\": \"قابلیت جستجو\",\n  \"7UOvbT\": \"آفلاین\",\n  \"7YkSA2\": \"سردسته انجمن\",\n  \"7gMmSL\": \"واکنش\",\n  \"7hp70g\": \"NIP-05\",\n  \"7jfPsW\": \"محتوای مقاله چند بخشی\",\n  \"7nAz/z\": \"یادداشت کسانی که خارج از گروه معتمد شما هستند را خموش کنید\",\n  \"7pFGAQ\": \"بستن رله ها\",\n  \"8/vBbP\": \"({n}) بازنشر\",\n  \"89q5wc\": \"تایید بازنشر\",\n  \"8BDFvJ\": \"آیین نامه استفاده از تگ های e و p در رویداد متنی برای کلاینت ها\",\n  \"8ED/4u\": \"پاسخ به\",\n  \"8HJxXG\": \"ثبت‌نام\",\n  \"8QDesP\": \"زپ کردن {n} ساتوشی\",\n  \"8Rkoyb\": \"گیرنده\",\n  \"8Y6bZQ\": \"تقسیم زپ نامعتبر: {input}\",\n  \"8ZGqWl\": \"فرسته گروهی\",\n  \"8g2vyB\": \"نام زیادی طولانی است\",\n  \"8jmwT8\": \"\",\n  \"8v1NN+\": \"عبارت جفت\",\n  \"8xdDLn\": \"مجموعه هایی برای دنبال کردن\",\n  \"8za9Pq\": \"پیش نویس لیست محرمانه\",\n  \"9+Ddtu\": \"بعدی\",\n  \"9HU8vw\": \"پاسخ\",\n  \"9SvQep\": \"دنبال شوندگان {n}\",\n  \"9V0wg3\": \"رویداد تقویم RSVP\",\n  \"9WRlF4\": \"ارسال\",\n  \"9kO0VQ\": \"پنهان کردن یادداشت های خموش\",\n  \"9kSari\": \"تلاش دوباره برای انتشار\",\n  \"9pMqYs\": \"آدرس ناستر\",\n  \"9wO4wJ\": \"صورتحساب لایتنینگ\",\n  \"A86fJ+\": \"بازنشر کلی\",\n  \"ADmfQT\": \"والد\",\n  \"ALdW69\": \"یادداشت {name}\",\n  \"AN0Z7Q\": \"واژگان خموش\",\n  \"ASRK0S\": \"این نویسنده بیصدا شده است\",\n  \"AedFVZ\": \"ایجاد یا بروزرسانی محصول\",\n  \"Ai8VHU\": \"نگهداری نامحدود یادداشت ها روی رله\",\n  \"AkCxS/\": \"دلیل\",\n  \"AktAk2\": \"عالی\",\n  \"Am8glJ\": \"بازی\",\n  \"AqGfF4\": \"ایجاد کانال\",\n  \"Aujn2T\": \"تعداد\",\n  \"Awq32I\": \"اعلان‌های موبایلی\",\n  \"AxDOiG\": \"ماه\",\n  \"AyGauy\": \"ورود\",\n  \"B4C47Y\": \"نام خیلی کوتاه است\",\n  \"B6+XJy\": \"زپ شد\",\n  \"B6H7eJ\": \"nsec, npub, nip-05, hex\",\n  \"B7wvUM\": \"میتونی یک یا چند رله اضافه کنی، هر خط یکی.\",\n  \"BGCM48\": \"حق دسترسی به رله اسنورت، با یک سال نگهداری رویداد\",\n  \"BGGacK\": \"تلفیق AI / لیست های بردار\",\n  \"BQW4gi\": \"گروه های مبتنی بر رله\",\n  \"BWpuKl\": \"به‌روزآوری\",\n  \"BfuAQ5\": \"UI/UX مارکت\",\n  \"BjNwZW\": \"آدرس ناستر (nip05)\",\n  \"Blxcdx\": \"رله\",\n  \"Bo+O//\": \"HTTP Auth\",\n  \"C1LjMx\": \"کمک مالی با لایتنینگ\",\n  \"C6Lhhp\": \"رویداد زنده\",\n  \"C7642/\": \"نقل قول بازارسال\",\n  \"C81/uG\": \"خروج از حساب\",\n  \"C8FsOr\": \"سرورهای محبوب\",\n  \"C8HhVE\": \"پیشنهاد برای دنبال کردن\",\n  \"CA1efg\": \"مجموعه ویدئو\",\n  \"CHTbO3\": \"صورتحساب بارگیری نشد\",\n  \"CJx5Nd\": \"زپ به نمایه\",\n  \"CM+Cfj\": \"لیست دنبال ها\",\n  \"CM0k0d\": \"هرس لیست دنبال ها\",\n  \"CVWeJ6\": \"افراد محبوب\",\n  \"CYkOCI\": \"و {count} نفر دیگر شما را دنبال می کنند\",\n  \"Cdxwi0\": \"اطلاعیه های ریپازیتوری\",\n  \"CmZ9ls\": \"{n} بیصدا شده\",\n  \"Coy6SH\": \"تقویم\",\n  \"CsCUYo\": \"{n} ساتوشی\",\n  \"Cu/K85\": \"از {lang} ترجمه شده\",\n  \"CzHZoc\": \"چیدمان اجتماعی\",\n  \"D++Njw\": \"ارجاعات یادداشت متنی\",\n  \"D+KzKd\": \"به طور خودکار یادداشت ها را پس از بار شدن ذخیره کن\",\n  \"D09wbg\": \"تعریف مدال\",\n  \"D3idYv\": \"تنظیمات\",\n  \"D9xTLE\": \"پیغام مخفی کردن کانال\",\n  \"DBiVK1\": \"حافظه نهان\",\n  \"DKnriN\": \"ارسال ساتوشی\",\n  \"DZzCem\": \"{n} یادداشت اخیر را نشان بده\",\n  \"Dh3hbq\": \"زپ خودکار\",\n  \"Dn82AL\": \"زنده\",\n  \"DqUmXt\": \"محصول در مزایده فروش رفت\",\n  \"DrZqav\": \"درباره باید کمتر از {limit} حرف باشد\",\n  \"DtYelJ\": \"انتقال\",\n  \"Dx4ey3\": \"به هم ریختن همه\",\n  \"E3oB+t\": \"مرورگر\",\n  \"E5ZIPD\": \"<big>{amount}</big> <small>sats</small>\",\n  \"EHqHsu\": \"Invoice / Lightning Address\",\n  \"EJbFi7\": \"جستجو در یادداشت‌ها\",\n  \"ELbg9p\": \"ارائه دهندگان داده\",\n  \"EQKRE4\": \"نمایش مدال ها در صفحات نمایه\",\n  \"EWeVrH\": \"واکنش به یک سایت\",\n  \"EWyQH5\": \"همگانی\",\n  \"Ebl/B2\": \"ترجمه به {lang}\",\n  \"Ec+xLY\": \"مجموعه های نظارتی\",\n  \"EcZF24\": \"رله های سفارشی\",\n  \"EcfIwB\": \"نام کاربری موجود است\",\n  \"EcglP9\": \"کلید\",\n  \"EjFyoR\": \"آدرس کمک مالی برزنجیر\",\n  \"EnCOBJ\": \"خرید\",\n  \"EsHX35\": \"ببخشید، این نوع رویداد را بلد نیستیم({name})، لطفا اپلیکیشن دیگری را امتحان کنید!\",\n  \"F/6VqP\": \"سرور\",\n  \"F3l7xL\": \"افزودن حساب کاربری\",\n  \"F4eJ/3\": \"فهرست محرمانه\",\n  \"FDguSC\": \"{n} زپ\",\n  \"FHWpHC\": \"پاسخ کیف پول\",\n  \"FHvSk3\": \"احراز هویت کلاینت در رله ها\",\n  \"FMfjrl\": \"نمایش پیغام وضعیت در صفحات نمایه\",\n  \"FSYL8G\": \"پسند کاربران\",\n  \"FWJR1B\": \"گروههای کاربر\",\n  \"FcNSft\": \"مسائل رد شده HTTP به آدرس لایتنینگ ارائه شده ارجاع می شود\",\n  \"FdhSU2\": \"حالا برداشت کن\",\n  \"FfYsOb\": \"خطایی رخ داده است!\",\n  \"FmXUJg\": \"شما را دنبال می کند\",\n  \"FvanT6\": \"حساب ها\",\n  \"FzbSGg\": \"هیچ سروری برای ذخیره عکس/فیلم شما ثب نشده است، میتونی یکی امتحان کنی.\",\n  \"G/yZLu\": \"حذف\",\n  \"G1BGCg\": \"انتخاب کیف پول\",\n  \"G3A56c\": \"عضو Push\",\n  \"GFOoEE\": \"نمک\",\n  \"GIqktu\": \"NIP های پشتیبانی شده\",\n  \"GL8aXW\": \"نشانک ها ({n})\",\n  \"GSye7T\": \"آدرس لایتنینگ\",\n  \"GUlSVG\": \"آدرس ناستر شامل اسنورت خود را بردارید\",\n  \"Gcn9NQ\": \"لینک مگنت\",\n  \"GpkNYn\": \"تورنت\",\n  \"GqQeu/\": \"آدرس لایتنینگ نامعتبر\",\n  \"GspYR7\": \"{n} ناپسند\",\n  \"Gxcr08\": \"پخش رویداد\",\n  \"H+vHiz\": \"کلید Hex...\",\n  \"H/oroO\": \"کارکردن با رویدادهای ناشناخته\",\n  \"H0JBH6\": \"خروج\",\n  \"H0OG3T\": \"اطلاعات سردسته\",\n  \"H1GTaC\": \"لیست نشانک\",\n  \"H6/kLh\": \"سفارش پرداخت شده!\",\n  \"HAlOn1\": \"نام\",\n  \"HFls6j\": \"نام در دسترس خواهد بود\",\n  \"HOzFdo\": \"بيصدا شده\",\n  \"HWbkEK\": \"پاک کردن حافظه کش و بارگیری مجدد\",\n  \"HbefNb\": \"باز کردن کیف پول\",\n  \"HhcAVH\": \"شما این فرد را دنبال نمی کنید، اینجا کلیک کنید تا فایل های <i>{link}</i> را بارگیری کنید، یا <a><i>ترجیحات خود</i></a> را بروزرسانی کنید تا همیشه رسانه های همه را بارگیری کنید.\",\n  \"HpAmQZ\": \"مرور رله ها\",\n  \"HqRNN8\": \"پشتیبانی\",\n  \"HzSFeV\": \"مهر زمان انقضاء\",\n  \"I0tYZf\": \"ایجاد یا بروزرسانی یک غرفه\",\n  \"I1AoOu\": \"Last post {time}\",\n  \"IEwZvs\": \"مطمئنید می خواهید سنجاق یادداشت را بردارید؟\",\n  \"IIOul1\": \"Account Data\",\n  \"IKKHqV\": \"دنبال شوندگان\",\n  \"IOu4Xh\": \"باید عضو {tier} باشید تا به عرشه {app} دسترسی داشته باشید\",\n  \"IVbtTS\": \"به همه {n} ساتوشی زپ بزن\",\n  \"IWz1ta\": \"ترجمه خودکار\",\n  \"IcHcWj\": \"Last Seen:\",\n  \"Ig9/a1\": \"{n} ساتوشی به {name} فرستاده شد\",\n  \"IgsWFG\": \"توسط هیچ یک از کسانی که دنبال می کنید دنبال نشده اید\",\n  \"IoQq+a\": \"اینجا کلیک کنید تا بهرحال بارگیری کنید\",\n  \"IvjoDS\": \"متصل شد\",\n  \"Ix8l+B\": \"داغ‌ترین‌ یادداشت ها\",\n  \"J+dIsA\": \"اشتراک\",\n  \"J1iLmb\": \"اعلان ها مجاز نیستند\",\n  \"J2HeQ+\": \"از ویرگول برای جدا کردن کلمات استفاده کنید. مثال کلمه ۱، کلمه ۲، کلمه۳\",\n  \"J2Q92B\": \"Emoji sets\",\n  \"J6N9xl\": \"Sign in with Android signer\",\n  \"JCIgkj\": \"نام کاربری\",\n  \"JGrt9q\": \"ارسال ساتوشی به {name}\",\n  \"JHEHCk\": \"زپ ({n})\",\n  \"JIVWWA\": \"ورزش\",\n  \"JPFYIM\": \"آدرس لایتنینگی وجود ندارد\",\n  \"JSx7y9\": \"عضویت در {site_name}{plan} به قیمت {price} و دریافت پاداش روبرو\",\n  \"JeoS4y\": \"بازنشر\",\n  \"Jh5zKH\": \"جستجوی لیست رله ها\",\n  \"JjGgXI\": \"جستجوی کاربران\",\n  \"JkLHGw\": \"وب سایت\",\n  \"JmcxzF\": \"Relays are servers you connect to for sending and receiving events. Aim for 4-8 relays.\",\n  \"JymXbw\": \"کلید خصوصی\",\n  \"K1wl1/\": \"Average Latency:\",\n  \"K3r6DQ\": \"حذف\",\n  \"K7AkdL\": \"نشان دادن\",\n  \"K9zklU\": \"External Content IDs\",\n  \"KAhAcM\": \"پیکربندی LNDHub را وارد کنید\",\n  \"KGmQjH\": \"Highlights\",\n  \"KJryGq\": \"Live Chat Message\",\n  \"KQvWvD\": \"حذف شده\",\n  \"KT9nox\": \"Protected Events\",\n  \"KahimY\": \"نوع ناشناخته رویداد: {kind}\",\n  \"KipVeG\": \"نگاشت کلیدهای ناستر به هویت اینترنتی مبتنی بر DNS\",\n  \"KtsyO0\": \"پین را وارد کنید\",\n  \"KyRp/q\": \"درخواست کیف پول\",\n  \"LBAnc7\": \"دیدن به عنوان کاربر؟\",\n  \"LEmxc8\": \"اهداف زپ\",\n  \"LKw/ue\": \"کد را اینجا ببینید {link}\",\n  \"LR1XjT\": \"پین خیلی کوتاه است\",\n  \"LXxsbk\": \"ناشناس\",\n  \"LgbKvU\": \"نظر\",\n  \"LhLvRx\": \"نام باید بین ۸ تا ۱۵ حرف باشد\",\n  \"LmdPXO\": \"نمی توان آدرس ناستر را تایید کرد\",\n  \"Lu5/Bj\": \"در Zapstr بازکنید\",\n  \"LuDBLj\": \"تورنت\",\n  \"Lw+I+J\": \"{n,plural,one {}=0{{name} زپ زد} other {{{name} و {n} نفر دیگر زپ زدند}}\",\n  \"LwYmVi\": \"زپ های این یادداشت بین کاربران روبرو تقسیم می شود.\",\n  \"M3Oirc\": \"منو اشکال زدایی\",\n  \"M6C/px\": \"سردسته شوید\",\n  \"MBAYRO\": \"\\\"کپی شناسه\\\" و \\\"کپی JSON رویداد\\\" را در منو زمینه هر پیام نشان می دهد\",\n  \"MI2jkA\": \"در دسترس نیست:\",\n  \"MKDHEa\": \"ورود به اتاق\",\n  \"MP54GY\": \"گذرواژه کیف پول\",\n  \"MWTx65\": \"صفحه پیش‌فرض\",\n  \"MYBYdJ\": \"یادداشت متنی کوتاه\",\n  \"MYUBaG\": \"احراز هویت کلاینت\",\n  \"MiMipu\": \"تنظیم به عنوان آدرس اصلی ناستر (nip05)\",\n  \"MkQ4FX\": \"تگ های پروکسی\",\n  \"Ml7+RS\": \"این لینک را برای دوستان خود بفرستید و جادوی ناستر را با آنان شریک شوید.\",\n  \"Mrpkot\": \"پرداخت برای اشتراک\",\n  \"MuVeKe\": \"خرید آدرس ناستر\",\n  \"Muhna4\": \"شمارش نتایج\",\n  \"MzRYWH\": \"خرید {item}\",\n  \"Mzizei\": \"حساب کاربری Iris.to\",\n  \"N2IrpM\": \"تایید\",\n  \"NAidKb\": \"اعلان‌ها\",\n  \"NAuFNH\": \"درحال حاضر یک اشتراک از این نوع دارید، لطفا تجدید کنید یا بپردازید\",\n  \"NDTFsp\": \"بازخورد شغل\",\n  \"NepkXH\": \"با {amount} ساتوشی نمی توانید رای دهید، لطفا مبلغ ساتوشی پیش فرض جدیدی برای زپ تنظیم کنید\",\n  \"NndBJE\": \"صفحه کاربران جدید\",\n  \"Nr9Yyx\": \"بازارسال\",\n  \"NxzeNU\": \"غیرفعال\",\n  \"O3Jz4E\": \"از کد دعوت خود استفاده کنید تا ساتوشی بدست آورید!\",\n  \"OEW7yJ\": \"زپ\",\n  \"OIqnZN\": \"گواهی مهرزمان باز برای رویدادها\",\n  \"OJHKIL\": \"بسته‌بندی هدیه\",\n  \"OKhRC6\": \"اشتراک‌گذاری\",\n  \"OLEm6z\": \"خطای ورود ناشناخته\",\n  \"OQSOJF\": \"یک آدرس ناستر رایگان بگیرید\",\n  \"OQXnew\": \"اشتراک شما هنوز فعال است، نمی توانید تجدید کنید\",\n  \"ORGv1Q\": \"ایجاد شد\",\n  \"ORa81+\": \"ادغام درخواست ها\",\n  \"OoZgbB\": \"بروزرسانی نشد، لطفا بعدا دوباره تلاش کنید\",\n  \"OuProE\": \"محتوای بلند\",\n  \"OxPdQ0\": \"در حال اسکن کردن {date}\",\n  \"P2o+ZZ\": \"آدرس ناستر نامعتبر\",\n  \"P61BTu\": \"کپی رویداد JSON\",\n  \"P7FD0F\": \"سیستم (پیش فرض)\",\n  \"P7nJT9\": \"جمع امروز (UTC): {amount} ساتوشی\",\n  \"P8JC58\": \"فاصله\",\n  \"PCSt5T\": \"ترجیحات\",\n  \"PXQ0z0\": \"دریافت در <b>{wallet}</b>\",\n  \"PamNxw\": \"سرفایل ناشناس: {name}\",\n  \"Pe0ogR\": \"تِم\",\n  \"PrsIg7\": \"واکنش ها در تمام صفحات نشان داده می شوند، اگر غیرفعال کنید نشان داده نمی شوند\",\n  \"QDFTjG\": \"{n} رله\",\n  \"QJfhKt\": \"کلید خصوصی مانند گذرواژه است، ولی قابل تغییر و بازیابی نیست. مواظب آن باشید و هرگز به کسی نشان ندهید. اگر کسی کلید عمومی شما را داشته باشد، برای همیشه به حساب کاربری شما دسترسی خواهد داشت.\",\n  \"QWhotP\": \"استخر زپ فقط در صورتیکه از یک اتصال کیف پول پشتیبانی شده (WebLN, LNC, LNDHub یا Nostr Wallet Connect) استفاده کنید کار می کند\",\n  \"QpaLA3\": \"پیغام کانال\",\n  \"Qxv0B2\": \"در حال حاضر {number} ساتوشی در استخر زپ خود دارید.\",\n  \"Qy6/Ft\": \"پیام خصوصی مستقیم\",\n  \"R/6nsx\": \"اشتراک\",\n  \"R81upa\": \"کسانی که دنبال می کنید\",\n  \"RDha9y\": \"خدمات دهنده کار نمی کند\",\n  \"RRz1cA\": \"Repository state announcements\",\n  \"RSr2uB\": \"نام کاربری فقط می‌تواند شامل حروف کوچک (a-z) و اعداد باشد.\",\n  \"RahCRH\": \"منقضی شده\",\n  \"RefZpK\": \"Short-form Portrait Video Event\",\n  \"RfhLwC\": \"توسط: {author}\",\n  \"RhDAoS\": \"مطمئنید می خواهید {id} را حذف کنید\",\n  \"RmxSZo\": \"Data Vending Machines\",\n  \"RoOyAh\": \"رله\",\n  \"Rs4kCE\": \"نشانک\",\n  \"S/NV2G\": \"بارگیری یادداشت: {id}\",\n  \"SFuk1v\": \"مجوزها\",\n  \"SLZGPn\": \"یک پین وارد کنید تا کلید خصوصی تان را رمزگذاری کنید، باید این پین را هر بار هنگام ورود به {site} وارد کنید.\",\n  \"SMO+on\": \"زپ زدن به {name}\",\n  \"SOqbe9\": \"بروزرسانی آدرس لایتنینگ\",\n  \"SP0+yi\": \"خرید اشتراک\",\n  \"SW3TFA\": \"Popular relays used by people you follow.\",\n  \"SYQtZ7\": \"پروکسی آدرس لایتنینگ\",\n  \"Sd0PKc\": \"مجموعه رله ها\",\n  \"SfwSIm\": \"ردیاب مشکل\",\n  \"ShdEie\": \"علامت‌گذاری همه به‌ عنوان خوانده شده\",\n  \"Sjo1P4\": \"سفارشی سازی\",\n  \"SmuYUd\": \"شما را چی صدا بزنیم؟\",\n  \"Ss0sWu\": \"همین الان پرداخت کنید\",\n  \"SsUQnC\": \"Application-specific Data\",\n  \"StKzTE\": \"نویسنده این یادداشت را به عنوان <i>موضوع حساس</i> علامت گذاری کرده\",\n  \"T83nqf\": \"Relays close to your geographic location.\",\n  \"TDR5ge\": \"رسانه درون یادداشت به طور خودکار برای افراد منتخب نمایش داده می شود، وگرنه فقط لینک نشان داده می شود\",\n  \"TGc5nI\": \"Handler information\",\n  \"TH1fFo\": \"تلگرام\",\n  \"TJo5E6\": \"پیش‌نمایش\",\n  \"TOG64f\": \"Use Local Relay\",\n  \"TP/cMX\": \"به پایان رسید\",\n  \"TaeBqw\": \"با افزونه ناستر وارد شوید\",\n  \"TdTXXf\": \"Learn more\",\n  \"TdtZQ5\": \"رمز ارز\",\n  \"Tdv6NY\": \"Interest sets\",\n  \"TgDKhI\": \"Calendar Events\",\n  \"TpgeGw\": \"Hex Salt..\",\n  \"Tpy00S\": \"افراد\",\n  \"TvKqBp\": \"liked\",\n  \"TwyMau\": \"حساب\",\n  \"U1aPPi\": \"توقف شنیدن\",\n  \"U30H69\": \"Community Definition\",\n  \"UJTWqI\": \"حذف از رله های من\",\n  \"ULXFfP\": \"Receive\",\n  \"UNjfWJ\": \"تمام امضاهای رویدادهای دریافت شده توسط رله ها را بررسی کن\",\n  \"UT7Nkj\": \"گپ جدید\",\n  \"UUPFlt\": \"کاربر باید هشدار محتوا را بپذیرد تا محتوای یادداشت نمایش داده شود.\",\n  \"UaCh1c\": \"Add Server\",\n  \"Ub+AGc\": \"ورود\",\n  \"Up5U7K\": \"مسدود کردن\",\n  \"Ups2/p\": \"Your application is pending\",\n  \"UrKTqQ\": \"شما یک حساب کاربری فعال iris.to دارید\",\n  \"UsCzPc\": \"Share a personalized invitation with friends!\",\n  \"UxgyeY\": \"کد معرفی شما {code} است\",\n  \"V20Og0\": \"Labeling\",\n  \"VOjC1i\": \"انتخاب کنید درکدام خدمات بارگذاری فایل می خواهید پیوست ها را بارگذاری کنید\",\n  \"VR5eHw\": \"کلید عمومی (npub/nprofile)\",\n  \"VcwrfF\": \"بله، لطفا\",\n  \"VfhYxG\": \"برای دیدن لیست کامل تغییرات می توانید روزنگار تغییرات را {here} ببینید\",\n  \"VlJkSk\": \"{n} بیصدا شده\",\n  \"VnXp8Z\": \"آواتار\",\n  \"W1yoZY\": \"بنظر می رسد اشتراک ندارید، می توانید یکی تهیه کنید {link}\",\n  \"W2PiAr\": \"{n} مسدود\",\n  \"W4SaxY\": \"محلی\",\n  \"W9355R\": \"صدادار\",\n  \"WeLEuL\": \"از سرور\",\n  \"Wj5TbN\": \"Issues\",\n  \"WmZhfL\": \"ترجمه خودکار یادداشت ها به زبان پیش فرض شما\",\n  \"WvGmZT\": \"آدرس ناستر/ نمایه ناستر/ کلید عمومی ناستر/ npub \",\n  \"X6tipZ\": \"ورود با کلید\",\n  \"X7xU8J\": \"nsec, npub, nip-05, hex, mnemonic\",\n  \"XECMfW\": \"ارسال مقدار مصرف\",\n  \"XICsE8\": \"میزبانان فایل\",\n  \"XPB8VV\": \"Alby wallet connection\",\n  \"XQiFEl\": \"Follows Relay Health\",\n  \"XSdWHA\": \"Redeem\",\n  \"XXm7jJ\": \"برچسب‌های پرطرفدار\",\n  \"XgWvGA\": \"واکنش ها\",\n  \"Xnimz0\": \"Sending from <b>{wallet}</b>\",\n  \"Xopqkl\": \"مبلغ پیش فرض زپ شما {number} ساتوشی است، مقادیر نمونه از روی این محاسبه شده اند.\",\n  \"YDMrKK\": \"کاربران\",\n  \"YDURw6\": \"خدمات URL\",\n  \"YH2RKk\": \"Popular media servers.\",\n  \"YQZY/S\": \"It looks like you dont follow enough people, take a look at {newUsersPage} to discover people to follow!\",\n  \"YR2I9M\": \"بدون کلید نمی توانید از {app} استفاده کنید، اگر از کلیدها پشتیبان نگیرید هیچ راهی برای بازیابی وجود ندارد. این کار فقط یک دقیقه وقت شما را می گیرد.\",\n  \"YU7ZYp\": \"Public Chat\",\n  \"YXA3AH\": \"فعال سازی واکنش ها\",\n  \"Yf3DwC\": \"Connect a wallet to send instant payments\",\n  \"YuoEb9\": \"Try another relay\",\n  \"Z48UEo\": \"Channel Metadata\",\n  \"Z4BMCZ\": \"عبارت جفت را وارد کنید\",\n  \"Z7kkeJ\": \"Delegated Event Signing\",\n  \"ZFe9tl\": \"Compose a note\",\n  \"ZKORll\": \"اکنون فعال کن\",\n  \"ZLmyG9\": \"مشارکت کنندگان\",\n  \"ZS+jRE\": \"ارسال تقسیم زپ به\",\n  \"Zff6lu\": \"نام کاربری iris.to/<b>{name}</b>برای شما رزرو شده است!\",\n  \"ZlIh4/\": \"Encrypted Direct Messages\",\n  \"ZlmK/p\": \"{name} شما را به دعوت می کند {app}\",\n  \"a1x4gD\": \"Media servers store media which you can share in notes as images and videos\",\n  \"a5UPxh\": \"توسعه دهندگان و پلتفرم های ارائه دهنده خدمات تایید NIP-05 را پیدا کن\",\n  \"a7TDNm\": \"یادداشت ها در لحظه در سربرگ همگانی و یادداشت ها پخش می شوند\",\n  \"aHje0o\": \"نام یا نام مستعار\",\n  \"aMaLBK\": \"افزونه های پشتیبانی شده\",\n  \"aRex7h\": \"Paid {amount} sats, fee {fee} sats\",\n  \"aSGz4J\": \"Connect to your own LND node with Lightning Node Connect\",\n  \"aWpBzj\": \"نمایش بیشتر\",\n  \"abbGKq\": \"{n} km\",\n  \"ak3MTf\": \"دعوت دوستان\",\n  \"b12Goz\": \"یادسپارها\",\n  \"b5vAk0\": \"شناسه شما به عنوان آدرس لایتنینگ عمل نموده و به LNURL انتخابی و آدرس لایتنینگ ارجاع خواهد داد\",\n  \"bF1MYT\": \"You are a community leader and are earning <b>{percent}</b> of referred users subscriptions!\",\n  \"bG00/W\": \"خدمات دهنده کار می کند\",\n  \"bJ+wrA\": \"Compute prune list\",\n  \"bLZL5a\": \"دریافت آدرس\",\n  \"bMphls\": \"با فقط حق خواندن وارد شدید\",\n  \"bQdA2k\": \"محتوای حساس\",\n  \"bep9C3\": \"کلید عمومی\",\n  \"bfvyfs\": \"ناشناس\",\n  \"bxv59V\": \"همین الان\",\n  \"c+1p0i\": \"Kind mute sets\",\n  \"c+JYNI\": \"نه، ممنون\",\n  \"c2T+1B\": \"Redirects\",\n  \"c35bj2\": \"اگر درباره سفارش NIP-05 سوالی دارید لطفا مستقیما به {link} پیام دهید\",\n  \"c3LlRO\": \"{n}KiB\",\n  \"c3g2hL\": \"دوباره منتشر کن\",\n  \"cFbU1B\": \"از Alby استفاده می کنید؟ به {link} بروید تا پیکربندی NWC خود را بگیرید!\",\n  \"cG/bKQ\": \"Native nostr wallet connection\",\n  \"cHCwbF\": \"عکاسی\",\n  \"cKbMRX\": \"Direct Message\",\n  \"cPIKU2\": \"دنبال کنندگان\",\n  \"cQfLWb\": \"URL..\",\n  \"cVcgLJ\": \"Media Servers\",\n  \"cWx9t8\": \"بیصدا کردن همه\",\n  \"cg1VJ2\": \"اتصال کیف پول\",\n  \"cnwHgH\": \"OpenTimestamps\",\n  \"cuP16y\": \"پشتیبانی از چند حساب\",\n  \"cuV2gK\": \"نام ثبت شده\",\n  \"cw1Ftc\": \"Live Activities\",\n  \"cyR7Kh\": \"برگشت\",\n  \"d+6YsV\": \"لیست برای خموش کردن:\",\n  \"d0qim7\": \"WoT Filter\",\n  \"d2ebEu\": \"عضو Push نیست\",\n  \"d7d0/x\": \"آدرس لایتنینگ\",\n  \"dK2CcV\": \"The public key is like your username, you can share it with anyone.\",\n  \"dOQCL8\": \"نام نمایشی\",\n  \"dZZIGe\": \"Modular Article Header\",\n  \"ddd3JX\": \"Popular Hashtags\",\n  \"deEeEI\": \"ثبت نام\",\n  \"djLctd\": \"Amount in sats\",\n  \"dmcsBA\": \"Classified Listing\",\n  \"dmsiLv\": \"یک تقسیم استخر زپ {n} برای توسعه دهندگان {site} به طور پیش فرض تنظیم شده است، اگر بخواهید می توانید آن را در {link} خاموش کنید.\",\n  \"e5x8FT\": \"Kind\",\n  \"e61Jf3\": \"به زودی\",\n  \"e7VmYP\": \"پین وارد کنید تا کلید خصوصی خود را باز کنید\",\n  \"e7qqly\": \"علامت‌گذاری همه به‌عنوان خوانده شده\",\n  \"eF0Re7\": \"از یک افزونه امضای ناستر برای ورود استفاده کنید\",\n  \"eHAneD\": \"شکلک واکنش\",\n  \"eJj8HD\": \"تایید کن\",\n  \"eSzf2G\": \"یک زپ تک {nIn} ساتوشی مبلغ {nOut} ساتوشی به استخر زپ تخصیص خواهد داد.\",\n  \"eW/Bj9\": \"Feed\",\n  \"eXT2QQ\": \"گپ گروهی\",\n  \"eZtOxB\": \"window.nostr capability for web browsers\",\n  \"egib+2\": \"{n,plural,one {}=1{و{n} دیگر} other{و{n} دیگر}}\",\n  \"ejEGdx\": \"خونه\",\n  \"eoV49s\": \"ضعیف\",\n  \"f1OxTe\": \"Community leaders are individuals who grow the nostr ecosystem by being active in their local communities and helping onboard new users. Anyone can become a community leader, but few hold the current honorary title.\",\n  \"f2CAxA\": \"Dump\",\n  \"fBI91o\": \"زَپ\",\n  \"fBlba3\": \"برای استفاده از {site} سپاسگذاریم، لطفا در صورت امکان کمک مالی بفرمایید.\",\n  \"fLIvbC\": \"Snort is an open source project built by passionate people in their free time, your donations are greatly appreciated\",\n  \"fOksnD\": \"نمی توان رای داد زیرا این خدمات LNURL از زپ پشتیبانی نمی کند\",\n  \"fQN+tq\": \"یادداشت هایی که برچسب هشدار محتوا دارند نشان بده\",\n  \"fWZYP5\": \"سنجاق شد\",\n  \"fX5RYm\": \"چند موضوع مورد علاقه انتخاب کنید\",\n  \"filwqD\": \"خوانده شده\",\n  \"fjAcWo\": \"بسته‌بندی هدیه\",\n  \"flnGvv\": \"چی تو ذهنت میگذره؟\",\n  \"fqwcJ1\": \"کمک مالی برزنجیر\",\n  \"fr+XYA\": \"Lightning Pub RPC\",\n  \"fsB/4p\": \"ذخیره شد\",\n  \"fucxlm\": \"Attach Media\",\n  \"furjvW\": \"Watch Stream\",\n  \"g5pX+a\": \"درباره\",\n  \"g985Wp\": \"رای ارسال نشد\",\n  \"gDzDRs\": \"شکلک برا ارسال هنگام واکنش به یک یادداشت\",\n  \"gXgY3+\": \"هنوز همه کلاینت ها از این پشتیبانی نمی کنند\",\n  \"gczcC5\": \"اشتراک\",\n  \"geppt8\": \"{count} ({count2} در حافظه)\",\n  \"gjBiyj\": \"در حال بارگیری...\",\n  \"gkMmvC\": \"Android Signer Application\",\n  \"gl1NeW\": \"Lists\",\n  \"go2/QF\": \"User server list\",\n  \"grQ+mI\": \"اثبات کار\",\n  \"gtNjNP\": \"Basic protocol flow description\",\n  \"h7jvCs\": \"{site} با هم بیشتر خوش میگذره!\",\n  \"h8XMJL\": \"مدال ها\",\n  \"h9M0rW\": \"User Metadata\",\n  \"hF6IN2\": \"Prune Follow List\",\n  \"hMQmIw\": \"Sync Account\",\n  \"hMzcSq\": \"پیام‌ها\",\n  \"hRTfTR\": \"PRO\",\n  \"hY4lzx\": \"پشتیبانی\",\n  \"hYOE+U\": \"دعوت\",\n  \"hicxcO\": \"نمایش پاسخ ها\",\n  \"hmZ3Bz\": \"رسانه\",\n  \"hniz8Z\": \"اینجا\",\n  \"hv/eRj\": \"Blocked relays list\",\n  \"hvFRBo\": \"Interaction\",\n  \"i/dBAR\": \"استخر زپ\",\n  \"i5gBFz\": \"Your sent and received payments will show up here.\",\n  \"iCqGww\": \"({n}) واکنش\",\n  \"iEoXYx\": \"مترجم DeepL\",\n  \"iGT1eE\": \"از تقلید شدن توسط حساب های کاربری تقلبی جلوگیری کنید\",\n  \"iHN12u\": \"مدیر\",\n  \"iICVoL\": \"{x} follows ({y} duplicates)\",\n  \"iNWbVV\": \"شناسه\",\n  \"iXPL0Z\": \"در اتصال ناامن با کلید خصوصی نمی توان وارد شد، لطفا در عوض از افزونه مدیریت کلید ناستر استفاده کنید\",\n  \"iYc3Ld\": \"Payments\",\n  \"icCxlA\": \"new users page\",\n  \"ieGrWo\": \"دنبال کردن\",\n  \"igUUst\": \"Group Chat Threaded Reply\",\n  \"ipHVx5\": \"Generate Invoice\",\n  \"itPgxd\": \"نمایه\",\n  \"izWS4J\": \"لغو دنبال کردن\",\n  \"j9xbzF\": \"ذخیره شده\",\n  \"jA3OE/\": \"{n,plural,one {}=1{{n} نوت جدید} other{{n} نوت جدید}}\",\n  \"jAmfGl\": \"عضویت شما در {site_name} منقضی شده است\",\n  \"jHa/ko\": \"پاک سازی خبرنامه\",\n  \"jMzO1S\": \"خطای داخلی: {msg}\",\n  \"jiAVXu\": \"Video Event\",\n  \"jvo0vs\": \"ذخیره\",\n  \"jzgQ2z\": \"{n} واکنش\",\n  \"k0kCJp\": \"Apply Now\",\n  \"k2veDA\": \"نوشتن\",\n  \"k7sKNy\": \"خدمات تایید NIP-05 خودمان، به پشتیبانی از توسعه این سایت کمک کنید و یک مدال ویژه درخشان در سایت ما بگیرید!\",\n  \"k9SQm1\": \"رله هایی که قبلاً به آنها وصل شده اید و به نظر قابل اعتماد هستند.\",\n  \"kEZUR8\": \"یک نام کاربری Iris ثبت کنید\",\n  \"kJYo0u\": \"{n,plural,one {}=0{{name} بازنشر کرد} other{{name} و {n} نفر دیگر بازنشر کردند}}\",\n  \"kKC9ya\": \"Wallet Info\",\n  \"kNd2FL\": \"Tidal login\",\n  \"kQAf2d\": \"انتخاب\",\n  \"kaaf1E\": \"الان\",\n  \"kc79d3\": \"موضوعات\",\n  \"klCm96\": \"Community Post Approval\",\n  \"kqPQJD\": \"پیکربندی استخر زپ\",\n  \"kuPHYE\": \"{n,plural,one {}=0{{name} پسندید} other{{name} و {n} نفر دیگر پسندیدند}}\",\n  \"l+ikU1\": \"همه چیز در {plan}\",\n  \"l3H1EK\": \"دوستان خود را دعوت کنید\",\n  \"l3nTjd\": \"Basic key derivation from mnemonic seed phrase\",\n  \"lCILNz\": \"هم اکنون خریداری کنید\",\n  \"lD3+8a\": \"پرداخت\",\n  \"lEnclp\": \"My events: {n}\",\n  \"lPWASz\": \"آدرس اسنورت ناستر\",\n  \"lTbT3s\": \"گذرواژه کیف پول\",\n  \"lbr3Lq\": \"Copy link\",\n  \"lfOesV\": \"Non-Zap\",\n  \"lgg1KN\": \"صفحه حساب کاربری\",\n  \"ll3xBp\": \"خدمات پروکسی تصویر\",\n  \"lnaT9F\": \"{n} دنبال شونده\",\n  \"lsNFM1\": \"کلیک کنید تا محتوای {link} را بارگیری کنید\",\n  \"lvlPhZ\": \"پرداخت صورتحساب\",\n  \"m/59y2\": \"Zap Request\",\n  \"m6h2Eg\": \"Handler recommendation\",\n  \"mCEKiZ\": \"{n} notes have been muted\",\n  \"mErPop\": \"بنظر می رسد هیچ شناسه NIP-05 ندارید، {link} بررسی کنید تا یکی بخرید!\",\n  \"mFtdYh\": \"{type} Worker Relay\",\n  \"mKAr6h\": \"دنبال کردن همه\",\n  \"mKh2HS\": \"خدمات بارگذاری فایل\",\n  \"mKhgP9\": \"{n,plural,one {}=0{} =1{زپ شده} other{زپ شده}}\",\n  \"mOFG3K\": \"Start\",\n  \"mfe8RW\": \"گزینه: {n}\",\n  \"mmPSWH\": \"Read Only\",\n  \"n1Whvj\": \"تعویض\",\n  \"n5l7tP\": \"Time-Based Calendar Event\",\n  \"n8k1SG\": \"{n}MiB\",\n  \"nD4frR\": \"Bid confirmation\",\n  \"nDejmx\": \"لغو مسدودی\",\n  \"nGBrvw\": \"نشانک\",\n  \"nGGDsi\": \"اعلان ها مجازند\",\n  \"nIchMQ\": \"Searching for account activity ({progress})\",\n  \"nPHrqp\": \"Coinjoin Pool\",\n  \"nUT0Lv\": \"Tools\",\n  \"nWQFic\": \"Renew\",\n  \"nihgfo\": \"به این مقاله گوش دهید\",\n  \"nwZXeh\": \"{n} مسدود\",\n  \"o/gK53\": \"Deck\",\n  \"o7e+nJ\": \"{n} دنبال کننده\",\n  \"oJ+JJN\": \"چیزی پیدا نشد\",\n  \"odFwjL\": \"فقط دنبال شوندگان\",\n  \"ojzbwv\": \"هی، بنظر می رسد هنوز آدرس ناستر ندارید، باید یکی بگیرید! {link} را ببینید\",\n  \"ozZ2Cj\": \"Badge Award\",\n  \"p4N05H\": \"بارگذاری\",\n  \"p9Ps2l\": \"{x}/{y} have relays ({percent})\",\n  \"pEEBFk\": \"Reliable Relays\",\n  \"pI+77w\": \"نسخه بازیابی قابل دانلود رله اسنورت\",\n  \"pRess9\": \"استخر زپ\",\n  \"plOM0t\": \"اموجی سفارشی\",\n  \"plg2Ua\": \"Channel Mute User\",\n  \"puLNUJ\": \"سنجاق\",\n  \"pyjJ5f\": \"Nostr Marketplace (for resilient marketplaces)\",\n  \"pzTOmv\": \"دنبال کنندگان\",\n  \"q3OuMw\": \"Torrent Comment\",\n  \"qAY40L\": \"Date-Based Calendar Event\",\n  \"qBYNMb\": \"Group Thread Reply\",\n  \"qD9EUF\": \"ایمیل پل پیام مستقیم <> برای آدرس اسنورت ناستر\",\n  \"qDwvZ4\": \"خطای ناشناخته\",\n  \"qFIVx4\": \"Profile Badges\",\n  \"qMePPG\": \"یادداشت\",\n  \"qMx1sA\": \"مبلغ پیش فرض زپ\",\n  \"qUJTsT\": \"مسدود شده\",\n  \"qXCbgZ\": \"Unlock\",\n  \"qZsKBR\": \"دوباره {tier}\",\n  \"qcJFEJ\": \"API اعلان ها غیر فعال است\",\n  \"qdGuQo\": \"کلید خصوصی شما (با هیچ کس درمیان نگذارید)\",\n  \"qfmMQh\": \"این یادداشت خموش شده است\",\n  \"qkvYUb\": \"افزودن به نمایه\",\n  \"qmJ8kD\": \"ترجمه انجام نشد\",\n  \"qtWLmt\": \"پسند\",\n  \"qyJtWy\": \"نمایش کمتر\",\n  \"qydxOd\": \"علوم\",\n  \"qz9fty\": \"پین نادرست\",\n  \"r3C4x/\": \"نرم افزار\",\n  \"r5srDR\": \"رمز کیف‌پول را وارد کنید\",\n  \"rAQG0X\": \"Relay List Metadata\",\n  \"rIsVe+\": \"Public chats list\",\n  \"rMgF34\": \"اکنون پشتیبان‌گیری شود\",\n  \"rRRXtB\": \"Lightning Zaps\",\n  \"rT14Ow\": \"افزودن رله\",\n  \"reFEEC\": \"در حال گزارش\",\n  \"rfuMjE\": \"(پیش‌فرض)\",\n  \"rkM7l8\": \"Encrypted Direct Message\",\n  \"rmdsT4\": \"{n} روز\",\n  \"rn52n9\": \"Public Chat Channels\",\n  \"rx1i0i\": \"لینک کوتاه\",\n  \"sFUkSN\": \"Bookmark sets\",\n  \"sKDn4e\": \"نمایش مدال ها\",\n  \"sUNhQE\": \"کاربر\",\n  \"sZQzjQ\": \"تقسیم زپ انجام نشد: {input}\",\n  \"saInmO\": \"The relay name shown is not the same as the full URL entered.\",\n  \"saorw+\": \"Event Deletion Request\",\n  \"sfL/O+\": \"Muted notes will not be shown\",\n  \"t79a6U\": \"Connection Success:\",\n  \"tDDiRL\": \"Interests list\",\n  \"tFpT/O\": \"Release artifact sets\",\n  \"tO1oq9\": \"Video Events\",\n  \"tOdNiY\": \"تاریک\",\n  \"tRGdV1\": \"Versioned Encryption\",\n  \"tU0ADf\": \"Unknown NIP-{x}\",\n  \"tVuVg9\": \"Video View Event\",\n  \"tf1lIh\": \"Free\",\n  \"th5lxp\": \"یادداشت را به زیرشاخه ای از رله نوشتنی تان بفرستید\",\n  \"thnRpU\": \"گرفتن NIP-05 تایید شده می تواند کمک کند:\",\n  \"tj6kdX\": \"{sign} {amount} sats\",\n  \"tjpYlr\": \"مقادیر رله\",\n  \"ttxS0b\": \"مدال پشتیبان\",\n  \"tzMNF3\": \"Status\",\n  \"u/vOPu\": \"پرداخت شده\",\n  \"u4I8q8\": \"Pin list\",\n  \"u81G9+\": \"Uptime\",\n  \"u9NoC1\": \"نام باید کمتر از {limit} حرف باشد\",\n  \"uCk8r+\": \"حساب کاربری دارید؟\",\n  \"uD7Els\": \"External Identities in Profiles\",\n  \"uJaMkO\": \"Relay list to receive DMs\",\n  \"uSV4Ti\": \"بازنشر لازم است به طور دستی تایید شود\",\n  \"uc0din\": \"ارسال ساتوشی های تقسیم شده به\",\n  \"ufvXH1\": \"Found {n} events\",\n  \"uhu5aG\": \"عمومی\",\n  \"un1nGw\": \"{n} یادداشت\",\n  \"usAvMr\": \"ویرایش نمایه\",\n  \"v8lolG\": \"شروع گپ\",\n  \"vB3oQ/\": \"می بایست یک لیست مخاطبین یا لیست کلیدهای عمومی باشد\",\n  \"vBsZhD\": \"Communities list\",\n  \"vN5UH8\": \"تصویر نمایه\",\n  \"vU/Q5i\": \"This tool will search for the last event published by all of your follows and remove those who have not posted in 6 months\",\n  \"vZ4quW\": \"NIP-05 یک ویژگی بر مبنای DNS است که کمک می کند هویت شما به عنوان کاربر تصدیق شود.\",\n  \"vhlWFg\": \"گزینه های نظرسنجی\",\n  \"vlbWtt\": \"یکی مجانی بگیرید\",\n  \"voxBKC\": \"دنبال شده توسط دوستان\",\n  \"vxwnbh\": \"مقداری کاری که برای اِعمال همه رویدادهای منتشر شده باید انجام گیرد\",\n  \"w1Fanr\": \"کسب و کار\",\n  \"w6qrwX\": \"نامناسب برای خانواده و محیط کار\",\n  \"wEQDC6\": \"ویرایش\",\n  \"wOyDTB\": \"File storage server list\",\n  \"wSZR47\": \"ثبت\",\n  \"wc9st7\": \"Media Attachments\",\n  \"whSrs+\": \"Nostr Public Chat\",\n  \"wih7iJ\": \"نام مسدود شده است\",\n  \"wlWMuh\": \"Patches\",\n  \"wofVHy\": \"نظارت\",\n  \"wqyN/i\": \"درباره {service} در {link} بیشتر بدانید\",\n  \"wtLjP6\": \"کپی کردن شناسه\",\n  \"x+3fl6\": \"My Relays\",\n  \"x/Fx2P\": \"با تقسیم بخشی از زپ های خود و اختصاص آن به استخر زپ، خدماتی را که استفاده می کنید تامین مالی نمایید!\",\n  \"x82IOl\": \"بيصدا\",\n  \"xEjBS7\": \"برای تو\",\n  \"xIcAOU\": \"آرا تسوط {type}\",\n  \"xIoGG9\": \"برو به\",\n  \"xPCyu+\": \"nostr: URI scheme\",\n  \"xaj9Ba\": \"تامین کننده\",\n  \"xbVgIm\": \"بارگیری خودکار رسانه\",\n  \"xhQMeQ\": \"منقضی می شود\",\n  \"xl4s/X\": \"شرایط دیگر:\",\n  \"xmcVZ0\": \"جستجو\",\n  \"xybOUv\": \"FAN\",\n  \"y/bmsG\": \"اجازه\",\n  \"y1Z3or\": \"زبان\",\n  \"yAztTU\": \"{n} eSats\",\n  \"yCLnBC\": \"LNURL یا آدرس لایتنینگ\",\n  \"yLzgxH\": \"رله های محبوب\",\n  \"yeX8yA\": \"Native App\",\n  \"z3UjXR\": \"Debug\",\n  \"z3Ukvq\": \"Draft Long-form Content\",\n  \"zCb8fX\": \"وزن\",\n  \"zFegDD\": \"مخاطب\",\n  \"zINlao\": \"مالک\",\n  \"zQvVDJ\": \"همه\",\n  \"zcaOTs\": \"مبلغ زپ به ساتوشی\",\n  \"zi9MdS\": \"Chess (PGN)\",\n  \"zm6qS1\": \"{n} دقیقه مطالعه\",\n  \"zonsdq\": \"خدمات LNURL بارگیری نشد\",\n  \"zvCDao\": \"به طور خودکار یادداشت های اخیر را نشان بده\",\n  \"zx0myy\": \"Participants\"\n}\n"
  },
  {
    "path": "packages/app/src/translations/fi_FI.json",
    "content": "{\n  \"+D82kt\": \"Haluatko varmasti jakaa uudelleen: {id}\",\n  \"+PzQ9Y\": \"Maksa nyt\",\n  \"+QM0PJ\": \"Synkronoi kaikki profiilisi tapahtumat paikalliseen välimuistiin.\",\n  \"+QMdsy\": \"Relay-tilastot\",\n  \"+UjDmN\": \"Kirjauduttu sisään kirjoitusoikeudella\",\n  \"+Vxixo\": \"Salainen ryhmäkeskutelu\",\n  \"+aZY2h\": \"Zap tyyppi\",\n  \"+tShPg\": \"seuraavat\",\n  \"+vA//S\": \"Kirjautumiset\",\n  \"+vIQlC\": \"Muista tallentaa seuraava salasana pystyäksesi hallitsemaan käyttäjätunnustasi tulevaisuudessa\",\n  \"+vVZ/G\": \"Yhdistä\",\n  \"+vj0U3\": \"muokkaa\",\n  \"+xliwN\": \"{name} jakoi uudelleen\",\n  \"/B8zwF\": \"Tilasi sellaisena kuin haluat 😌\",\n  \"/GCoTA\": \"Kirkas\",\n  \"/JE/X+\": \"Tilituki\",\n  \"/T7HId\": \"HTTP-tiedoston tallennuksen integrointi\",\n  \"/Xf4UW\": \"Lähetä nimettömiä käyttötietoja\",\n  \"/b1IHW\": \"Ryhmächat-viesti\",\n  \"/d6vEc\": \"Tee profiilistasi helpompi löytää ja jakaa\",\n  \"/ioUrF\": \"Tiedostosta\",\n  \"/n5KSF\": \"{n} ms\",\n  \"00LcfG\": \"Lataa lisää\",\n  \"01iNut\": \"Nostr-osoite ei kuulu sinulle\",\n  \"08zn6O\": \"Vientiavaimet\",\n  \"0Azlrb\": \"Hallitse\",\n  \"0BUTMv\": \"Etsi...\",\n  \"0MndVW\": \"Tavallinen LNDHub-lompakko (BTCPayServer / Alby / LNBits)\",\n  \"0jOEtS\": \"Virheellinen LNURL\",\n  \"0kOBMu\": \"Mainintojen käsittely\",\n  \"0mch2Y\": \"nimi sisältää sallimattomia merkkejä\",\n  \"0siT4z\": \"Politiikka\",\n  \"0uoY11\": \"Näytä tila\",\n  \"0yO7wF\": \"{n} sek\",\n  \"0zASjL\": \"Mene\",\n  \"1/BFEj\": \"git-juttuja\",\n  \"1Mo59U\": \"Haluatko varmasti poistaa tämän viestin kirjanmerkeistä?\",\n  \"1R43+L\": \"Anna Nostr Wallet Connect asetukset\",\n  \"1UWegE\": \"Muista varmuuskopioida avaimesi!\",\n  \"1c4YST\": \"Yhdistetty: {node} 🎉\",\n  \"1nYUGC\": \"{n} Seuraa\",\n  \"1o2BgB\": \"Tarkista allekirjoitukset\",\n  \"1ozeyg\": \"Luonto\",\n  \"1udzha\": \"Keskustelut\",\n  \"2/2yg+\": \"Lisää\",\n  \"25V4l1\": \"Banneri\",\n  \"25WwxF\": \"Eikö sinulla ole tiliä?\",\n  \"28oKbu\": \"Moderoidut yhteisöt\",\n  \"29sHFE\": \"Lompakko Connect\",\n  \"2BBGxX\": \"Aihe-tunniste tekstitapahtumissa\",\n  \"2HIqeO\": \"Käyttäjän emoji-luettelo\",\n  \"2IFGap\": \"Lahjoita\",\n  \"2LbrkB\": \"Anna salasana\",\n  \"2O2sfp\": \"Viimeistely\",\n  \"2Qsf9/\": \"Yleiset luettelot\",\n  \"2a2YiP\": \"{n} Kirjanmerkit\",\n  \"2k0Cv+\": \"Ei-tykkäyksiä ({n})\",\n  \"2mcwT8\": \"Uusi viesti\",\n  \"2oCF7O\": \"Ystävien ystävät seuraavat\",\n  \"2raFAu\": \"Sovelluskohtaiset tiedot\",\n  \"2ukA4d\": \"{n} tuntia\",\n  \"2z7Kky\": \"Uusimmat artikkelit\",\n  \"3/onCd\": \"Vastaukset\",\n  \"39AHJm\": \"Rekisteröidy\",\n  \"3GWu6/\": \"Käyttäjän tilat\",\n  \"3KNMbJ\": \"Artikkelit\",\n  \"3MKdAw\": \"Mediapalvelimiin tallennetut blobit\",\n  \"3QwfJR\": \"~{amount}\",\n  \"3adEeb\": \"{n} katsojat\",\n  \"3cc4Ct\": \"Vaalea\",\n  \"3gOsZq\": \"Kääntäjät\",\n  \"3kbIhS\": \"Untitled\",\n  \"3qnJlS\": \"Äänestät {amount} satsilla\",\n  \"3t3kok\": \"{n,plural,=1{{n} uusi viesti} muuta{{n} uutta viestiä}}\",\n  \"3tVy+Z\": \"{n} Seuraajaa\",\n  \"3yk8fB\": \"Lompakko\",\n  \"40VR6s\": \"Nostr Connect\",\n  \"41BSaT\": \"Tapahtumia yhteensä:\",\n  \"450Fty\": \"Ei mitään\",\n  \"47E53q\": \"Wiki\",\n  \"47FYwb\": \"Peruuta\",\n  \"48zn4v\": \"Tarjous\",\n  \"4IPzdn\": \"Pääkehittäjät\",\n  \"4L2vUY\": \"Uusi NIP-05-käyttäjätunnuksesi on:\",\n  \"4MjsHk\": \"Life\",\n  \"4OB335\": \"Ei-tykkäys\",\n  \"4P/kKm\": \"Yksityisen avaimen salaus\",\n  \"4Vmpt4\": \"Nostr Plebs on yksi ensimmäisistä NIP-05-tarjoajista alalla ja tarjoaa kohtuuhintaisia verkkotunnuksia\",\n  \"4Z3t5i\": \"Käytä imgproxya pakataksesi kuvat\",\n  \"4emo2p\": \"Puuttuvat välittäjät\",\n  \"4rYCjn\": \"Muistiinpano itselle\",\n  \"4wgYpI\": \"Suositellut sovelluskäsittelijät\",\n  \"5BVs2e\": \"zap\",\n  \"5CB6zB\": \"Zap-jaot\",\n  \"5PRWs7\": \"Ilmoitukset API käytössä\",\n  \"5dfmvv\": \"Zap Goal\",\n  \"5oTnfy\": \"Osta käyttäjätunnus\",\n  \"5qEWCr\": \"Tiedoston metatiedot\",\n  \"5u6iEc\": \"Siirrä julkiselle avaimelle\",\n  \"5vMmmR\": \"Käyttäjänimet eivät ole yksilöllisiä Nostrissa. Nostr-osoite on yksilöllinen ihmisystävällinen osoitteesi, joka on yksilöllinen sinulle rekisteröinnin yhteydessä.\",\n  \"5ykRmX\": \"Lähetä zap\",\n  \"6/hB3S\": \"Katso uusinta\",\n  \"60kEE3\": \"Mykistysluettelo\",\n  \"62nsdy\": \"Uudelleenyritys\",\n  \"634VVz\": \"Yhteys epäonnistui:\",\n  \"6559gb\": \"Uusi seuraajalistan pituus {length}\",\n  \"65BmHb\": \"Kuvan välittäminen epäonnistui palvelimelta {host}, napsauta tätä ladataksesi suoraan\",\n  \"6D4Hhn\": \"Suosittele relettä\",\n  \"6KGebm\": \"Tiiviste\",\n  \"6OSOXl\": \"Syy: <i>{reason}</i>\",\n  \"6WWD34\": \"Etsitään: {noteId}\",\n  \"6bgpn+\": \"Kaikki asiakkaat eivät tue tätä, saatat silti saada joitakin zappeja ikään kuin zap-jako ei olisi määritetty\",\n  \"6ewQqw\": \"Tykkäyksiä ({n})\",\n  \"6mr8WU\": \"Seuraaja\",\n  \"6pdxsi\": \"Ylimääräiset metatietokentät ja tunnisteet\",\n  \"6uMqL1\": \"Maksamaton\",\n  \"6xNr8c\": \"Vaihda tilejä\",\n  \"6xap9L\": \"Hyvä\",\n  \"7+Domh\": \"Viestit\",\n  \"712i26\": \"Välityspalvelin käyttää HODL-laskuja maksun välittämiseen, mikä piilottaa solmusi julkisen avaimen.\",\n  \"753yX5\": \"Tarra\",\n  \"769A8p\": \"Wikiartikkeli\",\n  \"77nkEO\": \"Relay-tietoasiakirja\",\n  \"7LFU8U\": \"Hakukyky\",\n  \"7UOvbT\": \"Offline\",\n  \"7YkSA2\": \"Yhteisön johtaja\",\n  \"7gMmSL\": \"Reaktio\",\n  \"7hp70g\": \"NIP-05\",\n  \"7jfPsW\": \"Modulaarinen artikkelin sisältö\",\n  \"7nAz/z\": \"Mykistä muistiinpanot ihmisiltä, jotka ovat luottamusverkostosi ulkopuolella.\",\n  \"7pFGAQ\": \"Sulje releet\",\n  \"8/vBbP\": \"Uudelleenjakoja ({n})\",\n  \"89q5wc\": \"Vahvista uudelleenjaot\",\n  \"8BDFvJ\": \"e- ja p-tunnisteiden käyttöä tekstitapahtumissa koskevat käytännöt asiakkaissa.\",\n  \"8ED/4u\": \"Reply To\",\n  \"8HJxXG\": \"Rekisteröidy\",\n  \"8QDesP\": \"Zap {n} satsia\",\n  \"8Rkoyb\": \"Vastaanottaja\",\n  \"8Y6bZQ\": \"Virheellinen zap-jako: {input}\",\n  \"8ZGqWl\": \"Ryhmän lanka\",\n  \"8g2vyB\": \"nimi on liian pitkä\",\n  \"8jmwT8\": \"bech32-koodatut kokonaisuudet\",\n  \"8v1NN+\": \"Pariliitoksen lause\",\n  \"8xdDLn\": \"Seuraa sarjoja\",\n  \"8za9Pq\": \"Luonnos luokitellusta luettelosta\",\n  \"9+Ddtu\": \"Seuraava\",\n  \"9HU8vw\": \"Vastaa\",\n  \"9SvQep\": \"Seuraa {n}\",\n  \"9V0wg3\": \"Kalenteri Tapahtuma RSVP\",\n  \"9WRlF4\": \"Lähetä\",\n  \"9kO0VQ\": \"Piilota mykistetyt nuotit\",\n  \"9kSari\": \"Yritä uudelleen julkaisemista\",\n  \"9pMqYs\": \"Nostr-osoite\",\n  \"9wO4wJ\": \"Lightning-lasku\",\n  \"A86fJ+\": \"Yleinen Repost\",\n  \"ADmfQT\": \"Vanhempi\",\n  \"ALdW69\": \"Viesti lähettäjältä {name}\",\n  \"AN0Z7Q\": \"Mykistetyt sanat\",\n  \"ASRK0S\": \"Tämä kirjoittaja on mykistetty\",\n  \"AedFVZ\": \"Luo tai päivitä tuote\",\n  \"Ai8VHU\": \"Rajoittamaton viestien säilytys Snort-välittäjällä\",\n  \"AkCxS/\": \"Syy\",\n  \"AktAk2\": \"Suuri\",\n  \"Am8glJ\": \"Peli\",\n  \"AqGfF4\": \"Kanavan luominen\",\n  \"Aujn2T\": \"Count\",\n  \"Awq32I\": \"Push-ilmoitukset\",\n  \"AxDOiG\": \"Kuukaudet\",\n  \"AyGauy\": \"Kirjaudu sisään\",\n  \"B4C47Y\": \"nimi on liian lyhyt\",\n  \"B6+XJy\": \"zappattu\",\n  \"B6H7eJ\": \"nsec, npub, nip-05, hex\",\n  \"B7wvUM\": \"Voit lisätä yhden tai useamman releen, yhden per rivi.\",\n  \"BGCM48\": \"Kirjoitusoikeus Snort-välittäjällä, 1 vuoden tapahtumahistorialla\",\n  \"BGGacK\": \"Tekoälyn sulautukset / vektoriluettelot\",\n  \"BQW4gi\": \"Relepohjaiset ryhmät\",\n  \"BWpuKl\": \"Päivitä\",\n  \"BfuAQ5\": \"Markkinapaikan UI/UX\",\n  \"BjNwZW\": \"Nostr-osoite (nip05)\",\n  \"Blxcdx\": \"Rele\",\n  \"Bo+O//\": \"HTTP-auth\",\n  \"C1LjMx\": \"Salama lahjoitus\",\n  \"C6Lhhp\": \"Suora tapahtuma\",\n  \"C7642/\": \"Lainaus Repost\",\n  \"C81/uG\": \"Kirjaudu ulos\",\n  \"C8FsOr\": \"Suosittuja palvelimia\",\n  \"C8HhVE\": \"Ehdotettuja seurattavia\",\n  \"CA1efg\": \"Videokokonaisuudet\",\n  \"CHTbO3\": \"Epäonnistunut laskun lataus\",\n  \"CJx5Nd\": \"Profiili Zaps\",\n  \"CM+Cfj\": \"Seurattavien lista\",\n  \"CM0k0d\": \"Karsia seurattavien listaa\",\n  \"CVWeJ6\": \"Suositut henkilöt\",\n  \"CYkOCI\": \"ja {count} muuta joita seuraat\",\n  \"Cdxwi0\": \"Talletussäiliön ilmoitukset\",\n  \"CmZ9ls\": \"{n} Mykistettyä\",\n  \"Coy6SH\": \"Kalenteri\",\n  \"CsCUYo\": \"{n} satsia\",\n  \"Cu/K85\": \"Käännetty kieleltä {lang}\",\n  \"CzHZoc\": \"Sosiaalinen kuvaaja\",\n  \"D++Njw\": \"Teksti Huomautus Viitteet\",\n  \"D+KzKd\": \"Zappää automaattisesti jokainen viesti, kun se ladataan\",\n  \"D09wbg\": \"Merkin määritelmä\",\n  \"D3idYv\": \"Asetukset\",\n  \"D9xTLE\": \"Kanava Piilota viesti\",\n  \"DBiVK1\": \"Välimuisti\",\n  \"DKnriN\": \"Lähetä satsit\",\n  \"DZzCem\": \"Näytä viimeisimmät {n} viestiä\",\n  \"Dh3hbq\": \"Automaattiset zapit\",\n  \"Dn82AL\": \"Live\",\n  \"DqUmXt\": \"Huutokauppana myytävä tuote\",\n  \"DrZqav\": \"Tietoja on oltava vähemmän kuin {limit} merkkiä\",\n  \"DtYelJ\": \"Siirto\",\n  \"Dx4ey3\": \"Vaihda kaikki\",\n  \"E3oB+t\": \"Selain\",\n  \"E5ZIPD\": \"<big>{amount}</big> <small>satsia</small>\",\n  \"EHqHsu\": \"Lasku / Lightning-osoite\",\n  \"EJbFi7\": \"Etsi muistiinpanoja\",\n  \"ELbg9p\": \"Datantoimittajat\",\n  \"EQKRE4\": \"Näytä merkit profiilisivuilla\",\n  \"EWeVrH\": \"Reaktio verkkosivustoon\",\n  \"EWyQH5\": \"Yleinen\",\n  \"Ebl/B2\": \"Käännä kielelle {lang}\",\n  \"Ec+xLY\": \"Kuratointisarjat\",\n  \"EcZF24\": \"Omat välittäjät\",\n  \"EcfIwB\": \"Käyttäjätunnus on käytettävissä\",\n  \"EcglP9\": \"Avain\",\n  \"EjFyoR\": \"Ketjussa oleva lahjoitusosoite\",\n  \"EnCOBJ\": \"Osta\",\n  \"EsHX35\": \"Valitettavasti emme ymmärrä tätä tapahtumalajia ({name}), kokeile sen sijaan jotakin seuraavista sovelluksista!\",\n  \"F/6VqP\": \"Palvelin\",\n  \"F3l7xL\": \"Lisää tili\",\n  \"F4eJ/3\": \"Luokitellut ilmoitukset\",\n  \"FDguSC\": \"{n} Zappia\",\n  \"FHWpHC\": \"Lompakon vastaus\",\n  \"FHvSk3\": \"Asiakkaiden todentaminen releitä varten\",\n  \"FMfjrl\": \"Näytä tilaviestit profiilisivuilla\",\n  \"FSYL8G\": \"Suositut käyttäjät\",\n  \"FWJR1B\": \"Käyttäjäryhmät\",\n  \"FcNSft\": \"Uudelleenohjaus antaa HTTP-uudelleenohjauksen toimitettuun salamaosoitteeseen.\",\n  \"FdhSU2\": \"Lunasta nyt\",\n  \"FfYsOb\": \"Tapahtui virhe!\",\n  \"FmXUJg\": \"seuraa sinua\",\n  \"FvanT6\": \"Tilit\",\n  \"FzbSGg\": \"Sinulla ei ole mediapalvelimia, yritä lisätä niitä.\",\n  \"G/yZLu\": \"Poista\",\n  \"G1BGCg\": \"Valitse lompakko\",\n  \"G3A56c\": \"Tilattu Push-ilmoitukset\",\n  \"GFOoEE\": \"Suola\",\n  \"GIqktu\": \"Tuetut kansalliset ohjeelliset ohjelmat\",\n  \"GL8aXW\": \"Kirjanmerkkejä ({n})\",\n  \"GSye7T\": \"Lightning-osoite\",\n  \"GUlSVG\": \"Lunasta sisältyvä Snort nostr-osoite\",\n  \"Gcn9NQ\": \"Magneettilinkki\",\n  \"GpkNYn\": \"Torrent\",\n  \"GqQeu/\": \"Virheellinen Lightning-osoite\",\n  \"GspYR7\": \"{n} Ei-tykkäys\",\n  \"Gxcr08\": \"Lähetystapahtuma\",\n  \"H+vHiz\": \"Hex-avain..\",\n  \"H/oroO\": \"Tuntemattomien tapahtumien käsittely\",\n  \"H0JBH6\": \"Kirjaudu ulos\",\n  \"H0OG3T\": \"Johtajan tiedot\",\n  \"H1GTaC\": \"Kirjanmerkkiluettelo\",\n  \"H6/kLh\": \"Tilaus maksettu!\",\n  \"HAlOn1\": \"Nimi\",\n  \"HFls6j\": \"nimi on myöhemmin saatavilla\",\n  \"HOzFdo\": \"Mykistetty\",\n  \"HWbkEK\": \"Tyhjennä välimuisti ja lataa uudelleen\",\n  \"HbefNb\": \"Avaa lompakko\",\n  \"HhcAVH\": \"Et seuraa tätä henkilöä, klikkaa tästä ladataksesi mediaa osoitteesta <i>{link}</i>, tai päivitä <a><i>asetuksesi</i></a> ladataksesi mediaa aina kaikilta.\",\n  \"HpAmQZ\": \"Relay arvostelut\",\n  \"HqRNN8\": \"Tuki\",\n  \"HzSFeV\": \"Viimeinen voimassaoloaika\",\n  \"I0tYZf\": \"Luo tai päivitä kioski\",\n  \"I1AoOu\": \"Viimeisin viesti {time}\",\n  \"IEwZvs\": \"Haluatko varmasti poistaa tämän viestin kiinnitetyistä?\",\n  \"IIOul1\": \"Tilitiedot\",\n  \"IKKHqV\": \"Seuraa\",\n  \"IOu4Xh\": \"Sinun täytyy olla {tier} tilaaja käyttääksesi {app} näkymää\",\n  \"IVbtTS\": \"Zap kaikki {n} sats\",\n  \"IWz1ta\": \"Automaattinen käännös\",\n  \"IcHcWj\": \"Viimeksi nähty:\",\n  \"Ig9/a1\": \"Lähetettiin {n} satsia käyttäjälle {name}\",\n  \"IgsWFG\": \"Ei seuraa kukaan, jota seuraat\",\n  \"IoQq+a\": \"Klikkaa tästä ladataksesi joka tapauksessa\",\n  \"IvjoDS\": \"Yhdistetty\",\n  \"Ix8l+B\": \"Suositut viestit\",\n  \"J+dIsA\": \"Tilaukset\",\n  \"J1iLmb\": \"Ilmoituksia ei sallita\",\n  \"J2HeQ+\": \"Käytä pilkkuja erottamaan sanat toisistaan, esim. sana1, sana2, sana3.\",\n  \"J2Q92B\": \"Emoji-sarjat\",\n  \"J6N9xl\": \"Sign in with Android signer\",\n  \"JCIgkj\": \"Käyttäjätunnus\",\n  \"JGrt9q\": \"Lähetä satseja käyttäjälle {name}\",\n  \"JHEHCk\": \"Zapit ({n})\",\n  \"JIVWWA\": \"Urheilu\",\n  \"JPFYIM\": \"Ei lightning-osoitetta\",\n  \"JSx7y9\": \"Tilaa {site_name} {plan} osoitteeseen {price} ja saat seuraavat palkinnot.\",\n  \"JeoS4y\": \"Jaa uudelleen\",\n  \"Jh5zKH\": \"Haku releiden luettelosta\",\n  \"JjGgXI\": \"Etsi käyttäjiä\",\n  \"JkLHGw\": \"Verkkosivusto\",\n  \"JmcxzF\": \"Releet ovat palvelimia, joihin muodostetaan yhteys tapahtumien lähettämistä ja vastaanottamista varten. Tavoitteena on 4-8 relettä.\",\n  \"JymXbw\": \"Yksityisavain\",\n  \"K1wl1/\": \"Keskimääräinen viive:\",\n  \"K3r6DQ\": \"Poista\",\n  \"K7AkdL\": \"Näytä\",\n  \"K9zklU\": \"Ulkoisen sisällön tunnukset\",\n  \"KAhAcM\": \"Anna LNDHub-asetukset\",\n  \"KGmQjH\": \"Kohokohdat\",\n  \"KJryGq\": \"Live chat-viesti\",\n  \"KQvWvD\": \"Poistettu\",\n  \"KT9nox\": \"Suojatut tapahtumat\",\n  \"KahimY\": \"Tuntematon tapahtumatyyppi: {kind}\",\n  \"KipVeG\": \"Nostr-avainten yhdistäminen DNS-pohjaisiin internet-tunnisteisiin\",\n  \"KtsyO0\": \"Syötä Pin\",\n  \"KyRp/q\": \"Lompakkopyyntö\",\n  \"LBAnc7\": \"Näytä käyttäjänä?\",\n  \"LEmxc8\": \"Zap Tavoitteet\",\n  \"LKw/ue\": \"Tutustu koodiin {link}\",\n  \"LR1XjT\": \"Liian lyhyt tappi\",\n  \"LXxsbk\": \"Nimetön\",\n  \"LgbKvU\": \"Kommentoi\",\n  \"LhLvRx\": \"Nimen tulee olla 8-15 merkkiä\",\n  \"LmdPXO\": \"Nostr-osoitetta ei voida tarkistaa\",\n  \"Lu5/Bj\": \"Avaa Zapstrissa\",\n  \"LuDBLj\": \"Torrentit\",\n  \"Lw+I+J\": \"{n,plural,=0{{name} zappasi} other{{name} & {n} muuta zappasivat}}\",\n  \"LwYmVi\": \"Zapit tässä viestissä jaetaan seuraaville käyttäjille.\",\n  \"M3Oirc\": \"Debug-valikot\",\n  \"M6C/px\": \"Ryhdy johtajaksi\",\n  \"MBAYRO\": \"Näyttää \\\"Kopioi tunniste\\\" ja \\\"Kopioi tapahtuman JSON\\\" jokaisen viestin valikossa\",\n  \"MI2jkA\": \"Ei saatavilla:\",\n  \"MKDHEa\": \"Liity huoneeseen\",\n  \"MP54GY\": \"Lompakon salasana\",\n  \"MWTx65\": \"Oletussivu\",\n  \"MYBYdJ\": \"Lyhyt teksti Huomautus\",\n  \"MYUBaG\": \"Asiakkaan todennus\",\n  \"MiMipu\": \"Asetetaan ensisijaiseksi Nostr-osoitteeksi (nip05).\",\n  \"MkQ4FX\": \"Proxy-tunnisteet\",\n  \"Ml7+RS\": \"Lähetä tämä linkki ystävillesi ja jaa nostrin taika.\",\n  \"Mrpkot\": \"Maksa tilaus\",\n  \"MuVeKe\": \"Osta nostr-osoite\",\n  \"Muhna4\": \"Tulosten laskeminen\",\n  \"MzRYWH\": \"Ostaa {item}\",\n  \"Mzizei\": \"Iris.tilille\",\n  \"N2IrpM\": \"Vahvista\",\n  \"NAidKb\": \"Ilmoitukset\",\n  \"NAuFNH\": \"Sinulla on jo tämäntyyppinen tilaus, ole hyvä ja uudista tai maksa\",\n  \"NDTFsp\": \"Työpalaute\",\n  \"NepkXH\": \"Ei voida äänestää {amount} satsilla, aseta toinen oletuszap-määrä\",\n  \"NndBJE\": \"Uusien käyttäjien sivu\",\n  \"Nr9Yyx\": \"Repostit\",\n  \"NxzeNU\": \"Kuollut\",\n  \"O3Jz4E\": \"Käytä kutsukoodia ansaitaksesi satseja!\",\n  \"OEW7yJ\": \"Zapit\",\n  \"OIqnZN\": \"OpenTimestamps -tapahtumien todistukset\",\n  \"OJHKIL\": \"Lahjakääre\",\n  \"OKhRC6\": \"Jaa\",\n  \"OLEm6z\": \"Tuntematon kirjautumisvirhe\",\n  \"OQSOJF\": \"Hanki ilmainen nostr-osoite\",\n  \"OQXnew\": \"Tilauksesi on yhä aktiivinen, et voi uusia sitä vielä\",\n  \"ORGv1Q\": \"Luotu\",\n  \"ORa81+\": \"Yhdistämispyynnöt\",\n  \"OoZgbB\": \"Päivitys epäonnistui, yritä uudelleen\",\n  \"OuProE\": \"Pitkämuotoinen sisältö\",\n  \"OxPdQ0\": \"Skannaus {date}\",\n  \"P2o+ZZ\": \"Virheellinen Nostr-osoite\",\n  \"P61BTu\": \"Kopioi tapahtuman JSON\",\n  \"P7FD0F\": \"Järjestelmä (oletus)\",\n  \"P7nJT9\": \"Tänään yhteensä (UTC): {amount} satsia\",\n  \"P8JC58\": \"Etäisyys\",\n  \"PCSt5T\": \"Asetukset\",\n  \"PXQ0z0\": \"Vastaanotto osoitteeseen <b>{wallet}</b>\",\n  \"PamNxw\": \"Tuntematon tiedostotunniste: {name}\",\n  \"Pe0ogR\": \"Teema\",\n  \"PrsIg7\": \"Reaktiot näytetään jokaisella sivulla, jos poistettu käytöstä reaktioita ei näytetä\",\n  \"QDFTjG\": \"{n} Välittäjää\",\n  \"QJfhKt\": \"Yksityinen avain on kuin salasana, mutta sitä ei voi nollata. Vartioi sitä huolellisesti äläkä koskaan näytä sitä kenellekään. Kun joku saa yksityisen avaimesi, hän pääsee tiliisi ikuisesti.\",\n  \"QWhotP\": \"Zap-pool toimii vain tuetuilla lompakkoyhteyksillä (WebLN, LNC, LNDHub tai Nostr Wallet Connect)\",\n  \"QpaLA3\": \"Kanavaviesti\",\n  \"Qxv0B2\": \"Sinulla on {number} satsia zap-poolissa.\",\n  \"Qy6/Ft\": \"Yksityiset suorat viestit\",\n  \"R/6nsx\": \"Tilaus\",\n  \"R81upa\": \"Henkilöt joita seuraat\",\n  \"RDha9y\": \"Palvelutyöntekijä ei ole käynnissä\",\n  \"RRz1cA\": \"Varaston tilailmoitukset\",\n  \"RSr2uB\": \"Käyttäjätunnus saa sisältää vain pieniä kirjaimia ja numeroita.\",\n  \"RahCRH\": \"Vanhentunut\",\n  \"RefZpK\": \"Lyhytmuotoinen muotokuvavideotapahtuma\",\n  \"RfhLwC\": \"Tekijä: {author}\",\n  \"RhDAoS\": \"Haluatko varmasti poistaa {id}\",\n  \"RmxSZo\": \"Data-automaatit\",\n  \"RoOyAh\": \"Välittäjät\",\n  \"Rs4kCE\": \"Kirjanmerkki\",\n  \"S/NV2G\": \"Lastausmerkintä: {id}\",\n  \"SFuk1v\": \"Luvat\",\n  \"SLZGPn\": \"Syötä pin yksityisen avaimesi salaamista varten, sinun on syötettävä tämä pin joka kerta, kun avaat {site}.\",\n  \"SMO+on\": \"Lähetä satseja käyttäjälle {name}\",\n  \"SOqbe9\": \"Päivitä Lightning-osoite\",\n  \"SP0+yi\": \"Osta tilaus\",\n  \"SW3TFA\": \"Seuraamiesi ihmisten käyttämät suositut releet.\",\n  \"SYQtZ7\": \"LN-osoitteen välityspalvelin\",\n  \"Sd0PKc\": \"Relesarjat\",\n  \"SfwSIm\": \"Ongelmanseuranta\",\n  \"ShdEie\": \"Merkitse kaikki luetuiksi\",\n  \"Sjo1P4\": \"Mukautettu\",\n  \"SmuYUd\": \"Miksi meidän pitäisi kutsua sinua?\",\n  \"Ss0sWu\": \"Maksa nyt\",\n  \"SsUQnC\": \"Sovelluskohtaiset tiedot\",\n  \"StKzTE\": \"Kirjoittaja on merkinnyt tämän huomautuksen <i>arkaluontoiseksi aiheeksi.</i>\",\n  \"T83nqf\": \"Maantieteellisen sijaintisi lähellä olevat releet.\",\n  \"TDR5ge\": \"Viestien mediasisältö näytetään automaattisesti valituille henkilöille, muille näytetään vain linkki\",\n  \"TGc5nI\": \"Käsittelijän tiedot\",\n  \"TH1fFo\": \"Telegrammi\",\n  \"TJo5E6\": \"Esikatselu\",\n  \"TOG64f\": \"Käytä paikallista relettä\",\n  \"TP/cMX\": \"Lopetettu\",\n  \"TaeBqw\": \"Kirjaudu sisään Nostr-laajennuksella\",\n  \"TdTXXf\": \"Lisätietoja\",\n  \"TdtZQ5\": \"Crypto\",\n  \"Tdv6NY\": \"Korkokokonaisuudet\",\n  \"TgDKhI\": \"Kalenteri Tapahtumat\",\n  \"TpgeGw\": \"Hex-suola..\",\n  \"Tpy00S\": \"Ihmiset\",\n  \"TvKqBp\": \"piti\",\n  \"TwyMau\": \"Tili\",\n  \"U1aPPi\": \"Lopeta kuunteleminen\",\n  \"U30H69\": \"Yhteisön määritelmä\",\n  \"UJTWqI\": \"Poista releistäni\",\n  \"ULXFfP\": \"Vastaanota\",\n  \"UNjfWJ\": \"Tarkista kaikki releiltä saadut tapahtuman allekirjoitukset\",\n  \"UT7Nkj\": \"Uusi keskustelu\",\n  \"UUPFlt\": \"Käyttäjien täytyy hyväksyä sisältövaroitus nähdäkseen viestisi sisällön.\",\n  \"UaCh1c\": \"Lisää palvelin\",\n  \"Ub+AGc\": \"Kirjaudu sisään\",\n  \"Up5U7K\": \"Estä\",\n  \"Ups2/p\": \"Hakemuksesi on vireillä\",\n  \"UrKTqQ\": \"Sinulla on aktiivinen iris.to-tili\",\n  \"UsCzPc\": \"Jaa henkilökohtainen kutsu ystävien kanssa!\",\n  \"UxgyeY\": \"Suosittelukoodisi on {code}\",\n  \"V20Og0\": \"Merkintä\",\n  \"VOjC1i\": \"Valitse palvelu, johon haluat ladata liitteitä\",\n  \"VR5eHw\": \"Julkinen avain (npub/nprofile)\",\n  \"VcwrfF\": \"Kyllä, kiitos.\",\n  \"VfhYxG\": \"Tarkastele muutoslogia {here} nähdäksesi kaikki muutokset\",\n  \"VlJkSk\": \"{n} mykistettyä\",\n  \"VnXp8Z\": \"Avatar\",\n  \"W1yoZY\": \"Et ole vielä tilannut, mutta käy {link} tilataksesi.\",\n  \"W2PiAr\": \"{n} Estettyä\",\n  \"W4SaxY\": \"Paikallinen\",\n  \"W9355R\": \"Poista mykistys\",\n  \"WeLEuL\": \"Palvelimelta\",\n  \"Wj5TbN\": \"Asiat\",\n  \"WmZhfL\": \"Käännä muistiinpanot automaattisesti paikalliselle kielelle\",\n  \"WvGmZT\": \"npub / nprofile / nostr-osoite\",\n  \"X6tipZ\": \"Kirjaudu sisään avaimella\",\n  \"X7xU8J\": \"nsec, npub, nip-05, hex, mnemonic\",\n  \"XECMfW\": \"Lähetä käyttötietoja\",\n  \"XICsE8\": \"Tiedostojen isäntäpalvelut\",\n  \"XPB8VV\": \"Alby-lompakon yhteys\",\n  \"XQiFEl\": \"Seuraa välittäjän tila\",\n  \"XSdWHA\": \"Lunasta\",\n  \"XXm7jJ\": \"Suositut tunnisteet\",\n  \"XgWvGA\": \"Reaktiot\",\n  \"Xnimz0\": \"Lähettäminen osoitteesta <b>{wallet}</b>\",\n  \"Xopqkl\": \"Oletus zap-määräsi on {number} satsia, esimerkit on laskettu tämän mukaan.\",\n  \"YDMrKK\": \"Käyttäjät\",\n  \"YDURw6\": \"Palvelun URL\",\n  \"YH2RKk\": \"Suosittuja mediapalvelimia.\",\n  \"YQZY/S\": \"Näyttää siltä, ettet seuraa tarpeeksi ihmisiä, katso {newUsersPage} löytääksesi ihmisiä, joita seurata!\",\n  \"YR2I9M\": \"Ei avaimia, ei {app}, Avaimia ei voi palauttaa, ellet tee niistä varmuuskopiota. Se vie vain minuutin.\",\n  \"YU7ZYp\": \"Julkinen keskustelu\",\n  \"YXA3AH\": \"Ota reaktiot käyttöön\",\n  \"Yf3DwC\": \"Yhdistä lompakko välittömien maksujen lähettämistä varten\",\n  \"YuoEb9\": \"Kokeile toista relettä\",\n  \"Z48UEo\": \"Kanavan metatiedot\",\n  \"Z4BMCZ\": \"Anna pariliitoslause\",\n  \"Z7kkeJ\": \"Delegoitu tapahtuman allekirjoittaminen\",\n  \"ZFe9tl\": \"Muistion laatiminen\",\n  \"ZKORll\": \"Aktivoi nyt\",\n  \"ZLmyG9\": \"Avustajat\",\n  \"ZS+jRE\": \"Lähetä zap splitit osoitteeseen\",\n  \"Zff6lu\": \"Käyttäjätunnus iris.to/<b>{name}</b> on varattu sinulle!\",\n  \"ZlIh4/\": \"Salatut suorat viestit\",\n  \"ZlmK/p\": \"{name} kutsui sinut {app}\",\n  \"a1x4gD\": \"Mediapalvelimet tallentavat mediaa, jota voit jakaa muistiinpanoissa kuvina ja videoina.\",\n  \"a5UPxh\": \"Tue kehittäjiä ja alustoja, jotka tarjoavat NIP-05-varmennuspalveluita\",\n  \"a7TDNm\": \"Viestit striimautuvat reaaliajassa yleiseen ja viestit-välilehteen\",\n  \"aHje0o\": \"Nimi tai nimimerkki\",\n  \"aMaLBK\": \"Tuetut laajennukset\",\n  \"aRex7h\": \"Maksettu {amount} satsia, maksu {fee} satsia\",\n  \"aSGz4J\": \"Yhdistä omaan LND-solmuun Lightning Node Connectin avulla\",\n  \"aWpBzj\": \"Näytä lisää\",\n  \"abbGKq\": \"{n} km\",\n  \"ak3MTf\": \"Kutsu ystäviä\",\n  \"b12Goz\": \"Mnemonic-lause\",\n  \"b5vAk0\": \"Käyttäjätunnuksesi toimii kuin lightning-osoite ja uudelleenohjaa valitsemaasi LNURLiin tai lightning-osoitteeseen\",\n  \"bF1MYT\": \"Olet yhteisön johtaja ja ansaitset <b>{percent}</b> viitattujen käyttäjien tilauksista!\",\n  \"bG00/W\": \"Palvelutyöntekijä käynnissä\",\n  \"bJ+wrA\": \"Karsintaluettelon laskeminen\",\n  \"bLZL5a\": \"Hae osoite\",\n  \"bMphls\": \"Kirjauduttu sisään vain lukuoikeudella\",\n  \"bQdA2k\": \"Arkaluontoinen sisältö\",\n  \"bep9C3\": \"Julkinen avain\",\n  \"bfvyfs\": \"Anon\",\n  \"bxv59V\": \"Juuri nyt\",\n  \"c+1p0i\": \"Ystävälliset mykistyssarjat\",\n  \"c+JYNI\": \"Ei kiitos\",\n  \"c2T+1B\": \"Ohjaa uudelleen\",\n  \"c35bj2\": \"Jos sinulla on kysymyksiä NIP-05-tilauksestasi, lähetä yksityisviesti {link}\",\n  \"c3LlRO\": \"{n}KiB\",\n  \"c3g2hL\": \"Lähetä uudelleen\",\n  \"cFbU1B\": \"Käytätkö Albya? Mene {link} saadaksesi NWC-asetuksesi!\",\n  \"cG/bKQ\": \"Natiivi nostr-lompakkoyhteys\",\n  \"cHCwbF\": \"Valokuvaus\",\n  \"cKbMRX\": \"Suora viesti\",\n  \"cPIKU2\": \"Seuraa\",\n  \"cQfLWb\": \"URL..\",\n  \"cVcgLJ\": \"Mediapalvelimet\",\n  \"cWx9t8\": \"Mykistä kaikki\",\n  \"cg1VJ2\": \"Yhdistä lompakko\",\n  \"cnwHgH\": \"OpenTimestamps\",\n  \"cuP16y\": \"Usean tilin tuki\",\n  \"cuV2gK\": \"nimi on rekisteröity\",\n  \"cw1Ftc\": \"Elävät aktiviteetit\",\n  \"cyR7Kh\": \"Takaisin\",\n  \"d+6YsV\": \"Luettelot mykistykseen:\",\n  \"d0qim7\": \"WoT-suodatin\",\n  \"d2ebEu\": \"Ei tilattu Push-ilmoituksia\",\n  \"d7d0/x\": \"LN-osoite\",\n  \"dK2CcV\": \"Julkinen avain on kuin käyttäjätunnuksesi, voit jakaa sen kenelle tahansa.\",\n  \"dOQCL8\": \"Näyttönimi\",\n  \"dZZIGe\": \"Modulaarinen artikkelin otsikko\",\n  \"ddd3JX\": \"Suosittuja hashtageja\",\n  \"deEeEI\": \"Rekisteröi\",\n  \"djLctd\": \"Määrä satseissa\",\n  \"dmcsBA\": \"Luokiteltu listaus\",\n  \"dmsiLv\": \"{site} kehittäjille on määritetty oletusarvoinen Zap Poolin jako {n} , voit poistaa sen käytöstä milloin tahansa osoitteessa {link}.\",\n  \"e5x8FT\": \"Kind\",\n  \"e61Jf3\": \"Tulossa pian\",\n  \"e7VmYP\": \"Anna pin avataksesi yksityisen avaimesi\",\n  \"e7qqly\": \"Merkitse kaikki luetuksi\",\n  \"eF0Re7\": \"Käytä sisäänkirjautumiseen nostr signer -laajennusta\",\n  \"eHAneD\": \"Reaktion emoji\",\n  \"eJj8HD\": \"Hanki varmennus\",\n  \"eSzf2G\": \"Yksittäinen {nIn} satsin zap jakaa {nOut} satsia zap-pooliin.\",\n  \"eW/Bj9\": \"Syöttö\",\n  \"eXT2QQ\": \"Ryhmächat\",\n  \"eZtOxB\": \"window.nostr-ominaisuus verkkoselaimissa\",\n  \"egib+2\": \"{n,plural,one {}=1{& {n} muut} other{& {n} muut}}\",\n  \"ejEGdx\": \"Etusivu\",\n  \"eoV49s\": \"Huono\",\n  \"f1OxTe\": \"Yhteisön johtajat ovat yksilöitä, jotka kasvattavat nostr ekosysteemiä toimimalla aktiivisesti paikallisyhteisöissä ja auttamalla uusia käyttäjiä. Kuka tahansa voi tulla yhteisön johtajaksi, mutta vain harvoilla on nykyinen kunniajäsenen titteli.\",\n  \"f2CAxA\": \"Dump\",\n  \"fBI91o\": \"Zap\",\n  \"fBlba3\": \"Kiitos, että käytät {site}, harkitse lahjoitusta, jos voit.\",\n  \"fLIvbC\": \"Snort on avoimen lähdekoodin projekti, jota intohimoiset ihmiset rakentavat vapaa-ajallaan, lahjoituksia arvostetaan suuresti.\",\n  \"fOksnD\": \"Ei voi äänestää, koska LNURL-palvelu ei tue zappeja\",\n  \"fQN+tq\": \"Näytä viestit, joissa on sisältövaroitus\",\n  \"fWZYP5\": \"Kiinnitetty\",\n  \"fX5RYm\": \"Valitse muutama kiinnostava aihe\",\n  \"filwqD\": \"Lue\",\n  \"fjAcWo\": \"Lahjakääreet\",\n  \"flnGvv\": \"Mitä mielessä?\",\n  \"fqwcJ1\": \"Ketjussa tapahtuva lahjoitus\",\n  \"fr+XYA\": \"Lightning Pub RPC\",\n  \"fsB/4p\": \"Tallennettu\",\n  \"fucxlm\": \"Liitä media\",\n  \"furjvW\": \"Katso suoratoistoa\",\n  \"g5pX+a\": \"Tietoja\",\n  \"g985Wp\": \"Äänestyksen lähetys epäonnistui\",\n  \"gDzDRs\": \"Emoji reagoitaessa viestiin\",\n  \"gXgY3+\": \"Ei tueta kaikissa asiakasohjelmissa vielä\",\n  \"gczcC5\": \"Tilaa\",\n  \"geppt8\": \"{count} ({count2} muistissa)\",\n  \"gjBiyj\": \"Ladataan...\",\n  \"gkMmvC\": \"Android Signer -sovellus\",\n  \"gl1NeW\": \"Luettelot\",\n  \"go2/QF\": \"Käyttäjän palvelinluettelo\",\n  \"grQ+mI\": \"Todiste työstä\",\n  \"gtNjNP\": \"Perusprotokollan kulun kuvaus\",\n  \"h7jvCs\": \"{site} on hauskempaa yhdessä!\",\n  \"h8XMJL\": \"Merkit\",\n  \"h9M0rW\": \"Käyttäjän metatiedot\",\n  \"hF6IN2\": \"Karsi seurattavien listaa\",\n  \"hMQmIw\": \"Synkronoi tili\",\n  \"hMzcSq\": \"Viestit\",\n  \"hRTfTR\": \"PRO\",\n  \"hY4lzx\": \"Tukee\",\n  \"hYOE+U\": \"Kutsu\",\n  \"hicxcO\": \"Näytä vastaukset\",\n  \"hmZ3Bz\": \"Media\",\n  \"hniz8Z\": \"täällä\",\n  \"hv/eRj\": \"Estettyjen releiden luettelo\",\n  \"hvFRBo\": \"Vuorovaikutus\",\n  \"i/dBAR\": \"Zap-pooli\",\n  \"i5gBFz\": \"Lähetetyt ja vastaanotetut maksut näkyvät täällä.\",\n  \"iCqGww\": \"Reaktioita ({n})\",\n  \"iEoXYx\": \"DeepL käännökset\",\n  \"iGT1eE\": \"Estä väärennettyjä tilejä jäljittelemästä sinua\",\n  \"iHN12u\": \"Admin\",\n  \"iICVoL\": \"{x} seuraa ({y} duplikaatit)\",\n  \"iNWbVV\": \"Käyttäjätunnus\",\n  \"iXPL0Z\": \"Ei voi kirjautua yksityisavaimella epäturvallisella yhteydellä, käytä Nostr-avainhallintaohjelmalaajennusta\",\n  \"iYc3Ld\": \"Maksut\",\n  \"icCxlA\": \"uusien käyttäjien sivu\",\n  \"ieGrWo\": \"Seuraa\",\n  \"igUUst\": \"Ryhmäkeskustelu Threaded Reply\",\n  \"ipHVx5\": \"Luo lasku\",\n  \"itPgxd\": \"Profiili\",\n  \"izWS4J\": \"Lopeta seuraaminen\",\n  \"j9xbzF\": \"Jo varmistettu\",\n  \"jA3OE/\": \"{n,plural,=1{{n} sat} other{{n} satia}}\",\n  \"jAmfGl\": \"{site_name} tilauksesi on päättynyt\",\n  \"jHa/ko\": \"Siivoa rehusi\",\n  \"jMzO1S\": \"Sisäinen virhe: {msg}\",\n  \"jiAVXu\": \"Videotapahtuma\",\n  \"jvo0vs\": \"Tallenna\",\n  \"jzgQ2z\": \"{n} Reaktiota\",\n  \"k0kCJp\": \"Hae nyt\",\n  \"k2veDA\": \"Kirjoita\",\n  \"k7sKNy\": \"Oma NIP-05-varmennuspalvelumme, auta tukemaan tämän sivuston kehitystä ja saat kiiltävän erikoismerkin sivuillemme!\",\n  \"k9SQm1\": \"Releet, joihin olet kytkenyt aiemmin ja jotka vaikuttavat luotettavilta.\",\n  \"kEZUR8\": \"Rekisteröi Iris-käyttäjätunnus\",\n  \"kJYo0u\": \"{n,plural,=0{{name} jakoi uudelleen} other{{name} & {n} muuta jakoivat uudelleen}}\",\n  \"kKC9ya\": \"Lompakon tiedot\",\n  \"kNd2FL\": \"Tidal kirjautuminen\",\n  \"kQAf2d\": \"Valitse\",\n  \"kaaf1E\": \"nyt\",\n  \"kc79d3\": \"Aiheet\",\n  \"klCm96\": \"Yhteisön viran hyväksyminen\",\n  \"kqPQJD\": \"Määritä zap-pooli\",\n  \"kuPHYE\": \"{n,plural,=0{{name} tykkäsi} other{{name} & {n} muuta tykkäsivät}}\",\n  \"l+ikU1\": \"Kaikki {plan}-suunnitelmassa\",\n  \"l3H1EK\": \"Kutsu kavereita\",\n  \"l3nTjd\": \"Perusavaimen johtaminen muistisääntöisestä siemenlauseesta\",\n  \"lCILNz\": \"Osta nyt\",\n  \"lD3+8a\": \"Maksa\",\n  \"lEnclp\": \"Minun tapahtumani: {n}\",\n  \"lPWASz\": \"Snort nostr-osoite\",\n  \"lTbT3s\": \"Lompakon salasana\",\n  \"lbr3Lq\": \"Kopioi linkki\",\n  \"lfOesV\": \"Non-Zap\",\n  \"lgg1KN\": \"tili\",\n  \"ll3xBp\": \"Kuvan välityspalvelin\",\n  \"lnaT9F\": \"Seuraa {n}\",\n  \"lsNFM1\": \"Napsauta ladataksesi sisältö {link}\",\n  \"lvlPhZ\": \"Maksa lasku\",\n  \"m/59y2\": \"Zap-pyyntö\",\n  \"m6h2Eg\": \"Käsittelijän suositus\",\n  \"mCEKiZ\": \"{n} nuotit on mykistetty\",\n  \"mErPop\": \"Sinulla ei taida olla vielä yhtään, mutta voit korjata asian nopeasti täältä: {link}!\",\n  \"mFtdYh\": \"{type} Työntekijän rele\",\n  \"mKAr6h\": \"Seuraa kaikkia\",\n  \"mKh2HS\": \"Tiedostojen latauspalvelu\",\n  \"mKhgP9\": \"{n,plural,=0{} =1{zappasi} other{zappasivat}}\",\n  \"mOFG3K\": \"Aloita\",\n  \"mfe8RW\": \"Vaihtoehto: {n}\",\n  \"mmPSWH\": \"Vain luku\",\n  \"n1Whvj\": \"Vaihda\",\n  \"n5l7tP\": \"Aikapohjainen kalenteritapahtuma\",\n  \"n8k1SG\": \"{n}MiB\",\n  \"nD4frR\": \"Tarjouksen vahvistus\",\n  \"nDejmx\": \"Poista esto\",\n  \"nGBrvw\": \"Kirjanmerkit\",\n  \"nGGDsi\": \"Ilmoitukset sallittu\",\n  \"nIchMQ\": \"Haetaan tilin toimintaa ({progress})\",\n  \"nPHrqp\": \"Coinjoin Pool\",\n  \"nUT0Lv\": \"Työkalut\",\n  \"nWQFic\": \"Renew\",\n  \"nihgfo\": \"Kuuntele tämä artikkeli\",\n  \"nwZXeh\": \"{n} estettyä\",\n  \"o/gK53\": \"Kansi\",\n  \"o7e+nJ\": \"{n} seuraajaa\",\n  \"oJ+JJN\": \"Mitään ei löytynyt :/\",\n  \"odFwjL\": \"Kirjaudu sisään\",\n  \"ojzbwv\": \"Hei, näyttää siltä ettei sinulla ole vielä Nostr-osoitetta, sinun pitäisi hankkia sellainen! Katso {link}\",\n  \"ozZ2Cj\": \"Badge-palkinto\",\n  \"p4N05H\": \"Lähetä\",\n  \"p9Ps2l\": \"{x}/{y} on välittäjiä ({percent})\",\n  \"pEEBFk\": \"Luotettavat releet\",\n  \"pI+77w\": \"Ladattavat varmuuskopiot Snort-välittäjältä\",\n  \"pRess9\": \"ZapPooli\",\n  \"plOM0t\": \"Mukautettu Emoji\",\n  \"plg2Ua\": \"Kanavan mykistys Käyttäjä\",\n  \"puLNUJ\": \"Kiinnitä\",\n  \"pyjJ5f\": \"Nostr Marketplace (joustaville markkinapaikoille)\",\n  \"pzTOmv\": \"Seuraajat\",\n  \"q3OuMw\": \"Torrent Kommentti\",\n  \"qAY40L\": \"Päivämäärään perustuva kalenteritapahtuma\",\n  \"qBYNMb\": \"Ryhmä Thread Vastaus\",\n  \"qD9EUF\": \"Sähköposti-silta Snort nostr-osoitteellesi\",\n  \"qDwvZ4\": \"Tuntematon virhe\",\n  \"qFIVx4\": \"Profiilimerkit\",\n  \"qMePPG\": \"Viesti\",\n  \"qMx1sA\": \"Oletus zap-määrä\",\n  \"qUJTsT\": \"Estetty\",\n  \"qXCbgZ\": \"Avaa\",\n  \"qZsKBR\": \"Renew {tier}\",\n  \"qcJFEJ\": \"Ilmoitukset API pois käytöstä\",\n  \"qdGuQo\": \"Yksityisavaimen on (älä jaa tätä kenellekään)\",\n  \"qfmMQh\": \"Tämä huomautus on mykistetty\",\n  \"qkvYUb\": \"Lisää profiiliin\",\n  \"qmJ8kD\": \"Käännös epäonnistui\",\n  \"qtWLmt\": \"Tykkää\",\n  \"qyJtWy\": \"Näytä vähemmän\",\n  \"qydxOd\": \"Tiede\",\n  \"qz9fty\": \"Väärä tappi\",\n  \"r3C4x/\": \"Ohjelmisto\",\n  \"r5srDR\": \"Anna lompakon salasana\",\n  \"rAQG0X\": \"Relelistan metatiedot\",\n  \"rIsVe+\": \"Julkisten keskustelujen luettelo\",\n  \"rMgF34\": \"Varmuuskopioi nyt\",\n  \"rRRXtB\": \"Salamaniskut\",\n  \"rT14Ow\": \"Lisää välittäjiä\",\n  \"reFEEC\": \"Raportointi\",\n  \"rfuMjE\": \"(Oletus)\",\n  \"rkM7l8\": \"Salattu suora viesti\",\n  \"rmdsT4\": \"{n} päivää\",\n  \"rn52n9\": \"Julkiset keskustelukanavat\",\n  \"rx1i0i\": \"Lyhyt linkki\",\n  \"sFUkSN\": \"Kirjanmerkkisarjat\",\n  \"sKDn4e\": \"Näytä merkit\",\n  \"sUNhQE\": \"käyttäjä\",\n  \"sZQzjQ\": \"Zap-jaon jäsentäminen epäonnistui: {input}\",\n  \"saInmO\": \"Näytetty releen nimi ei ole sama kuin syötetty täydellinen URL-osoite.\",\n  \"saorw+\": \"Tapahtuman poistopyyntö\",\n  \"sfL/O+\": \"Mykistettyjä nuotteja ei näytetä\",\n  \"t79a6U\": \"Yhteyden onnistuminen:\",\n  \"tDDiRL\": \"Luettelo kiinnostuksen kohteista\",\n  \"tFpT/O\": \"Julkaise artefaktisarjat\",\n  \"tO1oq9\": \"Videotapahtumat\",\n  \"tOdNiY\": \"Tumma\",\n  \"tRGdV1\": \"Versionoitu salaus\",\n  \"tU0ADf\": \"Tuntematon NIP-{x}\",\n  \"tVuVg9\": \"Video View Tapahtuma\",\n  \"tf1lIh\": \"Vapaa\",\n  \"th5lxp\": \"Lähetä viesti osajoukolle kirjoitusvälittäjiäsi\",\n  \"thnRpU\": \"NIP-05-varmennuksen hankkiminen voi auttaa:\",\n  \"tj6kdX\": \"{sign} {amount} satsia\",\n  \"tjpYlr\": \"Välittäjämittarit\",\n  \"ttxS0b\": \"Tukijamerkki\",\n  \"tzMNF3\": \"Tila\",\n  \"u/vOPu\": \"Maksettu\",\n  \"u4I8q8\": \"Nastaluettelo\",\n  \"u81G9+\": \"Käyntiaika\",\n  \"u9NoC1\": \"Nimen on oltava vähemmän kuin {limit} merkkiä\",\n  \"uCk8r+\": \"Onko sinulla jo tili?\",\n  \"uD7Els\": \"Ulkoiset identiteetit profiileissa\",\n  \"uJaMkO\": \"Relay-luettelo DM:ien vastaanottamiseksi\",\n  \"uSV4Ti\": \"Uudelleenjaot vaativat manuaalisen vahvistuksen\",\n  \"uc0din\": \"Lähetä satsin jako osoitteeseen\",\n  \"ufvXH1\": \"Löytyi {n} tapahtumat\",\n  \"uhu5aG\": \"Julkinen\",\n  \"un1nGw\": \"{n} viestiä\",\n  \"usAvMr\": \"Muokkaa profiilia\",\n  \"v8lolG\": \"Aloita keskustelu\",\n  \"vB3oQ/\": \"On oltava yhteystietoluettelo tai pubkey-luettelo\",\n  \"vBsZhD\": \"Yhteisöjen luettelo\",\n  \"vN5UH8\": \"Profiilikuva\",\n  \"vU/Q5i\": \"Tämä työkalu etsii kaikkien seuraajiesi viimeksi julkaiseman tapahtuman ja poistaa ne, jotka eivät ole julkaisseet 6 kuukauteen\",\n  \"vZ4quW\": \"NIP-05 on DNS-pohjainen varmennusspesifikaatio, joka auttaa vahvistamaan sinut oikeaksi käyttäjäksi.\",\n  \"vhlWFg\": \"Äänestyksen vaihtoehdot\",\n  \"vlbWtt\": \"Hanki ilmainen\",\n  \"voxBKC\": \"Ystävien seuraama\",\n  \"vxwnbh\": \"Tehtävän työmäärä julkaistuille tapahtumille\",\n  \"w1Fanr\": \"Liiketoiminta\",\n  \"w6qrwX\": \"NSFW\",\n  \"wEQDC6\": \"Muokkaa\",\n  \"wOyDTB\": \"Tiedoston tallennuspalvelinluettelo\",\n  \"wSZR47\": \"Lähetä\",\n  \"wc9st7\": \"Medialiitteet\",\n  \"whSrs+\": \"Nostr julkinen chat\",\n  \"wih7iJ\": \"nimi on estetty\",\n  \"wlWMuh\": \"Laastarit\",\n  \"wofVHy\": \"Moderointi\",\n  \"wqyN/i\": \"Lue lisää {service} palvelusta osoitteessa {link}\",\n  \"wtLjP6\": \"Kopioi tunniste\",\n  \"x+3fl6\": \"Minun releeni\",\n  \"x/Fx2P\": \"Tue käyttämiesi palveluiden kehitystä jakamalla osa zapeistasi rahastoon!\",\n  \"x82IOl\": \"Mykistä\",\n  \"xEjBS7\": \"Sinulle\",\n  \"xIcAOU\": \"{type}:n äänet\",\n  \"xIoGG9\": \"Siirry\",\n  \"xPCyu+\": \"nostr: URI-suunnitelma\",\n  \"xaj9Ba\": \"Tarjoaja\",\n  \"xbVgIm\": \"Lataa media automaattisesti\",\n  \"xhQMeQ\": \"Vanhenee\",\n  \"xl4s/X\": \"Lisäehdot:\",\n  \"xmcVZ0\": \"Etsi\",\n  \"xybOUv\": \"FAN\",\n  \"y/bmsG\": \"Salli\",\n  \"y1Z3or\": \"Kieli\",\n  \"yAztTU\": \"{n} eSats\",\n  \"yCLnBC\": \"LNURL tai Lightning-osoite\",\n  \"yLzgxH\": \"Suositut releet\",\n  \"yeX8yA\": \"Natiivisovellus\",\n  \"z3UjXR\": \"Vianmääritys\",\n  \"z3Ukvq\": \"Luonnos pitkästä sisällöstä\",\n  \"zCb8fX\": \"Paino\",\n  \"zFegDD\": \"Ota yhteyttä\",\n  \"zINlao\": \"Omistaja\",\n  \"zQvVDJ\": \"Kaikki\",\n  \"zcaOTs\": \"Satsien zap-määrä\",\n  \"zi9MdS\": \"Shakki (PGN)\",\n  \"zm6qS1\": \"{n} minuuttia lukea\",\n  \"zonsdq\": \"Epäonnistunut LNURL-palvelun lataus\",\n  \"zvCDao\": \"Näytä uusimmat viestit automaattisesti\",\n  \"zx0myy\": \"Osallistujat\"\n}\n"
  },
  {
    "path": "packages/app/src/translations/fr_FR.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Êtes-vous sûr que vous voulez republier: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payer Maintenant\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Synchroniser tous les évènements de votre profil dans le cache local\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stats du relais\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connecté avec accès en écriture\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat de Groupe Secret\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Type de Zap\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"suivants\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connexions\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Assurez-vous d'enregistrer le mot de passe suivant afin de gérer votre identifiant à l'avenir\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connecter\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"éditer\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" a reposté\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votre espace comme vous le souhaitez 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Effacer\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Support de compte\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"Intégration du stockage de fichiers HTTP\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envoyer des données anonymes sur l'utilisation\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Message de chat de groupe\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rendez votre profil plus facile à trouver et à partager\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du dossier\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voir plus\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"L'adresse Nostr ne vous appartient pas\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clés d'exportation\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gérer\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chercher...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Portefeuille générique LNDHub (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL invalide\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traitement des mentions\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"le nom contient des caractères non autorisés\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Politique\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afficher l'état\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secondes\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aller\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"trucs git\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Êtes-vous sûr de vouloir supprimer cette note de vos favoris ?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accéder à la configuration de Nostr Wallet Connect\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Veillez à sauvegarder vos clés !\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connecté à : \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Abonnements\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vérifier les signatures\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nature\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ajouter\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bannière\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vous n'avez pas de compte ?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Communautés modérées\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connexion au portefeuille\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Étiquette de sujet dans les événements textuels\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste des emoji de l'utilisateur\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Faire un don\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saisissez le mot de passe\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Finition\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listes génériques\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Favoris\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"N'aime pas (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nouvelle note\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suivi par les amis des amis\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Données spécifiques à l'application\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" heures\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Derniers articles\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Réponses\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"S'inscrire\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Statuts de l'utilisateur\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Articles\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blobs stockés sur les serveurs médiatiques\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" téléspectateurs\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clair\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traducteurs\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sans titre\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vous votez avec \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" nouvelle note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" nouvelles notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Abonnés\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Portefeuille\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total des événements :\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aucun\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Annuler\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offre\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Développeurs principaux\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votre indicatif NIP-05 est:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"La vie\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ne pas aimer\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chiffrement par clé privée\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs est l'un des premiers fournisseurs NIP-05 dans l'espace et offre une bonne collection de domaines à des prix raisonnables\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utiliser imgproxy pour compresser les images\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais manquants\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note à Soi-même\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manipulateurs d'applications recommandés\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Splits\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"API de notifications activée\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Objectif Zap\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acheter Identifiant\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Métadonnées des fichiers\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transférer vers la clé publique\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les noms d'utilisateur ne sont pas uniques sur Nostr. L'adresse nostr est votre adresse unique lisible par l'homme qui vous est unique lors de votre inscription.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envoyer zap\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Regarder la rediffusion\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste des sourds\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Réessayer\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Échec de la connexion :\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nouvelle longueur de la liste de suivi \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Échec du proxy de l'image de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", cliquez ici pour la charger directement\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recommander le relais\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sceau\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Motif : \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vous cherchez : \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tous les clients ne supportent pas cette fonction, il se peut que vous receviez encore quelques zaps comme si la division des zaps n'était pas configurée.\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aime (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suivi par\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Champs de métadonnées et balises supplémentaires\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non payé\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Changer de compte\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bon\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"Le mandataire utilise des factures HODL pour transmettre le paiement, ce qui masque la clé publique de votre nœud.\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Étiquette\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Article Wiki\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Document d'information sur le relais\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Capacité de recherche\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hors ligne\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leader de la communauté\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Réaction\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contenu modulaire des articles\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mettez en sourdine les notes des personnes qui ne font pas partie de votre réseau de confiance.\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fermer les relais\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposte (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirmer la republication\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conventions relatives à l'utilisation par les clients des balises e et p dans les événements textuels\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Répondre à\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"S'inscrire\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zapper \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bénéficiaire\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fractionnement non valide du zap : \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fil du groupe\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"le nom est trop long\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"entités encodées en bech32\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Phrase d'appairage\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suivre les ensembles\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Projet de liste d'annonces classées\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suivant\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Répondre\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suit \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendrier Événement RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envoyer\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masquer les notes en sourdine\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Réessayer la publication\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adresse Nostr\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Facture Lightning\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost générique\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note par \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mots en sourdine\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cet auteur a été mis en sourdine\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Créer ou mettre à jour un produit\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conservation illimitée des notes sur le relais Snort\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Raison\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Superbe\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jeu\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Création d'un canal\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compte\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications push\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mois\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se Connecter\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"le nom est trop court\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zappé\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vous pouvez ajouter un ou plusieurs relais, un par ligne.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accès en écriture au relais Snort, avec conservation des évènements pendant 1 an\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Embeddings AI / Listes vectorielles\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Groupes basés sur le relais\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Actualiser\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Place de marché UI/UX\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adresse Nostr (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auth HTTP\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Don Lightning\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Événement en direct\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost de citation\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se déconnecter\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Serveurs populaires\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utilisateurs recommandés\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jeux vidéo\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Échec du chargement de la facture\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps de profil\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste de suivi\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Élaguer la liste de suivi\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personnes tendances\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"et \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" autres que vous suivez\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Annonces de dépôt\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Mis en sourdine\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendrier\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traduit de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Graphique social\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Texte Note Références\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap automatiquement chaque note quand elle est chargée\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Définition du badge\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paramètres\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Canal Masquer le message\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cache\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envoyer des sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afficher les \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dernières notes\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap automatique\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vivre\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Produit vendu aux enchères\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"À propos doit être inférieur à \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" caractères\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transférer\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tout afficher\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Navigateur\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sats\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Facture / Adresse Lightning\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes de recherche\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fournisseurs de données\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afficher les badges sur les pages de profil\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Réaction à un site web\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traduire en \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ensembles de curation\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais personnalisés\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Le nom d'utilisateur est disponible\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clé\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adresse de don On-Chain\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acheter\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Désolé, nous ne comprenons pas ce type d'événement (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), veuillez essayer l'une des applications suivantes à la place !\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Serveur\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ajouter un Compte\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Annonces classées\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Réponse du portefeuille\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Authentification des clients auprès des relais\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afficher les messages d'état sur les pages de profil\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utilisateurs tendances\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Groupes d'utilisateurs\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirect émet une redirection HTTP vers l'adresse éclair fournie\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obtenir maintenant\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Une erreur est survenue!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"vous suit\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comptes\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vous n'avez pas de serveurs de médias, essayez d'en ajouter.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retirer\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sélectionnez un portefeuille\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonné aux pushs\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sel\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"PIN soutenus\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Favoris (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adresse Lightning\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Réclamez votre adresse nostr Snort incluse\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lien Magnet\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adresse Lightning invalide\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" N'aime pas\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Diffuser l'évènement\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clé hexadécimale..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Faire face à des événements inconnus\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se Déconnecter\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Infos du leader\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste des signets\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Commande Payée!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nom\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"le nom sera disponible plus tard\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mis en sourdine\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vider le cache et recharger\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ouvrir le Wallet\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vous ne suivez pas cette personne, cliquez ici pour charger les médias de \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", ou mettez à jour \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"vos préférences\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" pour toujours charger les médias de tout le monde.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Critiques des relais\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Soutien\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Horaire d'expiration\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Créer ou mettre à jour une stalle\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dernier message \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Êtes-vous sûr de vouloir désépingler cette note?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Données du compte\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnements\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vous devez être abonné à \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" pour accéder à \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" deck\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zapper tous les \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traduction automatique\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dernière visite :\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envoyé \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats à \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pas suivi par quelqu'un que vous suivez\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cliquez ici pour télécharger\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connecté\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes tendances\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnements\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications non autorisées\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utiliser des virgules pour séparer les mots, par exemple mot1, mot2, mot3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jeux d'Emoji\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nom d’utilisateur\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envoyer des sats à \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Le sport\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aucune adresse Lightning\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnez-vous à \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" pour \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" et recevez les récompenses suivantes\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposter\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recherche dans la liste des relais\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rechercher des utilisateurs\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Site Internet\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les relais sont des serveurs auxquels vous vous connectez pour envoyer et recevoir des événements. Visez 4 à 8 relais.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clé Privée\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Temps de latence moyen :\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supprimer\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Montrer\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"ID de contenu externe\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Entrez la configuration LNDHub\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Points forts\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Chat Message\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supprimé\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Événements protégés\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Type d'événement inconnu : \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Correspondance entre les clés Nostr et les identifiants internet basés sur le DNS\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saisir l'identifiant\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Demande de portefeuille\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voir en tant qu'utilisateur ?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Goals\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Consultez le code \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Épingle trop courte\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonyme\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Commenter\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Le nom doit comporter entre 8 et 15 caractères\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impossible de vérifier l'adresse Nostr\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ouvrir avec Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrents\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" a zappé\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" autres ont zappé\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les zaps sur cette note seront répartis entre les utilisateurs suivants.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menus de débogage\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Devenir un leader\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Affiche \\\"Copy ID\\\" et \\\"Copy Event JSON\\\" dans le menu contextuel de chaque message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pas disponible:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salle de réunion\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mot de passe du portefeuille\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Page par défaut\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note de texte courte\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Authentification du client\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Définir l'adresse Nostr primaire (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tags Proxy\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envoyez ce lien à vos amis et partagez la magie de nostr.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payer pour l'abonnement\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acheter une adresse nostr\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comptage des résultats\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acheter \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.pour compte\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirmer\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vous avez déjà un abonnement de ce type, veuillez renouveler ou payer\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retour d'information sur l'emploi\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impossible de voter avec \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, veuillez définir un autre montant zap par défaut\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Page des nouveaux utilisateurs\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mort\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utilisez votre code d'invitation pour gagner des sats !\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Attestations OpenTimestamps pour les événements\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emballage cadeau\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Partager\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erreur de connexion inconnue\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obtenir une adresse nostr gratuite\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votre abonnement est toujours actif, vous ne pouvez pas le renouveler pour le moment\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Créé\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fusionner les demandes\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Échec de la mise à jour, veuillez réessayer.\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contenu de longue durée\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Analyse du \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adresse Nostr invalide\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copier l'événement JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Système (Défaut)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total aujourd'hui (UTC) : \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distance\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Préférences\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Réception vers \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"En-tête du fichier inconnu : \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thème\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les réactions seront affichées sur chaque page, si désactivées aucune réaction ne sera affichée\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relais\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"La clé privée est comme un mot de passe, mais elle ne peut pas être réinitialisée. Gardez-la précieusement et ne la montrez jamais à personne. Une fois que quelqu'un possède votre clé privée, il a accès à votre compte pour toujours.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool ne fonctionne que si vous utilisez l'une des connexions de portefeuille supportées (WebLN, LNC, LNDHub ou Nostr Wallet Connect)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Message du canal\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vous avez actuellement \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats dans votre réserve de zap.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages directs privés\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnement\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personnes que vous suivez\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Le Service Worker ne fonctionne pas\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Annonces de l'état du référentiel\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Le nom d'utilisateur ne doit contenir que des lettres minuscules et des chiffres.\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expiré\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Événement vidéo de portrait en format court\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Par : \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Êtes-vous sûr que vous voulez supprimer \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distributeurs automatiques de données\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Favori\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note de chargement : \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permissions\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saisissez un code PIN pour crypter votre clé privée. Vous devez saisir ce code PIN à chaque fois que vous ouvrez le site \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envoyer zap à \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mettre à jour l'adresse Lightning\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acheter un abonnement\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais populaires utilisés par les personnes que vous suivez.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy d'adresse LN\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jeux de relais\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suivi des problèmes\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tout marquer comme lu\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personnaliser\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment devrions-nous vous appeler ?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payer maintenant\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Données spécifiques à l'application\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"L'auteur a marqué cette note comme étant un sujet sensible \"\n    },\n    {\n      \"children\": [],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais proches de votre situation géographique.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les médias dans les notes seront automatiquement affichés pour les personnes sélectionnées, sinon seul le lien sera affiché\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Informations sur le gestionnaire\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avant-première\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utiliser le relais local\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fin de contrat\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se connecter avec Nostr Extension\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"En savoir plus\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crypto\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jeux d'intérêt\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendrier des événements\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sel Hex..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personnes\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"aimé\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compte\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cessez d'écouter\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Définition de la communauté\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retirer de mes relais\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recevoir\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vérifier toutes les signatures d'événement reçues des relais\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nouvelle Discussion\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les utilisateur-trice-s doivent accepter l'avertissement de contenu pour afficher le contenu de votre note.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ajouter un serveur\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se connecter\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bloquer\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votre demande est en attente\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vous avez un compte iris.to actif\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Partagez une invitation personnalisée avec vos amis !\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votre code de référence est \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Étiquetage\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Choisissez le service d'hébergement vers lequel vous souhaitez héberger les pièces jointes\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clé publique (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Oui, s'il vous plaît\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pour voir la liste complète des changements, vous pouvez consulter le journal des modifications (changelog) \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" mis en sourdine\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il semble que vous n'avez aucun abonnement, vous pouvez en obtenir un \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bloqué\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Locale\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retirer sourdine\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du serveur\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enjeux\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traduction automatique des notes dans la langue locale\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / nostr address\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"S'identifier avec la clé\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnémonique\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envoyer des données d'utilisation\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hébergeurs de fichiers\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connexion au portefeuille Alby\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suivi de la santé du relais\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Racheter\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hashtags tendance\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Réactions\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envoi depuis \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votre montant de zap par défaut est \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, les valeurs d'exemple sont calculées à partir de ceci.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utilisateurs\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL de service\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Serveurs de médias populaires.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il semble que vous ne suivez pas assez de personnes, jetez un coup d'œil à \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" pour découvrir des personnes à suivre !\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pas de clés, pas de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", il n'y a aucun moyen de le réinitialiser si vous ne sauvegardez pas. Cela ne prend qu'une minute.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat public\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activer les réactions\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connectez un portefeuille pour envoyer des paiements instantanés\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Essayer un autre relais\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Métadonnées du canal\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Entrez la phrase d'appairage\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Délégation de signature d'événements\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Composer une note\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activer Maintenant\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributeurs\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envoyer les zap splits à\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Le nom d'utilisateur iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" vous est réservé !\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages directs cryptés\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" vous a invité à rejoindre \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les serveurs de médias stockent les médias que vous pouvez partager dans les notes sous forme d'images et de vidéos.\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Financer les développeurs et plateformes fournissant des services de vérification NIP-05\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les notes seront diffusées en temps réel dans l'onglet global et dans l'onglet notes\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nom ou pseudonyme\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Extensions prises en charge\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payé \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, frais \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connectez-vous à votre propre nœud LND avec Lightning Node Connect\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Montrer plus\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inviter des amis\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnémonique\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votre identifiant agira comme une adresse Lightning et redirigera vers l'adresse LNURL ou Lightning de votre choix\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vous êtes un leader de la communauté et vous gagnez \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" des abonnements des utilisateurs parrainés !\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker en fonctionnement\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calculer la liste d'élagage\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obtenir l'adresse\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connecté avec un accès en lecture seule\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contenu sensible\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clé publique\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonyme\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Juste maintenant\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kind mute sets\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non merci\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirections\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Si vous avez une question concernant votre commande NIP-05, veuillez contacter en DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Republier\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vous utilisez Alby ? Allez sur \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" pour obtenir votre configuration NWC !\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connexion au portefeuille nostr natif\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Photographie\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Message direct\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnements\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Serveurs de médias\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tout mettre en sourdine\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connecter un portefeuille\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Support multi-comptes\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"le nom est enregistré\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activités en direct\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retourner\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listes pour la mise en sourdine :\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Filtre WoT\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non abonné aux pushs\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adresse LN\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"La clé publique est comme votre nom d'utilisateur, vous pouvez la partager avec n'importe qui.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nom à afficher\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"En-tête d'article modulaire\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hashtags populaires\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registre\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quantité en sats\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Annonces classées\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Une répartition par défaut du Zap Pool de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" a été configurée pour les développeurs de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" . Vous pouvez la désactiver à tout moment dans \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Type\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prochainement\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saisissez votre code PIN pour déverrouiller votre clé privée\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marquer tout comme lu\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utiliser une extension de nostr signer pour se connecter\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Émoji de réaction\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se faire vérifier\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Un seul zap de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats allouera \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats à la pool de zap.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alimentation\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Discussion de groupe\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"capacité window.nostr pour les navigateurs web\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" autre\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" autres\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accueil\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pauvre\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les leaders de la communauté sont des personnes qui développent l'écosystème de nostr en étant actifs dans leurs communautés locales et en aidant à l'intégration de nouveaux utilisateurs. Tout le monde peut devenir un leader de la communauté, mais peu de personnes détiennent ce titre honorifique.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Décharge\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Merci d'utiliser \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \". Veuillez envisager de faire un don si vous le pouvez.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort est un projet open source construit par des passionnés pendant leur temps libre, vos dons sont très appréciés\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impossible de voter car le service LNURL ne prend pas en charge les zaps\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afficher les messages qui ont un tag d'avertissement de contenu\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Épinglé\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Choisissez quelques sujets d'intérêt\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lire\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emballages cadeaux\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Qu'avez-vous en tête?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Don On-Chain\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enregistré\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Joindre un média\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Regarder la diffusion\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"À propos\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Échec de l'envoi du vote\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji à envoyer en cas de réaction à une note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tous les clients ne supportent pas encore ceci\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"S'abonner\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" en mémoire)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chargement...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Application Android Signer\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listes\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste des serveurs d'utilisateurs\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preuve de Travail\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Description du flux de protocole de base\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" est plus amusant ensemble !\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Métadonnées de l'utilisateur\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste de suivi de l'élagage\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Synchroniser le compte\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporte\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invitation\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afficher les réponses\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les médias\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"ici\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste des relais bloqués\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interaction\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vos paiements envoyés et reçus apparaîtront ici.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Réactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traductions DeepL\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Empêcher les faux comptes de vous imiter\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Administrateur\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" suit (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" doublons)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gérer\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impossible de se connecter avec une clé privée via une connexion non sécurisée, veuillez utiliser une extension de gestionnaire de clés Nostr à la place\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paiements\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"page des nouveaux utilisateurs\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suivre\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat de groupe Réponse filtrée\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Générer la facture\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ne plus suivre\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Déjà sauvegardé\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votre abonnement à \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" a expiré\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nettoyez votre flux\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erreur interne : \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Événement vidéo\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sauvegarder\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Réactions\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Postuler\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Écrire\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notre propre service de vérification NIP-05, aidez à soutenir le développement de ce site et obtenez un badge spécial brillant sur notre site !\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les relais auxquels vous vous êtes déjà connecté et qui semblent fiables.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enregistrer un nom d'utilisateur pour Iris\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" a reposté\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" autres ont reposté\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Informations sur le portefeuille\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connexion à Tidal\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sélectionner\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"maintenant\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sujets\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Approbation du poste communautaire\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Configurer le pool de zaps\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" a liké\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" autres ont liké\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tout dans \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invitez vos amis\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dérivation d'une clé de base à partir d'une phrase de base mnémotechnique\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acheter Maintenant\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payer\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mes évènements : \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adresse nostr Snort\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mot de passe du portefeuille\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copier le lien\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"compte\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service proxy d'images\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnements \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cliquez pour afficher le contenu de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payer Facture\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Demande de Zap\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recommandation du gestionnaire\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" les notes ont été mises en sourdine\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"On dirait que vous n'en avez pas, consultez \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" pour en acheter un!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Travailleurs relais\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suivre tout\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service d'hébergement de fichiers\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zappé\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zappé\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Démarrer\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option : \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lecture seule\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Changer\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Événement du calendrier basé sur le temps\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"Mio\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirmation de l'offre\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Débloquer\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Favoris\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications autorisées\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recherche de l'activité du compte (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coinjoin Pool\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Outils\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renouveler\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Écouter cet article\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bloqué\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pont\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" abonnés\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aucun résultat :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnements seulement\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hé, il semble que vous n'avez pas encore d'adresse Nostr, vous devriez en obtenir une ! Consultez \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prix de l'insigne\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Importer\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ont des relais (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais fiables\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sauvegardes téléchargeables depuis le relais Snort\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji personnalisé\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Canal Mute Utilisateur\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Épingler\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (pour les places de marché résilientes)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnés\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Commentaire sur le torrent\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Événement du calendrier basé sur la date\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Réponse au fil de discussion du groupe\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> pont DM pour votre adresse Snort nostr\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Une erreur inconnue s'est produite\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges de profil\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Montant des Zaps par défaut\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bloqué\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Déverrouiller\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renouveler \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"API de notifications désactivée\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votre Clé Privée Est (ne la partagez avec personne)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cette note a été mise en sourdine\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ajouter au Profil\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"La traduction a échoué\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afficher moins\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"La science\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broche incorrecte\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logiciel\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Entrez le mot de passe du portefeuille\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Métadonnées de la liste de relais\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste des chats publics\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sauvegarder maintenant\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les coups de foudre\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ajouter Relais\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rapports\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Défaut)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Message direct crypté\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" jours\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chaînes de discussion publiques\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lien court\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jeux de signets\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges d'exposition\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"utilisateur\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Échec de l'analyse de la division zap : \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Le nom du relais affiché n'est pas le même que l'URL complet saisi.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Demande de suppression d'un événement\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les notes en sourdine ne seront pas affichées\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Réussite de la connexion :\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste d'intérêts\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Publication d'ensembles d'artefacts\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Événements vidéo\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sombre\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chiffrement versionné\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inconnu PNM-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vidéo Voir l'événement\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gratuit\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envoyer la note à un sous-ensemble de vos relais d'écriture\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obtenir la vérification NIP-05 peut aider :\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Métriques du relais\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge de Supporter\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Statut\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payé\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste des broches\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Temps de fonctionnement\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Le nom doit être inférieur à \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" caractères\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vous avez déjà un compte ?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"Identités externes dans les profils\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste de relais pour la réception des DM\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les republications seront automatiquement confirmées\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envoyer les splits de sats à\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" évènements trouvés\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Publique\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modifier le Profil\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Démarrer la discussion\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il doit s'agir d'une liste de contacts ou d'une liste de clés publiques\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste des communautés\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image de profil\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cet outil recherche le dernier événement publié par toutes les personnes que vous suivez et supprime celles qui n'ont pas publié depuis 6 mois\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 est une spécification de vérification basée sur DNS qui permet de vous valider en tant qu'utilisateur réel.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Choix proposés\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"En obtenir un gratuit\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suivi par des amis\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quantité de travail à appliquer à tous les événements publiés\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Entreprises\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modifier\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liste des serveurs de stockage de fichiers\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Soumettre\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pièces jointes aux médias\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat Public Nostr\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"le nom est bloqué\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les écussons\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modération\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"En savoir plus sur \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sur \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copier Identifiant\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mes relais\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Financez les services que vous utilisez en fractionnant une partie de tous vos zaps en un ensemble de fonds !\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mode Sourdine\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pour vous\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes par \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aller à\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr : Schéma URI\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fournisseur\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Charger automatiquement le média\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expire\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conditions supplémentaires :\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chercher\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"FAN\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Autoriser\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Langue\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL ou adresse Lightning\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais populaires\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Application native\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Débogage\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rédiger un contenu de longue durée\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poids\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contacted\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Propriétaire\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tout\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zapper montant en sats\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Échecs (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" minutes de lecture\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Échec du chargement du service LNURL\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afficher automatiquement les dernières notes\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Les participants\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/he_IL.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/hr_HR.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jeste li sigurni da želite ponovno objaviti: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sync all events for your profile into local cache\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Stats\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logged in with write access\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vrsta Zap-a\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"following\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prijave\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obavezno spremite sljedeću lozinku kako biste u budućnosti mogli upravljati svojim računom\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poveži\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"edit\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your space the way you want it 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Podrška za račun\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP File Storage Integration\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send anonymous usage metrics\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat Message\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Olakšajte pronalazak i dijeljenje svog profila\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"From File\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" mikrosekundi\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr address does not belong to you\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upravljaj\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pretraga...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic LNDHub wallet (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nevažeći LNURL\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handling Mentions\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"ime sadrži nepodržane znakove\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Politics\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show Status\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sekundi\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"git stuff\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jeste li sigurni da želite ukloniti ovu bilješku iz trake s oznakama?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Be sure to back up your keys!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Povezano s: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Pratitelja\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check Signatures\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nature\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Razgovori\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dodaj\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Natpis\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Don't have an account?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderated Communities\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Connect\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subject tag in text events\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"User emoji list\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Doniraj\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unesi lozinku\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Finish\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic lists\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Oznake\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ne sviđa se (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Note\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed by friends of friends\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Application-specific data\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sati\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Latest Articles\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Replies\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign Up\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"User Statuses\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Articles\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blobs stored on mediaservers\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" viewers\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Svijetlo\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevoditelji\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Untitled\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Glasate sa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats-a\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" nova bilješka\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" novih bilješki\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Pratitelji\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total Events:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nijedan\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Otkaži\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bid\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primarni Developeri\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vaš novi NIP-05 nadimak je:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Life\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ne sviđa mi se\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key Encryption\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs je jedan od prvih NIP-05 pružatelja usluge u svemiru i nudi široku kolekciju domena po razumnim cijenama\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Koristi imgproxy za komprimiranje slika\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Missing Relays\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bilješka sebi\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recommended Application Handlers\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Splits\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications API Enabled\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Goal\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kupi Nadimak\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"File Metadata\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prebaci na Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pošalji zap\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Replay\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute list\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retry\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connection Failed:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"New follow list length \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recommend Relay\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seal\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Looking for: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this, you may still receive some zaps as if zap splits was not configured\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sviđa se (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed by\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Extra metadata fields and tags\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Neplaćeno\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch accounts\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Good\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bilješke\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Label\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki article\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Information Document\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search Capability\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offline\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Leader\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modular Article Content\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute notes from people who are outside your web of trust\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Close Relays\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ponovna dijeljenja (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Potvrdi ponovno dijeljenje\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conventions for clients' use of e and p tags in text events\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply To\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign up\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sat-ove\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recipient\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid zap split: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Thread\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"ime predugo\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"bech32-encoded entities\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fraza za uparivanje\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow sets\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Draft Classified Listing\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sljedeće\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Odgovori\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Praćenja \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar Event RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pošalji\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hide muted notes\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retry publishing\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adresa\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning račun\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic Repost\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Matični\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted Words\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ovaj je autor utišan\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create or update a product\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Neograničeno zadržavanje bilješki na releju Snort\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Razlog\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Great\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Game\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Creation\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Count\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Push notifications\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Months\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prijava\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"ime prekratko\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zappano\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can add a single or multiple relays, one per line.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pristup za pisanje Snort releju, s 1 godinom zadržavanja događaja\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AI Embeddings / Vector lists\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay-based Groups\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ažuriraj\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marketplace UI/UX\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr address (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP Auth\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Event\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quote Repost\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Odjava\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Servers\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video sets\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Neuspješno učitavanje računa\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow List\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prune follow list\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"and \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" others you follow\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repository announcements\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Stišan\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevedeno s \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Social Graph\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Text Note References\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatski zappaj svaku bilješku kad se učita\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge Definition\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Postavke\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Hide Message\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cache\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pošalji sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prikaži posljednje \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bilješke\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatski Zap\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Product sold as an auction\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"About must be less than \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" characters\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prijenos\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle all\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Browser\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sats\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invoice / Lightning Address\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search notes\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show badges on profile pages\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction to a website\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Globalno\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevedi na \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Curation sets\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username is available\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ključ\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain Donation Address\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kupi\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sorry, we dont understand this event kind (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), please try one of the following apps instead!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dodaj Račun\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Classified Listings\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Response\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Authentication of clients to relays\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show status messages on profile pages\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"User groups\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirect issues HTTP redirect to the supplied lightning address\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preuzmi Sad\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Došlo je do pogreške!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"vas prati\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accounts\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"You dont have any media servers, try adding some.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ukloni\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Odaberite novčanik\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribed to Push\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supported NIPs\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Oznake (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Potvrdi svoju uključenu Snort nostr adresu\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnetni Link\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid Lightning Address\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislajkova\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Event\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Ključ..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dealing with Unknown Events\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Odjava\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leader Info\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark list\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Narudžba plaćena!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ime\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"ime će biti dostupno kasnije\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utišano\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Otvori novčanik\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You don't follow this person, click here to load media from \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", or update \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"your preferences\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to always load media from everybody.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay reviews\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Support\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expiration Timestamp\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create or update a stall\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Last post \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jeste sigurni da želite otkačiti bilješku?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Data\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"You must be a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" subscriber to access \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" deck\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap all \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Translate\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Last Seen:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not followed by anyone you follow\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click here to load anyway\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pretplate\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications Not Allowed\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use commas to separate words e.g. word1, word2, word3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji sets\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Korisničko ime\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sport\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search relays list\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Web stranica\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays are servers you connect to for sending and receiving events. Aim for 4-8 relays.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Privatni Ključ\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Average Latency:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Izbriši\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prikaži\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"External Content IDs\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unesi LNDHub konfiguraciju\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Highlights\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Chat Message\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Izbrisano\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Protected Events\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tip nepoznatog eventa: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mapping Nostr keys to DNS-based internet identifiers\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Pin\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Request\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"View as user?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Goals\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin too short\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonimno\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Komentiraj\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name must be between 8 and 15 characters\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cannot verify Nostr Address\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrents\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps on this note will be split to the following users.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Izbornici za uklanjanje pogrešaka\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Become a leader\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prikazuje \\\"Kopiraj ID\\\" i \\\"Kopiraj JSON događaja\\\" u kontekstnom izborniku svake poruke\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nije dostupno:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Join Room\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lozinka za novčanik\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zadana Stranica\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Short Text Note\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Client Authentication\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set as primary Nostr address (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy Tags\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send this link to your friends and share the magic of the nostr.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Plati za pretplatu\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Counting results\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kupnja \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.to account\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Potvrdi\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Već imate pretplatu ovog tipa, molimo obnovite pretplatu ili kupite novu\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Job Feedback\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ne možete glasati sa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, molimo postavite drukčiji defaultni iznos zap-a\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stranica za nove korisnike\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dead\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use your invite code to earn sats!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-ovi\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps Attestations for Events\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gift Wrap\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Podijeli\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nepoznata pogreška kod prijave\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free nostr address\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vaša je pretplata i dalje aktivna, još ju ne možete obnoviti\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kreirano\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Merge Requests\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to update, please try again\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Long-form Content\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scanning \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid Nostr Address\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kopiraj JSON događaj\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sustav (zadano)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ukupno danas (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sati\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distance\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Postavke\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Receiving to \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nepoznati header file-a: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tema\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reakcije će biti prikazane na svakoj stranici, a ako je to onemogućeno, reakcije se neće prikazati\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Releja\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"The private key is like a password, but it cannot be reset. Guard it carefully and never show it to anyone. Once someone has your private key, they will have access to your account forever.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Message\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Direct Messages\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker Not Running\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repository state announcements\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username must only contain lowercase letters and numbers\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Isteklo\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Short-form Portrait Video Event\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Od: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jeste li sigurni da želite obrisati \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Vending Machines\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Releji\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Oznaka\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading note: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permissions\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter a pin to encrypt your private key, you must enter this pin every time you open \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ažuriraj Lightning Adresu\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular relays used by people you follow.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy LN adrese\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay sets\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Problem Tracker\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prilagođeno\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"What should we call you?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Plati Odmah\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Application-specific Data\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"The author has marked this note as a \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sensitive topic\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays close to your geographic location.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handler information\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use Local Relay\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ended\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Nostr Extension\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Learn more\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crypto\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interest sets\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar Events\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"liked\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stop listening\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Definition\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove from my relays\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Receive\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check all event signatures received from relays\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Korisnici moraju prihvatiti upozorenje o sadržaju kako bi prikazali sadržaj Vaše bilješke.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Server\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign In\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blokiraj\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your application is pending\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"You have an active iris.to account\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share a personalized invitation with friends!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your referral code is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Labeling\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Odaberite kroz koji servis želite učitati privitke\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Javni ključ (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Yes please\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"To see a full list of changes you can view the changelog \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" utišano\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Čini se kako nemate nikakve pretplate, možete pronaći neke na \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blokirano\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Local\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ponovno uključi\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"From Server\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Issues\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically translate notes to your local language\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / nostr address\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with key\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send usage metrics\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alby wallet connection\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows Relay Health\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Hashtags\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reakcije\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sending from \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL usluge\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular media servers.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont follow enough people, take a look at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to discover people to follow!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"No keys, no \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", There is no way to reset it if you don't back up. It only takes a minute.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Chat\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Omogući reakcije\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect a wallet to send instant payments\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Try another relay\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Metadata\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unesite frazu za uparivanje\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delegated Event Signing\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compose a note\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aktivirajte Odmah\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suradnici\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap splits to\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" is reserved for you!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encrypted Direct Messages\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" invited you to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media servers store media which you can share in notes as images and videos\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Financirajte developere i platforme koje pružaju NIP-05 verifikacijske usluge\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name or nym\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supported Extensions\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, fee \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect to your own LND node with Lightning Node Connect\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prikaži više\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite Friends\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonički\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vaš nadimak će se ponašati kao lightning adresa i preusmjerit će Vas na odabrani LNURL ili Lightning adresu\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are a community leader and are earning \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" of referred users subscriptions!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker Running\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compute prune list\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Address\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logged in with read-only access\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Osjetljiv sadržaj\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Javni Ključ\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upravo sada\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kind mute sets\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"No thanks\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirects\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ako imate upit o svojoj NIP-05 narudžbi, molimo da pošaljete poruku \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Native nostr wallet connection\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Photography\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Direct Message\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Praćenja\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media Servers\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utišaj sve\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Spojiti Novčanik\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Podrška za više računa\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"ime je registrirano\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Activities\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Natrag\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lists to mute:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"WoT Filter\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not Subscribed to Push\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Adresa\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"The public key is like your username, you can share it with anyone.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ime za prikaz\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modular Article Header\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Hashtags\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Register\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount in sats\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Classified Listing\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"A default Zap Pool split of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" has been configured for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" developers, you can disable it at any time in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kind\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dolazi uskoro\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pin to unlock your private key\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Označi sve kao pročitano\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use a nostr signer extension to sign in\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emotikon reakcije\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verificiraj Se\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Feed\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"window.nostr capability for web browsers\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Home\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poor\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community leaders are individuals who grow the nostr ecosystem by being active in their local communities and helping onboard new users. Anyone can become a community leader, but few hold the current honorary title.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dump\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", please consider donating if you can.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time, your donations are greatly appreciated\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ne možete glasati jer LNURL usluga ne podržava zap-ove\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show posts that have a content warning tag\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prikačeno\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a few topics of interest\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pročitaj\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gift Wraps\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Što ti je na umu?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain Donation\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Spremljeno\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Attach Media\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Stream\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dodatne informacije\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Glasanje nije uspjelo\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emotikon za slanje kao reakcija na bilješku\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Svi klijenti još ne podržavaju ovo\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pretplatite se\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" in memory)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Učitavanje...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Android Signer Application\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lists\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"User server list\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Basic protocol flow description\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" is more fun together!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Značke\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"User Metadata\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prune Follow List\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sync Account\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poruke\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Podržava\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pokaži odgovore\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"ovdje\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked relays list\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interaction\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your sent and received payments will show up here.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reakcije (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL prijevodi\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Spriječite lažne račune da vas oponašaju\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Admin\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" follows (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" duplicates)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nadimak\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nije moguće prijaviti se pomoću privatnog ključa na nesigurnoj vezi, molimo koristite Nostr produžetak za upravljanje ključevima\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payments\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"new users page\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prati\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat Threaded Reply\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generate Invoice\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prestani pratiti\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Already backed up\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" subscription is expired\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clean up your feed\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interna pogreška: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video Event\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Spremi\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reakcija\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apply Now\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Piši\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Naša vlastita usluga provjere NIP-05, pomozite u razvoju ove stranice i dobijte sjajnu posebnu značku na našoj stranici!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays which you have connected to before and appear to be reliable.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Register an Iris username\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Info\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidal login\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"sad\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Topics\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Post Approval\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Configure zap pool\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sve u \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite your friends\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Basic key derivation from mnemonic seed phrase\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kupi Odmah\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Plati\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"My events: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr adresa\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lozinka novčanika\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy link\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"stranica računa\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Slika proxy usluga\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" praćenja\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kliknite kako biste učitali sadržaj na \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Plati Račun\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Request\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handler recommendation\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes have been muted\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"Izgleda kako ga nemate, provjerite \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" kako biste ga kupili!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Worker Relay\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prati sve\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usluga učitavanja datoteka\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zappan\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zappano\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mogućnosti: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read Only\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Promijeni\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Time-Based Calendar Event\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bid confirmation\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Odblokiraj\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Oznake\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications Allowed\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Searching for account activity (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coinjoin Pool\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tools\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listen to this article\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blokirano\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deck\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" pratitelja\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ništa nije pronađeno :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pokaži samo pratiteljima\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge Award\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" have relays (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reliable Relays\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sigurnosne kopije koje se mogu preuzeti sa Snort releja\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Emoji\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Mute User\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prikači\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (for resilient marketplaces)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pratitelji\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent Comment\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Date-Based Calendar Event\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Thread Reply\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pošaljite e-poruku <> DM bridge za svoju Snort nostr adresu\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nepoznata pogreška\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Badges\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zadani iznos Zap-a\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blokirano\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications API Disabled\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vaš Privatni Ključ Je (nemojte ga dijeliti ni sa kim)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been muted\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dodati na Profil\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prijevod neuspješan\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show less\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Science\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Incorrect pin\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unesite lozinku novčanika\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay List Metadata\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public chats list\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back up now\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Zaps\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dodaj relej\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reporting\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Zadano)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encrypted Direct Message\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dana\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Chat Channels\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Short link\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark sets\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show Badges\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to parse zap split: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"The relay name shown is not the same as the full URL entered.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Event Deletion Request\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted notes will not be shown\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connection Success:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interests list\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Release artifact sets\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video Events\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tamno\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Versioned Encryption\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video View Event\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Free\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provjera NIP-05 može pomoći:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Metrics\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Značka za pruženu podršku\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Status\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Plaćeno\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin list\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uptime\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name must be less than \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" characters\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Already have an account?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"External Identities in Profiles\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay list to receive DMs\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ponovna dijeljenja morate potvrditi ručno\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats splits to\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Found \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" events\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uredi profil\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Must be a contact list or pubkey list\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Communities list\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Image\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"This tool will search for the last event published by all of your follows and remove those who have not posted in 6 months\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 je specifikacija za provjeru temeljena na DNS-u koja vam pomaže potvrditi da ste pravi korisnik.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mogućnosti ankete\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed by friends\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Business\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uredi\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"File storage server list\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Submit\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media Attachments\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Public Chat\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ime je blokirano\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Patches\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderation\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saznajte više informacija o \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" na \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kopiraj ID\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"My Relays\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utišaj\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"For you\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Idi na\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: URI scheme\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatski učitaj medije\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Isteče\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Additional Terms:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pretraži\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"FAN\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Allow\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jezik\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL ili Lightning Adresa\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Relays\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Native App\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Draft Long-form Content\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weight\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kontakt\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vlasnik\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sve\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iznos Zap-a u sats-ima\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chess (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" mins to read\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Neuspješno učitavanje LNURL usluge\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatski prikaži najnovije bilješke\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Participants\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/hu_HU.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Biztos, hogy újra közzéteszi: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fizetés most\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"A profil összes eseményének szinkronizálása a helyi gyorsítótárba\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átjátszó-statisztikák\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejelentkezve írási hozzáféréssel\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Titkos csoportos csevegés\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-típus\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"követettek\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejelentkezések\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"A jövőbeni fogantyúkezelés érdekében győződjön meg arról, hogy elmentette a következő jelszót\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kapcsolódás\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"szerkesztés\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" újra közzétette\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az Ön tere, ahogyan Ön szeretné 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kiürítés\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fióktámogatás\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP fájltárolási integráció\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonimizált használati metrikák küldése\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csoportos csevegési üzenet\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tegye a profilját könnyebben megtalálhatóvá és -megoszthatóbbá\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fájlból\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" mmp\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Továbbiak betöltése\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"A Nostr-cím nem az Öné\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kulcsok exportálása\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kezelés\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Keresés…\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Általános LNDHub pénztárca (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Érvénytelen LN-webcím\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Említések kezelése\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"a név nem engedélyezett karaktereket tartalmaz\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Politika\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Állapot megjelenítése\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" mp\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mehet\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"git cuccok\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Biztosan eltávolítja a könyvjelzőkből ezt a bejegyzést?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adja meg a Nostr Wallet Connect konfigurációt\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"A kulcsairól, mindenképpen készítsen biztonsági másolatot!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kapcsolódva ehhez: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Követett\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aláírások ellenőrzése\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Természet\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beszélgetések\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hozzáadás\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profilplakát\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Még nincs fiókja?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderált közösségek\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Connect\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tárgycímke szöveges eseményekben\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felhasználói hangulatjelek listája\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adományozás\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adja meg a jelszavát\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Befejezés\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Általános listák\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Könyvjelző\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"(\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \") embernek nem tetszik\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Új bejegyzés\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Barátok barátai által követve\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alkalmazásspecifikus adatok\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ó\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Legutóbbi cikkek\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Válaszok\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Regisztráció\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felhasználói állapotok\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cikkek\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Média-kiszolgálókon tárolt csomók\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" néző\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Világos\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fordítók\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cím nélkül\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ön \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshival szavaz\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" új bejegyzés\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" új bejegyzés\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Követő\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pénztárca\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Összes esemény:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nincs\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mégse\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ajánlat\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elsődleges fejlesztők\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az Ön új NIP-05 fogantyúja a következő:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Élet\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem tetszik\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Privát kulcs-titkosítás\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"A Nostr Plebs az egyik legelső NIP-05 szolgáltató a térben, és jó domain-kollekciót kínál elfogadható áron.\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az imgproxy használata a képek tömörítéséhez\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hiányzó átjátszók\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejegyzés magamnak\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ajánlott alkalmazás-fogantyúk\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-megosztások\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Értesítési API engedélyezve\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-cél\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fogantyú vásárlása\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fájlmetaadatok\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átvitel a nyilvános kulcsra\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"A Nostron a felhasználónevek nem egyediek. A nostr-cím az Ön egyedi, ember által olvasható címe, amely a regisztrációjától kezdődően egyedi.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap küldése\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visszajátszás megtekintése\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista némítása\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Újra\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem sikerült kapcsolódni:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Új követési lista hossza \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem sikerült a proxyképet a(z) \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" kiszolgálóról betölteni. Kattintson ide a közvetlen betöltéshez\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átjátszó ajánlása\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bélyeg\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indoklás: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"A következő keresése: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem minden kliens támogatja ezt, ezért előfordulhat, hogy továbbra is úgy kapja a Zap-eket, mintha a Zap-megosztás nem lett volna konfigurálva\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tetszik neki(k): (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Általa követve:\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Extra metaadatmezők és címkék\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fizetetlen\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fiókváltás\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jó\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejegyzések\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"A proxy HODL-számlákat használ a fizetés továbbítására, ami elrejti az Ön csomópontjának pubkey-jét.\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felirat\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki-cikk\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átjátszó információs dokumentuma\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Keresési képesség\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offline\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Közösségi vezető\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reakció\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moduláris cikktartalom\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Némítsa el a bizalmi hálózatán kívül álló személyek bejegyzéseit.\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Közeli átjátszók\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"(\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \") alkalommal lett közzétéve\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Közzétevés megerősítése\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az „e” és „p” címkék szöveges eseményekben való használatára vonatkozó konvenciók a kliensek számára\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Válasz erre:\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Regisztráció\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshi\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kedvezményezett\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Érvénytelen Zap-megosztás: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csoportszál\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"túl hosszú név\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"bech32-kódolt egységek\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Párosító kifejezés\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Készletek követése\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apróhirdetés-piszkozat\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Következő\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Válasz\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Követett\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Naptár Esemény RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Küldés\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Némított bejegyzések elrejtése\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Közzététel újrapróbálása\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-cím\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning-számla\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Általános közzétevés\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Szülő\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bejegyzése\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Némított szavak\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ez a felhasználó némítva van\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Termék létrehozása vagy frissítése\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Korlátlan bejegyzésmegőrzés a Snort-átjátszókon\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indoklás\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nagyszerű\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Játék\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csatorna-létrehozás\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Szám\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Push-értesítések\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hó\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejelentkezés\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"túl rövid név\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-elt\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hozzáadhat egy vagy több átjátszót, soronként egyet-egyet.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Írási jog a Snort átjátszóhoz, 1 év eseménymegőrzéssel\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AI beágyazások / vektorlisták\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átjátszó-alapú csoportok\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Frissítés\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Piactér UI/UX\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-cím (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átjátszó\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP-hitelesítés\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning-adomány\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Élő esemény\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Közzétevés idézettként\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kijelentkezés\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Népszerű kiszolgálók\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Javasolt követendő személyek\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Videókészletek\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem sikerült betölteni a számlát \"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil-Zap-ek\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Követőlista\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Követőlista tisztítása\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felkapott emberek\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"és \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" további ember, akiket Ön követ\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tárolójelentések\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Némított\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Naptár\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshi\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"A következő nyelvről fordítva: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Közösségi grafikon\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Szöveges bejegyzés-hivatkozások\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betöltéskor automatikusan Zap-eljen minden bejegyzést\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kitűző meghatározása\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beállítások\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csatornaelrejtési üzenet\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gyorsítótár\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Satoshi küldése\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"A legutóbbi \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bejegyzés megjelenítése\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatikus Zap-elés\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Élő\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aukción értékesített termék\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"A névjegy szövegének kevesebbnek kell lennie, mint \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" karakter\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átvitel\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Összes átkapcsolása\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Böngésző\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"satoshi\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Számla / Lightning-cím\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejegyzések keresése\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adatszolgáltatók\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kitűzők megjelenítése a profiloldalakon\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reakció egy weboldalra\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Globális\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fordítás a következő nyelvre: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kurátori készletek\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Egyéni átjátszók\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"A felhasználónév elérhető\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kulcs\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain adomány-cím\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vásárlás\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ismeretlen esemény: (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), próbálja helyette az alábbi alkalmazások egyikét!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kiszolgáló\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fiók hozzáadása\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apróhirdetések\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zap\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pénztárcaválasz\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"A kliensek hitelesítése az átjátszók felé\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Állapotüzenetek megjelenítése a profiloldalakon\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felkapott felhasználók\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felhasználói csoportok\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hibajegyek átirányítása HTTP-átirányítással a tárolt lightning-címre\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beszerzés most\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hiba történt!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"követi Önt\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fiókok\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Önnek nincs médiakiszolgálója, próbáljon meg néhányat hozzáadni.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eltávolítás\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pénztárca kiválasztása\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Előfizetett a Push-szolgáltatásra\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Támogatott NIP-ek\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"(\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \") Könyvjelző\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning-cím\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Szerezze be a hozzá tartozó Snort nostr-címet\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mágnes-hivatkozás\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Érvénytelen Lightning-cím\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" embernek nem tetszik\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Esemény közvetítése\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex kulcs…\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ismeretlen események feldolgozása\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kijelentkezés\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vezetői információk\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Könyvjelzőlista\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rendelés fizetve!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Név\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"a név később elérhető lesz\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Némított\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ürítse ki a gyorsítótárat és töltse be újra\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pénztárca megnyitása\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ön nem követi ezt a személyt, kattintson a következő hivatkozásra a média betöltéséhez a webhelyről: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", vagy frissítse \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"beállításait\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", hogy a média-tartalmakat mindig mindenkitől betöltse.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vélemények az átjátszóról\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Támogatás\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lejárati időbélyeg\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Állomás létrehozása vagy frissítése\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Legutóbbi hozzászólás ekkor: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Biztosan megszünteti ennek a bejegyzésnek a kitűzését?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fiókadatok\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Követettek\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" előfizetőnek kell lennie ahhoz, hogy hozzáférjen a(z) \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"-fedélzethez\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az összes Zap-elése \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshival\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatikus fordítás\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utoljára látta:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshi elküldve neki: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem követi senki azok közül, akiket Ön követ\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kattintson ide a betöltéshez\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kapcsolódott\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felkapott bejegyzések\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Előfizetések\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az értesítések nincsenek engedélyezve\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Szavak vesszővel elválasztva, például: 1. szó, 2. szó, 3. szó\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hangulatjel-készletek\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejelentkezés Android aláíró segítségével\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felhasználónév\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Satoshi küldése neki: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"(\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \") Zap\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sport\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nincs Lightning-cím\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fizessen elő a(z) \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" webhelyre \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" áron, és megkapja a következő jutalmakat\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Újra közzétevés\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átjátszólista keresése\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felhasználók keresése\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weboldal\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az átjátszók olyan kiszolgálók, amelyekhez az események küldésekor és fogadásakor kapcsolódik. Törekedjen 4-8 átjátszóval való kapcsolatra.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nyilvános kulcs\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átlagos várakozási idő:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Törlés\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Megjelenítés\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Külső tartalom-azonosítók\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adja meg az LNDHub konfigurációt\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kiemelések\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Élő csevegési üzenet\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Törölve\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Védett események\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ismeretlen eseménytípus: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"A Nostr kulcsok leképezése DNS-alapú internetes azonosítókra\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adja meg a Pin-kódot\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pénztárca-kérés\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Megtekintés felhasználóként?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-célok\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ellenőrizze a forráskódot \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"A Pin-kód túl rövid\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Névtelen\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hozzászólás\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"A névnek 8 és 15 karakter között kell lennie\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"A Nostr-címet nem lehet hitelesíteni\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Megnyitás itt: Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrentek\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" Zap-elt\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" és további \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" ember Zap-elt\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ezen a bejegyzésen lévő Zap-ek a következő felhasználók között lesznek megosztva.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hibaelhárító menü\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Váljon vezetővé\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Megjeleníti az „Azonosító másolása a vágólapra” és az „Esemény másolása a vágólapra JSON-ként” opciót az egyes üzenetek kontextusmenüjében.\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem érhető el:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csatlakozás a szobához\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pénztárca jelszava\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alapértelmezett oldal\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rövid szöveges bejegyzés\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kliens hitelesítése\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beállítás mint elsődleges Nostr-cím (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy-címkék\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Küldje el a barátainak ezt a hivatkozást, és ossza meg velük a nostr varázsát.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Előfizetés kifizetése\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-cím vásárlása\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eredmények számlálása\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" vásárlása\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.to fiók\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Megerősítés\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Értesítések\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Már van egy ilyen típusú előfizetése, újítsa meg vagy fizesse ki\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \" Feladat-visszajelzés\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem lehetséges \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshival szavazni, állítson be alapértelmezettnek más Zap-összeget\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Új felhasználók oldala\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Újra közzétevések\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Halott\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Használja a meghívókódját, hogy satoshit keressen!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps tanúsítványok az eseményekhez\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ajándékcsomagolás\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Megosztás\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ismeretlen bejelentkezési hiba\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Szerezzen be egy ingyenes Nostr-címet\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az Ön előfizetése még aktív, így nem tudja megújítani\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Létrehozva\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beolvasztási kérelmek\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem sikerült frissíteni, próbálja meg újra\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hosszú formátumú tartalom\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beolvasás \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Érvénytelen Nostr-cím\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Esemény másolása a vágólapra JSON-ként\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rendszer (Alapértelmezett)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ma összesen (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshi\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Távolság\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beállítások\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fogadás a következő pénztárcába: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ismeretlen fájlfejléc: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Téma\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"A reakciók minden oldalon megjelennek, de ha letiltja őket nem jelennek meg\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" átjátszó\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"A privát kulcs olyan, mint egy jelszó, de nem lehet visszaállítani. Vigyázzon rá gondosan, és soha ne mutassa meg senkinek. Ha valaki a privát kulcsát egyszer megszerzi, örökre hozzáférhet az Ön fiókjához.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"A Zap-gyűjtő csak akkor működik, ha a támogatott pénztárcakapcsolatok egyikét használja (WebLN, LNC, LNDHub vagy Nostr Wallet Connect)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csatornaüzenet\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jelenleg a Zap-gyüjtőben \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshi van.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Privát közvetlen üzenetek\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Előfizetés\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emberek, akiket Ön követ\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"A szolgáltatás-feldolgozó nem fut\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"A tároló állapotjelentései\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"A felhasználónév csak kisbetűket és számokat tartalmazhat\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lejárt\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rövid formátumú portrévideó-esemény\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Általa: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Biztosan törölni akarja a következőt?: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adatértékesítő-gépek\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átjátszók\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Könyvjelző\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A következő bejegyzés betöltése: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Engedélyek\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"A privát kulcs titkosításához adjon meg egy PIN-kódot. Ezt a PIN-kódot minden alkalommal meg kell adnia, amikor a következő oldalt megnyitja: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap küldése neki: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning-cím frissítése\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Előfizetés vásárlása\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az Ön által követett emberek által használt népszerű átjátszók.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN-címproxy\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átjátszókészletek\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Problémakövető\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Összes megjelölése olvasottként\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Egyéni\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hogyan hívhatjuk Önt?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fizetés most\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alkalmazásspecifikus adatok\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"A bejegyzés szerzője \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"kényes témaként\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" jelölte meg ezt a bejegyzést\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az Ön földrajzi elhelyezkedéséhez közeli átjátszók.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"A bejegyzésekben található média bizonyos emberek számára automatikusan megjelenik, másoknak pedig egy hivatkozás lesz helyette\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fogantyú-információk\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Előnézet\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Helyi átjátszó használata\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Véget ért\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejelentkezés Nostr kiterjesztéssel\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tudjon meg többet\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crypto\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Érdeklődési készletek\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Naptári események\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt…\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emberek\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tetszett\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fiók\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hallgatás leállítása\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Közösségi meghatározás\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eltávolítás az átjátszók közül\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fogadás\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ellenőrizze az átjátszókról kapott összes esemény aláírását\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Új csevegés\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"A felhasználóknak el kell fogadniuk a tartalmi figyelmeztetést ahhoz, hogy megjelenjen az Ön bejegyzésének tartalma.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kiszolgáló hozzáadása\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejelentkezés\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Letiltás\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az Ön jelentkezése folyamatban van\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Önnek már van egy aktív iris.to fiókja\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ossza meg a személyes meghívóját a barátaival!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az Ön ajánló kódja a következő: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Feliratozás\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Válassza ki, hogy melyik feltöltési szolgáltatásba szeretné feltölteni a mellékleteket\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nyilvános kulcs (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Igen\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"A változások teljes listája \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" tekinthető meg\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" némított\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profilkép\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Úgy tűnik, nincs előfizetése, a következő hivatkozáson keresztül szerezhet egyet: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Tiltott\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Helyi\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Némítás visszavonása\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"A kiszolgálóról\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hibajegyek\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatikusan lefordítja a bejegyzéseket az Ön helyi nyelvére\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofil / nostr-cím\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejelentkezés kulccsal\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, helyreállító-magmondat\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Használati metrikák küldése\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fájlkiszolgálók\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alby pénztárca-kapcsolat\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Követett emberek által használt kiszolgálók állapota\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beváltás\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felkapott hashtagek\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reakciók\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Küldés ebből a következő pénztárcából: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az alapértelmezett Zap-összeg \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshi, a példaértékek kiszámítása ebből történik.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felhasználók\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Szolgáltatás webcíme\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Népszerű médiakiszolgálók.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Úgy tűnik, hogy nem követ elég embert, nézzen szét a következő helyen: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", hogy felfedezzen olyan embereket, akiket követhet!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nincsenek kulcsok, nincs \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", Nincs mód a visszaállításra, ha nem készít biztonsági mentést. Csak egy percet vesz igénybe.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nyilvános csevegés\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reakciók engedélyezése\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adjon meg egy pénztárcát az azonnali fizetések küldéséhez\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Próbáljon ki egy másik átjátszót\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csatorna-metaadatok\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Párosító kifejezés megadása\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átruházásos esemény-aláírás\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejegyzés készítése\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aktiválás most\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Közreműködők\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-megosztások küldése ide:\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"A felhasználónév iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Önnek van fenntartva!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Titkosított közvetlen üzenetek\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" meghívta Önt ide: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"A médiakiszolgálók olyan médiát tárolnak, amelyet a bejegyzésekben megoszthat képként és videóként.\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Finanszírozza a NIP-05 hitelesítési szolgáltatásokat nyújtó fejlesztőket és platformokat\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"A bejegyzések a globális- és a bejegyzések fülek alatt valós időben jelennek meg\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Név vagy becenév\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Támogatott kiterjesztések\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshi kifizetve, amelynek díja \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshi\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kapcsolódás a saját LND csomópontjához a Lightning Node Connect segítségével\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Továbbiak megjelenítése\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Barátok meghívása\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Helyreállító-magmondat\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az Ön fogantyúja lightning-címként fog működni, és átirányítja a kiválasztott LN-webcímet vagy Lightning-címet.\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ön egy közösségi vezető, és \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"-ot kap az ajánlott felhasználók előfizetéseiből!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"A szolgáltatás-feldolgozó fut\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista tisztításának kiszámítása\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cím beszerzése\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejelentkezve csak olvasási hozzáféréssel\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Érzékeny tartalom\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nyilvános kulcs\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Névtelen\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csak most\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kedves némító-készletek\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átirányítások\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ha kérdése van a NIP-05 rendelésével kapcsolatban, írjon közvetlen üzenetet ide: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Újraközvetítés\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Albyt használ? Nyissa meg a következő hivatkozást az NWC konfigurációjának lekéréséhez: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beépített nostr-pénztárca kapcsolat\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fényképezés\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Közvetlen üzenet\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Követettek\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Webcím…\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Médiakiszolgálók\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Összes némítása\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kapcsolódás pénztárcához\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Több fiók támogatása\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"a név már regisztrálva van\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Élő tevékenységek\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vissza\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listák a némításhoz:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"WoT szűrő\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"A Push-szolgáltatásra Ön nincs előfizetve\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN-cím\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"A nyilvános kulcs olyan, mint a felhasználónév, bárkivel megoszthatja.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Megjelenítendő név\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moduláris cikkfejléc\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Népszerű hashtagek\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Regisztráció\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Összeg satoshiban\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apróhirdetések\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"A(z) \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"-os alapértelmezett Zap-gyűjtő megosztása a(z) \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" fejlesztői számára lett beállítva, ezt bármikor letilthatja a(z) \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" oldalon.\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fajta\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hamarosan\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"A privát kulcs feloldásához írja be a PIN-kódot\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az összes megjelölése olvasottként\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Használjon Nostr-aláíró-kiterjesztést a bejelentkezéshez\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reakció-hangulatjel\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hitelesítés beszerzése\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Egyetlen \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshis Zap a Zap-gyűjtőben \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshit foglal le.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hírfolyam\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csoportos csevegés\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"window.nostr képesség webböngészők számára\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"és további \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"és további \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kezdőlap\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gyenge\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"A közösségi vezetők olyan személyek, akik a nostr ökoszisztémát növelik azáltal, hogy aktívak a helyi közösségükben, és segítenek az új felhasználók felvételében. Bárki lehet közösségi vezető, de jelenleg csak kevesen viselik ezt a megtisztelő címet.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kidobás\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Köszönjük, hogy a(z) \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" oldalt használja, ha teheti fontolja meg az adományozást.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"A Snort egy nyílt forráskódú projekt, amelyet szenvedélyes emberek építenek szabadidejükben, adományait nagyra értékeljük.\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem szavazhat, mert az LN-webcím szolgáltatója nem támogatja a Zap-elést\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tartalmi figyelmeztetés-címkével ellátott bejegyzések megjelenítése\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kitűzött\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Válasszon ki néhány érdekes témát\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Olvasás\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ajándékcsomagolások\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mire gondol?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain adomány\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mentve\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Média csatolása\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Közvetítés megtekintése\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Névjegy\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem sikerült elküldeni a szavazatot\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hangulatjel küldése, amikor egy bejegyzésre reagál\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem minden kliens támogatja\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Előfizetés\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" a memóriában)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betöltés…\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Androidos aláíró-alkalmazás\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listák\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felhasználói kiszolgálólista\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Munka-bizonyítás (PoW)\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alapvető protokollfolyam-leírás\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" együtt sokkal szórakoztatóbb!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kitűzők\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felhasználói metaadatok\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Követőlista tisztítása\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fiók szinkronizálása\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Üzenetek\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Támogatások\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meghívás\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Válaszok megjelenítése\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Média\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"itt\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Letiltott átjátszók listája\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interakció\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-gyűjtő\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Itt jelennek meg az Ön által küldött és fogadott fizetések.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"(\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \") reakció\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL fordító\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Megakadályozza, hogy hamis fiókok utánozzák Önt\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adminisztrátor\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" követett (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" másolat)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fogantyú\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem lehet bejelentkezni a privát kulccsal egy nem biztonságos kapcsolaton keresztül, használjon helyette egy Nostr-kulcskezelő-bővítményt\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fizetések\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"új felhasználók oldala\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Követés\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csoportos csevegés-szálas válasz\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Számla előállítása\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Követés megszüntetése\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Már van biztonsági mentésem\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" satoshi\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" satoshi\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az Ön \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"-előfizetése lejárt\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tisztítsa meg a hírfolyamát\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Belső hiba: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Videóesemény\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mentés\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reakció\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elfogadás most\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Írás\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"A saját NIP-05 hitelesítési szolgáltatásunk, amelynek a használatával ennek az oldalnak a fejlesztését segítheti és ezzel egy speciális kitűzőt is szerezhet!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Olyan átjátszók, amelyekhez már korábban is csatlakozott, és megbízhatónak tűnnek.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Regisztráljon egy Iris felhasználónevet\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" közzétette\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" és további \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" ember közzétette\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pénztárca információ\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejelentkezés Tidalba\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kiválasztás\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"most\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Témák\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Közösségi bejegyzés jóváhagyása\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-gyűjtő konfigurálása\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" kedvelte\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" és további \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" ember kedvelte\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Minden ebben: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Barátok meghívása\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alapvető kulcs származtatása a helyreállító-magmondatból\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vásárlás most\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kifizetés\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saját események: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr-cím\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pénztárca jelszava\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hivatkozás másolása\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"fiókoldal\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kép-proxy szolgáltató\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" követett\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kattintson a tartalom betöltéséhez innen: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Számla kifizetése\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-kérés\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fogantyú-ajánlás\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bejegyzés elnémítva\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"Úgy tűnik, hogy Önnek még nincs, a következő hivatkozáson keresztül tud vásárolni egyet: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dolgozó-átjátszó\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Összes követése\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fájlfeltöltő-szolgáltatás\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"Zap-elt\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"Zap-elt\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indítás\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lehetőség: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csak olvasható\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Váltás\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Időalapú naptáresemény\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az ajánlat megerősítése\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Letiltás megszüntetése\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Könyvjelzők\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Értesítések engedélyezve\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fióktevékenység keresése (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coinjoin-gyűjtő\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eszközök\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Megújítás\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hallgassa meg ezt a cikket\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" letiltott\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fedélzet\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" követő\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nincs találat :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csak a követettek\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Úgy tűnik, hogy Ön még nem rendelkezik Nostr-címmel, érdemes lenne beszereznie egyet! Tekintse meg a következőt: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kitűzőnyeremény\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Feltöltés\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" átjátszóval rendelkezik (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Megbízható kiszolgálók\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Letölthető biztonsági mentések a Snort-átjátszóról\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-gyűjtő\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Egyéni hangulatjel\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csatorna-felhasználó némítása\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kitűzés\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-piactér (a rugalmas piacterekhez)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Követők\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent-megjegyzés\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dátum-alapú naptáresemény\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csoportszálas válasz\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"E-mail <> közvetlen üzenet-híd a Snort nostr-címhez\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ismeretlen hiba\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil-kitűzők\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejegyzés\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alapértelmezett Zap-összeg\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Letiltva\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Feloldás\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" megújítása\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Értesítési API letiltva\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az Ön privát kulcsa (ne ossza meg senkivel)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ez a bejegyzés némítva lett\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hozzáadás a profilhoz\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \" Nem sikerült lefordítani\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tetszik\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kevesebb megjelenítése\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tudomány\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Helytelen Pin-kód\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Szoftver\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adja meg a pénztárca jelszavát\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átjátszólista-metaadat\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nyilvános csevegések listája\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Biztonsági mentés most\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning-Zap-ek\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átjátszó hozzáadása\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejelentés\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Alapértelmezett)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Titkosított közvetlen üzenet\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" nap\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nyilvános csevegőcsatornák\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rövid hivatkozás\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Könyvjelző-készletek\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kitűzők megjelenítése\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"felhasználó\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem sikerült feldolgozni a Zap-megosztást: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"A megjelenített átjátszó neve nem egyezik a megadott teljes webcímmel.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eseménytörlési kérelem\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"A némított bejegyzések nem fognak megjelenni\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sikeres kapcsolat:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Érdeklődések listája\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tárgykészletek kiadása\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Videóesemények\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sötét\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verzióval ellátott titkosítás\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ismeretlen NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Videómegtekintési esemény\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingyenes\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bejegyzés küldése az írási átjátszók egy részhalmazának\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"A NIP-05 hitelesítése segíthet:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satoshi\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átjátszómetrikák\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Támogatói kitűző\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Állapot\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fizetve\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kitűzési lista\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Üzemidő\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"A névnek kevesebb karakterből kell állnia, mint \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" karakter\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Már van fiókja?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"Külső identitások a profilokban\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Átjátszólista a közvetlen üzenetek fogadásához\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az újra közzétevésekhez kézi megerősítés szükséges\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Satoshi-megosztások küldése ide:\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" esemény megtalálva\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nyilvános\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bejegyzés\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil szerkesztése\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Csevegés indítása\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Egy névjegylistának vagy egy nyilvános kulcslistának kell lennie\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Közösségek listája\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profilkép\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ez az eszköz megkeresi az Ön összes követettje által utoljára közzétett eseményt, és eltávolítja azokat, akik 6 hónapja nem tettek közzé semmit.\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"A NIP-05 egy DNS alapú azonosítási specifikáció, ami segít az Ön valós személyének bizonyításában.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Szavazási beállítások\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Szerezzen be ingyen egyet\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Barátok által követve\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Az összes közzétett eseményre alkalmazandó munka mennyisége\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Üzleti\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felnőtt tartalom\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Szerkesztés\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fájltárolási kiszolgáló lista\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beküldés\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Média-mellékletek\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr nyilvános csevegés\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"a név le van tiltva\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Foltok\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderáció\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"További információ a következőről: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" a következő hivatkozáson keresztül érhető el: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Azonosító másolása\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saját átjátszók\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Finanszírozza az Ön által használt szolgáltatásokat úgy, hogy az összes Zap egy részét egy támogatói gyűjtőből osztja meg!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Némítás\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Önnek\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Szavazatok \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" szerint\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ugrás ide\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: URI-séma\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Szolgáltató\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Média automatikus betöltése\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lejár\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"További feltételek:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Keresés\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"RAJONGÓ\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Engedélyezés\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nyelv\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSatoshi\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN-webcím vagy Lightning-cím\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Népszerű átjátszók\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beépített alkalmazás\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hibakeresés\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hosszú formátumú tartalom piszkozata\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Súly\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ismerős\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tulajdonos\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Összes\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-összeg satoshiban\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sakk (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 0,\n      \"value\": \"olvasási idő: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" perc\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem sikerült betölteni az LN-webcím-szolgáltatást\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatikusan jelenítse meg a legutóbbi bejegyzéseket\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Résztvevők\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/id_ID.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Yakin ingin memposting ulang: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bayar Sekarang\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menyinkronkan semua peristiwa untuk profil Anda ke dalam cache lokal\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Statistik Relai\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masuk dengan akses tulis\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obrolan Grup Rahasia\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tipe Zap\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"berikut ini\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masuk\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Harap pastikan untuk menyimpan kata sandi berikut untuk mengelola pegangan Anda di masa mendatang\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menghubungkan\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"sunting\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" diposting ulang\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ruang Anda seperti yang Anda inginkan 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jelas\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dukungan Akun\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"Integrasi Penyimpanan File HTTP\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim metrik penggunaan anonim\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pesan Obrolan Grup\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jadikan profil Anda lebih mudah untuk ditemukan dan dibagikan\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dari File\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Memuat lebih banyak\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamat yang tidak sesuai dengan Anda\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci Ekspor\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengelola\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cari...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dompet LNDHub umum (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL Tidak valid\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menangani Penyebutan\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"nama memiliki karakter yang tidak diizinkan\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Politik\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tampilkan Status\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" detik\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pergi.\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"barang git\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apa Anda yakin Anda ingin memindahkan catatan ini dari penanda buku?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masukkan konfigurasi Nostr Wallet Connect\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pastikan untuk mencadangkan kunci Anda!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terhubung ke: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Mengikuti\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Periksa Tanda Tangan\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alam\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Percakapan\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tambahkan\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Spanduk\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Belum memiliki akun?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Komunitas yang Dimoderasi\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dompet Terhubung\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tag subjek dalam peristiwa teks\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar emoji pengguna\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sumbangkan\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masukkan kata sandi\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Selesai\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar generik\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Penanda Buku\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak disukai (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catatan Baru\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Diikuti oleh teman dari teman\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data khusus aplikasi\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" jam\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Artikel Terbaru\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balasan\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Status Pengguna\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Artikel\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gumpalan yang disimpan di server media\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" pemirsa\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cahaya\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penerjemah\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tanpa judul\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anda memberikan suara dengan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" catatan baru\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" catatan-catatan baru\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Pengikut\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dompet\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total Acara:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak ada\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Membatalkan\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penawaran\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pengembang Utama\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama NIP-05 baru Anda adalah:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kehidupan\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak disukai\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enkripsi Kunci Pribadi\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs adalah salah satu penyedia NIP-05 pertama di ruang ini dan menawarkan koleksi domain yang bagus dengan harga terjangkau\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gunakan imgproxy untuk mengkompresi gambar\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relai yang Hilang\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catatan untuk diri sendiri\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penangan Aplikasi yang Direkomendasikan\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Splits\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"API Pemberitahuan Diaktifkan\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Goal\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beli Pegangan\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadata File\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer ke Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama pengguna tidak unik di Nostr. Alamat Nostr adalah alamat unik Anda yang dapat dibaca manusia yang unik untuk Anda pada saat pendaftaran.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim zap\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menonton Pemutaran Ulang\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar bisu\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coba lagi.\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Koneksi Gagal:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Panjang daftar ikuti baru \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gagal memproxy gambar dari \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", klik di sini untuk memuat secara langsung\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Merekomendasikan Relay\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Segel\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alasan: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mencari: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak semua klien mendukung ini, Anda mungkin masih menerima beberapa zap seolah-olah zap splits tidak dikonfigurasi\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suka (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Diikuti oleh\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bidang dan tag metadata tambahan\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Belum dibayar\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pindah akun\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bagus.\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catatan\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy menggunakan faktur HODL untuk meneruskan pembayaran, yang menyembunyikan pubkey dari node Anda\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Label\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Artikel wiki\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dokumen Informasi Relay\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kemampuan Pencarian\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offline\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tokoh Masyarakat\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaksi\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konten Artikel Modular\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Membisukan catatan dari orang yang berada di luar jaringan kepercayaan Anda\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tutup Relai\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Posting ulang (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konfirmasi Posting Ulang\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konvensi untuk penggunaan tag e dan p oleh klien dalam acara teks\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Membalas ke\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sat\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penerima\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap split tidak valid: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utas Grup\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"nama terlalu panjang\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"entitas yang dikodekan bech32\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Frasa pasangan\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ikuti set\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Draf Daftar Rahasia\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berikutnya\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Membalas\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengikuti \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acara Kalender RSVP Acara\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengirim\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menyembunyikan nada yang dibisukan\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mencoba menerbitkan ulang\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamat No.\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Faktur Lightning\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost Generik\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Orang Tua\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catatan oleh \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kata-kata yang dibisukan\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penulis ini telah dibisukan\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Membuat atau memperbarui produk\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penyimpanan catatan tak terbatas pada relai Snort\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alasan\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bagus.\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permainan\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pembuatan Saluran\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menghitung\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pemberitahuan push\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bulan\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masuk\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"nama terlalu pendek\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"telah di-zap\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anda dapat menambahkan satu atau beberapa relay, satu per baris.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Akses tulis ke relai Snort, dengan retensi kejadian selama 1 tahun\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penyematan AI / Daftar vektor\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grup Berbasis Relai\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Memperbarui\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"UI/UX Pasar\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamat lengkap (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP Auth\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donasi Petir\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acara Langsung\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kutip Ulang\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Keluar\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server Populer\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berikut yang Disarankan\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set video\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gagal memuat faktur\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar Ikuti\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pangkas daftar pengikut\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Orang-orang yang sedang tren\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"dan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" orang lain yang Anda ikuti\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pengumuman repositori\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dibisukan\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kalender\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Diterjemahkan dari \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grafik Sosial\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catatan Teks Referensi\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secara otomatis membunyikan setiap nada saat dimuat\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Definisi Lencana\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pengaturan\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saluran Sembunyikan Pesan\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cache\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim sat\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tampilkan catatan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" terbaru\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Langsung\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Produk yang dijual sebagai lelang\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tentang harus kurang dari \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" karakter\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alihkan semua\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Browser\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sats\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Faktur / Alamat Kilat\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catatan pencarian\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penyedia Data\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menampilkan lencana di halaman profil\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaksi terhadap situs web\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terjemahkan ke \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set kurasi\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relai Khusus\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama pengguna tersedia\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamat Donasi On-chain\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Membeli\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maaf, kami tidak memahami jenis acara ini (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), silakan coba salah satu dari aplikasi berikut ini sebagai gantinya!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tambah Akun\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar yang diklasifikasikan\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zap\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tanggapan Dompet\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Otentikasi klien ke relai\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menampilkan pesan status di halaman profil\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pengguna yang sedang tren\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kelompok pengguna\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masalah pengalihan masalah pengalihan HTTP ke alamat petir yang disediakan\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klaim Sekarang\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terjadi kesalahan!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"mengikutimu\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Akun\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anda tidak memiliki server media, coba tambahkan beberapa.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hapus\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pilih Dompet\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berlangganan Push\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Garam\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP yang didukung\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penanda buku (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamat Petir\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klaim alamat nostr Snort Anda yang disertakan\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tautan Magnet\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamat Petir Tidak Valid\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Tidak suka\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acara Siaran\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci Hex..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berurusan dengan Peristiwa yang Tidak Diketahui\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Keluar\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Info Pemimpin\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar penanda\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pesanan Dibayar!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"nama akan tersedia nanti\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dibisukan\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hapus cache dan muat ulang\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buka Dompet\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anda tidak mengikuti orang ini, klik di sini untuk memuat media dari \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", atau perbarui \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"preferensi Anda\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" untuk selalu memuat media dari semua orang.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ulasan Relay\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dukungan\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stempel Waktu Kedaluwarsa\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Membuat atau memperbarui kios\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Posting terakhir \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apakah Anda yakin Anda ingin menghilangkan sematan catatan ini?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Akun\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengikuti\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anda harus menjadi pelanggan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" untuk mengakses \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dek\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap semua \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terjemahan Otomatis\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terakhir terlihat:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dikirim \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats ke \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak diikuti oleh siapa pun yang Anda ikuti\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klik di sini untuk tetap memuat\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terhubung\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catatan Tren\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Langganan\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pemberitahuan Tidak Diizinkan\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gunakan koma untuk memisahkan kata, misalnya kata1, kata2, kata3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set emoji\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama pengguna\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim foto ke \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Olahraga\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak ada alamat petir\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berlangganan ke \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" untuk mendapatkan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dan dapatkan hadiah berikut\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cari daftar relai\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cari pengguna\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Situs web\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay adalah server yang Anda sambungkan untuk mengirim dan menerima peristiwa. Usahakan untuk menggunakan 4-8 relay.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci Pribadi\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Latensi rata-rata:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hapus\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tampilkan\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"ID Konten Eksternal\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masukkan konfigurasi LNDHub\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sorotan\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pesan Obrolan Langsung\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dihapus\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acara yang Dilindungi\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jenis acara tidak diketahui: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Memetakan kunci Nostr ke pengenal internet berbasis DNS\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masukkan Pin\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permintaan Dompet\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lihat sebagai pengguna?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Goals\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lihat kode \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin terlalu pendek\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonim\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Komentar\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama harus terdiri dari 8 hingga 15 karakter\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak dapat memverifikasi Alamat Nostr\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buka di Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrents\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" disetrum\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" yang lain disetrum\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps pada catatan ini akan dibagi ke pengguna berikut.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menu\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menjadi seorang pemimpin\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menampilkan \\\"Salin ID\\\" dan \\\"Salin Event JSON\\\" di menu konteks pada setiap pesan\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak tersedia:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ruang Bergabung\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kata sandi dompet\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Halaman Bawaan\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catatan Teks Pendek\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Otentikasi Klien\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tetapkan sebagai alamat Nostr utama (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tag Proksi\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim tautan ini ke teman Anda dan bagikan keajaiban nostr.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bayar untuk berlangganan\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beli alamat nostr\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menghitung hasil\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Membeli \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Akun Iris.to\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konfirmasi\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pemberitahuan\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anda sudah memiliki langganan jenis ini, silakan perbarui atau bayar\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Umpan Balik Pekerjaan\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak dapat memilih dengan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, harap tetapkan jumlah zap default yang berbeda\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Halaman pengguna baru\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mati\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gunakan kode undangan Anda untuk mendapatkan sats!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-zap\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pengesahan OpenTimestamps untuk Acara\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bungkus kado\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bagikan\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kesalahan login tidak dikenal\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dapatkan alamat nostr gratis\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"Langganan Anda masih aktif, Anda belum dapat memperbarui\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dibuat\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gabungkan Permintaan\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gagal memperbarui, coba lagi\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konten bentuk panjang\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Memindai \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamat Tidak Valid\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salin Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sistem (Bawaan)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total hari ini (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sat\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jarak\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferensi\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menerima ke \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Header file tidak dikenal: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tema\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaksi akan ditampilkan di setiap halaman, jika dinonaktifkan, tidak ada reaksi yang akan ditampilkan\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relai\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci pribadi seperti kata sandi, tetapi tidak dapat diatur ulang. Jaga baik-baik dan jangan pernah menunjukkannya kepada siapa pun. Setelah seseorang memiliki kunci pribadi Anda, mereka akan memiliki akses ke akun Anda selamanya.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool hanya berfungsi jika Anda menggunakan salah satu koneksi dompet yang didukung (WebLN, LNC, LNDHub, atau Nostr Wallet Connect)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pesan Saluran\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saat ini Anda memiliki \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sat di zap pool Anda.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pesan Langsung Pribadi\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berlangganan\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Orang yang Anda ikuti\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pekerja Layanan Tidak Berjalan\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pengumuman status repositori\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama pengguna hanya boleh terdiri dari huruf kecil dan angka\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kedaluwarsa\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acara Video Potret Bentuk Pendek\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Oleh: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anda yakin ingin menghapus \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mesin Penjual Data\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relai-relai\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penanda buku\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catatan pemuatan: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Izin\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masukkan pin untuk mengenkripsi kunci pribadi Anda, Anda harus memasukkan pin ini setiap kali Anda membuka \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim zap ke \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Perbarui Alamat Petir\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beli Langganan\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay populer yang digunakan oleh orang yang Anda ikuti.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proksi Alamat LN\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set relai\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pelacak Masalah\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tandai semua sudah dibaca\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kustomisasi\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kami harus memanggilmu dengan sebutan apa?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bayar Sekarang\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Khusus Aplikasi\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penulis telah menandai catatan ini sebagai topik sensitif \"\n    },\n    {\n      \"children\": [],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relai yang dekat dengan lokasi geografis Anda.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media di catatan akan secara otomatis ditampilkan untuk orang yang dipilih, jika tidak, hanya tautan yang akan ditampilkan\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Informasi penanganannya\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pratinjau\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gunakan Relai Lokal\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berakhir\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masuk dengan Nostr Extension\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pelajari lebih lanjut\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kripto\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set bunga\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acara Kalender\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Garam Hex..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Orang\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"menyukai\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Akun\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berhenti mendengarkan\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Definisi Komunitas\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hapus dari relai saya\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menerima\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Periksa semua tanda tangan peristiwa yang diterima dari relay\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obrolan Baru\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pengguna harus menerima peringatan konten untuk menampilkan konten catatan Anda.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tambahkan Server\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masuk\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blokir\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permohonan Anda sedang menunggu keputusan\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anda memiliki akun iris.to yang aktif\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bagikan undangan yang dipersonalisasi dengan teman-teman!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kode referral Anda adalah \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pelabelan\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pilih layanan unggah mana yang ingin Anda unggahkan lampirannya\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci publik (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ya, silakan.\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Untuk melihat daftar lengkap perubahan, Anda dapat melihat changelog \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dibisukan\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sepertinya Anda tidak memiliki langganan, Anda bisa mendapatkannya \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Diblokir\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lokal\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berhenti membisukan\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dari Server\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masalah\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menerjemahkan catatan secara otomatis ke bahasa lokal Anda\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"alamat npub / nprofile / nostr\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masuk dengan kunci\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim metrik penggunaan\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Host file\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Koneksi dompet Alby\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengikuti Kesehatan Relai\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tebus\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tagar yang Sedang Tren\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaksi\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengirim dari \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jumlah zap default Anda adalah \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, nilai contoh dihitung dari ini.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pengguna\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL layanan\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server media populer.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sepertinya Anda tidak mengikuti cukup banyak orang, lihatlah \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" untuk menemukan orang yang bisa diikuti!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak ada kunci, tidak ada \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", Tidak ada cara untuk mengatur ulang jika Anda tidak mencadangkannya. Hanya butuh waktu satu menit.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obrolan Publik\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aktifkan reaksi\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hubungkan dompet untuk mengirim pembayaran instan\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coba relai lain\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadata Saluran\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masukkan frasa pasangan\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penandatanganan Acara yang Didelegasikan\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Membuat catatan\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aktifkan Sekarang\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kontributor\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim zap split ke\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama pengguna iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" disediakan untuk Anda!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pesan Langsung Terenkripsi\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" mengundang Anda ke \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server media menyimpan media yang dapat Anda bagikan dalam catatan sebagai gambar dan video\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Danai pengembang-pengembang dan platform-platform yang menyediakan layanan verifikasi NIP-05\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catatan akan mengalir secara real time ke tab global dan catatan\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama atau nym\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ekstensi yang Didukung\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berbayar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, gratis \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sambungkan ke node LND Anda sendiri dengan Lightning Node Connect\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tampilkan lebih banyak\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Undang Teman\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pegangan Anda akan bertindak seperti alamat kilat dan akan mengarahkan ke LNURL atau alamat Lightning yang Anda pilih\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anda adalah pemimpin komunitas dan mendapatkan \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dari langganan pengguna yang direferensikan!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pekerja Layanan Menjalankan\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menghitung daftar pangkas\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dapatkan Alamat\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masuk dengan akses hanya-baca\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konten Sensitif\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci Publik\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Baru saja\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set bisu yang baik\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak, terima kasih.\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pengalihan\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jika Anda memiliki pertanyaan tentang pesanan NIP-05 Anda, silakan DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menyiarkan Lagi\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menggunakan Alby? Kunjungi \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" untuk mendapatkan konfigurasi NWC Anda!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Koneksi dompet nostr asli\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fotografi\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pesan Langsung\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Yang diikuti\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server Media\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bisukan semua\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hubungkan Dompet\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stempel Waktu Terbuka\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dukungan multi akun\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"nama terdaftar\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kegiatan Langsung\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kembali\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar yang akan dibisukan:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Filter WoT\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak Berlangganan Push\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamat LN\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci publik seperti nama pengguna Anda, Anda dapat membaginya dengan siapa pun.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama tampilan\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tajuk Artikel Modular\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tagar Populer\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jumlah dalam sat\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar yang diklasifikasikan\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pemisahan Zap Pool default \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" telah dikonfigurasi untuk pengembang \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" , Anda dapat menonaktifkannya kapan saja di \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Baik\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Segera hadir\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masukkan pin untuk membuka kunci pribadi Anda\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tandai Semua Telah Dibaca\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gunakan ekstensi penanda tangan nostr untuk masuk\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji reaksi\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dapatkan Verifikasi\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Satu zap dari \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats akan mengalokasikan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats ke zap pool.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pakan\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obrolan Grup\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"kemampuan window.nostr untuk browser web\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" lainnya\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" lainnya\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beranda\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Miskin\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pemimpin komunitas adalah individu yang mengembangkan ekosistem Nostr dengan aktif di komunitas lokal mereka dan membantu pengguna baru. Siapa pun dapat menjadi pemimpin komunitas, tetapi hanya sedikit yang memegang gelar kehormatan saat ini.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dump\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terima kasih telah menggunakan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", mohon pertimbangkan untuk berdonasi jika Anda bisa.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort adalah proyek sumber terbuka yang dibangun oleh orang-orang yang bersemangat di waktu luang mereka, donasi Anda sangat dihargai\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak dapat memberikan suara karena layanan LNURL tidak mendukung zaps\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menampilkan postingan yang memiliki tag peringatan konten\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Disematkan\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pilih beberapa topik yang menarik\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Baca\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bungkus Kado\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apa yang sedang kamu pikirkan?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donasi On-chain\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Disimpan\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lampirkan Media\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menonton Streaming\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tentang\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gagal mengirim suara\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji untuk dikirim saat bereaksi terhadap sebuah catatan\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Belum semua klien mendukung hal ini\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berlangganan\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dalam memori)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Memuat...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aplikasi Penandatangan Android\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar server pengguna\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bukti Pekerjaan\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deskripsi aliran protokol dasar\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" lebih menyenangkan jika dilakukan bersama-sama!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lencana\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadata Pengguna\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pangkas Daftar Pengikut\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sinkronisasi Akun\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pesan-pesan\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dukungan\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengundang\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tampilkan balasan-balasan\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"di sini\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar relai yang diblokir\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interaksi\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pembayaran yang Anda kirim dan terima akan muncul di sini.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaksi-reaksi (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL terjemahan\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cegah akun palsu meniru Anda\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Admin\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" berikut (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" duplikat)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menangani\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak dapat masuk dengan kunci pribadi pada koneksi yang tidak aman, gunakan ekstensi pengelola kunci Nostr sebagai gantinya\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pembayaran\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"halaman pengguna baru\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ikuti\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balasan Beralur Obrolan Grup\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hasilkan Faktur\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berhenti mengikuti\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sudah dicadangkan\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Langganan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Anda telah kedaluwarsa\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bersihkan feed Anda\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kesalahan internal: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acara Video\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Simpan\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reaksi\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar Sekarang\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tulis\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Layanan verifikasi NIP-05 kami sendiri, bantu dukung pengembangan situs ini dan dapatkan lencana khusus yang mengkilap di situs kami!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relai yang telah Anda sambungkan sebelumnya dan tampaknya dapat diandalkan.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mendaftarkan nama pengguna Iris\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" diposkan ulang\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" yang lain diposting ulang\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Info Dompet\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masuk pasang surut\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pilih\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"sekarang\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Topik\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Persetujuan Pos Komunitas\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengkonfigurasi zap pool\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" menyukai\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" yang lain menyukai\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Semuanya di \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Undang teman Anda\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Derivasi kunci dasar dari frasa benih mnemonik\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beli Sekarang\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bayar\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acara saya: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamat hidung mendengus\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kata sandi dompet\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salin tautan\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"halaman akun\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Layanan proxy gambar\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengikuti \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klik untuk memuat konten dari \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bayar Faktur\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permintaan Zap\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rekomendasi penanganannya\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" catatan telah dibisukan\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sepertinya Anda belum memilikinya, kunjungi \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" untuk membelinya!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relai Pekerja\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ikuti semua\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Layanan unggah berkas\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"di-zap\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"di-zap\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mulai\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opsi: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hanya Baca\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beralih\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acara Kalender Berbasis Waktu\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konfirmasi penawaran\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buka blokir\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penanda-penanda buku\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pemberitahuan Diizinkan\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mencari aktivitas akun (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kolam Renang Coinjoin\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Peralatan\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Memperbaharui\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dengarkan artikel ini\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" diblokir\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dek\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" pengikut\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak ada yang ditemukan :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hanya yang diikuti\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hei, sepertinya Anda belum memiliki Nostr Address, Anda harus mendapatkannya! Lihat \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penghargaan Lencana\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unggah\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" memiliki relay (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relai yang Andal\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cadangan yang dapat diunduh dari relai Snort\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji Khusus\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pengguna Bisu Saluran\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sematkan\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (untuk pasar yang tangguh)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pengikut\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Komentar Torrent\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acara Kalender Berbasis Tanggal\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balasan Utas Grup\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> Jembatan DM untuk alamat nostr Snort Anda\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kesalahan yang tidak diketahui\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lencana Profil\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catatan\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jumlah Zap bawaan\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Diblokir\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Membuka kunci\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Perbarui \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"API Pemberitahuan Dinonaktifkan\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci Pribadi Anda Adalah (jangan bagikan ini dengan siapa pun)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catatan ini telah dibisukan\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tambahkan ke Profil\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terjemahan gagal\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seperti\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tampilkan lebih sedikit\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sains\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin salah\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Perangkat lunak\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masukkan kata sandi dompet\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadata Daftar Relai\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar obrolan publik\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back up sekarang\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Zaps\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tambahkan Relay\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pelaporan\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Bawaan)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pesan Langsung Terenkripsi\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hari\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saluran Obrolan Publik\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tautan pendek\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set penanda\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tampilkan Lencana\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"pengguna\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gagal mengurai zap split: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama relai yang ditampilkan tidak sama dengan URL lengkap yang dimasukkan.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permintaan Penghapusan Acara\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nada yang dibisukan tidak akan ditampilkan\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Koneksi Berhasil:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar minat\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Melepaskan set artefak\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acara Video\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gelap\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enkripsi Berversi\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP tidak diketahui-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acara Tampilan Video\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gratis\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengirim catatan ke subset dari relai tulis Anda\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mendapatkan verifikasi NIP-05 dapat membantu:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metrik Relai\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lencana Pendukung\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Status\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sudah dibayar\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar pin\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Waktu kerja\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama harus kurang dari \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" karakter\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sudah memiliki akun?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"Identitas Eksternal dalam Profil\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar relai untuk menerima DM\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Posting ulang perlu dikonfirmasi secara manual\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengirimkan split sat ke\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ditemukan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" acara\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Publik\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" catatan\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sunting profil\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mulai obrolan\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Harus berupa daftar kontak atau daftar pubkey\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar komunitas\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gambar Profil\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alat ini akan mencari acara terakhir yang dipublikasikan oleh semua pengikut Anda dan menghapus mereka yang belum memposting dalam 6 bulan\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 adalah spesifikasi verifikasi berbasis DNS yang membantu memvalidasi Anda sebagai pengguna nyata.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opsi Jajak Pendapat\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dapatkan yang gratis\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Diikuti oleh teman-teman\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jumlah pekerjaan yang harus diterapkan pada semua acara yang dipublikasikan\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bisnis\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sunting\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar server penyimpanan file\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lampiran Media\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obrolan Publik Nostr\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nama diblokir\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tambalan\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderasi\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cari tahu info selengkapnya tentang \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" di \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salin ID\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relai Saya\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Danai layanan yang Anda gunakan dengan membagi sebagian dari semua zap Anda ke dalam kumpulan dana!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bisukan\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Untukmu\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voting oleh \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pergi ke\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: Skema URI\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penyedia\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Memuat media secara otomatis\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kedaluwarsa\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ketentuan Tambahan:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cari\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"KIPAS\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Izinkan\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bahasa\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL atau Alamat Kilat\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relai Populer\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aplikasi Asli\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Draf Konten Bentuk Panjang\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berat\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kontak\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pemilik\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Semua\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jumlah zap dalam sat\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catur (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" menit untuk membaca\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gagal memuat layanan LNURL\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tampilkan catatan terbaru secara otomatis\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Peserta\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/it_IT.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vuoi davvero ripostare: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagamenti ora\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sincronizzare tutti gli eventi del proprio profilo nella cache locale\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Statistiche della staffetta\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accesso con accesso in scrittura\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat di gruppo segreta\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tipo di zap\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"di seguito\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accedi\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Assicurati di salvare la seguente password per gestire il tuo profilo in futuro\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connetti\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"modifica\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ripubblicato\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il vostro spazio come lo volete voi 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Libero\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Servizio clienti\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"Integrazione dell'archiviazione file HTTP\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inviare metriche di utilizzo anonime\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messaggio di chat di gruppo\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rendi il tuo profilo più facile da trovare e condividere\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Da file\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Per saperne di più\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"L'indirizzo Nostr non appartiene all'utente\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chiavi di esportazione\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gestisci\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cerca...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Portafoglio generico LNDHub (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL non valido\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gestione delle menzioni\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"il nome ha caratteri non ammessi\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Politica\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostra stato\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sec\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vai\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"roba di git\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vuoi davvero rimuovere questa nota dai preferiti?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inserire la configurazione di Nostr Wallet Connect\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Assicuratevi di eseguire il backup delle chiavi!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connessione a: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" seguiti\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Firma degli assegni\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Natura\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversazioni\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aggiungi\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Intestazione\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non avete un account?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comunità moderate\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Portafoglio Connect\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tag oggetto negli eventi di testo\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenco emoji dell'utente\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dona\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inserisci la password\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Finitura\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenchi generici\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" preferiti\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non mi piace (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nuova nota\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguito da amici di amici\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dati specifici dell'applicazione\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ore\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Articoli più recenti\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Risposte\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iscriviti\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stati dell'utente\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Articoli\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blob memorizzati sui mediaserver\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" spettatori\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chiaro\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traduttori\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Senza titolo\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stai votando con \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" nuova nota\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" nuove note\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Seguaci\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Portafoglio\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Collegamento Nostr\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Totale eventi:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nessuno\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Annulla\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offerta\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sviluppatori principali\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il tuo nuovo nome utente NIP-05 è:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"La vita\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non mi piace\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crittografia a chiave privata\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs è uno dei primi provider NIP-05 e offre una grande collezione di domini a prezzi ragionevoli\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utilizza imgproxy per comprimere le immagini\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relè mancanti\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note personali\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gestori di applicazioni consigliati\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Spaccati Zap\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifiche API abilitate\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obiettivo Zap\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acquista Handle\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadati dei file\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trasferisci a Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"I nomi utente non sono unici su Nostr. L'indirizzo nostr è l'indirizzo unico leggibile dall'uomo che vi è stato assegnato al momento della registrazione.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invia zap\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Guarda il replay\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenco dei silenziosi\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Riprova\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connessione fallita:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nuova lunghezza dell'elenco dei seguaci \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non è stato possibile inviare l'immagine di proxy da \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", fare clic qui per caricarla direttamente\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Raccomandare il relè\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sigillo\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Motivo: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alla ricerca di: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non tutti i client supportano questa funzione, per cui è possibile che si ricevano ancora alcuni zap come se la suddivisione in zap non fosse configurata.\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mi piace (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguito da\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Campi di metadati e tag extra\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non pagato\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cambio di account\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buono\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il proxy utilizza le fatture HODL per inoltrare il pagamento, nascondendo la pubkey del nodo.\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Etichetta\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Articolo Wiki\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Documento informativo sul relè\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Capacità di ricerca\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non in linea\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leader della comunità\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reazione\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contenuto modulare dell'articolo\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Silenziare le note di persone che non rientrano nella vostra rete di fiducia.\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chiudere i relè\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Riposta (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conferma Riposta\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Convenzioni per l'uso da parte dei clienti dei tag e e p negli eventi di testo\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rispondi a\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iscriviti\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Destinatario\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Divisione zap non valida: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thread di gruppo\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nome troppo lungo\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"entità codificate in bech32\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Frase di accoppiamento\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguire i set\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bozza dell'elenco degli annunci\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avanti\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rispondi\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Segue \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendario Evento RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invia\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nascondere le note in sordina\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Riprova a pubblicare\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indirizzo Nostr\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fattura Lightning\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost generico\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parente\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota di \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parole mute\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Questo autore è stato silenziato\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Creare o aggiornare un prodotto\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ritenzione illimitata della nota sul relè Snort\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Motivo\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grande\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gioco\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Creazione di canali\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conteggio\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifiche push\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mesi\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accedi\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"nome troppo corto\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"hai messo zap\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"È possibile aggiungere uno o più relè, uno per linea.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scriva accesso al relay Snort, con 1 anno di ritenzione dell'evento\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Incorporazioni AI / Elenchi vettoriali\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gruppi basati su relè\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aggiorna\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"UI/UX del mercato\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indirizzo Nostr (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relè\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"Autorizzazione HTTP\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donazione di fulmini\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento dal vivo\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Riposta la citazione\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Disconnettiti\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server popolari\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguiti suggeriti\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set di video\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impossibile caricare la fattura\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profilo Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguire l'elenco\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Potare l'elenco dei follower\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Persone di tendenza\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"e \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" altri che segui\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Annunci del repository\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Silenziato\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendario\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" saturazione\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tradotto da \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grafico sociale\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Testo Nota Riferimenti\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap automaticamente ogni nota quando caricata\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Definizione di badge\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impostazioni\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Canale Nascondi messaggio\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cache\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invia sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visualizza le ultime \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" note\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap automatico\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"In diretta\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prodotto venduto all'asta\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il testo deve essere inferiore a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" caratteri\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trasferisci\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seleziona tutti\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Browser\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"saturazione\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indirizzo di fatturazione / Lightning\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note di ricerca\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fornitori di dati\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostra i badge sulle pagine del profilo\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reazione a un sito web\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Globale\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traduci in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set di curatela\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relè personalizzati\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il nome utente è disponibile\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chiave\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indirizzo per le donazioni in catena\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acquista\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Spiacenti, non comprendiamo questo tipo di evento (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), prova invece una delle seguenti applicazioni!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aggiungi Account\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inserzioni classificate\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zap\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Risposta del portafoglio\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Autenticazione dei client ai relay\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostra i messaggi di stato sulle pagine del profilo\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utenti di tendenza\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gruppi di utenti\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il reindirizzamento emette un reindirizzamento HTTP verso l'indirizzo lightning fornito\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rivendica Ora\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Si è verificato un errore!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"ti segue\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conti\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non avete server multimediali, provate ad aggiungerne qualcuno.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rimuovi\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seleziona portafoglio\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abbonato a Push\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"PNI supportati\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferiti (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indirizzo del fulmine\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rivendica il tuo indirizzo nostr Snort incluso\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Link magnetico\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrente\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indirizzo Lightning non valido\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Non mi piace\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento di trasmissione\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chiave esadecimale..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gestire gli eventi sconosciuti\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Disconnettiti\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Info sul leader\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenco dei segnalibri\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ordine pagato!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nome\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"il nome sarà disponibile in seguito\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Silenziato\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancellare la cache e ricaricare\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apri portafoglio\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se non segui questa persona, clicca qui per caricare i media da \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", oppure aggiorna \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"le tue preferenze\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" per caricare sempre i media da tutti.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recensioni dei relè\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporto\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data di scadenza\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Creare o aggiornare una bancarella\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ultimo messaggio \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sei sicuro di voler staccare questa nota?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dati del conto\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Segue\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Per accedere al mazzo \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" è necessario essere abbonati a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" .\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap tutti i saturazioni di \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traduzione automatica\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"L'ultima volta che è stato visto:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invia \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non è seguito da nessuno di quelli che segui\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fare clic qui per caricare comunque\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Collegato\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note di tendenza\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abbonamenti\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifiche non consentite\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utilizzare le virgole per separare le parole, ad esempio parola1, parola2, parola3.\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set di emoji\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nome utente\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inviare saggi a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"(\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \") Zap\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lo sport\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nessun indirizzo per i fulmini\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abbonatevi a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" per \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" e riceverete i seguenti premi\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Riposta\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ricerca nell'elenco dei relè\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ricerca utenti\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sito web\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"I relè sono server a cui ci si collega per inviare e ricevere eventi. Puntate a 4-8 relè.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chiave Privata\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Latenza media:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elimina\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visualizza\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"ID contenuti esterni\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inserisci la configurazione LNDHub\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Punti salienti\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messaggio della chat dal vivo\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eliminato\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eventi protetti\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tipo di evento sconosciuto: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mappatura delle chiavi Nostr agli identificatori Internet basati su DNS\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inserire il pin\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Richiesta di portafoglio\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visualizzare come utente?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obiettivi Zap\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scopri il codice \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin troppo corto\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonimo\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Commenta\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il nome deve essere compreso tra 8 e 15 caratteri\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impossibile verificare l'indirizzo Nostr\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aprire su Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrenti\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" colpiti\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" altri zapping\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gli zapping su questa nota saranno suddivisi tra i seguenti utenti.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menu debug\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Diventare leader\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostra \\\"Copia ID\\\" e \\\"Copia evento JSON\\\" nel menu contestuale di ogni messaggio\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non disponibile:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sala riunioni\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Password del portafoglio\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagina di default\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Breve nota di testo\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Autenticazione del cliente\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impostato come indirizzo primario Nostr (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tag Proxy\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inviate questo link ai vostri amici e condividete la magia del nostr.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paga l'abbonamento\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acquistare l'indirizzo nostr\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Risultati del conteggio\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acquista \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.to conto\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conferma\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifiche\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hai già un abbonamento di questo tipo, si prega di rinnovare o pagare\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Feedback sul lavoro\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impossibile votare con \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, imposta un importo diverso di zap predefinito\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagina dei nuovi utenti\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ripostamenti\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Morto\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usa il tuo codice invito per guadagnare sats!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Attestazioni OpenTimestamps per gli eventi\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impacco regalo\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Condividi\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Errore di login sconosciuto\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ottenere un indirizzo nostr gratuito\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"L'abbonamento è ancora attivo, non puoi ancora rinnovare\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Creato\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unire le richieste\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aggiornamento non riuscito, riprovare\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contenuti di lunga durata\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scansione \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indirizzo Nostr non valido\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copia evento JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sistema (Predefinito)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Totale oggi (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sat\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distanza\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferenze\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ricezione a \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Intestazione del file sconosciuta: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tema\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Le reazioni saranno mostrate in ogni pagina. Se disabilitate, non verranno mostrate\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" relay\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"La chiave privata è come una password, ma non può essere resettata. Conservatela con cura e non mostratela mai a nessuno. Se qualcuno possiede la chiave privata, avrà accesso al vostro account per sempre.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool funziona solo se si utilizza una delle connessioni di portafoglio supportate (WebLN, LNC, LNDHub o Nostr Wallet Connect).\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messaggio del canale\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Attualmente hai \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats nel tuo pool di zap.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messaggi diretti privati\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abbonamento\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Persone che segui\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il Service Worker non è in esecuzione\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Annunci sullo stato del repository\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il nome utente deve contenere solo lettere minuscole e numeri\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scaduto\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento video di ritratto in formato ridotto\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Creato da: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vuoi davvero eliminare \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"?\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distributori automatici di dati\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferito\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota di caricamento: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permessi\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inserire un pin per crittografare la chiave privata; questo pin deve essere inserito ogni volta che si apre \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inviare zap a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aggiorna indirizzo Lightning\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acquista l'abbonamento\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"I relè più utilizzati dalle persone che seguite.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy Indirizzo LN\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set di relè\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tracciamento dei problemi\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contrassegnare tutte le letture\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personalizzato\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Come dovremmo chiamarla?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paga ora\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dati specifici dell'applicazione\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"L'autore ha contrassegnato questa nota come argomento sensibile \"\n    },\n    {\n      \"children\": [],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relè vicini alla vostra posizione geografica.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"I media nelle note verranno mostrati automaticamente per le persone selezionate, altrimenti verrà mostrato solo il link.\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Informazioni sul gestore\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegramma\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anteprima\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utilizzare il relè locale\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terminato\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accedi con l'estensione Nostr\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Per saperne di più\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crittografia\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set di interessi\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendario eventi\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Persone\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"piaciuto\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conto\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Smettere di ascoltare\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Definizione di comunità\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rimuovere dai miei relè\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ricevere\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Controllare tutte le firme degli eventi ricevute dalle staffette\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nuova chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gli utenti devono accettare l'avviso di contenuto per mostrare il contenuto della nota.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aggiungi server\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accedi\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocca\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"La vostra domanda è in sospeso\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avete un account iris.to attivo\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Condividete un invito personalizzato con gli amici!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il vostro codice di riferimento è \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Etichettatura\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scegli quale servizio vuoi usare per caricare gli allegati\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chiave pubblica (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sì, per favore\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Per vedere l'elenco completo delle modifiche è possibile consultare il changelog \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" silenziato\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sembra che tu non abbia alcun abbonamento, puoi ottenere un \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bloccato\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Locale\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Riattiva\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Da Server\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Problemi\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tradurre automaticamente le note nella lingua locale\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofilo / indirizzo nostr\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accedi con la chiave\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invio di metriche di utilizzo\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ospiti di file\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connessione al portafoglio Alby\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Segue la salute della staffetta\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Riscatto\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hashtag di tendenza\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reazioni\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invio da \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"La quantità di zap predefinita è \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, i valori di esempio sono calcolati da questo valore.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utenti\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL del servizio\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"I server multimediali più diffusi.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sembra che tu non segua abbastanza persone, dai un'occhiata a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" per scoprire le persone da seguire!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nessun tasto, nessun \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", non c'è modo di resettarlo se non si fa il backup. Ci vuole solo un minuto.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat pubblica\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abilita reazioni\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Collegare un portafoglio per inviare pagamenti istantanei\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prova un altro relè\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadati del canale\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inserisci la frase di accoppiamento\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Firma di eventi delegati\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comporre una nota\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Attiva adesso\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributori\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inviare gli split zap a\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il nome utente iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" è riservato a voi!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messaggi diretti criptati\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" vi ha invitato a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"I server multimediali memorizzano i media che possono essere condivisi nelle note come immagini e video.\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sviluppatori di fondi e piattaforme che forniscono servizi di verifica NIP-05\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Le note verranno trasmesse in tempo reale nella scheda globale e in quella delle note.\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nome o nomenclatura\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Estensioni supportate\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"A pagamento \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, a pagamento \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Collegarsi al proprio nodo LND con Lightning Node Connect\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostra altro\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invitare gli amici\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonico\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il tuo handle si comporterà come un indirizzo lightning e reindirizzerà al LNURL o all'indirizzo Lightning selezionato\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sei un leader della comunità e stai guadagnando \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" con gli abbonamenti degli utenti segnalati!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lavoratore del servizio in esecuzione\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calcolo dell'elenco di potatura\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ottieni l'indirizzo\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accesso con accesso in sola lettura\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contenuto sensibile\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chiave Pubblica\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proprio adesso\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set di mute gentili\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"No grazie\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reindirizzamenti\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se hai una richiesta sul tuo ordine NIP-05, scrivimi in privato \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trasmissione di nuovo\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utilizzate Alby? Vai su \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" per ottenere la tua configurazione NWC!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connessione nativa al portafoglio nostr\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fotografia\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messaggio diretto\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguiti\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL...\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server multimediali\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Silenzia tutti\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Collega il portafoglio\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporto per più account\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"il nome è registrato\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Attività dal vivo\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indietro\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenchi da silenziare:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Filtro WoT\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non sono abbonato a Push\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indirizzo LN\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"La chiave pubblica è come il vostro nome utente: potete condividerla con chiunque.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nome visualizzato\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Intestazione modulare dell'articolo\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hashtag popolari\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registro\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quantità in saturazioni\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenco classificato\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Per gli sviluppatori di \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" è stata configurata una suddivisione predefinita del pool Zap di \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" , che può essere disabilitata in qualsiasi momento in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gentile\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prossimamente\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inserire il pin per sbloccare la chiave privata\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Segna tutto come letto\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usare un'estensione nostr signer per accedere\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji di reazione\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verifica il tuo account\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Un singolo zap di \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats assegnerà \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats al pool di zap.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alimentazione\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat di gruppo\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"funzionalità window.nostr per i browser web\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"e \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" altri\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"e \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" altri\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Casa\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Povero\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"I leader della comunità sono persone che fanno crescere l'ecosistema nostr essendo attivi nelle loro comunità locali e aiutando a coinvolgere nuovi utenti. Chiunque può diventare un community leader, ma pochi detengono questo titolo onorifico.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scarico\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grazie per aver utilizzato il sito \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", considerate l'idea di fare una donazione se potete.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort è un progetto open source costruito da persone appassionate nel loro tempo libero; le vostre donazioni sono molto apprezzate.\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impossibile votare perché il servizio LNURL non supporta gli zap\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostra i messaggi che hanno un tag di avviso di contenuto\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Attaccato\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scegliere alcuni argomenti di interesse\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leggi\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confezioni regalo\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"A cosa pensi?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donazione a catena\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lampo Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salvato\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Allegare i supporti\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Guarda lo streaming\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Info\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impossibile inviare il voto\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji da inviare quando reagisci a una nota\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non tutti i clienti lo supportano ancora\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abbonati\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" in memoria)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Caricamento...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Applicazione Android Signer\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenchi\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenco dei server utente\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prova di lavoro\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Descrizione del flusso del protocollo di base\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" è più divertente insieme!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distintivi\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadati utente\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Potare Seguire l'elenco\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account di sincronizzazione\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messaggi\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporto\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invito\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostra le risposte\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"qui\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenco dei relè bloccati\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interazione\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Piscina Zap\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Qui vengono visualizzati i pagamenti inviati e ricevuti.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reazioni (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL traduzioni\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impedisci agli account falsi di imitarti\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Admin\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" segue (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" duplicati)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impossibile effettuare il login con la chiave privata su una connessione insicura. Utilizza un'estensione Nostr key manager\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagamenti\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"pagina dei nuovi utenti\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Segui\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat di gruppo Risposta filtrata\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generare la fattura\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profilo\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Smetti di seguire\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Già eseguito il backup\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"L'abbonamento a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" è scaduto\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pulite il vostro feed\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Errore interno: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento video\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salva\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reazioni\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Candidarsi ora\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scrivi\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il nostro servizio di verifica NIP-05, aiuta a supportare lo sviluppo di questo sito e ottieni un distintivo speciale multicolore!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relè che sono stati collegati in precedenza e che sembrano essere affidabili.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registrazione di un nome utente Iris\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" ripubblicato\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" altri ripostati\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Info sul portafoglio\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accesso a Tidal\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Selezionare\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"adesso\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Argomenti\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Approvazione del post comunitario\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Configurare il pool zap\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" piaciuto\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" è piaciuto ad altri\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tutto in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invita i tuoi amici\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Derivazione della chiave di base dalla frase seme mnemonica\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acquista adesso\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paga\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"I miei eventi: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Indirizzo nostr snort\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Password del portafoglio\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copiare il link\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagina del profilo\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Servizio proxy di immagini\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Segui \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clicca per caricare il contenuto da \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fattura Di Pagamento\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Richiesta Zap\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Raccomandazione del gestore\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" le note sono state messe in sordina\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sembra che tu non ne abbia uno, controlla \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" per comprarne uno!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relè per lavoratori\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Segui tutti\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Servizio caricamento file\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inizio\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opzione: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Solo lettura\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cambia\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento calendario basato sul tempo\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conferma dell'offerta\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sblocca\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferiti\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifiche consentite\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ricerca dell'attività del conto (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Piscina Coinjoin\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Strumenti\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rinnovare\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ascolta questo articolo\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bloccato\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ponte\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" seguaci\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nessun risultato\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Solo seguaci\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ehi, sembra che tu non abbia ancora un indirizzo Nostr, dovresti procurartene uno! Dai un'occhiata a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premio distintivo\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Caricare\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hanno relè (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relè affidabili\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Backup scaricabili dal relè Snort\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji personalizzate\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Canale Muto Utente\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (per i marketplace resilienti)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguaci\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Commento sul torrente\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento calendario basato sulla data\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Risposta alla discussione di gruppo\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge per il tuo indirizzo nostr Snort\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Errore sconosciuto\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge del profilo\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quantità Zap predefinita\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bloccato\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sbloccare\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rinnovare \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifiche API disabilitate\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"La tua chiave privata è (non condividerla con nessuno)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Questa nota è stata messa in sordina\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aggiungi al Profilo\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traduzione fallita\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Come\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostra meno\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scienza\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin non corretto\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inserire la password del portafogli\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadati dell'elenco relè\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenco delle chat pubbliche\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torna indietro ora\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lampi di luce\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aggiungi Relays\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Segnalazione\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Predefinito)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messaggio diretto crittografato\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" giorni\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Canali di chat pubblici\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Collegamento breve\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set di segnalibri\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostra badge\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"utente\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impossibile analizzare lo split zap: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il nome del relè visualizzato non corrisponde all'URL completo inserito.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Richiesta di cancellazione di un evento\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Le note mute non vengono visualizzate\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Successo della connessione:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenco degli interessi\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rilascio di set di artefatti\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eventi video\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scuro\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crittografia con versioni\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sconosciuto NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento di visualizzazione video\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gratuito\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inviare la nota a un sottoinsieme di relè di scrittura\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ottenere la verifica NIP-05 può aiutare:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" saturazione\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metriche del relè\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distintivo del sostenitore\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stato\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagato\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenco dei pin\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tempo di attività\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Il nome deve essere inferiore a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" caratteri\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avete già un account?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"Identità esterne nei profili\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenco relè per ricevere i DM\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"I reposts devono essere confermati manualmente\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inviare gli split sats a\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trovato \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eventi\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pubblico\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" note\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modifica profilo\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avviare la chat\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deve essere un elenco di contatti o un elenco di pubkey\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenco delle comunità\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Immagine del profilo\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Questo strumento cercherà l'ultimo evento pubblicato da tutti i vostri follower e rimuoverà quelli che non hanno pubblicato in 6 mesi.\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 è una specifica di verifica basata su DNS che ti aiuta a convalidare come un utente reale.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opzioni del sondaggio\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ottenere un omaggio\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguito da amici\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quantità di lavoro da applicare a tutti gli eventi pubblicati\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Affari\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modifica\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Elenco dei server di archiviazione dei file\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invia\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Allegati multimediali\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat pubblica di Nostr\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"il nome è bloccato\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toppe\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderazione\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Per saperne di più su \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" clicca \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copia ID\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"I miei relè\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Finanziate i servizi che utilizzate dividendo una parte di tutti i vostri zap in un pool di fondi!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Silenzia\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Per voi\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voti per \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vai a\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: Schema URI\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fornitore\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Carica automaticamente i media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scadenza\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Condizioni aggiuntive:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cerca\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"VENTILATORE\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Consentire\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lingua\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL o indirizzo Lightning\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relè popolari\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"App nativa\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bozza di contenuti di forma lunga\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Peso\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contatta\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proprietario\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tutto\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quantità di Zap in sats\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scacchi (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" minuti da leggere\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Caricamento del servizio LNURL fallito\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visualizza automaticamente le ultime note\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Partecipanti\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/ja_JP.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"をリポストしますか？\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"今すぐ支払う\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロフィールの全イベントをローカルキャッシュに同期\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレー統計\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"書き込み権限ありでログインしました\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"秘密のグループチャット\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップの種類\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"フォロー\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"ログイン\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"ハンドルを管理し続けるために、必ず、以下のパスワードを保存してください\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"接続\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"エディット\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" がリポスト\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"思い通りのあなたの空間😌。\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"クリア\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"アカウントサポート\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTPファイルストレージの統合\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"匿名で利用状況を送信します\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"グループチャットメッセージ\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロフィールを見つけやすく、共有しやすくなる\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"ファイルから\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"ミリ秒\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"さらに読み込む\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostrアドレスはあなたのものではありません\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"エクスポート・キー\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"管理\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"検索する\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"汎用LNDHubウォレット(BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"無効なLNURL\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"メンションへの対応\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"名前に使用できない文字が含まれています\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"政治\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"ステータス表示\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"秒\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"行く\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"ギット\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"本当にこの投稿をブックマークから削除しますか？\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Wallet Connectの設定値を入力\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"鍵は必ずバックアップしておくこと！\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"に接続しました🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" フォロー\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"小切手署名\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"自然\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"会話\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"追加\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"バナー\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"アカウントをお持ちでないですか？\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"モデレートされたコミュニティ\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"ウォレット・コネクト\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"テキストイベントの件名タグ\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザー絵文字リスト\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"寄付\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"パスワードを入力\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"終了\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"一般的なリスト\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ブックマーク\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"イヤ (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"新規投稿\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"フレンドのフレンドにフォローされました\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"アプリケーション固有のデータ\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"時間\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"最新記事\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"返信\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"会員登録\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザーステータス\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"記事\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"メディアサーバーに保存されたブロブ\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"〜\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 視聴者\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"ライト\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"翻訳者\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"無題\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"satsで投票します\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"件の新しい投稿\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"件の新しい投稿\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" フォロワー\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"財布\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"ノストルコネクト\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"総イベント数\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"なし\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"ウィキ\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"キャンセル\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"入札\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"主要な開発者\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"新しいNIP-05ハンドル:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"人生\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"イヤ\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"秘密鍵暗号化\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebsは宇宙で最初のNIP-05プロバイダのひとつで、豊富なドメインをリーズナブルな価格で提供します\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"imgproxyを使って画像を圧縮します\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレーがありません\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"自分用メモ\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"推奨アプリケーション・ハンドラ\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップ\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップ・スプリッツ\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"通知APIが有効\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップゴール\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"ハンドルを購入する\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"ファイルのメタデータ\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"以下の公開鍵に転送する\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostrのユーザー名は誰でも同じものを取得可能です。Nostrアドレスは登録時にあなただけに寄与されたオリジナルアドレスです。\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップする\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"リプレイを見る\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"ミュートリスト\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"リトライ\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"接続に失敗しました：\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"新規フォローリストの長さ \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"から画像のプロキシに失敗しました。ここをクリックして直接読み込みます\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"推奨リレー\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"シール\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"理由： \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"探している： \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"すべてのクライアントがこれをサポートしているわけではありません。\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"スキ (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"フォロワー：\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"追加のメタデータ・フィールドとタグ\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"未払い\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"アカウントの切り替え\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"グッド\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"投稿\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロキシは支払いを転送するためにHODLインボイスを使用し、あなたのノードのパブキーを隠します。\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"ラベル\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"ウィキ記事\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"中継情報ドキュメント\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"検索機能\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"オフライン\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"コミュニティーリーダー\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"反応\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"モジュール式記事コンテンツ\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"信頼関係のない人からのメモはミュートする\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"クローズリレー\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"リポスト (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"リポストの確認\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"クライアントがテキストイベントでeタグとpタグを使用する際の規約\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"返信先\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"新規登録\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satsをザップする\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"受取人\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"無効なザップ・スプリット： \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"グループスレッド\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"名前が長すぎます\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"bech32エンコードされたエンティティ\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"ペアリングフレーズ\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"フォローセット\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"クラシファイド・リスティング（草案\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"次へ\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"返信\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" フォロー\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"カレンダー イベント参加登録\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"送信\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ミュートした投稿を隠す\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"リトライ・パブリッシング\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostrアドレス\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ライトニング インボイス\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"一般的な再投稿\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"返信元\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" の投稿\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"ミュートされた言葉\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"投稿者はミュートされています\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"製品の作成または更新\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snortリレーにおける無期限のノート保持\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"理由\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"素晴らしい\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ゲーム\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"チャンネル作成\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"カウント\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"プッシュ通知\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"ヶ月\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"ログイン\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"名前が短すぎます\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップしました\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"1行に1つ、または複数のリレーを追加できます。\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snortリレーへの書き込み、1年間イベントを保持\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AIエンベッディング／ベクトルリスト\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレーベースのグループ\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"更新\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"マーケットプレイスのUI/UX\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"ノスタルアドレス（nip05）\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレー\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP認証\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"ライトニング・ドネーション\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"ライブイベント\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"引用 リポスト\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"ログアウト\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"人気サーバー\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"おすすめのフォロー\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"ビデオセット\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"インボイスの読み込みに失敗しました\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロフィール・ザップ\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"フォローリスト\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"フォローリストの整理\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"話題のユーザー\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"とその他 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 人のあなたのフォロワー\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"リポジトリからのお知らせ\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ミュート\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"カレンダー\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"から翻訳\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"ソーシャルグラフ\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"参考文献\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"読み込んだ全ての投稿に自動でザップします\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"バッジの定義\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"設定\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"チャンネル非表示メッセージ\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"キャッシュ\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"satoshiを送る\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"最新の投稿\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"件を表示\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"自動ザップ\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"ライブ\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"オークション販売商品\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"自己紹介は \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 文字未満にする必要があります\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"転送\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"すべてトグル\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"ブラウザ\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sats\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"インボイス／Lightningアドレス\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"検索メモ\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"データプロバイダ\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロフィールページにバッジを表示\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"ウェブサイトへの反応\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"グローバル\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"に翻訳\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"キュレーション・セット\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"カスタムリレー\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザー名が利用可能\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"鍵\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"オンチェーン寄付先\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"購入\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"申し訳ございませんが、このイベントの種類 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \") を理解していません。代わりに以下のアプリをお試しください！\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"サーバー\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"アカウントを追加する\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"クラシファイド・リスティング\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ザップ\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"財布の反応\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレーに対するクライアントの認証\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロフィールページにステータスメッセージを表示\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"話題のユーザー\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザーグループ\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"提供されたライトニングアドレスにHTTPリダイレクトを発行する。\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"今すぐ要求する\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"エラーが発生しました！\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"フォローされています\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"アカウント\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"メディアサーバーがない。\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"削除\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"ウォレットを選択する\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"プッシュを受け取る\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"ソルト\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"対応NIPs\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"ブックマーク (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"ライトニングアドレス\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"特典に含まれるSnort Nostrアドレスを要求する\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"マグネットリンク\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"激流\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"無効なLightningアドレス\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" イヤ\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"ブロードキャスト・イベント\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Keyを入力\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"未知の出来事への対処\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"ログアウト\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"リーダー情報\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"ブックマーク一覧\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"支払いが完了しました！\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"名前\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"名前は後で使用できるようになります\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"ミュート中\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"キャッシュをクリアして再読み込み\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"ウォレットを開く\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"この人物をフォローしていない場合は、ここをクリックして \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"からメディアを読み込むか、または \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"設定を更新して\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" から常に全員からメディアを読み込むようにしてください。\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレーレビュー\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"サポート\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"有効期限タイムスタンプ\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"屋台の作成または更新\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"最終投稿 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"本当にこの投稿のピン留めを解除しますか？\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"アカウントデータ\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \" フォロー\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" デッキにアクセスするには \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" の登録が必要です\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" サット\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"自動翻訳\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"最後に見たのは\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satsを\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"に送りました\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"あなたがフォローしている誰にもフォローされていません\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"とにかくロードするにはここをクリック\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"接続済み\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"話題の投稿\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"サブスクリプション\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"通知を許可しない\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"コンマで単語を区切る（例：word1, word2, word3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"絵文字セット\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザー名\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"satsを\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"送る\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップ (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"スポーツ\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"ライトニングアドレスがありません\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" に登録すると、以下の特典が受けられる。\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"リポスト\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレーリスト検索\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザーを検索\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"ウェブサイト\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレーとは、イベントを送受信するために接続するサーバーのこと。リレーは4～8台を目安に。\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"秘密鍵\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"平均待ち時間：\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"削除\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"表示\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"外部コンテンツID\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNDHubの設定値を入力\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"ハイライト\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"ライブチャットメッセージ\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"削除済み\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"保護されたイベント\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"不明なイベント種別: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"NostrキーとDNSベースのインターネット識別子のマッピング\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"ピンを入力\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"財布のリクエスト\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザーとして表示\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップ・ゴール\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"コードはこちらでご確認ください: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"ピンが短すぎる\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"匿名\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"コメント\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"名前は8～15文字にする必要があります\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostrアドレスを確認できません\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zapstrで開く\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"奔流\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"このノートのザップは以下のユーザーに分割されます。\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"デバッグメニュー\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"リーダーになる\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"「IDをコピー」と「イベントJSONをコピー」を全てのメッセージのコンテキストメニューに表示します\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"利用不可:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"ジョイン・ルーム\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"ウォレットパスワード\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"既定のページ\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"短いテキストノート\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"クライアント認証\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"プライマリNostrアドレスに設定(nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロキシタグ\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"このリンクを友達に送って、Nostrの魔法を共有しましょう。\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"サブスクリプションに支払う\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostrアドレスを購入\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"カウント結果\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"の購入\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"アイリス・アカウント\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"確認\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"お知らせ\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"このタイプのサブスクリプションを既にお持ちです。更新もしくは支払いをお願いいたします\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"仕事のフィードバック\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satsでは投票できないので、既定のザップ額を変更してください。\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"新規ユーザーページ\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"再投稿\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"デッド\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"招待コードを使ってsatsを獲得しよう！\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップ\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"イベントのOpenTimestamps認証\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"ギフトラップ\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"共有\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"未知のログインエラー\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"無料のnostrアドレスを取得する\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"サブスクリプションがまだ有効なため、更新することができません\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"登録日\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"リクエストのマージ\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"アップデートに失敗しました。\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"長編コンテンツ\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"スキャン \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"無効なNostrアドレス\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"イベントJSONをコピー\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"システム (デフォルト)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"本日の合計額 (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"距離\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザー設定\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" に受信中\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"不明なファイルヘッダー: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"外観\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"すべてのページでリアクションが表示されます。無効にするとリアクションは表示されません\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" リレー\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"秘密鍵はパスワードのようなものですが、リセットすることはできません。注意深く守り、決して誰にも見せないようにしてください。一度秘密鍵を知られると、その人は永遠にあなたのアカウントにアクセスすることができます。\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Poolは、サポートされているウォレットコネクション (WebLN, LNC, LNDHub, Nostr Wallet Connect) のいずれかを使用する場合にのみ機能します。\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"チャンネルメッセージ\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"現在、Zap Poolには\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satsあります。\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"プライベート・ダイレクト・メッセージ\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"サブスクリプション\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"あなたがフォローしている人\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"サービスワーカーが実行されていません\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"リポジトリ状態のアナウンス\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザー名には小文字と数字のみを使用すること\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"失効\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"短編ポートレート・ビデオ・イベント\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"制作者: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"を削除しますか？\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"データ自動販売機\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレー\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"ブックマーク\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"ロードノート： \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"アクセス許可\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"秘密鍵を暗号化するためにピンを入力します。 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"を開くたびにこのピンを入力する必要があります。\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップを\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"に送る\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ライトニングアドレスの更新\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"サブスクリプションの購入\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"あなたがフォローしている人々が使用している人気のリレー。\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNアドレス プロキシ\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレーセット\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロブレム・トラッカー\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"すべて既読\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"カスタム\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"何て呼べばいい？\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"今すぐ支払う\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"アプリケーション固有のデータ\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"筆者はこのノートを \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"センシティブ・トピック\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"としている。\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"地理的に近いリレー。\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"選択したユーザーの投稿ではメディアが自動的に表示され、それ以外はリンクのみが表示されます\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"ハンドラー情報\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"プレビュー\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"ローカル・リレーを使用\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"終了\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostrエクステンションでサインイン\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"もっと詳しく\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"暗号\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"インタレスト・セット\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"カレンダー・イベント\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Saltを入力\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザー\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"好き\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"アカウント\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"聞くのをやめる\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"コミュニティの定義\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレーから外す\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"受取\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレーから受け取ったすべてのイベント署名をチェックする\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"新規チャット\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザーは、投稿内容の表示のためにコンテンツ警告へ同意する必要があります。\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"サーバーの追加\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"サインイン\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"ブロック\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"申請は保留中です\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"iris.toアカウントをお持ちの方\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"パーソナライズされた招待状を友人と共有する！\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"紹介コードは \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" です\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"ラベリング\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"添付ファイルをアップロードするためのサービスを選択してください\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"公開鍵 (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"はい、お願いします\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"変更点の全リストは変更履歴 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" で確認できます。\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ミュート\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"アバター\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"サブスクリプションをお持ちでないようです。\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"から入手することができます\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ブロック\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"ローカル\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"ミュート解除\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"サーバーより\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"課題\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"メモを現地語に自動翻訳\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / nostr address\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"キーでサインイン\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"利用状況データを送信する\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"ファイルホスト\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Albyウォレットの接続\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"フォローしている人のリレーの状態\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"償還\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"話題のハッシュタグ\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"リアクション\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" から送金中\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"デフォルトのザップ量は\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satsで、例示された値はここから算出されます。\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザー\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"サービスURL\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"人気のメディアサーバー。\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 、フォローする人を探してみてください！\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"鍵もない、 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" もない、というときにバックアップがないとリセットする方法はありません。すぐに終わります。\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"公開チャット\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"リアクションを有効にする\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"即時支払いのためにウォレットを接続\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"別のリレーを試す\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"チャンネルのメタデータ\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ペアリングフレーズを入力\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"イベント署名の委任\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"メモを作成する\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"今すぐ有効化\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"貢献者\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップ・スプリットの送信先\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザー名 iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" はあなたのために予約されています！\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"暗号化されたダイレクトメッセージ\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" から \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" に招待されました\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"メディア・サーバーは、画像やビデオとしてノートに共有できるメディアを保存します。\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05認証サービスを提供するプラットフォームや開発者に資金援助する\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"グローバルタブと投稿タブで投稿がリアルタイムに流れるようになります\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"名前またはニックネーム\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"対応エクステンション\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satsの支払い、手数料 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Node Connectで自分のLNDノードに接続する\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"もっと見る\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"友人を招待する\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"ニーモニック\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"あなたのハンドルはライトニングアドレスのように動作し、選択したLNURLまたはライトニングアドレスに転送されます\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"あなたはコミュニティリーダーであり、紹介されたユーザーのサブスクリプションの \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" を獲得しています！\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"サービスワーカー実行中\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"整理リストを生成\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"アドレス取得\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"読み取り専用でログインしました\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"センシティブなコンテンツ\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"公開鍵\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"匿名\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"たった今\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"親切なミュートセット\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"遠慮する\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"リダイレクト\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05の注文に関するお問い合わせは、DMにて\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"までお願いします。\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"キロバイト\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"再送信\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Albyをお使いですか？\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"にアクセスすると、NWCの設定が取得できます！\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ネイティブnostrウォレットの接続\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"写真撮影\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"ダイレクト・メッセージ\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"フォロー中\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URLを入力\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"メディア・サーバー\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"全てミュート\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"ウォレットを接続\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"オープンタイムスタンプ\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"マルチアカウント対応\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"既に登録された名前です\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"ライブ活動\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"戻る\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"ミュートするリスト\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"WoTフィルター\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"プッシュ通知未登録\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"ライトニング アドレス\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"公開鍵はユーザー名のようなもので、誰とでも共有できる。\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"表示名\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"モジュール式記事ヘッダー\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"人気のハッシュタグ\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"登録\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"sats額\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"クラシファイド・リスティング\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" の開発者向けに、 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" のデフォルトの Zap Pool 分割が設定されていますが、 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"でいつでも無効にできます。\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"種別\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"まもなく開始\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"ピンを入力して秘密鍵を解除する\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"全て既読にする\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"サインインにはnostr署名者拡張機能を使用する。\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"リアクションの絵文字\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"認証を得る\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satsを1回ザップすると、\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" satsがZap Poolに割り当てられます。\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"フィード\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"グループチャット\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"ウェブブラウザ用のwindow.nostr機能\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"と他 \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 人\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"と他 \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 人\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"ホーム\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"貧しい\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"コミュニティーリーダーとは、ローカルコミュニティーで積極的に活動し、新しいユーザーの参加を支援することで、nostrのエコシステムを成長させる個人のことです。コミュニティーリーダーには誰でもなることができますが、現在の名誉ある称号を持つ人はほとんどいません。\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"出力\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップ\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"をご利用いただきありがとうございます。可能であれば寄付をご検討ください。\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snortは、情熱的な人々が自由時間を使って構築したオープンソースプロジェクトであり、あなたの寄付を大いに歓迎します\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURLサービスがザップに対応していないため投票できません\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"コンテンツ警告タグのついた投稿を表示する\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"ピン留めされた投稿\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"興味のあるトピックをいくつか選ぶ\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"読み取り\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"ギフト包装\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"思いつくことは？\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"オン・チェーン・ドネーション\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"ライトニング・パブRPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"保存済み\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"メディアを添付する\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"配信を見る\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"自己紹介\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"投票を送信できませんでした\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"投稿にリアクションしたときに送る絵文字\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"まだすべてのクライアントがこれをサポートしているわけではありません。\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"購読\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" in memory)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"読込中…\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"アンドロイド署名アプリケーション\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"リスト\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザーサーバーリスト\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"プルーフオブワーク\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"基本的なプロトコルの流れの説明\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 一緒にいる方が楽しい！\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"バッジ\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザー・メタデータ\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"フォローリストの整理\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"同期アカウント\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"メッセージ\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロ\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"対応\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"招待\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"返信を見る\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"メディア\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"こちら\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"ブロック・リレー・リスト\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"交流\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"送受した支払いはここに表示されます。\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"リアクション (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL翻訳\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"なりすましを防ぎます\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"管理者\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" がフォロー（\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" が共通）\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"ハンドル\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"安全でない接続では秘密鍵でログインすることはできません。代わりにNostrキーマネージャー拡張機能を使用してください。\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"支払い\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"新規ユーザーページ\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"フォロー\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"グループチャット スレッド返信\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"インボイスを作成\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロフィール\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"フォロー解除\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"バックアップ済み\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 、有効期限が切れています。\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"フィードをきれいにする\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"内部エラー：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"ビデオイベント\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"保存\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" リアクション\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"今すぐ適用\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"書き込み\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"私たち独自のNIP-05認証サービスです。このサイトの開発を支援し、ピカピカの特別なバッジを私たちのサイトで使えるようになります！\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"以前接続したことがあり、信頼できると思われるリレー。\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Irisユーザー名の登録\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"財布情報\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"タイダルログイン\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"選択\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"たった今\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"トピック\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"コミュニティ・ポストの承認\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザッププールの設定\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"で提供されるすべて\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"友達を招待\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"ニーモニック・シード・フレーズからの基本鍵導出\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"今すぐ購入\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"支払う\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"私のイベント \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort Nostrアドレス\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"ウォレットパスワード\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"リンクをコピーする\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"ノンザップ\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"アカウントページ\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"画像プロキシサービス\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" フォロー\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"クリックして \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" からのコンテンツを読み込む\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"インボイスの支払い\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップ・リクエスト\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"ハンドラー推薦\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 音が小さくなった\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"お持ちでないようです。\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"から購入しましょう！\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 作業員リレー\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"全てフォロー\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"ファイル添付サービス\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"がザップしました\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"がザップしました\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"スタート\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"オプション: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"読み取り専用\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"切り替え\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"時間ベースのカレンダー・イベント\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"入札確認\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"ブロック解除\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"ブックマーク\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"通知を許可\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"アカウントの活動を検索中 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"コインプール\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"ツール\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"リニューアル\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"この記事を聴く\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ブロック\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"デッキ\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" フォロワー\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"何も見つかりません (´･ω･`)\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"フォローのみ\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"まだNostrアドレスを持ってないようだね！以下のリンクをチェックして、ぜひ手に入れよう：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"バッジ賞\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"アップロード\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" がリレーを持っています (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"信頼性の高いリレー\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snortリレーからダウンロードできるバックアップ\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザッププール\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"カスタム絵文字\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"チャンネル・ミュート・ユーザー\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ピン留め\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace（弾力性のあるマーケットプレイス用）\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"フォロワー\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"激流コメント\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"日付ベースのカレンダー・イベント\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"グループスレッド返信\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort Nostrアドレス用の、EmailとDMの中継\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"不明なエラー\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロフィール・バッジ\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"投稿\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"既定のザップ額\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"ブロック\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ロック解除\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"リニューアル \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"通知APIは無効です\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"秘密鍵 (誰とも共有しないこと)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"このメモはミュートされています\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロフィールに追加\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"翻訳できませんでした\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"スキ\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"表示を減らす\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"サイエンス\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"ピンが正しくない\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"ソフトウェア\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"ウォレットのパスワードを入力\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレーリストのメタデータ\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"公開チャットリスト\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"今すぐバックアップ\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"ライトニング・ザップ\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレーを追加する\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"報告\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(デフォルト)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"暗号化ダイレクトメッセージ\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"日\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"公開チャットチャンネル\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"ショートリンク\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"ブックマークセット\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"バッジを表示\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"ユーザー\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap split の解析に失敗しました: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"表示されるリレー名は、入力された完全なURLと同じではありません。\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"イベント削除リクエスト\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"ミュートした投稿は表示されません\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"コネクションの成功\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"趣味リスト\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"アーティファクト・セットのリリース\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ビデオ・イベント\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"ダーク\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"バージョン暗号化\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"不明 NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ビデオ鑑賞会\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"無料\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"書き込みリレーの一部に投稿を送信する\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05認証を得るメリット:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"リレー・メトリクス\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"サポーターバッジ\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"ステータス\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"支払済\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"ピンリスト\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"アップタイム\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"名前は \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 文字未満にする必要があります\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"すでにアカウントをお持ちですか？\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロファイルにおける外部アイデンティティ\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"DMを受信するリレーリスト\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"リポスト前に確認を表示します\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"サッツ・スプリットを送信する\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" イベント\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"パブリック\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 投稿\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロフィールを編集\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"チャットを開始\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"コンタクトリストまたはパブキーリストであること\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"コミュニティ一覧\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロフィール画像\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"このツールは、あなたがフォローしている全員の発信した最後のイベントを検索し、6ヶ月以内に投稿していない者を削除します。\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05は、ユーザが本物であることを検証するDNSベースの仕組みです。\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"投票オプション\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"無料版を入手\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"友達がフォロー中\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"公開イベントに適用する作業量\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"ビジネス\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"編集\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"ファイル・ストレージ・サーバー一覧\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"投稿する\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"メディア・アタッチメント\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr公開チャット\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"名前がブロックされています\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"パッチ\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"モデレーション\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"の詳細を\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"で見る\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"IDをコピー\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"私のリレー\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"利用しているサービスへ支援するため、自分のザップの一部をプールに集めましょう！\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"ミュート\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"あなたへ\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"による投票\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"開く:\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr：URIスキーム\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"プロバイダ\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"メディアを自動で読み込む\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"有効期限\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"その他の条件\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"検索\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"ファン\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"許可\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"言語\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" イーサット\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURLまたはライトニングアドレス\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"人気のリレー\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"ネイティブアプリ\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"デバッグ\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"長編コンテンツの草稿\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"重量\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"連絡先\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"運営者\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"すべて\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"ザップ額 (satoshi)\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"チェス (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 分\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURLサービスの読み込みに失敗しました\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"最新の記事を自動で表示する\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"参加者\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/ko_KR.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"다시 게시하시겠습니까? \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"지금 결제하기\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"프로필의 모든 이벤트를 로컬 캐시에 동기화합니다.\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이 통계\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"쓰기 권한으로 로그인\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"비밀 그룹 채팅\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap 유형\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"팔로잉\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"로그인\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"향후 핸들 관리를 위해 다음 비밀번호를 저장해 두시기 바랍니다.\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"연결\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"수정\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 0,\n      \"value\": \"리포스트: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"원하는 대로 꾸미는 나만의 공간 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"지우기\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"계정 지원\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP 파일 스토리지 통합\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"익명 사용량 지표 보내기\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"그룹 채팅 메시지\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"프로필을 더 쉽게 찾고 공유하세요\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"파일에서\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"더 보기\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"노스트르 주소는 당신의 소유가 아닙니다.\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"내보내기 키\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"관리\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"검색...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"일반 LNDHub 지갑(BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"잘못된 LNURL\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"멘션 처리하기\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"이름에 허용되지 않는 문자가 있습니다.\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"정치\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"상태 표시\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 초\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"이동\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"git 물건\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"이 노트를 북마크에서 제거하시겠습니까?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"노스트르 월렛 커넥트 구성 입력\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"키를 백업해 두세요!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"에 연결되었습니다: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 팔로잉\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"서명 확인\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"자연\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"대화\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"추가\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"배너\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"계정이 없으신가요?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"관리되는 커뮤니티\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"월렛 연결\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"텍스트 이벤트의 제목 태그\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자 이모티콘 목록\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"기부하기\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"비밀번호 입력\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"완료\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"일반 목록\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 북마크\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"싫어요 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"새 노트\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"친구의 친구로부터 팔로우\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"애플리케이션별 데이터\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 시간\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"최신 기사\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"답글\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"가입하기\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자 상태\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"기사\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"미디어 서버에 저장된 블롭\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 시청자\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"라이트 모드\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"번역기\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"제목 없음\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats로 투표 중입니다.\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 새 노트\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 새 노트\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 팔로워\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"지갑\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"총 이벤트:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"없음\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"취소\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"입찰\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"기본 개발자\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"새로운 NIP-05 핸들이 있습니다:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"생활\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"싫어요\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"개인 키 암호화\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs는 업계 최초의 NIP-05 제공업체 중 하나이며 합리적인 가격으로 다양한 도메인 모음을 제공합니다.\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"이미지 프록시를 사용하여 이미지 압축\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"누락된 릴레이\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"나에게 노트하기\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"권장 애플리케이션 핸들러\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap 분할\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"알림 API 허용됨\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap 목표\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"핸들 구매\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"파일 메타데이터\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pubkey로 전송\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"노스트르에서 사용자 아이디는 고유하지 않습니다. 노스트르 주소는 등록 시 부여되는 사람이 읽을 수 있는 고유한 주소로, 회원님에게만 부여됩니다.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap 보내기\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"다시보기 보기\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"음소거 목록\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"재시도\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"연결에 실패했습니다:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"새로운 팔로우 목록 길이 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"에서 이미지를 프록시하지 못했습니다. 직접 로드하려면 여기를 클릭하세요.\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이 추천\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"봉인\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"이유: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"찾고 있습니다: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"모든 클라이언트가 이를 지원하는 것은 아니며, Zap 분할이 구성되지 않은 것처럼 일부 Zap을 받을 수 있습니다.\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"좋아요 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"팔로우됨\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"추가 메타데이터 필드 및 태그\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"미결제\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"계정 전환\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Good\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"노트\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"프록시는 HODL 인보이스를 사용하여 결제를 전달하고 노드의 공개키를 숨깁니다.\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"라벨\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"위키 문서\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이 정보 문서\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"검색 기능\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"오프라인\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"커뮤니티 리더\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"반응\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"모듈형 기사 콘텐츠\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"신뢰망 외부에 있는 사람들의 노트 음소거하기\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이 닫기\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"리포스트 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"리포스트 확인\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"텍스트 이벤트에서 클라이언트의 e 및 p 태그 사용에 대한 규칙\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"답글\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"회원가입\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"수신자\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"잘못된 Zap 분할: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"그룹 스레드\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"너무 긴 이름입니다\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"bech32로 인코딩된 엔티티\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"페어링 문구\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"팔로우 세트\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"기밀 목록 초안\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"다음\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"답글\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"팔로우\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"캘린더 이벤트 RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"보내기\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"뮤트된 노트 숨기기\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"게시 재시도\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"노스트르 주소\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"라이트닝 인보이스\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"일반 재게시\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"상위\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"노트 작성됨: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"뮤트된 단어\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"이 작성자는 뮤트되었습니다.\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"제품 생성 또는 업데이트\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort 릴레이에서 무제한 노트 보존\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"이유\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Great\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"게임\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"채널 생성\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Count\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"푸시 알림\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"개월\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"로그인\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"너무 짧은 이름입니다\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSEC, NPUB, NIP-05, HEX\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"한 줄당 하나씩 하나 또는 여러 개의 릴레이를 추가할 수 있습니다.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"스노트 릴레이에 대한 쓰기 액세스 권한, 이벤트 보존 기간 1년\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AI 임베딩 / 벡터 목록\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이 기반 그룹\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"업데이트\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"마켓플레이스 UI/UX\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 주소 (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP 인증\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"라이트닝 도네이션\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"라이브 이벤트\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"인용 리포스트\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"로그아웃\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"인기 서버\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"추천 팔로우\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"비디오 세트\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"인보이스를 로드하지 못했습니다.\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"프로필 Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"팔로우 목록\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"팔로우 목록 정리\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"현재 뜨는 인물\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"및 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 팔로우하는 다른 사람\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"리포지토리 공지사항\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 뮤트됨\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"캘린더\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"에서 번역됨\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"소셜 그래프\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"텍스트 노트 참조\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"로드 시 모든 노트를 자동으로 Zap\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"배지 정의\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"설정\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"채널 메시지 숨기기\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"캐시\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap 보내기\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"최신 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 노트 보기\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"자동 Zap\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"라이브\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"경매로 판매되는 제품\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"정보는 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 문자 미만이어야 합니다.\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"전송\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"모두 토글\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"브라우저\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sats\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"인보이스 / 라이트닝 주소\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"노트 검색\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"데이터 제공자\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"프로필 페이지에 배지 표시\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"웹사이트에 대한 반응\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"글로벌\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"으로 번역하기\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"큐레이션 세트\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자 지정 릴레이\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자 이름 사용 가능\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"키\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"온체인 기부 주소\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"구매\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"죄송합니다, 이 이벤트 종류(\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")를 이해하지 못합니다. 대신 다음 앱 중 하나를 사용해 보세요!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"서버\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"계정 추가\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"분류된 목록\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"지갑 응답\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이에 대한 클라이언트 인증\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"프로필 페이지에 상태 메시지 표시\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"현재 뜨는 유저\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자 그룹\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"리디렉션 이슈 제공된 라이트닝 주소로 HTTP 리디렉션을 발행합니다.\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"지금 신청하기\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"오류가 발생했습니다!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"당신을 팔로우함\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"계정\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"미디어 서버가 없는 경우 미디어 서버를 추가해 보세요.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"제거\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"지갑 선택\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"푸시 구독\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"솔트\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"지원되는 NIP\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"북마크 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"라이트닝 주소\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"포함된 Snort 노스트르 주소를 신청하세요.\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"마그넷 주소\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"토렌트\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"잘못된 라이트닝 주소\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 싫어요\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"브로드캐스트 이벤트\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"헥스 키...\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"알 수 없는 이벤트 처리\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"로그아웃\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"리더 정보\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"북마크 목록\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"주문 결제 완료!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"이름\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"이름은 나중에 사용할 수 있습니다.\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"음소거\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"캐시 지우기 및 리로드\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"지갑 열기\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"이 사용자를 팔로우하지 않는 경우 여기를 클릭하여 \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"에서 미디어를 로드하거나 \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"환경설정\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 을 업데이트하여 모든 사용자의 미디어를 항상 로드하세요.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이 리뷰\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"지원\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"만료 타임스탬프\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"매점 생성 또는 업데이트\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"최근 게시물 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"이 노트를 고정 해제하시겠습니까?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"계정 데이터\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"팔로우\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 덱에 액세스하려면 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 구독자여야 합니다.\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"모든 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zap\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"자동 번역\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"마지막으로 본:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats를 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"으로 전송\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"내가 팔로우하는 사람이 팔로우하지 않음\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"어쨌든 로드하려면 여기를 클릭하세요.\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"연결됨\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"현재 인기있는 노트\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"구독\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"허용되지 않는 알림\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"쉼표를 사용하여 단어 구분(예: 단어1, 단어2, 단어3)\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"이모티콘 세트\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자 이름\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"으로 수능 성적 보내기\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"스포츠\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"라이트닝 주소 없음\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ( \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" )을 구독하고 다음과 같은 보상을 받으세요.\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"리포스트\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"검색 릴레이 목록\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자 검색\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"웹사이트\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이는 이벤트를 보내고 받기 위해 연결하는 서버입니다. 릴레이는 4~8개를 목표로 합니다.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"개인 키\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"평균 지연 시간:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"삭제\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"표시\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"외부 콘텐츠 ID\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNDHub config 입력\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"하이라이트\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"실시간 채팅 메시지\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"삭제됨\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"보호된 이벤트\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"알 수 없는 이벤트 종류: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 키를 DNS 기반 인터넷 식별자에 매핑하기\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"핀 입력\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"지갑 요청\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자로 보겠습니까?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap 목표\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"코드 확인 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"핀이 너무 짧음\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"익명\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"댓글\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"이름은 8~15자 사이여야 합니다.\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"노스트르 주소를 확인할 수 없습니다.\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zapstr에서 열기\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"토렌트\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 기타 zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"이 노트의 쨉은 다음 사용자에게 분할됩니다.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"디버그 메뉴\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"리더 되기\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"각 메시지의 컨텍스트 메뉴에 'ID 복사' 및 '이벤트 JSON 복사'를 표시합니다.\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용할 수 없습니다:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"조인 룸\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"지갑 비밀번호\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"기본 페이지\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"짧은 텍스트 노트\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"클라이언트 인증\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"기본 Nostr 주소로 설정(nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"프록시 태그\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"이 링크를 친구에게 보내 노스트르의 마법을 공유하세요.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"구독 요금 결제\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"노스트르 주소 구매\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"집계 결과\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 구매하기\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.to 계정\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"확인\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"알림\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"이미 이 유형의 구독이 있는 경우 갱신하거나 결제하세요.\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"작업 피드백\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 수능으로 투표할 수 없습니다. 다른 기본 쨉 양을 설정하세요.\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"신규 사용자 페이지\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"재게시\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dead\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"초대 코드를 사용하여 수능 점수를 획득하세요!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"이벤트용 오픈타임스탬프 증명\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"선물 포장\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"공유\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"알 수 없는 로그인 오류\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"무료 노스트르 주소 받기\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"구독이 아직 활성 상태이며 아직 갱신할 수 없습니다.\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"생성됨\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"요청 병합\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"업데이트에 실패했습니다. 다시 시도하세요.\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"긴 형식의 콘텐츠\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"스캔 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"잘못된 노스트르 주소\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"이벤트 JSON 복사\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"시스템(기본값)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"오늘 합계(UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"거리\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"기본 설정\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"으로 수신\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"알 수 없는 파일 헤더: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"테마\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"모든 페이지에 반응이 표시되며, 비활성화하면 반응이 표시되지 않습니다.\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 릴레이\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"개인 키는 비밀번호와 같지만 재설정할 수 없습니다. 누구에게도 보여주지 말고 소중히 보관하세요. 누군가 내 비공개 키를 알게 되면 계정에 영원히 액세스할 수 있게 됩니다.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool은 지원되는 지갑 연결 중 하나를 사용하는 경우에만 작동합니다(WebLN, LNC, LNDHub 또는 Nostr Wallet Connect).\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"채널 메시지\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"현재 잽 풀에 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats가 있습니다.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"비공개 쪽지\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"구독\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"내가 팔로우하는 사람들\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"서비스 작업자가 실행되지 않음\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"리포지토리 상태 공지\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자 아이디는 소문자와 숫자만 포함해야 합니다.\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"만료됨\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"숏폼 인물 동영상 이벤트\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"작성자: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"삭제하시겠습니까?\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"데이터 자동판매기\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"북마크\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"로딩 참고: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"권한\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"개인 키를 암호화하려면 핀을 입력하세요. \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"을 열 때마다 이 핀을 입력해야 합니다.\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"으로 zap 보내기\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"라이트닝 주소 업데이트\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"구독 구매\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"내가 팔로우하는 사람들이 사용하는 인기 릴레이.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN 주소 프록시\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이 세트\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"문제 추적기\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"모두 읽음 표시\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자 지정\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"당신을 어떻게 부를까요?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"지금 결제\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"애플리케이션별 데이터\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"작성자는 이 메모를 \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"민감한 주제로 표시했습니다.\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"지리적 위치에 가까운 릴레이.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"선택한 사람에게는 노트의 미디어가 자동으로 표시되고, 그렇지 않으면 링크만 표시됩니다.\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"핸들러 정보\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"텔레그램\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"미리보기\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"로컬 릴레이 사용\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"종료됨\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 확장 프로그램으로 로그인\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"자세히 알아보기\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"암호화\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"이자 세트\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"캘린더 이벤트\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"헥스 솔트...\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"사람\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"좋아요\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"계정\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"듣기 중단\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"커뮤니티 정의\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"내 릴레이에서 제거\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"수신\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이에서 받은 모든 이벤트 서명 확인\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"새 채팅\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"노트의 콘텐츠를 표시하려면 사용자가 콘텐츠 경고를 수락해야 합니다.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"서버 추가\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"로그인\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"차단\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"신청이 보류 중입니다.\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"활성 iris.to 계정이 있습니다.\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"맞춤화된 초대장을 친구들과 공유하세요!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"추천 코드는 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"라벨링\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"첨부파일을 업로드할 업로드 서비스를 선택하세요.\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"공개 키(npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"예\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"전체 변경 사항 목록을 보려면 변경 로그( \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")를 참조하세요.\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 뮤트됨\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"아바타\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"구독이 없는 것 같은데, 구독할 수 있습니다 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 차단됨\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"로컬\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"뮤트 해제\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"서버에서\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"이슈\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"노트를 현지 언어로 자동 번역\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"NPUB/NPROFILE/NOSTR 주소\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"키로 로그인\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSEC, NPUB, NIP-05, HEX, 니모닉\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용량 메트릭 보내기\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"파일 호스트\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alby 지갑 연결\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이 상태 팔로우\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"인기 해시태그\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"반응\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"에서 보내기\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"기본 Zap 금액은 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats이며, 예제 값은 이 값에서 계산됩니다.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"서비스 URL\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"인기 있는 미디어 서버.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"팔로우하는 사람이 충분하지 않은 것 같다면 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 에서 팔로우할 사람을 찾아보세요!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"키 없음, \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", 백업하지 않으면 재설정할 방법이 없습니다. 1분밖에 걸리지 않습니다.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"공개 채팅\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"반응 활성화\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"지갑을 연결하여 즉시 결제 보내기\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"다른 릴레이 시도하기\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"채널 메타데이터\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"페어링 문구 입력\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"위임 이벤트 서명\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"노트 작성\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"지금 활성화\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"기여자\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"다음 주소로 Zap을 분할하여 보냅니다.\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자 이름 iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 은 귀하를 위해 예약되었습니다!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"암호화된 쪽지\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"에 초대되었습니다.\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"미디어 서버는 노트에서 이미지와 동영상으로 공유할 수 있는 미디어를 저장합니다.\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 검증 서비스를 제공하는 펀드 개발자 및 플랫폼\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"노트가 글로벌 및 노트 탭으로 실시간 스트리밍됩니다.\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"이름 또는 님\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"지원되는 확장 프로그램\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"유료 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 수능, 유료 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 수능\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"라이트닝 노드 커넥트로 자체 LND 노드에 연결하기\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"자세히 보기\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"친구 초대\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"니모닉\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"핸들은 라이트닝 주소처럼 작동하며 선택한 LNURL 또는 라이트닝 주소로 리디렉션됩니다.\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"귀하는 커뮤니티 리더이며 추천 사용자 구독을 \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 받고 있습니다!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"서비스 워커 실행 중\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"가지치기 목록 계산\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"주소 가져오기\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"읽기 전용 액세스 권한으로 로그인\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"민감한 콘텐츠\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"공개 키\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"지금 바로\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"종류 음소거 세트\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"아니요\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"리디렉션\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 주문에 대한 문의 사항이 있으시면 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"으로 이메일을 보내주세요.\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"다시 브로드캐스트\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alby를 사용하시나요? \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 로 이동하여 NWC 설정을 받으세요!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"네이티브 노스트르 지갑 연결\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"사진\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"쪽지\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"팔로잉\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL...\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"미디어 서버\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"모두 뮤트\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"지갑 연결\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"오픈타임스탬프\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"다중 계정 지원\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"이름이 등록됨\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"라이브 활동\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"뒤로\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"뮤트할 목록을 클릭합니다:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"WoT 필터\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"푸시 구독하지 않음\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN 주소\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"공개 키는 사용자 아이디와 같아서 누구와도 공유할 수 있습니다.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"표시 이름\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"모듈식 기사 헤더\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"인기 해시태그\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"등록하기\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"수능 금액\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"기밀 목록\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 개발자를 위한 기본 Zap 풀 분할은 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 으로 설정되어 있으며, \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"에서 언제든지 비활성화할 수 있습니다.\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"종류\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"곧 출시 예정\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"비밀번호를 입력하여 개인 키 잠금 해제\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"모두 읽음 표시\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr 서명자 확장 프로그램을 사용하여 로그인하기\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"반응 이모티콘\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"인증 받기\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats를 한 번 탭하면 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats가 탭 풀에 할당됩니다.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"피드\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"그룹 채팅\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"웹 브라우저용 window.nostr 기능\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 기타\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 기타\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"홈\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poor\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"커뮤니티 리더는 지역 커뮤니티에서 활발히 활동하며 새로운 사용자의 온보딩을 도와 노스트르 생태계를 성장시키는 개인입니다. 누구나 커뮤니티 리더가 될 수 있지만, 현재 명예 직함을 가진 커뮤니티 리더는 소수에 불과합니다.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dump\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"이용해 주셔서 감사합니다 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", 가능하다면 기부를 고려해 주세요.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort는 열정적인 사람들이 여가 시간에 만든 오픈 소스 프로젝트이며, 여러분의 기부는 대단히 감사합니다.\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL 서비스가 zaps를 지원하지 않아 투표할 수 없습니다.\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"콘텐츠 경고 태그가 있는 글 표시\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"고정됨\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"관심 있는 몇 가지 주제를 선택하세요.\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"읽기\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"선물 포장\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"무슨 생각을 하고 계신가요?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"온체인 기부\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"라이트닝 펍 RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"저장됨\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"미디어 첨부\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"스트림 보기\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"정보\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"투표를 보내지 못했습니다.\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"노트에 반응할 때 보낼 이모티콘\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"아직 모든 클라이언트가 이를 지원하는 것은 아닙니다.\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"구독\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (메모리 내\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"로딩 중...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Android 서명자 애플리케이션\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"목록\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자 서버 목록\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"작업 증명\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"기본 프로토콜 흐름 설명\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 함께하면 더 즐겁습니다!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"배지\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자 메타데이터\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"팔로우 목록 정리\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"계정 동기화\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"메시지\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"지원\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"초대\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"답글 표시\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"미디어\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"여기\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"차단된 릴레이 목록\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"상호 작용\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"송금 및 수취한 결제 금액이 여기에 표시됩니다.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"리액션 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL 번역\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"가짜 계정의 사용자 모방 방지\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"관리자\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 팔로우 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 중복)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"핸들\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"안전하지 않은 연결에서 개인 키로 로그인할 수 없는 경우, 대신 Nostr 키 관리자 확장 프로그램을 사용하세요.\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"결제\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"신규 사용자 페이지\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"팔로우\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"그룹 채팅 스레드 댓글\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"인보이스 생성\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"프로필\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"언팔로우\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"이미 백업됨\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 수능\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 수능\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 구독이 만료되었습니다.\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"피드 정리\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"내부 오류: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"비디오 이벤트\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"저장\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 반응\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"지금 신청하기\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"쓰기\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"저희만의 NIP-05 인증 서비스를 통해 이 사이트의 개발을 지원하고 반짝이는 특별 배지를 받으세요!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"이전에 연결한 적이 있고 신뢰할 수 있는 것으로 보이는 릴레이입니다.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris 사용자 이름 등록\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 재게시 됨\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 기타 재게시 됨\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"지갑 정보\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidal 로그인\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"선택\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"지금\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"주제\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"커뮤니티 게시물 승인\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap 풀 구성\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 좋아요\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 기타 좋아요\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"의 모든 것\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"친구 초대하기\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"니모닉 시드 구문에서 기본 키 파생\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"지금 구매하기\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"결제\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"내 이벤트: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort Nostr 주소\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"지갑 비밀번호\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"링크 복사\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"계정 페이지\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"이미지 프록시 서비스\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"팔로잉 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"에서 콘텐츠를 로드하려면 클릭하세요.\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"인보이스 결제\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap 요청\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"핸들러 추천\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 메모가 음소거되었습니다.\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"없는 것 같으니 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 에서 구매하세요!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 작업자 릴레이\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"모두 팔로우하기\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"파일 업로드 서비스\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"시작\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"옵션: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"읽기 전용\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"스위치\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"시간 기반 캘린더 이벤트\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"입찰 확인\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"차단 해제\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"북마크\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"허용된 알림\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"계정 활동 검색 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"코인조인 풀\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"도구\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"갱신\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"이 문서 듣기\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 차단됨\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"데크\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 팔로워\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"찾을 수 없음 :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"팔로우만\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"아직 노스트르 주소가 없으신 것 같은데, 지금 바로 생성하세요! \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"에서 확인하세요.\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"배지 어워드\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"업로드\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 릴레이가 있습니다 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"신뢰할 수 있는 릴레이\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort 릴레이에서 다운로드 가능한 백업\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"맞춤 이모티콘\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"채널 음소거 사용자\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"핀\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"노스트르 마켓플레이스(탄력적인 마켓플레이스용)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"팔로워\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"토렌트 댓글\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"날짜 기반 캘린더 이벤트\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"그룹 토론글 댓글\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"이메일 <> DM 브릿지로 Snort 노스트르 주소 보내기\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"알 수 없는 오류\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"프로필 배지\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"노트\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"기본 Zap 금액\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"차단됨\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"잠금 해제\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"갱신 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"알림 API 비허용됨\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"개인 키 (누구와도 공유하지 마세요)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"이 메모는 뮤트되었습니다.\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"프로필에 추가\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"번역 실패\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"좋아요\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"덜 보기\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"과학\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"잘못된 핀\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"소프트웨어\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"지갑 비밀번호 입력\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이 목록 메타데이터\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"공개 채팅 목록\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"지금 백업하기\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"라이트닝 잽\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이 추가\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"보고\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(기본값)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"암호화된 쪽지\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 일수\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"공개 채팅 채널\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"짧은 링크\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"북마크 세트\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"배지 표시\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"사용자\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap 분할을 분석 실패했습니다: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"표시된 릴레이 이름이 입력한 전체 URL과 동일하지 않습니다.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"이벤트 삭제 요청\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"뮤트된 노트는 표시되지 않습니다\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"연결 성공:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"관심 목록\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"아티팩트 세트 릴리스\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"비디오 이벤트\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"버전별 암호화\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"알 수 없는 NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"비디오 보기 이벤트\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"무료\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"쓰기 릴레이의 하위 집합에 노트 보내기\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 인증을 받으면 도움이 될 수 있습니다:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"릴레이 메트릭\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"서포터 배지\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"상태\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"유료\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"핀 목록\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"가동 시간\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"이름은 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 자 미만이어야 합니다.\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"이미 계정이 있으신가요?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"프로필의 외부 신원\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"DM을 받을 릴레이 목록\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"재게시물을 수동으로 확인해야 합니다.\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sats을 다음 주소로 분할 전송합니다.\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 이벤트 찾기\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"공개\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 노트\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"프로필 수정\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"채팅 시작\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"연락처 목록 또는 공개키 목록이어야 합니다.\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"커뮤니티 목록\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"프로필 이미지\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"이 도구는 내 모든 팔로워가 마지막으로 게시한 이벤트를 검색하고 6개월 동안 게시하지 않은 팔로워를 삭제합니다.\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05는 실제 사용자인지 확인하는 데 도움이 되는 DNS 기반 인증 사양입니다.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"투표 옵션\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"무료로 받기\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"친구 팔로우\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"게시된 모든 이벤트에 적용할 작업량\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"비즈니스\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"수정\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"파일 스토리지 서버 목록\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"제출하기\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"미디어 첨부 파일\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 공개 채팅\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"이름이 차단됨\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"패치\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"중재\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"자세한 정보는 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 에서 확인하세요.\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"ID 복사\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"내 릴레이\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"모든 Zap의 일부를 자금 풀로 분할하여 사용하는 서비스에 자금을 지원하세요!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"뮤트\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"나를 위한\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"투표 작성자: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"다음으로 이동\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: URI 체계\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"공급자\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"미디어 자동 로드\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"만료\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"추가 약관:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"검색\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"FAN\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"허용\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"언어\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL 또는 라이트닝 주소\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"인기 릴레이\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"네이티브 앱\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"긴 형식의 콘텐츠 초안 작성\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"무게\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"연락처\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"소유자\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"모두\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap 금액의 sats\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"체스 (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 읽는 데 걸리는 시간(분)\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL 서비스를 로드하지 못했습니다.\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"최신 노트 자동 표시\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"참가자\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/ms_MY.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sync all events for your profile into local cache\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Stats\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logged in with write access\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"following\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"edit\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ruang Anda seperti yang Anda inginkan 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP File Storage Integration\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send anonymous usage metrics\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat Message\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"From File\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Minta Lebih\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr address does not belong to you\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cari...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic LNDHub wallet (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handling Mentions\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Politics\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show Status\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"git stuff\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Be sure to back up your keys!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Periksa JSON\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alam Dunya\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tiada profil?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderated Communities\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Connect\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subject tag in text events\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"User emoji list\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dana\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sila taip pwd anda\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Selesai\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic lists\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Booo (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Note\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed by friends of friends\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Application-specific data\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" jam\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Latest Articles\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Replies\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign Up\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"User Statuses\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Articles\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blobs stored on mediaservers\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" viewers\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagi\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penerjemah\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Untitled\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total Events:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kosong\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tolak\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bid\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pelooper Utama\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama NIP-05 baru anda adalah:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kehidupan\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bpp\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key Encryption\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Missing Relays\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota tersendiri\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recommended Application Handlers\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Splits\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications API Enabled\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Goal\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"File Metadata\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim zap\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Replay\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute list\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cuba lagi.\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connection Failed:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"New follow list length \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recommend Relay\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seal\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alasan: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Looking for: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this, you may still receive some zaps as if zap splits was not configured\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"ThumbsUp (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed by\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Extra metadata fields and tags\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch accounts\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Good\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Label\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki article\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Information Document\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search Capability\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offline\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Leader\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modular Article Content\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute notes from people who are outside your web of trust\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Close Relays\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conventions for clients' use of e and p tags in text events\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply To\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign up\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sat\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penerima\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid zap split: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Thread\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"nama terlalu panjang\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"bech32-encoded entities\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow sets\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Draft Classified Listing\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Selanjut-nya\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Membalas\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengintip \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar Event RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengirim\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hide muted notes\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retry publishing\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Alamat\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic Repost\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tua\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kata-kata yang dibisukan\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penulis ini telah dibisukan\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create or update a product\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alasan\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Great\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Game\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Creation\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Count\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Push notifications\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bulan\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"nama terlalu pendek\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"telah di-zap\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can add a single or multiple relays, one per line.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AI Embeddings / Vector lists\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay-based Groups\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marketplace UI/UX\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamat Nostr (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP Auth\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Event\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quote Repost\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Servers\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video sets\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow List\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prune follow list\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"and \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" others you follow\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repository announcements\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dibisukan\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Social Graph\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Text Note References\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge Definition\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Hide Message\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cache\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim sat\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tampilkan nota2 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" terbaru\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Product sold as an auction\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"About must be less than \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" characters\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle semua-nya\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Browser\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sats\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invoice / Lightning Address\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search notes\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show badges on profile pages\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction to a website\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seluruh Alam\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terjemahkan ke \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Curation sets\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama tersedia\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain Donation Address\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beli\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sorry, we dont understand this event kind (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), please try one of the following apps instead!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Classified Listings\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zap\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Response\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Authentication of clients to relays\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show status messages on profile pages\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"User groups\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirect issues HTTP redirect to the supplied lightning address\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terjumpa error!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"mengintip kamu\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accounts\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"You dont have any media servers, try adding some.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hapus\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribed to Push\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Garam\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supported NIPs\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Link-nota (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamat Lightning\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Link Magnet\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid Lightning Address\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Booo\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Event\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dealing with Unknown Events\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leader Info\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark list\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"nama akan tersedia nanti\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dibisukan\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hapus cache dan reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You don't follow this person, click here to load media from \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", or update \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"your preferences\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to always load media from everybody.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay reviews\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Support\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expiration Timestamp\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create or update a stall\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Last post \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Data\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pengintip\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"You must be a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" subscriber to access \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" deck\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap semua \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Translate\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Last Seen:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telah kirim \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats ke \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not followed by anyone you follow\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click here to load anyway\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications Not Allowed\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use commas to separate words e.g. word1, word2, word3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji sets\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim sats ke \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sport\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak ada alamat Lightning\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search relays list\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search ulama\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Situs web\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays are servers you connect to for sending and receiving events. Aim for 4-8 relays.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci 'Private'\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Average Latency:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Padam\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"External Content IDs\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Highlights\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Chat Message\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dipadam\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Protected Events\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jenis 'event' tidak diketahui: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mapping Nostr keys to DNS-based internet identifiers\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masukkan Pin\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Request\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"View as user?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Goals\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"PIN terlalu pendek\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonim\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name must be between 8 and 15 characters\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cannot verify Nostr Address\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buka di Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrents\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps on this note will be split to the following users.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menu Debug\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Become a leader\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak tersedia:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Join Room\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"pwd dompet\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Short Text Note\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Client Authentication\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tetapkan sebagai alamat Nostr utama (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy Tags\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send this link to your friends and share the magic of the nostr.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beli alamat nostr\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Counting results\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"item\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Akun Iris.to\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Job Feedback\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Halaman 'users' baru\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dead\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use your invite code to earn sats!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-zap\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps Attestations for Events\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gift Wrap\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kesalahan login tidak dikenal\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dapatkan alamat nostr gratis\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"Langganan anda masih aktif, anda belum dapat memperbarui-nya\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dilahir\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Merge Requests\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to update, please try again\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Long-form Content\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scanning \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid Nostr Address\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salin 'Event' JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sistem (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total hari ini (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distance\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prefs\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Receiving to \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Header file tidak dikenal: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tema\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"The private key is like a password, but it cannot be reset. Guard it carefully and never show it to anyone. Once someone has your private key, they will have access to your account forever.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Message\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saat ini Anda memiliki \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sat di zap pool Anda.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Direct Messages\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Orang yang Anda mengintip\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker Not Running\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repository state announcements\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama hanya boleh diterima jika ia huruf kecilan dan ber-angka\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kedaluwarsa\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Short-form Portrait Video Event\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Oleh: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anda yakin ingin memadam \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ke?\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Vending Machines\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"relay-relay\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penanda\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading note: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permissions\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter a pin to encrypt your private key, you must enter this pin every time you open \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim zap ke \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Perbarui Alamat 'Lightning'\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beli Langganan\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular relays used by people you follow.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy Alamat LN\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay sets\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Problem Tracker\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tandai semua sudah dibaca\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kami memanggilmu dengan nama apa?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bayar Sekarang\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Application-specific Data\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"The author has marked this note as a \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sensitive topic\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays close to your geographic location.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handler information\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use Local Relay\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telah Tamat\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masuk dengan Extension Nostr\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Learn more\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kripto\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interest sets\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar Events\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Garam Hex..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ummah\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"liked\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stop listening\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Definition\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hapus dari `relay` saya\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Receive\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check all event signatures received from relays\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat Baru\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Server\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masuk\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blok\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your application is pending\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"anda memiliki akun iris.to yang aktif\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share a personalized invitation with friends!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your referral code is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Labeling\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci pub (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ya, silakan.\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"To see a full list of changes you can view the changelog \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"n\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Diblok\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Local\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berhenti bisu-kan\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"From Server\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Issues\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically translate notes to your local language\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"alamat npub / nprofile / nostr\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Masuk dengan kunci\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemo\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim metrik penggunaan\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Host fail\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alby wallet connection\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows Relay Health\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Hashtags\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emojis\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sending from \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL app layanan\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular media servers.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont follow enough people, take a look at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to discover people to follow!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"No keys, no \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", There is no way to reset it if you don't back up. It only takes a minute.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Chat\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aktifkan kiriman Emojis\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect a wallet to send instant payments\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Try another relay\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Metadata\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delegated Event Signing\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compose a note\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim zap split ke\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" telah disediakan untuk Anda!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encrypted Direct Messages\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" invited you to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media servers store media which you can share in notes as images and videos\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama atau nym\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"'Extension' yang Didukung\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, fee \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect to your own LND node with Lightning Node Connect\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Minta Lebih\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite Friends\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemo\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are a community leader and are earning \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" of referred users subscriptions!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker Running\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compute prune list\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dapatkan Alamat\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logged in with read-only access\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci Pub\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Baru saja\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kind mute sets\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak, terima kasih.\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirects\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menyiarkan Lagi\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Native nostr wallet connection\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Photography\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Direct Message\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengintipi\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media Servers\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bisukan semua\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"nama terdaftar\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Activities\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pulang\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lists to mute:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"WoT Filter\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not Subscribed to Push\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamat LN\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"The public key is like your username, you can share it with anyone.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nama tampilan\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modular Article Header\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Hashtags\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Daftar\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount in sats\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Classified Listing\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"A default Zap Pool split of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" has been configured for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" developers, you can disable it at any time in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kind\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pin to unlock your private key\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gunakan 'extension' penanda mecha nostr untuk masuk\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Feed\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat Kumpulan\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"window.nostr capability for web browsers\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Home\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poor\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community leaders are individuals who grow the nostr ecosystem by being active in their local communities and helping onboard new users. Anyone can become a community leader, but few hold the current honorary title.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dump\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kumpulan kami amat menghargai masa anda bersama \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", mohon sumbangan titis pulah anda jika anda mampu.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time, your donations are greatly appreciated\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show posts that have a content warning tag\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Disematkan\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pilih beberapa topik yang menarik\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Baca\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gift Wraps\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apa yang sedang kamu pikirkan?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain Donation\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"ye Simpan!\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Attach Media\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Stream\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tentang\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"sub-to\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" in memory)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Android Signer Application\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lists\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"User server list\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof-of-Work\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Basic protocol flow description\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" lebih seronok jikalau bersama!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lencana\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"User Metadata\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prune Follow List\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sync Account\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Msg2\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tampilkan balasan\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"di sini\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked relays list\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interaction\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your sent and received payments will show up here.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"terjemahan DeepL\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cegah akaun palsu meniru Anda\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Admin\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" follows (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" duplicates)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payments\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"new users page\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat Threaded Reply\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generate Invoice\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Already backed up\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Langganan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Anda telah kedaluwarsa\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clean up your feed\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video Event\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apply Now\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays which you have connected to before and appear to be reliable.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Register an Iris username\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Info\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidal login\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"sekarang\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Topiks\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Post Approval\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Configure zap pool\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Semuanya dlm \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite your friends\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Basic key derivation from mnemonic seed phrase\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beli Sekarang\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bayar\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"My events: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy link\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"halaman akun\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Request\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handler recommendation\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes have been muted\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Worker Relay\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read Only\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beralih\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Time-Based Calendar Event\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bid confirmation\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penanda2 buku\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications Allowed\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Searching for account activity (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coinjoin Pool\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tools\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dengar audio artikel ini\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" di-blok\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deck\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidak ada yang ditemukan :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge Award\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" have relays (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reliable Relays\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Emoji\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Mute User\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sematkan\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (for resilient marketplaces)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent Comment\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Date-Based Calendar Event\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Thread Reply\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"'Error' yang tidak diketahui\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Badges\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Di-blok\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Perbarui \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications API Disabled\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kunci Pribadi Anda Adalah (jangan bagi-kan ini dgn sesiapa pun ye!)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Catatan ini telah dibisukan\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tambahkan ke Profil\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terjemahan gagal\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Minta kurang\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Science\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"salah PIN\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay List Metadata\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public chats list\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back up now\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Zaps\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tambah-kan Relay\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reporting\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encrypted Direct Message\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hari\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Chat Channels\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Link pendek\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark sets\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show Badges\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"insa\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to parse zap split: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"The relay name shown is not the same as the full URL entered.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Event Deletion Request\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted notes will not be shown\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connection Success:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interests list\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Release artifact sets\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video Events\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Malam\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Versioned Encryption\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video View Event\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Free\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengirim catatan ke subset dari relay tulis Anda\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metrik Relay\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lencana Pendukung\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Status\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sudah dibayar\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin list\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uptime\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name must be less than \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" characters\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sudah memiliki akun?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"External Identities in Profiles\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay list to receive DMs\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mengirimkan 'sats split' ke\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Found \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" events\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mulai chat\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Must be a contact list or pubkey list\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Communities list\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gambar Profil\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"This tool will search for the last event published by all of your follows and remove those who have not posted in 6 months\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dapatkan yang gratis\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed by friends\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Perniagaan\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"File storage server list\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kirim\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media Attachments\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Public Chat\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nama tlh di-blok\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Patches\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderation\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salin ID\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"My Relays\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bisukan\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"For you\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pergi ke\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: URI scheme\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penyedia\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Additional Terms:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"FAN\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Allow\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Relays\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Native App\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Draft Long-form Content\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weight\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chess (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" mins to read\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Participants\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/nl_NL.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weet je het zeker dat je dit wil herplaatsen: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nu uitbetalen\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Synchroniseer alle gebeurtenissen voor je profiel naar de lokale cache\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Estafette statistieken\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aangemeld met schrijftoegang\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Geheime Groep Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"volgend op\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aanmeldingen\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zorg ervoor dat u het volgende wachtwoord opslaat om uw account in de toekomst te beheren\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verbind\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"bewerken\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Heeft herplaatst\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jouw ruimte zoals jij die wilt 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Duidelijk\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account hulp\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"Integratie HTTP bestandsopslag\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anoniem gebruiksgegevens verzenden\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bericht groeps-chat\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maak je profiel gemakkelijker om te vinden en te delen\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uit bestand\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meer laden\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-adres is niet van jou\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sleutels exporteren\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beheren\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zoeken naar...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generieke LNDHub portemonnee (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ongeldig LNURL\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Omgaan met vermeldingen\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"naam heeft verboden tekens\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Politiek\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toon status\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" seconden\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ga naar\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Git dingen\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weet u zeker dat u deze notitie uit bladwijzers wilt verwijderen?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voer Nostr Wallet Connect configuratie in\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maak een back-up van je sleutels!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verbonden met: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Volgend\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handtekeningen controleren\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Natuur\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gesprekken\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toevoegen\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Omslagfoto\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Heb je geen account?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gemodereerde gemeenschappen\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Portemonnee aansluiten\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onderwerp-tag in tekstgebeurtenissen\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji-lijst gebruiker\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Doneer\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wachtwoord invoeren\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afwerking\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Algemene lijsten\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bladwijzers\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Niet leuk (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nieuwe opmerking\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gevolgd door vrienden van vrienden\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toepassingsspecifieke gegevens\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" uur geleden\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Laatste artikelen\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Antwoorden\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aanmelden\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruikersstatussen\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Artikelen\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blobs opgeslagen op mediaservers\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" kijkers\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Licht\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vertalers\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zonder titel\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je stemt met \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" nieuwe note\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" nieuwe notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Volgers\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Portemonnee\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr aansluiten\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Totaal aantal evenementen:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Geen\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Annuleer\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bod\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primaire ontwikkelaars\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uw nieuwe NIP-05 handvat is:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leven\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vind-ik-niet-leuks\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encryptie met privé-sleutel\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"NostrPlebs is een van de eerste Nostr NIP-05 providers en biedt een goede verzameling domeinen aan tegen redelijke prijzen\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruik imgproxy om foto's te comprimeren\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ontbrekende relais\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notitie aan mijzelf\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aanbevolen applicatieverwerkers\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zappen\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Splitsingen\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meldingen API ingeschakeld\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Doel\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Koop Account-Naam\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metagegevens bestand\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Overzetten naar Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruikersnamen zijn niet uniek op Nostr. Het Nostr adres(!) is uw unieke account label (e.g. name@nostrplebs.com).\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zend zap\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bekijk herhaling\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lijst dempen\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opnieuw proberen\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verbinding mislukt:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nieuwe volglijst lengte \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy afbeelding laden van \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" is mislukt, klik hier om direct te laden\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais aanbevelen\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afdichting\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reden: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Op zoek naar: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Niet alle clients ondersteunen dit, het kan zijn dat je nog steeds zaps ontvangt alsof zap-splitsingen niet is geconfigureerd.\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gevolgd door\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Extra metagegevensvelden en tags\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Niet betaald\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accounts wisselen\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Goed\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy gebruikt HODL facturen om de betaling door te sturen, wat de pubkey van je knooppunt verbergt\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Label\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki artikel\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Document met informatie over relais\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zoeken\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offline\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leider Gemeenschap\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactie\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modulaire artikelinhoud\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Demp notities van mensen die buiten je web van vertrouwen vallen\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais sluiten\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bevestig Reposts\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conventies voor het gebruik door klanten van e en p tags in tekstgebeurtenissen\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Antwoord op\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aanmelden\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ontvanger\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ongeldige zap-splitsing: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Groepsdraad\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"naam is te lang\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"bech32-gecodeerde entiteiten\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paring-zin\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sets volgen\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ontwerpclassificatie\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Volgende\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reageren\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Volgend \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kalender Evenement RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verzend\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verberg gedempte noten\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opnieuw publiceren\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adres\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generieke repost\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opmerking door \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gedempte woorden\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deze auteur is gedempt\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Een product maken of bijwerken\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onbeperkt note-behoud op Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reden\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Geweldig\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Spel\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kanaal Creatie\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Graaf\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pushmeldingen\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maanden\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inloggen\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"naam is te kort\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je kunt één of meerdere relais toevoegen, één per lijn.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Schrijf toegang tot Snort relays en 1 jaar note-opslag\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AI inbeddingen / vectorlijsten\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relaisgroepen\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Updaten\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marktplaats UI/UX\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-adres (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP-autorisatie\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bliksem donatie\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live evenement\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Citaat Repost\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uitloggen\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Populaire servers\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voorgestelde Accounts\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Videosets\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invoice laden mislukt\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profiel Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Volg lijst\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Volglijst snoeien\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Accounts\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"en \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" anderen die je volgt\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repository aankondigingen\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Gedempt\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kalender\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vertaald vanuit \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sociale grafiek\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tekst Opmerking Referenties\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap elke note automatisch wanneer geladen\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge Definitie\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Instellingen\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kanaal verbergen Bericht\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cache\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sats verzenden\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toon laatste \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Product verkocht als veiling\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"Over moet minder dan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" tekens bevatten\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alles Toggeren\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Browser\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sats\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Factuur / Bliksemadres\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opmerkingen zoeken\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data aanbieders\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges tonen op profielpagina's\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactie op een website\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vertalen naar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Curation sets\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruikersnaam is beschikbaar\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sleutel\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adres voor on-chain donatie\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kopen\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sorry, we begrijpen dit soort evenementen niet (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), probeer in plaats daarvan een van de volgende apps!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account toevoegen\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advertenties\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactie op portemonnee\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Authenticatie van clients naar relais\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Statusberichten tonen op profielpagina's\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Accounts\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruikersgroepen\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirect geeft HTTP-omleiding naar het opgegeven bliksemadres\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim nu\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Er is een fout opgetreden!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"volgt u\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rekeningen\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je hebt geen mediaservers, probeer er een paar toe te voegen.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verwijderen\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Selecteer Wallet\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Geabonneerd op Push\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zout\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ondersteunde NIP's\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bladwijzers (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning adres\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim je inbegrepen Snort Nostr adres\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ongeldig bliksemadres\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uitzendingsevenement\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Omgaan met onbekende gebeurtenissen\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uitloggen\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leider Info\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bladwijzerlijst\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bestelling betaald!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Naam\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"naam zal later beschikbaar zijn\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gedempt\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cache wissen en herladen\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open wallet\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je volgt deze persoon niet, klik hier om media te laden van \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", of update \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"je voorkeuren\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" om altijd media van iedereen te laden.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais beoordelingen\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ondersteuning\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vervaldatum\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Een kraam maken of bijwerken\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Laatste bericht \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weet u zeker dat u deze note wilt losmaken?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accountgegevens\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Volgers\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je moet een \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" abonnee zijn om toegang te krijgen tot \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" deck\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap alle \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatisch vertalen\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Laatst gezien:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats verzonden naar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Niet gevolgd door iemand die je volgt\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klik hier om toch te laden\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aangesloten\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnementen\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meldingen Niet toegestaan\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruik komma's om woorden te scheiden, bijv. woord1, woord2, woord3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji sets\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruikersnaam\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stuur sats naar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sport\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Geen lightning adres\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonneer je op \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" voor \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" en ontvang de volgende beloningen\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lijst met relais zoeken\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zoek Account\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais zijn servers waarmee je verbinding maakt voor het verzenden en ontvangen van gebeurtenissen. Streef naar 4-8 relais.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Privésleutel\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gemiddelde wachttijd:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wis\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weergeven\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Externe inhoud-ID's\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voer LNDHub config in\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hoogtepunten\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live chatbericht\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verwijderd\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beschermde gebeurtenissen\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onbekende event soort: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-sleutels in kaart brengen naar DNS-gebaseerde internetidentifiers\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin invoeren\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Portemonnee Aanvraag\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bekijken als gebruiker?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Doelen\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bekijk de code \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin te kort\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anoniem\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opmerking\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"De naam moet tussen 8 en 15 tekens lang zijn\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kan Nostr-adres niet verifiëren\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open op Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrents\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" gezapped\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" anderen\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps op deze notitie worden opgesplitst naar de volgende gebruikers.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug-menu\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Een leider worden\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toont \\\"Kopieer ID\\\" en \\\"Kopieer Event JSON\\\" in het context menu bij elk bericht\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Niet beschikbaar:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kamer\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wachtwoord Wallet\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Standaardpagina\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Korte tekst\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klantverificatie\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Instellen als primair Nostr-adres (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy-tags\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stuur deze link naar je vrienden en deel de magie van de nostr.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betaal abonnement\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Koop Nostr adres\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Resultaten tellen\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" kopen\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.naar rekening\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bevestig\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meldingen\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"U heeft al een abonnement van dit type, gelieve te vernieuwen of te betalen\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Feedback\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kan niet stemmen met \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, stel een ander standaard zap bedrag in\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nieuwe gebruikerspagina\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dood\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruik je uitnodigingscode om sats te verdienen!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps Attestaties voor gebeurtenissen\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cadeauverpakking\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deel\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onbekende inlogfout\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ontvang een gratis nostr adres\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uw abonnement is nog actief, u kunt nog niet vernieuwen\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aangemaakt\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verzoeken samenvoegen\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bijwerken mislukt, probeer het opnieuw\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inhoud in lange vorm\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scannen \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ongeldig Nostr-adres\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kopieer JSON event\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Systeem (Standaard)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Totaal vandaag (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afstand\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voorkeuren\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ontvangen naar \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onbekende bestandsheader: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thema\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reacties worden op elke pagina getoond, indien uitgeschakeld worden er geen reacties getoond\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"De privésleutel is als een wachtwoord, maar kan niet gereset worden. Bewaak het zorgvuldig en laat het nooit aan iemand zien. Zodra iemand je privésleutel heeft, heeft hij of zij voor altijd toegang tot je account.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool werkt alleen als u een van de ondersteunde wallet connecties gebruikt (WebLN, LNDHub of Nostr Wallet Connect)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kanaalbericht\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Op dit moment heb je \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in je Zap-Pool.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Directe privéberichten\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnement\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensen die je volgt\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker wordt niet uitgevoerd\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repository statusmeldingen\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruikersnaam mag alleen kleine letters en cijfers bevatten\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verlopen\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kort Portret Video Evenement\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Door: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weet u zeker dat u dit wilt verwijderen \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gegevensautomaten\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bladwijzers\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Belading: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rechten\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voer een pincode in om je privésleutel te coderen. Je moet deze pincode elke keer invoeren als je \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"opent.\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stuur zap naar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Adres\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonnement kopen\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Populaire relais die worden gebruikt door mensen die je volgt.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN adres Proxy\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais sets\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Probleemzoeker\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Markeer alle als gelezen\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hoe moeten we je noemen?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nu betalen\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toepassingsspecifieke gegevens\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"De auteur heeft deze opmerking gemarkeerd als een \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"gevoelig onderwerp\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais in de buurt van je geografische locatie.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notities wordt automatisch getoond voor de geselecteerde personen, anders wordt alleen de link getoond\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Informatie over behandelaar\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voorbeeld\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lokaal relais gebruiken\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beëindigd\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aanmelden met Nostr Extensie\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meer informatie\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crypto\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interessesets\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kalender Evenementen\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personen\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"ik vond  leuk\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stop met luisteren\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Communautaire definitie\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verwijderen uit mijn relais\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ontvang\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Controleer alle ontvangen evenementhandtekeningen van estafettes\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nieuwe Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruikers moeten akkoord gaan met de waarschuwing van de inhoud om de inhoud van uw notitie te tonen.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server toevoegen\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aanmelden\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blokkeren\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uw aanvraag is in behandeling\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je hebt een actieve iris.to account\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deel een persoonlijke uitnodiging met vrienden!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je verwijzingscode is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Label\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kies naar welke service u bijlagen wilt uploaden\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Publieke sleutel (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ja graag\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voor een volledige lijst met wijzigingen kun je de changelog \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"bekijken.\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" gedempt\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profielfoto\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Het lijkt erop dat je geen abonnement hebt, je kan er één \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" krijgen\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Geblokkeerd\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lokaal\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Niet langer negeren\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Van server\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Problemen\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vertaal notities automatisch naar je eigen taal\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / nostr adres\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aanmelden met sleutel\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruiksgegevens verzenden\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alby portemonnee aansluiting\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Volgt Estafette Gezondheid\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inwisselen\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Hashtags\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reacties\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verzenden van \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uw standaard zap bedrag is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, voorbeeldwaarden worden hiermee berekend.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruikers\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service-URL\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Populaire mediaservers.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Het lijkt erop dat je niet genoeg mensen volgt, kijk eens op \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" om mensen te ontdekken die je kunt volgen!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"Geen sleutels, geen \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", Er is geen manier om het te resetten als je geen back-up maakt. Het duurt maar een minuut.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Openbare chat\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reacties inschakelen\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sluit een portemonnee aan om directe betalingen te versturen\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Probeer een ander relais\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kanaal metagegevens\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voer koppelingszin in\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gedelegeerde ondertekening\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Een notitie samenstellen\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activeer Nu\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bijdragers\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-splitsingen verzenden naar\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruikersnaam iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" is voor jou gereserveerd!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Versleutelde rechtstreekse berichten\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" uitgenodigd op \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mediaservers slaan media op die je kunt delen in notities als afbeeldingen en video's\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Support ontwikkelaars en platforms die NIP-05 identificatie-diensten aanbieden\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes zullen in real-time worden gestreamt naar het Global en Notes tabblad\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Naam of nym\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ondersteunde extensies\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betaald \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, vergoeding \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maak verbinding met je eigen LND-knooppunt met Lightning Node Connect\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toon meer\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vrienden uitnodigen\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uw Nostr adres gedraagt zich als een Lightning adres en stuurt zaps door naar uw gekozen LNURL/Lightning adres\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je bent een gemeenschapsleider en verdient \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" van doorverwezen gebruikersabonnementen!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Werker Loopt\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snellijst berekenen\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adres krijgen\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aangemeld met alleen-lezen toegang\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gevoelige inhoud\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Publieke sleutel\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zojuist\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stomme sets\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Geen dank\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Omleidingen\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voor vragen over je NIP-05 bestelling stuur een DM: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opnieuw uitzenden\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruik je Alby? Ga naar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" om je Nostr Wallet Connect in te stellen!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inheemse nostr-portemonneeverbinding\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fotografie\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Direct bericht\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Volgt\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media Servers\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Demp allen\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet verbinden\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ondersteuning voor meerdere accounts\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"naam is geregistreerd\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live activiteiten\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Terug\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lijsten om te dempen:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"WoT-filter\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Niet geabonneerd op Push\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"De publieke sleutel is net als je gebruikersnaam, je kunt deze met iedereen delen.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weergavenaam\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modulaire artikelkop\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Populaire hashtags\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registreer\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bedrag in sats\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Geclassificeerde lijst\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Een standaard Zap Pool-splitsing van \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" is geconfigureerd voor \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ontwikkelaars, je kunt dit op elk moment uitschakelen in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vriendelijk\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Binnenkort beschikbaar\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin invoeren om je privésleutel te ontgrendelen\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alles markeren als gelezen\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruik een nostr signer-extensie om aan te melden\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji reactie\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Word geverifieerd\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Een enkele zap van \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats zal \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats toewijzen aan de zap pool.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voer\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Groepschat\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"window.nostr mogelijkheid voor webbrowsers\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" andere\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" andere\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Home\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Slecht\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community leaders zijn personen die het nostr ecosysteem laten groeien door actief te zijn in hun lokale gemeenschappen en nieuwe gebruikers te helpen. Iedereen kan een gemeenschapsleider worden, maar slechts weinigen dragen de huidige eretitel.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dump\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bedankt voor het gebruik van \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", overweeg alsjeblieft om te doneren als je kunt.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is een open source project dat wordt gebouwd door gepassioneerde mensen in hun vrije tijd. Uw donaties worden zeer gewaardeerd.\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kan niet stemmen omdat LNURL-service geen zaps ondersteunt\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berichten tonen met een waarschuwingslabel\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vastgezet\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kies een paar interessante onderwerpen\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lezen\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cadeauverpakkingen\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Waar denk je aan?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ketting Donatie\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bliksem Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opgeslagen\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media bijvoegen\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stream bekijken\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Over ons\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kan code niet verzenden\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji die wordt verstuurd wanneer u reageert op een note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nog niet alle Nostr Apps ondersteunen dit\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abonneer\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" in geheugen)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Laden...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Android ondertekenapplicatie\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lijsten\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gebruikersserverlijst\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beschrijving basisprotocolstroom\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" is samen leuker!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metagegevens gebruiker\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snoeien Volglijst\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Synchroniseer account\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Berichten\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ondersteuningen\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uitnodigen\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reacties tonen\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"hier\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Geblokkeerde relaislijst\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interactie\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je verzonden en ontvangen betalingen worden hier weergegeven.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reacties (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL vertalingen\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voorkom dat nepaccounts je imiteren\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Admin\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" volgt (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" duplicaten)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hendel\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kan niet inloggen met een privésleutel in een onbeveiligde omgeving, gebruik in plaats daarvan een Nostr key manager extensie\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betalingen\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"pagina voor nieuwe gebruikers\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Volgen\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Groepschat Antwoord met draad\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Factuur genereren\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profiel\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ontvolgen\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Al een back-up gemaakt\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uw \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" abonnement is verlopen\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ruim je feed op\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interne fout: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video-evenement\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opslaan\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reacties\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nu solliciteren\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Schrijven\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onze eigen NIP-05 verificatieservice ondersteunt de ontwikkeling van deze site en geeft u een speciale badge op onze site!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relais waarop je eerder hebt aangesloten en die betrouwbaar lijken te zijn.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registreer een Iris-gebruikersnaam\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" gerepost\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" anderen gerepost\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Portemonnee-info\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inloggen voor getijden\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Selecteer\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"nu\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onderwerpen\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Goedkeuring communautaire post\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-pool configureren\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" geliked\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" anderen geliked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alles in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nodig je vrienden uit\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Basissleutel afleiden uit mnemonische zaadzin\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Koop nu\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betaal\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mijn evenementen: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Koop Nostr adres\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wachtwoord Wallet\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Link kopiëren\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Niet-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"accountoverzicht\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxyservice voor afbeeldingen\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Volgend \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klik om inhoud van \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" te laden\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betaal invoice\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap verzoek\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aanbeveling voor behandelaar\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" noten zijn gedempt\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"Het lijkt erop dat je er geen hebt, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" om er een te kopen!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relais voor werknemer\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Volg allen\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File Upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Optie: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alleen lezen\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wissel\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tijdgebonden kalendergebeurtenis\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bevestiging bod\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deblokkeer\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bladwijzers\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meldingen toegestaan\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zoeken naar accountactiviteit (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cojoin Pool\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gereedschap\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vernieuw\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Luister naar dit artikel\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" geblokkeerd\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dek\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" volgers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Niets gevonden :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alleen volgend\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, het lijkt erop dat je nog geen Nostr Adres hebt. Overweeg om er een te nemen! Bekijk \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uploaden\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hebben relais (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betrouwbare relais\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadbare back-ups van Snort relay\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aangepaste emoji\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kanaal dempen Gebruiker\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vastmaken aan profielpagina\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marktplaats (voor veerkrachtige marktplaatsen)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Volgers\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent Commentaar\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Op datum gebaseerd kalendergebeuren\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Groepsdraad beantwoorden\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"E-mail <> DM bridge voor je Snort Nostr adres\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onbekende fout\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profiel badges\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opmerking\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Standaard Zap-bedrag\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Geblokkeerd\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ontgrendel\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vernieuw \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meldingen API uitgeschakeld\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uw privésleutel is (deel dit met niemand)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deze opmerking is gedempt\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toevoegen aan Profiel\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vertaling mislukt\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vind ik leuk\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Minder tonen\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wetenschap\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verkeerde pin\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voer wallet wachtwoord in\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metagegevens relaallijst\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Openbare chatlijst\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nu terug naar boven\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bliksemschichten\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays toevoegen\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rapportage\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Standaard)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Versleuteld rechtstreeks bericht\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dagen\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Openbare chatkanalen\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Korte link\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bladwijzersets\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges tonen\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"gebruiker\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mislukt bij het parsen van zap-splitsing: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"De getoonde relaisenaam is niet hetzelfde als de volledige URL die is ingevoerd.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aanvraag voor verwijderen evenement\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gedempte noten worden niet weergegeven\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Succesvolle verbinding:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Belangenlijst\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Artefactsets vrijgeven\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video-evenementen\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donker thema\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Versiescryptie\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onbekend NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video bekijken evenement\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gratis\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stuur notitie naar een subset van schrijfrelays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 geverifieerd worden kan helpen:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relaisgegevens\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Status\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betaald\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Speldenlijst\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uptime\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"De naam moet uit minder dan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" tekens bestaan.\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Heb je al een account?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"Externe identiteiten in profielen\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay-lijst om DM's te ontvangen\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts moeten handmatig worden bevestigd\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stuur satsplitsingen naar\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gevonden \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" evenementen\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Openbaar\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Opmerkingen\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bewerk Profiel\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moet een contactlijst of pubkey-lijst zijn\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gemeenschappen lijst\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profiel afbeelding\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deze tool zoekt naar het laatste evenement dat door al je volgers is gepubliceerd en verwijdert degenen die al 6 maanden niets hebben gepost.\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is een DNS-gebaseerde identificatie die helpt u te valideren als een bepaalde gebruiker.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Opties\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verkrijg er één gratis\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gevolgd door vrienden\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hoeveelheid werk van toepassing op alle gepubliceerde events\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bedrijf\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bewerk\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lijst met bestandsopslagservers\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stuur  in\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media Bijlagen\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Openbare Chat\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"naam is geblokkeerd\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Patches\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderatie\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meer informatie over \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bij \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kopieer ID\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mijn relais\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ondersteun diensten die je gebruikt door een deel van je zaps in een pot geld te splitsen!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dempen\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voor jou\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stemmen via \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ga naar\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: URI-schema\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aanbieder\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatisch video's laden\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verloopt op\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aanvullende voorwaarden:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zoeken\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"VENTILATOR\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sta  toe.\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Taal\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL of Lightning Address\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Populaire relais\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inheemse app\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opstellen van long-form content\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gewicht\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eigenaar\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alle\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap hoeveelheid in sats\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Schaken (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" mins om te lezen\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Laden van LNURL service mislukt\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recente notities automatisch weergeven\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deelnemers\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/no_NO.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/pa_IN.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/pl_PL.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/pt_BR.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tem certeza que deseja repostar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagar agora\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sincronizar todos os eventos de seu perfil no cache local\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Estatísticas de revezamento\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Efetuou login com acesso de gravação\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversa em grupo secreta\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tipo de Zap\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"seguintes\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Por favor, salve sua senha em um lugar seguro para poder gerenciar seu perfil no futuro\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conectar\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"editar\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" repostou\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seu espaço do jeito que você quer 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Limpo\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suporte da conta\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"Integração do armazenamento de arquivos HTTP\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envie métricas de uso anônimas\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensagem de bate-papo em grupo\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Faça seu perfil seja mais fácil de achar e compartilhar\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Do arquivo\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Carregar mais\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"O endereço Nostr não pertence a você\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Exportar Chaves\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gerenciar\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pesquisar...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Carteira LNDHub genérica (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL inválida\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manuseio de menções\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"o nome possui caracteres não permitidos\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Política\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar status\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" segundos\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ir\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"coisas do git\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tem certeza que deseja remover esta nota dos favoritos?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Insira a configuração da Nostr Wallet Connect\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Não se esqueça de fazer backup de suas chaves!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conectado em: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Seguindo\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Assinaturas de cheques\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Natureza\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversas\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adicionar\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Não tem uma conta?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comunidades moderadas\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conexão da carteira\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Etiqueta de assunto em eventos de texto\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de emojis do usuário\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Doaçōes\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Insira a senha\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acabamento\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listas genéricas\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Favoritos\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Descurtidas (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nova Nota\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguido por amigos de amigos\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dados específicos do aplicativo\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" horas\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Artigos mais recentes\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Respostas\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registrar-se\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Status do usuário\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Artigos\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blobs armazenados em servidores de mídia\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" espectadores\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claro\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tradutores\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sem título\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Você está votando com \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" post novo\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" posts novos\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Seguidores\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Carteira\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total de eventos:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nenhum\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancelar\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proposta\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Desenvolvedores principais\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seu novo identificador NIP-05 é:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vida\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Descurtir\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Criptografia de chave privada\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs é um dos primeiros provedores NIP-05 e oferece uma boa coleção de domínios a preços razoáveis\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usar imgproxy para comprimir imagens\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés ausentes\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota pessoal\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manipuladores de aplicativos recomendados\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Splits\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"API de notificações ativada\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Objetivo do Zap\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comprar Identificador\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadados do arquivo\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transferir para Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nomes de usuário não são únicos no Nostr. O endereço do nostr é seu único endereço legível para um humano que é exclusivo para você no momento do registro.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar Zap\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Assistir ao replay\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de silêncio\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repetir\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Falha na conexão:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Novo tamanho da lista de seguidores \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Falha ao fazer proxy da imagem de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", clique aqui para carregar diretamente\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recomendar o relé\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Selo\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Motivo: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Procurando por: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem todos os clientes suportam isso; você ainda poderá receber alguns zaps como se a divisão de zaps não estivesse configurada\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Curtidas (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguido por\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Campos de metadados e tags extras\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Não pago\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trocar de conta\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bom\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notas\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"O proxy usa faturas HODL para encaminhar o pagamento, o que oculta a chave pública de seu nó\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rótulo\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Artigo da Wiki\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Documento de informações do relé\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Capacidade de pesquisa\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Off-line\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Líder de Comunidade\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reação\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conteúdo modular do artigo\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Silenciar notas de pessoas que não fazem parte de sua rede de confiança\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fechar relés\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repostagens (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirmar Republicações\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Convenções para o uso de tags e e p pelos clientes em eventos de texto\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Responder a\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Criar conta\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar Zap de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beneficiário\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Divisão de zap inválida: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Discussão em grupo\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"nome longo demais\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"entidades codificadas por bech32\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Frase de pareamento\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguir conjuntos\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rascunho de listagem de classificados\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Próximo\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Responder\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguindo \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendário Evento RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ocultar notas silenciadas\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repetir publicação\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Endereço do Nostr\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fatura da Lightning\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Genéricos Repost\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Antecessor\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Palavras silenciadas\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Este autor foi silenciado\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Criar ou atualizar um produto\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retenção de notas ilimitada no relé Snort\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Motivo\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Excelente\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jogo\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Criação de canais\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contagem\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notificações Push\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meses\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"nome curto demais\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"enviado\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Você pode adicionar um único ou vários relés, um por linha.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acesso de escrita ao retransmissor Snort, com 1 ano de retenção de eventos\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AI Embeddings / Listas de vetores\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grupos baseados em relés\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Atualizar\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"UI/UX do Marketplace\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Endereço Nostr (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relé\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"Autenticação HTTP\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Doação relâmpago\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento ao vivo\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repostagem de citação\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sair\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Servidores populares\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usuários sugeridos\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conjuntos de vídeos\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Falha ao carregar invoice\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps de perfil\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de seguidores\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Podar a lista de seguidores\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pessoas em destaque\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"e \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" outros que você segue\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anúncios de repositório\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" silenciado(s)\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendário\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traduzido do \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gráfico social\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Texto Nota Referências\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar zap automaticamente para todas notas ao carregar\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Definição de crachá\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Configurações\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensagem de ocultação de canal\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cache\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar últimas \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notas\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap automático\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ao vivo\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Produto vendido como um leilão\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"O nome deve ter menos de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" caracteres\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transferir\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alternar entre todos\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Navegador\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"saturação\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fatura / Endereço do raio\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notas de pesquisa\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provedores de dados\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar emblemas nas páginas de perfil\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reação a um site\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traduzir para \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conjuntos de curadoria\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays customizados\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"O nome de usuário está disponível\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chave\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Endereço de doação em cadeia\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comprar\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Desculpe, mas não entendemos esse tipo de evento (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"). Em vez disso, experimente um dos seguintes aplicativos!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Servidor\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adicionar conta\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listagens de classificados\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Resposta da carteira\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Autenticação de clientes para retransmissores\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar mensagens de status nas páginas de perfil\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usuários em alta\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grupos de usuários\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirect emite redirecionamento HTTP para o endereço de raio fornecido\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Solicitar agora\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Um erro aconteceu!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"segue você\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contas\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Você não tem nenhum servidor de mídia, tente adicionar alguns.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remover\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Selecionar carteira\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inscrito no Push\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIPs com suporte\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Favoritos (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Endereço Lightning\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reivindicar seu endereço do Snort no Nostr\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Link Magnet\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Endereço inválido do Lightning\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" não curtiram\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento de transmissão\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chave Hex..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lidando com eventos desconhecidos\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sair\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Informação do Líder\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de favoritos\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pedido pago!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nome\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"nome vai estar disponível mais tarde\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Silenciado\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apagar cache e recarregar\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abrir Carteira\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se você não segue essa pessoa, clique aqui para carregar mídia de \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"ou atualize \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"suas preferências\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" para sempre carregar mídia de todos.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avaliações do relé\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suporte\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Carimbo de data e hora de expiração\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Criar ou atualizar um estande\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Última postagem \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tem certeza de que deseja desafixar essa nota?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dados da Conta\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguindo\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Você precisa ser assinante do site \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" para acessar o \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" deck\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap todos os \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tradução automática\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visto pela última vez:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviou \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats para \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Não é seguido por ninguém que você segue\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clique aqui para carregar\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conectado\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notas em alta\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Assinaturas\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notificações Não Permitidas\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use vírgulas para separar palavras, por exemplo, palavra1, palavra2, palavra3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conjuntos de emojis\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nome de usuário\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar sats para \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Esporte\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nenhum endereço lightning\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inscreva-se em \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" para \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" e receba os seguintes prêmios\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repostar\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pesquisar lista de relés\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Procurar usuários\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Os relés são servidores aos quais você se conecta para enviar e receber eventos. O objetivo é ter de 4 a 8 relés.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chave Privada\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Latência média:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deletar\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"IDs de conteúdo externo\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Insira a configuração LNDHub\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Destaques\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensagem de bate-papo ao vivo\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Excluído\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eventos protegidos\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tipo de evento desconhecido: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mapeamento de chaves Nostr para identificadores de Internet baseados em DNS\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inserir PIN\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Solicitação de carteira\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visualizar como usuário?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metas do Zap\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confira o código \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pino muito curto\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anônimo\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comentar\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"O nome deve ter entre 8 e 15 caracteres\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Não foi possível verificar endereço Nostr\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Abrir no Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrents\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" enviou um Zap\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" e \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" outro(s) enviaram Zaps\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Os zaps dessa nota serão divididos para os seguintes usuários.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menu de depuração\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torne-se um líder\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostra \\\"Copiar ID\\\" e \\\"Copiar JSON de eventos\\\" no menu de contexto em cada mensagem\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Não disponível:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sala de reuniões\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Senha da carteira\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Página padrão\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota de texto curto\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Autenticação do cliente\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Definido como endereço Nostr primário (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tags de proxy\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Envie este link para seus amigos e compartilhe a magia do nostr.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagar por assinatura\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comprar endereço Nostr\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Resultados da contagem\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comprando \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.para contabilizar\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirmar\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notificações\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Você já tem uma assinatura deste tipo, por favor, renove ou pague\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Feedback do trabalho\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Não é possível votar com \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, por favor defina uma quantidade de zap padrão diferente\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nova página de usuários\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repostagens\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Morto\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use seu código de convite para ganhar sats!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Atestados OpenTimestamps para eventos\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Embalagem para presente\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compartilhar\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erro de login desconhecido\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obtenha um endereço de correio eletrônico gratuito\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sua assinatura ainda está ativa, você não pode renovar ainda\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Criado\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Solicitações de mesclagem\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Falha ao atualizar. Tente novamente\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conteúdo de formato longo\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Digitalização \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Endereço Nostr Inválido\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copiar JSON do Evento\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sistema (Padrão)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total hoje (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distância\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferências\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recebimento para \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cabeçalho de arquivo desconhecido: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tema\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reações serão mostradas em todas as páginas, se desativadas, nenhuma reação será mostrada\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relés\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"A chave privada é como uma senha, mas não pode ser redefinida. Guarde-a com cuidado e nunca a mostre a ninguém. Quando alguém tiver sua chave privada, terá acesso à sua conta para sempre.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"O Zap Pool só funciona se você usar uma das conexões de carteira suportadas (WebLN, LNC, LNDHub ou Nostr Wallet Connect)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensagem do canal\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Você tem atualmente \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats no seu grupo de zap.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensagens diretas privadas\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Assinatura\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pessoas que você segue\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trabalhador de serviço não está sendo executado\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anúncios de estado do repositório\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"O nome de usuário deve conter apenas letras minúsculas e números\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expirado\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento de vídeo de retrato de formato curto\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Por: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tem certeza de que deseja excluir \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Máquinas de venda automática de dados\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Favoritar\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota de carregamento: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permissões\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Insira um PIN para criptografar sua chave privada. Você deve inserir esse PIN sempre que abrir o site \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar zap para \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Atualizar endereço Lightning\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comprar assinatura\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés populares usados por pessoas que você segue.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy de endereço LN\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conjuntos de relés\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rastreador de problemas\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marcar todos como lidos\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Customizar\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Como devemos chamá-lo?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagar agora\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dados específicos do aplicativo\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"O autor marcou esta nota como um tópico sensível \"\n    },\n    {\n      \"children\": [],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés próximos à sua localização geográfica.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"A mídia nas notas será mostrada automaticamente para os usuários selecionados, caso contrário apenas o link será mostrado\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Informações do manipulador\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prévia\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usar relé local\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Final\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Faça login com a extensão Nostr\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saber mais\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Criptografia\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conjuntos de juros\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendário de eventos\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pessoas\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"gostou\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conta\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pare de ouvir\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Definição de comunidade\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remover de meus relés\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Receber\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verifique todas as assinaturas de eventos recebidas dos revezamentos\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Novo chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Os usuários devem aceitar o aviso de conteúdo para mostrar o conteúdo da sua nota.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adicionar Servidor\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Entrar\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bloquear\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seu aplicativo está pendente\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Você tem uma conta ativa no iris.to\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compartilhe um convite personalizado com seus amigos!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seu código de referência é \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Etiquetagem\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Escolha para qual serviço fazer upload dos arquivos\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chave pública (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sim, por favor\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Para ver uma lista completa das alterações, você pode visualizar o changelog \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" silenciado(s)\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parece que você não tem nenhuma assinatura, você pode obter uma aqui \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bloqueado\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Local\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Desmutar\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Do servidor\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Problemas\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traduzir automaticamente as anotações para seu idioma local\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / nostr endereço\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fazer login com a chave\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nseg, npub, nip-05, hex, mnemônico\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar métricas de uso\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Servidores de arquivos\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conexão da carteira Alby\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acompanha o Relay Health\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Resgatar\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hashtags em Alta\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reações\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviando de \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sua quantidade padrão de zap é de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, valores de exemplo são calculados a partir disso.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usuários\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL do serviço\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Servidores de mídia populares.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parece que você não segue um número suficiente de pessoas. Dê uma olhada em \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" para descobrir pessoas para seguir!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sem chaves, sem \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", não há como redefini-lo se você não fizer o backup. Isso leva apenas um minuto.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bate-papo público\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Habilitar reações\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conecte uma carteira para enviar pagamentos instantâneos\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tente outro relé\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadados do canal\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inserir frase de pareamento\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Assinatura de eventos delegados\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Escrever uma nota\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ativar agora\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Colaboradores\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar divisões de zap para\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"O nome de usuário iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" está reservado para você!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensagens diretas criptografadas\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" convidou você para \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Os servidores de mídia armazenam mídia que pode ser compartilhada em notas como imagens e vídeos\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Financie desenvolvedores e plataformas que fornecem serviços de verificação NIP-05\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"As notas serão transmitidas em tempo real na guia global e de notas\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nome ou nym\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Extensões suportadas\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pago \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, taxa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conecte-se ao seu próprio nó LND com o Lightning Node Connect\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar mais\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Convidar amigos\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemônica\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seu identificador atuará como um endereço lightning e redirecionará para a LNURL escolhida ou endereço Lightning\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Você é um líder da comunidade e está ganhando \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" de assinaturas de usuários referidos!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trabalhador de serviço em execução\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calcular lista de poda\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obter endereço\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Efetuou login com acesso somente leitura\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conteúdo sensível\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chave pública\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anônimo\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Agora há pouco\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conjuntos de mudo gentil\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Não, obrigado\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirecionamentos\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se você tiver uma pergunta sobre o seu pedido NIP-05, por favor envie uma mensagem privada \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transmitir novamente\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usando o Alby? Vá para \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" para obter a sua configuração de NWC!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conexão nativa da carteira do usuário\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fotografia\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensagem direta\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguindo\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL...\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Servidores de Mídia\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Silenciar todos\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conectar carteira\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suporte a múltiplas contas\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"nome registrado\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Atividades ao vivo\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Voltar\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listas para silenciar:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Filtro WoT\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Não está inscrito no Push\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Endereço LN\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"A chave pública é como seu nome de usuário, você pode compartilhá-la com qualquer pessoa.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Exibir nome\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cabeçalho de artigo modular\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hashtags populares\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registro\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quantidade em sats\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listagem de classificados\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uma divisão padrão do Zap Pool de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" foi configurada para desenvolvedores de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" . Você pode desativá-la a qualquer momento em \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tipo\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Em breve\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Digite o PIN para desbloquear sua chave privada\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marcar todas como lidas\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usar uma extensão de signatário do nariz para fazer login\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emojis de reação\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obter verificação\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Um único zap de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats irá alocar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats para o pool de zap.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alimentação\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat em grupo\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recurso window.nostr para navegadores da Web\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" outros\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" outros\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Início\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ruim\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Os líderes da comunidade são indivíduos que aumentam o ecossistema da nostr sendo ativos em suas comunidades locais e ajudando a integrar novos usuários. Qualquer pessoa pode se tornar um líder de comunidade, mas poucos possuem o título honorário atual.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Despejo\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obrigado por usar o site \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \". Se possível, considere fazer uma doação.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"O Snort é um projeto de código aberto criado por pessoas apaixonadas em seu tempo livre. Suas doações são muito apreciadas\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Não é possível votar porque o serviço LNURL não suporta zaps\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar postagens que tenham uma tag de aviso de conteúdo\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fixado\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Escolha alguns tópicos de interesse\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lida\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Embalagens para presentes\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"No que você está pensando?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Doação em cadeia\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salvo\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anexar mídia\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Assistir à transmissão\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sobre\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Falha ao enviar o voto\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji a ser enviado quando reagir a uma nota\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nem todos os clientes suportam isso ainda\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Assinar\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" na memória)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Carregando...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aplicativo Android Signer\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listas\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de servidores de usuários\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prova de trabalho\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Descrição básica do fluxo do protocolo\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" é mais divertido juntos!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emblemas\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadados do usuário\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de acompanhamento do Prune\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sincronizar Conta\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensagens\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suporta\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Convite\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Exibir respostas\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mídia\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"aqui\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de relés bloqueados\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interação\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Piscina Zap\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seus pagamentos enviados e recebidos serão exibidos aqui.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reações (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Traduções DeepL\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Impedir que contas falsas imitem você\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Administrador\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" segue (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" duplicatas)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Identificador\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Não é possível fazer login com a chave privada em uma conexão insegura, por favor, use uma extensão para gerenciar chaves do Nostr\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagamentos\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"página de novos usuários\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguir\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat em grupo Resposta encadeada\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gerar fatura\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Perfil\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deixar de seguir\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Backup já feito\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sua assinatura do \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" expirou\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Limpe seu feed\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erro interno: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento em vídeo\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salvar\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reações\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aplicar agora\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Escrever\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nosso próprio serviço de verificação NIP-05, ajude no desenvolvimento deste site e obtenha uma insígnia especial no nosso site!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés aos quais você já se conectou antes e que parecem ser confiáveis.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registre um nome de usuário Iris\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" repostou\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" e \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" outros repostaram\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Informações sobre a carteira\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login no Tidal\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Selecione\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"agora\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tópicos\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aprovação de postes comunitários\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Configurar o pool de zap\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" curtiu\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" e \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" outros curtiram\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tudo no \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Convide seus amigos\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Derivação de chave básica a partir de frase-semente mnemônica\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comprar agora\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagar\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meus eventos: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Endereço do Snort no Nostr\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Senha da carteira\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copiar link\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Não-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"página da conta\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Serviço de proxy de imagem\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguindo \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clique para carregar o conteúdo do \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pagar fatura\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Solicitação do Zap\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recomendação do manipulador\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" as notas foram silenciadas\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parece que você não tem nenhuma, verifique \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" para comprar uma!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Revezamento de trabalhadores\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguir todos\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Serviço de upload de arquivos\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iniciar\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opção: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Somente leitura\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alternar\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento de calendário com base no tempo\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirmação da proposta\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Desbloquear\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Favoritos\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notificações Permitidas\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Procurando por atividade de conta (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Piscina de Coinjoin\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ferramentas\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renovar\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ouça este artigo\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bloqueados\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deck\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" seguidores\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nada foi encontrado :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguindo somente\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, parece que você ainda não tem um endereço no Nostr, você deveria ter um! Confira \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prêmio Badge\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" têm relés (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés confiáveis\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cópias baixáveis do relé do Snort\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji personalizado\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Canal Mudo Usuário\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fixar\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (para marketplaces resilientes)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguidores\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comentário do Torrent\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento de calendário baseado em data\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Resposta da linha de discussão do grupo\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"E-mail <> ponte DM para seu endereço de usuário do Snort\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Erro desconhecido\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emblemas de perfil\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nota\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Valor padrão de Zap\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bloqueado\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Desbloquear\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renovar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"API de notificações desativada\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sua chave privada é (não compartilhe isso com ninguém)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Esta nota foi silenciada\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adicionar ao perfil\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Falha na tradução\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Curtir\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar menos\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ciência\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pino incorreto\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Digite a senha da carteira\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadados da lista de retransmissão\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de bate-papos públicos\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fazer backup agora\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Raios\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Adicionar Relés\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relatórios\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Padrão)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mensagem direta criptografada\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dia(s)\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Canais de Chat Públicos\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Link curto\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conjuntos de marcadores\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar crachás\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"usuário\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Falha ao analisar a divisão zap: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"O nome do relé mostrado não é o mesmo que o URL completo inserido.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Solicitação de exclusão de evento\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"As notas silenciadas não serão mostradas.\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sucesso na conexão:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de interesses\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liberar conjuntos de artefatos\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Eventos em vídeo\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Noturno\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Criptografia com controle de versão\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Desconhecido NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Evento de exibição de vídeo\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grátis\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar nota a um subconjunto dos seus relés de escrita\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obter a verificação do NIP-05 pode ajudar a:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" saturação\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Métricas de relé\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emblema de apoiador\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Status\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pago\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de pinos\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tempo de atividade\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"O nome deve ter menos de \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" caracteres\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Já tem uma conta?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"Identidades externas em perfis\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de retransmissão para receber DMs\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repostagens precisam ser confirmadas manualmente\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar sats splits para\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encontrado \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eventos\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Público\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notas\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Editar perfil\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iniciar chat\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deve ser uma lista de contatos ou uma lista de chaves públicas\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de comunidades\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imagem do perfil\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Essa ferramenta pesquisará o último evento publicado por todos os seus seguidores e removerá aqueles que não publicaram em 6 meses\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 é uma especificação de verificação baseada em DNS que ajuda a validar você como um usuário real.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Opções de enquete\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obtenha um gratuitamente\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seguido por amigos\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quantidade de trabalho para aplicar a todos os eventos publicados\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Negócios\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Editar\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista de servidores de armazenamento de arquivos\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enviar\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anexos de mídia\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chat Público do Nostr\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"o nome está bloqueado\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Patches\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderação\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Descubra mais informações sobre \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" em \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copiar ID\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meus relés\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Financie os serviços que você utiliza dividindo uma parte de todos os seus zaps em uma reserva de fundos!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Silenciar\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Para você\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votos por \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ir para\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: Esquema URI\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provedor\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Carregar mídia automaticamente\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expira em\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Termos adicionais:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pesquisar\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"FAN\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permitir\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Idioma\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL ou endereço Lightning\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relés populares\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aplicativo nativo\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Depurar\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rascunho de conteúdo longo\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Peso\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contato\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dono\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Todos\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quantidade de Zap em sats\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Xadrez (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" minutos para ler\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Falha ao carregar o serviço LNURL\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mostrar automaticamente as últimas notas\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Participantes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/pt_PT.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/ro_RO.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/ru_RU.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вы уверены, что хотите сделать репост: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Выплатить сейчас\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Синхронизируйте все события для вашего профиля в локальном кэше\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Статистика эстафеты\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Войти с правом записи\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Секретный групповой чат\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Тип запа\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"подписки\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Логины\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Пожалуйста, обязательно сохраните следующий пароль, чтобы в будущем управлять своим хэндлом\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подключиться\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"редактировать\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" сделал репост\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ваше пространство таким, каким вы его хотите видеть 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поддержка аккаунта\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"Интеграция с HTTP-хранилищем файлов\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отправлять показатели анонимного использования\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сообщение в групповом чате\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Упростить поиск и распространение вашего профиля в Nostr\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Из файла\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" мс\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Загрузить больше\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"Адрес Nostr не принадлежит вам\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ключи экспорта\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Управление\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поиск...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Общий кошелек LNDHub (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Неверный LNURL\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Работа с упоминаниями\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"имя содержит запрещенные символы\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Политика\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Показать статус\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" секунд\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Перейти на сайт\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"git-файлы\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вы уверены, что хотите удалить эту заметку из закладок?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Введите конфигурацию Nostr Wallet Connect\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Не забудьте сделать резервную копию своих ключей!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подключен к: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Подписчиков\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Контрольные подписи\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Природа\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Беседы\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Добавить\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Баннер\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"У вас нет учетной записи?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Модерируемые сообщества\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Connect\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Тег темы в текстовых событиях\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список пользовательских эмодзи\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поддержать\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Введите пароль\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отделка\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Общие списки\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Закладок\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Дизлайки (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Новая заметка\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"За ним следуют друзья друзей\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Данные для конкретного применения\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" часов\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Последние статьи\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ответы\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Зарегистрироваться\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Статусы пользователей\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Статьи\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Блоки, хранящиеся на серверах-посредниках\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" зрители\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Светлый\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Переводчики\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Без названия\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вы голосуете \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" сатами\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" новая заметка\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" новые заметки\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Подписчиков\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Кошелек\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Всего событий:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ничьи\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вики\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отменить\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Заявка\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Основные разработчики\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ваш новый NIP-05:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Жизнь\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Дизлайк\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Шифрование с закрытым ключом\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs является одним из первых сервисов NIP-05 и предлагает хорошую коллекцию доменов по приемлемым ценам\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Использовать imgproxy для сжатия изображений\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отсутствующие реле\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Заметка самому себе\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Рекомендуемые манипуляторы для нанесения\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Splits\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"API уведомлений включен\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Цель\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Приобрести хэндл\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Метаданные файла\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Перевести на Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Имя пользователя не является уникальным на Nostr. Nostr адрес - это ваш уникальный человеко читаемый адрес, который уникален для вас при регистрации.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отправить зап\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Смотреть повтор\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список отключения звука\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retry\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Соединение не удалось:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Новая длина списка подписчиков \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Не удалось загрузить изображение через \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", нажмите здесь, чтобы загрузить напрямую\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Рекомендовать реле\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Уплотнение\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Причина: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"В поисках: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Не все клиенты поддерживают это, вы все равно можете получить некоторые запы, как если бы запределение не было настроено\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Лайки (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Также подписаны\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Дополнительные поля метаданных и теги\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Не оплачено\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Переключение счетов\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Хорошо\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Заметки\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy использует HODL-счета для пересылки платежа, что скрывает pubkey вашего узла\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Этикетка\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вики-статья\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Информационный документ о реле\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Возможность поиска\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offline\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Общественный лидер\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Реакция\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Модульное содержание статей\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отключайте звук на записях от людей, которые не входят в вашу сеть доверия\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Реле закрытия\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Репосты (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подтверждать репосты\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Правила использования клиентами тегов e и p в текстовых событиях\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply To\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Зарегистрироваться\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Запнуть \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" сат\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Получатель\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Неверный zap сплит: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Групповая нить\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"имя слишком длинное\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"сущности в кодировке bech32\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Фраза для сопряжения\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Следите за наборами\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Проект классифицированного объявления\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Далее\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ответить\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подписан(а) на \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Календарь Событие RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отправить\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Скрыть приглушенные ноты\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Повторная публикация\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr адрес\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Лайтнинг-инвойс\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic Repost\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ветка\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Заметка на сайте \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Приглушенные слова\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Этот автор был заглушен\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Создание или обновление продукта\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Снятие ограничения срока хранения ваших заметок на релее Snort\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Причина\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Великий\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Игра\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Создание канала\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Граф\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Push-уведомления\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Месяцы\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вход\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"имя слишком короткое\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вы можете добавить одно или несколько реле, по одному на линию.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Возможность трансляции на релей Snort с сохранением заметок в течение года\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вкрапления ИИ / Векторные списки\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Группы на основе ретрансляции\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Обновить\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"UI/UX торговой площадки\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ностровый адрес (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Реле\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP-авторизация\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Молниеносное пожертвование\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Живое событие\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Перепост цитаты\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Выход\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Популярные серверы\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Предложенные подписки\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Видеосюжеты\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Не удалось загрузить инвойс\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Профиль Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список для следования\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сокращение списка подписчиков\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Популярные профили\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"и \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" других, за которыми вы следите.\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Объявления о репозиториях\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" заглушен\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Календарь\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Переведено с \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Социальный график\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Текст Примечание Ссылки\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Автоматически запать каждую загружаемую заметку\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Определение значка\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Настройки\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Канал Скрыть сообщение\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Кэш\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Послать саты\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Показать последние \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" заметки\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Авто Зап\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Прямой эфир\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Товар продается на аукционе\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"\\\"Об\\\" должен содержать менее \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" символов\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Перевод\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle all\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Браузер\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sats\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Счет-фактура / Адрес молнии\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поисковые заметки\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Данные провайдера\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Показывать значки на страницах профиля\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Реакция на веб-сайт\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Глобальная лента\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Перевести на \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Наборы для курирования\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Кастомные релеи\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Имя пользователя доступно\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ключ\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Адрес цепочки пожертвований\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Купить\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Извините, мы не понимаем этот тип события (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), пожалуйста, попробуйте одно из следующих приложений вместо этого!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сервер\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Добавить аккаунт\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Классифицированные объявления\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Запов\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ответ кошелька\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Аутентификация клиентов для ретрансляторов\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Показывать статусные сообщения на страницах профиля\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Трендовые пользователи\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Группы пользователей\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirect осуществляет HTTP-переадресацию на указанный адрес молнии\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Получить сейчас\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Произошла ошибка!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"подписан(а) на Вас\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Счета\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"У вас нет медиасерверов, попробуйте добавить их.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Удалить\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Выберите кошелек\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подпишитесь на Push\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Соль\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поддерживаемые НИПы\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Закладки (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Адрес\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Получите Nostr адрес от Snort\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet-ссылка\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Торрент\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Неверный адрес молнии\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Дизлайк\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Трансляция события\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex ключа..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Работа с неизвестными событиями\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Выйти\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Информация о руководителе\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список закладок\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Заказ оплачен!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Имя\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"имя будет доступно позже\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Заглушен\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Очистить кэш и перезагрузить\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Открыть кошелек\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вы не подписаны на этого человека, нажмите здесь, чтобы загрузить медиа из \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", или обновите \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"ваши предпочтения\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" чтобы всегда загружать медиа от всех.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отзывы о реле\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поддержка\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Срок действия\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Создание или обновление кабинки\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Последнее сообщение \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вы уверены, что хотите открепить эту заметку?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Данные учетной записи\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подписки\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вы должны быть подписчиком \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" , чтобы получить доступ к \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" deck\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Зафиксировать все сателлиты \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Автоперевод\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Последний раз его видели:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отправлено \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats на \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"За вами никто не следит\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Нажмите здесь для загрузки\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подключено\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Популярные заметки\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подписки\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Уведомления запрещены\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Используйте запятые для разделения слов, например, слово1, слово2, слово3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Наборы эмодзи\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Имя пользователя\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отправить sats на \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Запы (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Спорт\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Нет адреса молнии\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подпишитесь на \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" для \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" и получите следующие вознаграждения\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список реле для поиска\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поиск пользователей\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сайт\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Реле - это серверы, к которым вы подключаетесь для отправки и получения событий. Ориентируйтесь на 4-8 реле.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Приватный ключ\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Средняя задержка:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Удалить\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Показать\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Идентификаторы внешнего содержимого\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Введите конфигурацию LNDHub\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Основные моменты\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сообщение в чате\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Удалено\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Защищенные события\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Неизвестный тип события: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сопоставление ключей Nostr с интернет-идентификаторами на основе DNS\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Введите пин-код\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Запрос кошелька\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Просматривать как пользователь?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Цели\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Проверьте код \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Слишком короткий штифт\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Аноним\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Комментарий\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Имя должно содержать от 8 до 15 символов\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Невозможно проверить адрес Nostr\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Открыть на Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Торренты\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" другие zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Записки по этой заметке будут распределены между следующими пользователями.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Меню отладки\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Станьте лидером\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Показывает \\\"Копировать ID\\\" и \\\"Копировать JSON\\\" в контекстном меню каждой заметки\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Недоступно:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Комната для регистрации\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Пароль кошелька\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Страница по умолчанию\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Краткая текстовая заметка\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Аутентификация клиента\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Установить в качестве основного адреса Nostr (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Теги прокси\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отправьте эту ссылку своим друзьям и поделитесь магией ностра.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Оплатить подписку\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Купить ностровый адрес\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Результаты подсчета\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Покупка \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.to account\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подтвердить\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Уведомления\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"У вас уже есть подписка этого типа, пожалуйста, обновите или оплатите ее.\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отзывы о работе\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вы не можете голосовать \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" сатами, пожалуйста, установите другую сумму запа по умолчанию\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Страница новых пользователей\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Репосты\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Мертвые\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Используйте свой код приглашения, чтобы заработать саты!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Запы\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Аттестации OpenTimestamps для событий\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подарочная упаковка\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поделиться\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Неизвестная ошибка при логине\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Получить бесплатный ностровый адрес\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ваша подписка все еще активна, продлить ее пока что невозможно\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Создано\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Слияние запросов\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Не удалось обновить, попробуйте еще раз\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Контент в длинной форме\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сканирование \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Неверный адрес ностры\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Копировать JSON события\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Системный (по умолчанию)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Всего сегодня (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" сат\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Расстояние\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Настройки\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Получение на \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Неизвестный заголовок файла: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Скин\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Реакции будут отображаться на каждой странице; если реакции отключены, они не будут отображаться\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Релеи\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Закрытый ключ похож на пароль, но его нельзя сбросить. Храните его тщательно и никогда никому не показывайте. Если кто-то завладеет вашим закрытым ключом, он навсегда получит доступ к вашей учетной записи.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool работает только в том случае, если вы используете одно из поддерживаемых соединений кошельков (WebLN, LNC, LNDHub или Nostr Wallet Connect)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сообщение канала\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"В настоящее время в вашем пуле zap имеется \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" сатов.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Личные прямые сообщения\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подписка\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Люди, за которыми вы следите\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сервисный работник не запущен\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Объявления о состоянии репозитория\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Имя пользователя должно содержать только строчные буквы и цифры\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Срок действия истёк\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Короткометражное портретное видео\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Автор: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вы уверены, что хотите удалить \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Торговые автоматы по продаже данных\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Релеи\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Закладка\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Примечание к загрузке: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Разрешения\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Введите пин-код для шифрования закрытого ключа, который необходимо вводить каждый раз, когда вы открываете сайт \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отправить zap на \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Обновить лайтнинг-адрес\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Приобрести подписку\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Популярные реле, используемые людьми, за которыми вы следите.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Прокси лайтнинг-адреса\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Наборы реле\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отслеживание проблем\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отметить все прочитанное\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Настраиваемые\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Как мы должны вас называть?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Оплатить сейчас\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Данные для конкретного применения\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Автор пометил эту заметку как \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"чувствительную тему\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Реле в непосредственной близости от вашего географического положения.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Медиафайлы в заметках будут автоматически показаны для выбранных людей, в противном случае будет показана только ссылка\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Информация об обработчике\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Предварительный просмотр\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Используйте местное реле\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Окончание\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вход в систему с помощью расширения Nostr\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Узнать больше\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Криптовалюта\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Интересные наборы\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"События календаря\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Пользователи\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"понравилось\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Счет\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Перестаньте слушать\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Определение сообщества\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Удалить из моих реле\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Получить\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Проверьте все подписи, полученные от ретрансляторов\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Новый чат\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Пользователи должны принять предупреждение, чтобы увидеть содержание вашей заметки.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Добавить сервер\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Войти\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Блок\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ваше заявление находится на рассмотрении\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"У вас есть активная учетная запись iris.to\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поделитесь персональным приглашением с друзьями!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ваш реферальный код: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Маркировка\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Выберите каким сервисом Вы бы хотели пользоваться для загрузки медиа\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Публичный ключ (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Да, пожалуйста\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Полный список изменений вы можете посмотреть в журнале изменений \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" заглушено\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Аватар\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Похоже, у вас нет подписок, вы можете оформить подписку \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Заблокировано\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Местный\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Разблокировать\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"От сервера\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вопросы\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Автоматический перевод заметок на местный язык\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / nostr address\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вход в систему с помощью ключа\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отправка показателей использования\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Хозяева файлов\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подключение кошелька Alby\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Следит за здоровьем эстафеты\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Выкупить\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Модные хэштеги\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Реакции\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отправка из \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"По умолчанию величина zap равна \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, примерные значения рассчитываются исходя из этого.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Пользователи\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL-адрес сервиса\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Популярные медиасерверы.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Похоже, вы не следите за достаточным количеством людей, загляните на \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" , чтобы узнать, за кем следить!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"Нет ключей, нет \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", нет возможности сбросить настройки, если не сделать резервную копию. Это займет всего минуту.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Общественный чат\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Включить реакции\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подключите кошелек для отправки мгновенных платежей\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Попробуйте другое реле\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Метаданные канала\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Введи фразу для сопряжения\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Делегированное подписание событий\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Составьте заметку\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Активировать\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сделали вклад\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отправляйте сплиты zap в\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Имя пользователя iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" зарезервировано для Вас!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Зашифрованные прямые сообщения\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" пригласил вас на сайт \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"На медиасерверах хранятся медиафайлы, которыми можно делиться в заметках в виде изображений и видео.\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поддержать разработчиков и платформы, предоставляющие услуги NIP-05\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Заметки в режиме реального времени будут поступать на вкладку \\\"Глобальные и заметки\\\".\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Имя или название\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поддерживаемые расширения\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Платно \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, платно \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подключение к собственному узлу LND с помощью Lightning Node Connect\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Развернуть\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" км\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Пригласите друзей\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Мнемоническая фраза\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ваш хэндл будет выступать в качестве лайтнинг-адреса и перенаправлять запы на выбранный вами LNURL или LN адрес\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вы являетесь лидером сообщества и зарабатываете \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" от подписок привлеченных пользователей!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сервисный работник запущен\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список подверженных вычислений\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Получить адрес\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Войти с правом записи\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Контент 18+\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Публичный ключ\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Только что\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Наборы для отключения звука\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Нет, спасибо\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Перенаправления\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Если у Вас есть вопросы по поводу NIP-05, отправьте сообщение \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"КиБ\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Транслировать снова\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Используете Alby? Зайдите на сайт \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" , чтобы получить конфигурацию NWC!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подключение кошелька Native nostr\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Фотография\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Прямое сообщение\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подписки\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Медиасерверы\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Заглушить всех\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подключить кошелек\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поддержка нескольких аккаунтов\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"имя зарегистрировано\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Живая деятельность\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Назад\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Списки для отключения звука:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Фильтр WoT\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Не подписаны на Push\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Лайтнинг-адрес\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Открытый ключ - это как ваше имя пользователя, вы можете поделиться им с кем угодно.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отображаемое имя\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Модульный заголовок статьи\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Популярные хэштеги\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Регистр\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сумма в сатоши\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Классифицированное объявление\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Для разработчиков \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" по умолчанию настроено разделение Zap Pool на \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" , вы можете отключить его в любой момент в \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Добрый\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"В разработке\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Введите пин-код для разблокировки закрытого ключа\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отметить все как прочитанные\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Использование расширения nostr signer для входа в систему\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Эмодзи реакции\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Получить верификацию\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"При единичном загрузке \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" сатов в пуле загрузчиков будет выделено \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" сатов.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Корм\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Групповой чат\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Возможность window.nostr для веб-браузеров\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" другие\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" другие\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Главная\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Бедный\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Лидеры сообщества - это люди, которые развивают экосистему nostr, проявляя активность в своих местных сообществах и помогая привлекать новых пользователей. Стать лидером сообщества может каждый, но лишь немногие носят это почетное звание.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Свалка\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Спасибо за использование сайта \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", пожалуйста, рассмотрите возможность пожертвования, если это возможно.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort - это проект с открытым исходным кодом, созданный увлеченными людьми в свободное от работы время, и ваши пожертвования будут высоко оценены.\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Не удается проголосовать, потому что Ваш LNURL-провайдер не поддерживает запы\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Показать сообщения, которые имеют предупреждающий тег\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Закреплённые\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Выберите несколько тем, представляющих интерес\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Прочитано\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подарочные упаковки\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поделитесь мнением\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Цепное пожертвование\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сохранено\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Прикрепить носитель\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Смотреть поток\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"О себе\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Не удалось проголосовать\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Эмодзи реакции на заметки\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Пока поддерживается не всеми клиентами\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подписаться\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" in memory)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Загрузка...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Приложение для подписи в Android\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Списки\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список серверов пользователей\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Доказательство работы\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Описание базового потока протоколов\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" вместе веселее!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Бейджи\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Метаданные пользователя\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список подписчиков\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Учетная запись синхронизации\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сообщения\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поддержка\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Пригласите\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Показать ответы\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"СМИ\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"здесь\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список заблокированных реле\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Взаимодействие\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Здесь отображаются отправленные и полученные платежи.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Реакции (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Переводы от DeepL\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Бороться с имитирующими Вас поддельными аккаунтами\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Администратор\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" следует (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" дубликаты)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Хэндл\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Не удается войти с помощью приватного ключа - ваше соединение небезопасно, пожалуйста, используйте расширение-менеджер ключей\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Платежи\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"страница новых пользователей\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подписаться\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Групповой чат Нитевидные ответы\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сформировать счет-фактуру\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Профиль\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отписаться\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Уже резервное копирование\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Срок действия вашей подписки \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" истек\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Очистка корма\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ошибка: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Видеособытие\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сохранить\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Реакции\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подать заявку сейчас\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Написать\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Наша собственная служба верификации NIP-05; помогите поддержать развитие этого сайта и получите блестящий специальный значок на нашем сайте!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Реле, к которым вы уже подключались и которые кажутся надежными.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Зарегистрируйте имя пользователя Iris\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" перепост\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" другие перепостили\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Информация о кошельке\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вход в систему Tidal\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Выберите\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"сейчас\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Темы\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Утверждение сообщений сообщества\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Настройка пула zap\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" понравилось\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" другим понравилось\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Все возможности \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Пригласите своих друзей\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Получение базового ключа из мнемонической начальной фразы\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Купить\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Заплатить\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Мои события: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-адрес от Snort\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Пароль кошелька\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Копировать ссылку\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"страница аккаунта\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Прокси-сервис для изображений\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подписан(а) на \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Нажми, чтобы загрузить контент с \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Оплатить счет\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Request\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Рекомендация обработчика\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ноты были приглушены\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"Похоже, Вы не верифицированы, перейдите на страничку \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", чтобы купить адрес!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Рабочее реле\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подписаться на всех\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Служба загрузки файлов\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Начало\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Опция: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Только чтение\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сменить\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Календарное событие, привязанное ко времени\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подтверждение заявки\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Разблокировать\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Закладки\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Уведомления разрешены\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поиск активности аккаунта (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Бассейн \\\"Коинджойн\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Инструменты\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Обновить\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Прослушать статью\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" заблокировано\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Палуба\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" подписчиков\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ничего не найдено :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Только подписки\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Эй, похоже, что у вас еще нет адреса Nostr, вы должны его получить! Загляните на \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Награда за значок\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Загрузить\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" есть реле (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Надежные реле\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Доступ к резервным копиям на релее Snort\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Пользовательские эмодзи\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Приглушение звука канала Пользователь\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Пин\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (для устойчивых торговых площадок)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подписчики\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Комментарий к торренту\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Событие календаря на основе даты\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Групповая тема Ответить\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Мост между email и личными сообщениями для Вашего Snort-адреса\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Неизвестная ошибка\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Значки профиля\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Заметка\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Размер Запа по умолчанию\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Заблокировано\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Разблокировать\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Обновить \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"API уведомлений отключен\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ваш приватный ключ (не делитесь им ни с кем)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Эта запись была отключена\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Добавить в профиль\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Перевод не удался\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Например,\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Свернуть\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Наука\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Неправильный вывод\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Программное обеспечение\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Введите пароль кошелька\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Метаданные списка реле\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список публичных чатов\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Создать резервную копию\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Молния\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Добавить реле\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отчетность\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(по умолчанию)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Зашифрованное прямое сообщение\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" дней\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Каналы публичного чата\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Краткая ссылка\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Наборы закладок\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Показать бейджи\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"пользователь\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Не удалось разобрать zap-раздел: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отображаемое имя реле не совпадает с введенным полным URL-адресом.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Запрос на удаление события\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Приглушенные ноты не будут отображаться\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Успех соединения:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список интересов\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Выпуск наборов артефактов\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Видеособытия\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Тёмная\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Версионное шифрование\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Неизвестный НИП-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Видео Просмотр события\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Бесплатно\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отправить заметку на подмножество Ваших пишущих релеев\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Получение подтверждения NIP-05 может помочь:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Метрики реле\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Бейдж Саппортера\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Статус\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Оплачено\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список контактов\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Время работы\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Имя должно содержать менее \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" символов\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"У вас уже есть учетная запись?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"Внешние идентификаторы в профилях\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список ретрансляторов для получения DM\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Репосты должны быть подтверждены вручную\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отправить сплиты sats по адресу\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Найдено \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" событий\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Общественность\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" заметок\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Редактировать профиль\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Начать общение\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Должен быть список контактов или список pubkey\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список сообществ\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Изображение профиля\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Этот инструмент найдет последнее событие, опубликованное всеми вашими подписчиками, и удалит тех, кто не публиковал информацию в течение 6 месяцев\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 - это спецификация проверки на основе DNS, которая помогает подтвердить тебя как реального пользователя.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Настройки опроса\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Получить бесплатно\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Подписчики друзей\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Объем работы по применению ко всем опубликованным событиям\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Бизнес\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Редактировать\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Список серверов хранения файлов\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отправить\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Медиаприложения\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Публичный чат Nostr\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"имя заблокировано\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Патчи\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Модерация\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Узнай больше о \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" в \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Скопировать ID\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Мои реле\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Финансируйте услуги, которыми вы пользуетесь, разделяя часть всех ваших \\\"запсов\\\" на пул фондов!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Заглушить\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Для вас\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Голосование на сайте \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Перейти\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: Схема URI\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Провайдер\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Автоматически загружать изображения\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Истекает\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Дополнительные условия:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Поиск\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"FAN\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Разрешить\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Язык\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL или Лайтнинг-адрес\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Популярные реле\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Нативное приложение\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Отладка\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Составление длинного контента\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Вес\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Связь\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Владелец\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Все\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Сумма Запа в сатах\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Шахматы (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" минут на чтение\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Не удалось загрузить службу LNURL\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Автоматически показывать новые заметки\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Участники\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/sr_SP.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/sv_SE.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Är du säker på att du vill dela vidare:\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utbetalning nu\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Synka alla händelser för din profil till lokal cache\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stafettstatistik\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inloggad med skrivbehörighet\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hemlig grupp chatt\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Typ\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"följer\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inloggningar\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se till att spara följande lösenord för att hantera din profil i framtiden\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anslut\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"redigera\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" delade\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ditt utrymme så som du vill ha det 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rensa\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konto Support\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"Integration av HTTP fillagring\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skicka anonyma användarvärden\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gruppchattmeddelande\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gör din profil enklare att hitta och dela\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Från filen\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ladda fler\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr-adressen tillhör inte dig\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Exportnycklar\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hantera\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sök...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generisk LNDHub-plånbok (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ogiltig LNURL\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hantering av omnämnanden\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"namnet har otillåtna tecken\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Politik\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visa status\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Starta\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"git-grejer\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Är du säker på att du vill ta bort den här anteckningen från bokmärken?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skriv in Nostr Wallet Connect konfiguration\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Se till att säkerhetskopiera dina nycklar!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ansluten till: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Följer\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kontrollera signaturer\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Natur\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konversationer\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lägg till\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Har du inget konto?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modererade Communities\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Plånbok Connect\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ämnestagg i texthändelser\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Användarens emoji-lista\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donera\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ange lösenord\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avsluta\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generiska listor\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bokmärken\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gillar inte (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ny anteckning\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följs av vänner till vänner\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Applikationsspecifika data\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" timmar\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Senaste artiklar\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Svar\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registrera dig\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Användarstatusar\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Artiklar\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blobbar lagrade på mediaservers\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" tittare\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ljust\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Översättare\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utan titel\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du röstar med \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" ny anteckning\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" nya anteckningar\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Följare\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Plånbok\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Totalt antal händelser:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingen\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avbryt\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bud\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primära Utvecklare\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Din nya NIP-05 är:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Liv\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ogilla\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kryptering med privat nyckel\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs är en av de första NIP-05 leverantörerna och erbjuder en bra samling domäner till rimliga priser\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Använd imgproxy för att komprimera bilder\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saknade reläer\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anteckning till mig själv\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rekommenderade applikationshanterare\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Splits\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"API för notifieringar aktiverat\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-mål\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Köp Namn\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadata för filer\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Överför till Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Användarnamn är inte unika på Nostr. Nostr-adressen är din unika människoläsbara adress som är unik för dig vid registrering.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skicka zap\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Titta på repris\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute-lista\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Försök igen\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anslutningen misslyckades:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ny längd på följelistan \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Det gick inte att proxybilden från \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", klicka här för att ladda direkt\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rekommendera relä\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tätning\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anledning: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Letar du efter..: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inte alla klienter stöder detta, kan du fortfarande få några zaps som om zap delning inte konfigurerades\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gillar (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följs av\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Extra metadatafält och taggar\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obetald\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Byta konto\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bra\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anteckningar\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy använder HODL-fakturor för att vidarebefordra betalningen, vilket döljer pubkey för din nod\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Etikett\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki-artikel\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dokument med information om reläet\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sökfunktionalitet\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Frånkopplad\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gemenskapens ledare\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaktion\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modulärt artikelinnehåll\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stäng av anteckningar från personer som du inte litar på\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stäng reläer\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delningar (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bekräfta Dela vidare\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konventioner för klienters användning av e- och p-taggar i texthändelser\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Svara till\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registrering\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mottagare\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ogiltig zapsplit: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grupptråd\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"namnet är för långt\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"bech32-kodade enheter\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parnings fras\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följ set\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utkast till klassificerad annonsering\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nästa\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Svara\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följer \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kalender Evenemang RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skicka\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dölj tystade anteckningar\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Försök att publicera igen\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adress\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning-faktura\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generisk Repost\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Förälder\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anteckning av \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tystade ord\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Denna författare har tystats\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skapa eller uppdatera en produkt\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Obegränsat antal anteckningar på Snort-relä\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anledning\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bra\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Spel\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skapande av kanaler\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Antal\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Push-meddelanden\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Månader\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logga in\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"namnet är för kort\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zappad\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du kan lägga till ett eller flera reläer, ett per rad.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skriv åtkomst till Snort relä med 1 års lagring av event\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AI-inbäddningar / vektorlistor\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reläbaserade grupper\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uppdatera\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marknadsplats UI/UX\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr adress (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relä\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP-autentisering\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning donation\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live-evenemang\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Citera Repost\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logga ut\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Populära servrar\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Föreslagna personer att följa\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Videouppsättningar\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Det gick inte att ladda fakturan\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följ lista\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rensa följelistan\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trendande personer\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"och \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" andra du följer\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meddelanden om förvar\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" tystad\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kalender\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Översatt från \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Social graf\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Text Not Referenser\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zappa automatiskt varje anteckning när den är laddad\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge Definition\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inställningar\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kanal Dölj meddelande\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cache\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skicka sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visa senaste \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" anteckningar\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Produkt som säljs som auktion\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"Om-sektionen måste vara mindre än \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" tecken\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Överför\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Växla alla\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Webbläsare\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sats\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Faktura / Lightning-adress\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sök anteckningar\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dataleverantörer\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visa emblem på profilsidor\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaktion på en webbplats\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Översätt till \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Curation-uppsättningar\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anpassade reläer\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Användarnamnet är tillgängligt\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nyckel\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donationsadress för On-chain\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Köpa\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tyvärr förstår vi inte den här typen av händelse (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), prova någon av följande appar istället!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lägg till konto\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rubricerade annonser\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Svar från plånboken\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Autentisering av klienter till reläer\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visa statusmeddelanden på profilsidor\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trendande användare\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Användargrupper\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirect utfärdar HTTP-redirect till den angivna lightning adressen\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hämta nu\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ett fel har uppstått!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"följer dig\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konton\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du har inga medieservrar, försök att lägga till några.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ta bort\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Välj plånbok\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prenumererar på Push\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stödda nationella vägledande program\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bokmärken (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning-adress\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hämta din inkluderade Snort nostr adress\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ogiltig Lightning-adress\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Ogillar\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sänd händelse\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hantering av okända händelser\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logga Ut\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Info om ledare\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista över bokmärken\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beställningen är betald!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Namn\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"namnet kommer att vara tillgängligt senare\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tystad\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rensa cache och ladda om\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Öppna plånbok\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du följer inte denna person, klicka här för att ladda media från \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", eller uppdatera \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"dina inställningar\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" för att alltid ladda media från alla.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recensioner av reläer\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stöd\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidsstämpel för utgång\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skapa eller uppdatera ett stall\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Senaste inlägg \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Är du säker på att du vill ta bort denna anteckningen?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kontouppgifter\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följer\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du måste vara \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" prenumerant för att få tillgång till \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" deck\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zappa alla \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto-översätt\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Senast sedd:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skickade \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats till \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följs inte av någon du följer\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klicka här för att ladda ändå\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ansluten\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trendande anteckningar\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prenumerationer\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notiser inte tillåtna\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Använd kommatecken för att skilja ord åt, t.ex. ord1, ord2, ord3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji-uppsättningar\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Användarnamn\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skicka sats till \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sport\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingen lightning adress\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prenumerera på \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" för \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" och få följande belöningar\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dela\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sök reläer lista\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sök användare\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Webbsida\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reläer är servrar som du ansluter till för att skicka och ta emot händelser. Sikta på 4-8 reläer.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Privat nyckel\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Genomsnittlig latenstid:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Radera\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visa\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"ID för externt innehåll\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ange LNDHub-konfiguration\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Höjdpunkter\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meddelande via livechatt\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Raderad\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skyddade händelser\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Okänd händelsetyp: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mappning av Nostr-nycklar till DNS-baserade internetidentifierare\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ange PIN-kod\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Begäran om plånbok\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visa som användare?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-mål\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kolla in koden \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"PIN-koden är för kort\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymt\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kommentar\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Namnet måste vara mellan 8 och 15 tecken\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kan inte verifiera Nostr-adress\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Öppna på Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrents\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zappade\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" andra zappade\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps på denna anteckning kommer att delas upp till följande användare.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bli en ledare\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visar \\\"Kopiera ID\\\" och \\\"Kopiera händelse JSON\\\" i kontextmenyn på varje meddelande\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inte tillgänglig:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gemensamt rum\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Plånbokens lösenord\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Förvald Sida\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kort text Anmärkning\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Autentisering av klient\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ange som primär Nostr adress (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy Taggar\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skicka denna länk till dina vänner och dela magin i nostr.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betala för prenumeration\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Köp nostr adress\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Räkna resultat\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Köper \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.to konto\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bekräfta\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifikationer\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du har redan en prenumeration av den här typen, vänligen förnya eller betala\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Feedback om jobbet\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kan inte rösta med \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, vänligen ange ett annat förvalt zap-belopp\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nya användares sida\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Död\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Använd din inbjudningskod för att tjäna sats!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps Attestationer för händelser\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Presentpapper\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dela\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Okänt inloggningsfel\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Få en gratis nostr adress\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"Din prenumeration är fortfarande aktiv, du kan inte förnya ännu\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skapad\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Slå samman förfrågningar\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Misslyckades med uppdateringen, försök igen\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Innehåll i lång form\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skanning \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ogiltig Nostr-adress\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kopiera händelse JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (standard)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Totalt idag (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avstånd\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inställningar\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tar emot till \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Okänd filrubrik: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tema\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaktioner kommer att visas på varje sida om inga reaktioner inaktiveras\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reläer\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Den privata nyckeln är som ett lösenord, men det går inte att återställa. Vakta den noga och visa den aldrig för någon. När någon har din privata nyckel har de tillgång till ditt konto för alltid.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool fungerar endast om du använder en av plånboksanslutningarna (WebLN, LNC, LNDHub eller Nostr Wallet Connect)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kanalmeddelande\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du har för närvarande \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats i din zap pool.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Privata direktmeddelanden\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prenumeration\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personer du följer\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker körs inte\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meddelanden om förvarets tillstånd\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Användarnamnet får bara innehålla gemener och siffror\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Förfallen\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Porträttvideo i kortformat Event\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Av: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Är du säker på att du vill radera \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Varuautomater för data\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reläer\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bokmärke\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Laddningsinformation: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Behörigheter\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ange en pin för att kryptera din privata nyckel, du måste ange denna pin varje gång du öppnar \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skicka zap till \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uppdatera Lightning-adress\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Köp Prenumeration\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Populära reläer som används av personer du följer.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Adress Proxy\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reläuppsättningar\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Problemspårare\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Markera alla som lästa\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anpassat\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vad ska vi kalla dig?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betala nu\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Applikationsspecifika data\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Författaren har markerat denna anteckning som ett \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"känsligt ämne\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reläer i närheten av din geografiska plats.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media i anteckningar visas automatiskt för valda personer, annars visas endast länken\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Information om handläggare\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Förhandsvisning\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Använd lokalt relä\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avslutade\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logga in med Nostr Extension\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Läs mer\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Krypto\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Räntesatser\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kalenderhändelser\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Personer\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"gillade\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konto\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sluta lyssna\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Definition av gemenskapen\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ta bort från mina reläer\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ta emot\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kontrollera alla signaturer mottagna från reläer\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ny chatt\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Användare måste acceptera innehållsvarningen för att visa innehållet i din anteckning.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lägg till server\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logga in\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blockera\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Din ansökan är under behandling\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du har ett aktivt iris.to konto\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dela en personlig inbjudan med dina vänner!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Din värvningskod är \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Märkning\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Välj vilken uppladdningstjänst du vill ladda upp bilagor till\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Publik nyckel (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ja tack\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"För att se en fullständig lista över ändringar kan du se ändringsloggen \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" tystad\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Det verkar som om du inte har några prenumerationer, du kan skaffa en \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blockerad\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lokal\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avtysta\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Från server\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Frågor\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Översätt automatiskt anteckningar till ditt lokala språk\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / nostr adress\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logga in med nyckel\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skicka användningsstatistik\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Filvärdar\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alby plånboksanslutning\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följer relä-hälsa\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lösa in\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trendande hashtaggar\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaktioner\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skickar från \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ditt förvalda zap-belopp är \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, exempelvärden beräknas utifrån detta.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Användare\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Populära medieservrar.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Det ser ut som om du inte följer tillräckligt många, ta en titt på \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" för att upptäcka personer att följa!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inga nycklar, ingen \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", Det finns inget sätt att återställa den om du inte säkerhetskopierar. Det tar bara en minut.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offentlig chatt\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aktivera reaktioner\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anslut en plånbok för att skicka omedelbara betalningar\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prova ett annat relä\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadata för kanaler\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ange parningsfras\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delegerad signering av evenemang\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skriva en anteckning\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aktivera nu\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bidragsgivare\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skicka zap-delning till\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Användarnamnet iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" är reserverat för dig!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Krypterade direktmeddelanden\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" bjöd in dig till \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Medieservrar lagrar media som du kan dela i anteckningar som bilder och videor\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Finansiera utvecklare och plattformar som tillhandahåller NIP-05 verifieringstjänster\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anteckningar kommer att strömmas i realtid in i global och antecknings fliken\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Namn eller nym\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tillägg som stöds\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betald \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, avgift \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anslut till din egen LND-nod med Lightning Node Connect\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visa mer\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bjud in vänner\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ditt namn kommer att fungera som en Lightning adress och kommer att omdirigeras till din valda LNURL eller Lightning adress\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Du är en community leader och tjänar \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" på hänvisade användares prenumerationer!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker i drift\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utarbeta en lista över gallringar\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skaffa adress\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inloggad med skrivskyddad åtkomst\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Känsligt innehåll\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Publik nyckel\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just nu\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kind mute sets\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nej tack\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Omdirigeringar\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Om du har en förfrågan om din NIP-05 beställning, vänligen DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sänd igen\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Använder du Alby? Gå till \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" för att få din NWC konfiguration!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Native nostr plånboksanslutning\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fotografi\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Direktmeddelande\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följer\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mediaservrar\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tysta alla\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anslut plånbok\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Öppna tidsstämplar\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stöd för flera konton\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"namnet är registrerat\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Levande aktiviteter\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tillbaka\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listor för att stänga av ljudet:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"WoT-filter\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prenumererar inte på Push\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Adress\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Den publika nyckeln är som ditt användarnamn, du kan dela den med vem som helst.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visnings namn\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modulär artikelrubrik\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Populära hashtags\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registrering\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Belopp i sats\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klassificerad annonsering\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"En standard Zap Pool split av \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" har konfigurerats för \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" utvecklare, du kan inaktivera den när som helst i \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Typ\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kommer snart\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ange pin för att låsa upp din privata nyckel\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Markera alla som lästa\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Använd ett nostr signer-tillägg för att logga in\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaktion emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bli Verifierad\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"En enda zap med \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats kommer att fördela \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats till zappoolen.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Foder\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gruppchatt\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"window.nostr-funktion för webbläsare\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" andra\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" andras\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hem\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dålig\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community leaders är personer som får nostrs ekosystem att växa genom att vara aktiva i sina lokala samhällen och hjälpa till att få in nya användare. Vem som helst kan bli community leader, men få har den nuvarande hederstiteln.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dumpa\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tack för att du använder \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", vänligen överväg att donera om du kan.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort är ett open source-projekt som byggs av passionerade människor på deras fritid, dina donationer uppskattas mycket\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kan inte rösta eftersom LNURL-tjänsten inte stöder zaps\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visa inlägg som har en varningstagg för innehåll\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fastnålad\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Välj några ämnen av intresse\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Läs\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gåvopaket\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vad tänker du på?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain donation\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blixt Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sparad\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bifoga media\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Titta på Streamen\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Om\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Misslyckades att skicka röst\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji att skicka när reagerar på en anteckning\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alla klienter stöder inte detta ännu\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prenumerera\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" i minnet)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Laddar...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Android-signeringsapplikation\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listor\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista över användarservrar\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beskrivning av grundläggande protokollflöde\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" är roligare tillsammans!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emblem\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadata för användare\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rensa följelistan\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Synkronisera konto\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Meddelanden\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Support\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inbjudan\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visa svar\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"här\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista över blockerade reläer\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interaktion\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dina skickade och mottagna betalningar kommer att visas här.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaktioner (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL översättningar\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Förhindra falska konton från att imitera dig\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Administratör\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" följer (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dubbletter)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Namn\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kan inte logga in med privat nyckel på en osäker anslutning, använd ett tillägg för Nostr key manager istället\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betalningar\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"sida för nya användare\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följ\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gruppchatt Trådat svar\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generera faktura\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profil\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sluta följ\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redan säkerhetskopierad\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ditt \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" abonnemang har löpt ut\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Städa upp i ditt flöde\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internt fel: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video Evenemang\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Spara\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reaktioner\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ansök nu\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skriv\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vår alldeles egna NIP-05 verifieringstjänst, hjälpa till att stödja utvecklingen av denna webbplats och få ett glänsande speciellt märke på vår webbplats!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reläer som du har anslutit till tidigare och som verkar vara tillförlitliga.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Registrera ett användarnamn för Iris\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" delade\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" andra delade\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Information om plånboken\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidal inloggning\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Välj\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"nu\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ämnen\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Godkännande av gemenskapspost\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Konfigurera zap-pool\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" gillade\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" andra gillade\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Allting i \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bjud in dina vänner\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grundläggande nyckel härledning från mnemonisk fröfras\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Köp Nu\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betala\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mina händelser: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr adress\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Plånbokens lösenord\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kopiera länk\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"konto sida\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bild proxy tjänst\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följer \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Klicka för att ladda innehåll från \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betala Faktura\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap-förfrågan\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rekommendation för handläggare\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" noter har dämpats\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"Det verkar som om du inte har någon, kolla \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" för att köpa en!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Arbetstagare Relä\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följ alla\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tjänst för filuppladdning\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alternativ: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Endast läsning\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Växla\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidsbaserad kalenderhändelse\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bekräftelse av bud\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avblockera\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bokmärken\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notiser tillåtna\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Söker efter kontoaktivitet (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coinjoin Pool\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Verktyg\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Förnya\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lyssna på denna artikel\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blockerad\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deck\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" följare\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inget hittat :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följer endast\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hej, det ser ut som du inte har en Nostr adress ännu, du bör skaffa en! Kolla in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge-utmärkelse\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ladda upp\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" har reläer (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pålitliga reläer\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nedladdningsbara säkerhetskopior från Snort relä\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anpassad emoji\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kanal Mute Användare\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fäst\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (för motståndskraftiga marknadsplatser)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följare\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent Kommentar\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Datumbaserad kalenderhändelse\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Svar på grupptråd\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"E-post <> DM brygga för din Snort nostr adress\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Okänt fel\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profilmärken\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anteckning\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Förvalt Zap-belopp\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blockerad\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lås upp\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Förnya \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"API för notifieringar avaktiverat\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Din privata nyckel är (dela inte detta med någon)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Den här anteckningen har tystats\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lägg till i min profil\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Översättning misslyckades\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gilla\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visa mindre\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vetenskap\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felaktig pin\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mjukvara\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ange lösenord för plånboken\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Metadata för relälista\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista över offentliga chattar\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Säkerhetskopiera nu\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blixtnedslag\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lägg till reläer\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rapportering\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Standard)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Krypterat direktmeddelande\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dagar\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offentliga chattkanaler\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kort länk\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bokmärkesuppsättningar\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visa emblem\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"användare\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Misslyckades att tolka zapsplit: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Det relänamn som visas är inte detsamma som den fullständiga URL som angetts.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Begäran om radering av evenemang\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tystade anteckningar kommer inte att visas\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Framgångsrik anslutning:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Intresseförteckning\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Släpp artefaktuppsättningar\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Videohändelser\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mörkt\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Versionerad kryptering\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Okänd NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video Visa händelse\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gratis\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skicka anteckning till en delmängd av dina skrivreläer\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Att få NIP-05 verifierat kan hjälpa:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relä statistik\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Emblem\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Status\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Betald\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stiftlista\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Drifttid\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Namnet måste vara mindre än \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" tecken\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Har du redan ett konto?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"Externa identiteter i profiler\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay-lista för att ta emot DM\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dela vidare måste bekräftas manuellt\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skicka sats-delningar till\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hittade \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" händelser\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Allmänheten\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" anteckningar\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redigera profil\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Starta chatt\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Måste vara en kontaktlista eller en pubkey lista\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista över samhällen\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profilbild\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Detta verktyg kommer att söka efter den senaste händelsen som publiceras av alla dina följande och ta bort dem som inte har postat i 6 månader\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 är en DNS-baserad verifieringsspec som hjälper till att validera dig som en riktig användare.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alternativ för omröstning\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Få en kostnadsfri\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Följs av vänner\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mängd arbete att tillämpas för alla publicerade händelser\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Företag\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ändra\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lista över server för fillagring\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skicka\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bilagor för media\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Publik Chatt\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"namnet är blockerat\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Plåster\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderation\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ta reda på mer om \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" på \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kopiera ID\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mina reläer\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Finansiera de tjänster som du använder genom att dela upp en del av alla dina zaps i en pool med pengar!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tysta\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"För dig\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Röster från \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gå till\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: URI-schema\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leverantör\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ladda media automatiskt\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Löper ut\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ytterligare villkor:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sök\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"FAN\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tillåt\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Språk\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Adress\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Populära reläer\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nativ app\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Felsökning\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utarbeta innehåll i lång form\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vikt\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kontakt\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ägare\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alla\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap belopp i sats\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Schack (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" min att läsa\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Det gick inte att ladda LNURL-tjänsten\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Visa automatiskt de senaste anteckningarna\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deltagare\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/sw_KE.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je, una uhakika unataka kuchapisha upya: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Malipo sasa\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sawazisha matukio yote ya wasifu wako kwenye akiba ya ndani\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Stats\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Umeingia na ufikiaji wa kuandika\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gumzo la Siri la Kikundi\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aina ya Zap\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"unafuata\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingizo\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tafadhali hakikisha kuwa umehifadhi nenosiri lifuatalo ili kudhibiti mpini wako katika siku zijazo\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unganisha\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"hariri\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" amechapisha upya\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mahali pako kama unavyotaka 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Safisha\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usaidizi wa Akaunti\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP File Storage Integration\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tuma takwimu za matumizi kwa siri\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat Message\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fanya wasifu wako kuwa rahisi kupata na kushiriki\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"From File\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dakika\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pakia zaidi\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anwani ya Nostr sio yako\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dhibiti\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tafuta...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mkoba wa kawaida wa LNDHub (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL isiyo halali\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handling Mentions\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"herufi katika jina imezuiliwa\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Siasa\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onyesha Hali\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sekunde\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enda\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"git stuff\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je, una uhakika unataka kuondoa kidokezo hiki kutoka kwa alamisho?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingiza usanidi wa Nostr Wallet Connect\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hakikisha kuhifadhi funguo zako!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imeunganishwa kwa: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Unafuata\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Angalia Saini\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Asili\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mazungumzo\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ongeza\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bango\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Huna akaunti?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderated Communities\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Connect\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subject tag in text events\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"User emoji list\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Changia\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hifadhi Nenosiri\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maliza\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic lists\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Alamisho\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Haipendwi (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nakala Mpya\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ikifuatiwa na marafiki wa marafiki\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Application-specific data\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" masaa\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Latest Articles\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Replies\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jisajili\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"User Statuses\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Makala\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blobs stored on mediaservers\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" viewers\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mwangaza\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watafsiri\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Untitled\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unapiga kura kwa kutumia \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" kidokezo kipya\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" kidokezo kipya\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Wafuasi\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total Events:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hakuna\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ghairi\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bid\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wasanidi wa Msingi\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 yako mpya ni:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maisha\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kutopenda\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key Encryption\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs ni mtoa huduma wa kwanza wa NIP-05 katika soko na hutoa mkusanyiko bora wa vikoa kwa bei nzuri\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tumia imgproxy kupunguza picha\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Zilizopotea\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kumbuka Wewe Mwenyewe\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recommended Application Handlers\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mgawanyiko wa Zap\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Taarifa za Kidukizo Zimeruhusiwa\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Goal\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nunua Kitambulisho\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"File Metadata\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hamisha kwa Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Majina ya mtumiaji si ya kipekee kwenye Nostr. Anwani ya nostr ni anwani yako ya kipekee inayoweza kusomwa na binadamu ambayo ni ya kipekee kwako unapojiandikisha.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tuma zap\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tazama Upya\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute list\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jaribu tena\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connection Failed:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Urefu mpya wa orodha ya kufuatilia \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imeshindwa kufanya upakiaji mbadala kutoka kwa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", bonyeza hapa ili upakie moja kwa moja\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recommend Relay\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seal\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sababu: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Looking for: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Haitumiki kwa wateja wote, bado unaweza kupokea zile zile kama kugawanywa kwa zap haiko imewezeshwa\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vipendwa (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kufuatiliwa na\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Extra metadata fields and tags\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Haijalipwa\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch accounts\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Good\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Noti\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy hutumia ankara za HODL kusonga malipo, ambayo huficha pubkey ya nodo yako\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Label\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki article\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Information Document\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search Capability\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nje ya mtandao\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kiongozi wa Jamii\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modular Article Content\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute notes from people who are outside your web of trust\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Close Relays\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Machapisho upya (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thibitisha Reposts\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conventions for clients' use of e and p tags in text events\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jibu Kwa\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jisajili\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mpokeaji\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap isiyofaa: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Thread\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jina refu sana\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"bech32-encoded entities\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maneno ya Kuoanisha\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow sets\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Draft Classified Listing\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inayofuata\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jibu\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anafuata \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar Event RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tuma\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ficha madokezo yaliyonyamazishwa\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jaribu tena kuchapisha\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anwani ya Nostr\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ankara ya Umeme\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic Repost\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mzazi\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kidokezo kutoka kwa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maneno Yaliyozuiwa\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mwandishi amenyamazishwa\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create or update a product\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hifadhi tukio bila kikomo kwenye reli ya Snort\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sababu\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Great\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mchezo\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Creation\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hesabu\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Taarifa za Push\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Miezi\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingia\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jina fupi sana\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"limezwapishwa\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can add a single or multiple relays, one per line.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Andika ufikiaji wa upeanaji wa Snort, na uhifadhi wa mwaka 1 wa tukio\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AI Embeddings / Vector lists\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay-based Groups\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sasisha\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marketplace UI/UX\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anwani ya nostr (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP Auth\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toleo la Umeme\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Event\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposti ya Ujumbe\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toka\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Servers\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inayopendekezwa Inafuata\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video sets\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hakuna uwezo wa kupakia ankara\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Orodha ya Kufuata\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Katiza orodha ya kufuata\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watu Wanaofanya Vizuri\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"na \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" wengine unao wafuatilia\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repository announcements\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Imenyamazishwa\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imetafsiriwa kutoka \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Grafu ya Jamii\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Text Note References\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap kila kidokezo kiotomatiki inapopakia\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge Definition\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mipangilio\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Hide Message\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hifadhi\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tuma sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onyesha vidokezo vya \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hivi karibuni\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap ya Kiotomatiki\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moja kwa moja\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Product sold as an auction\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kuhusu inapaswa kuwa chini ya \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" herufi\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hamisha\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badilisha yote\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Browser\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sati\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ankara / Anwani ya umeme\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tafuta vidokezo\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watoa Taarifa\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onyesha bendera kwenye kurasa za wasifu\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction to a website\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kote Duniani\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tafsiri hadi \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Curation sets\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reli Maalum\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jina la mtumiaji linapatikana\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Funguo\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anwani ya Mchango wa On-chain\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nunua\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sorry, we dont understand this event kind (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), please try one of the following apps instead!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ongeza Akaunti\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Classified Listings\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Response\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Authentication of clients to relays\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onyesha taarifa za hali kwenye kurasa za wasifu\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watu Wanaofanya Vizuri\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"User groups\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maelekezio ya HTTP yanarudishiwa kwa anwani ya lightning iliyotolewa\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dai sasa\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hitilafu imetokea!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"anafuata\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accounts\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"You dont have any media servers, try adding some.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ondoa\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chagua Pochi\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imejiunga na Push\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chumvi\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supported NIPs\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamisho (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anwani ya Umeme\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dai anwani yako ya Nostr iliyoundwa\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kiungo cha Magneti\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anwani isiyo halali ya Lightning\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tukio la Tangaza\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ufunguo wa Hex..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dealing with Unknown Events\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toka nje\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Habari za Kiongozi\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark list\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Agizo limelipwa!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jina\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"jina litapatikana baadae\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imenyamazishwa\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Futa akiba na upakie upya\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fungua Pochi\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Humfuati mtu huyu, bofya hapa ili kupakia midia kutoka \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", au usasishe \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"mapendeleo yako\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ili kupakia kila mara midia kutoka kwa kila mtu.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay reviews\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Support\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expiration Timestamp\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create or update a stall\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chapisho la mwisho \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je, una uhakika unataka kubandua kidokezo hiki?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data ya Akaunti\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anafuata\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lazima uwe mnunuzi wa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ili ufikie kisanduku cha \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap kila \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ameketi\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tafsiri Kiotomatiki\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Last Seen:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imetumwa sats \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" kwa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Haifuatwi na mtu yeyote unayemfuata\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bofya hapa ili kupakia hata hivyo\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vidokezo vinavyovuma\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usajili\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Arifa Haziruhusiwi\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tumia koma kutenganisha maneno k.m. neno1, neno2, neno3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji sets\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jina la mtumiaji\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tuma sats kwa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Michezo\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hakuna anwani ya umeme\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jiunge na \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" kwa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" na upokee tuzo zifuatazo\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposti\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search relays list\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tafuta watumiaji\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tovuti\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays are servers you connect to for sending and receiving events. Aim for 4-8 relays.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ufunguo wa Kibinafsi\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Average Latency:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Futa\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onyesha\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"External Content IDs\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingiza usanidi wa LNDHub\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Highlights\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Chat Message\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imefutwa\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Protected Events\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aina ya tukio lisilojulikana: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mapping Nostr keys to DNS-based internet identifiers\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weka Pini\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Request\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je, unaona kama mtumiaji?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Goals\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Angalia msimbo \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pini fupi sana\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Asiyejulikana\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toa maoni\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jina lazima liwe kati ya vibambo 8 na 15\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Haiwezi kuthibitisha Anwani ya Nostr\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fungua kwenye Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrents\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" wengine walizap\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps kwenye taarifa hii zitagawanywa kwa watumiaji wafuatao.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Menyu ya Utatuzi\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kuwa kiongozi\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onyesha 'Nakili Kitambulisho' na 'Nakili JSON' kwenye menyu ya muktadha kwa kila ujumbe\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Haipatikani:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Join Room\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nenosiri la Pochi\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ukurasa Chaguomsingi\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Short Text Note\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Client Authentication\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wekeza kama Anwani Kuu ya Nostr (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy Tags\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tuma kiungo hiki kwa marafiki wako na uishiriki uchawi wa nostr.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lipia usajili\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nunua anwani ya nostr\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Counting results\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unanunua \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Akaunti ya Iris.to\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thibitisha\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Arifa\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tayari una aina hii ya usajili, tafadhali sasisha au lipa\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Job Feedback\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Haiwezi kupiga kura na \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, tafadhali weka kiwango kingine cha default cha zap\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ukurasa Mpya wa Watumiaji\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dead\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tumia msimbo wako wa mwaliko kupata sats!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps Attestations for Events\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gift Wrap\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shiriki\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hitilafu isiyojulikana ya kuingia\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pata anwani ya nostr bure\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usajili wako bado unaendelea, bado huwezi kusasisha\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imeundwa\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Merge Requests\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imeshindwa kusasisha, tafadhali jaribu tena\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Long-form Content\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inachanganua \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anwani Isiyofaa ya Nostr\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nakili Tukio JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mfumo (Chaguo-msingi)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jumla ya leo (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distance\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mapendeleo\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inapokea kwa \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kijajuu cha faili kisichojulikana: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mandhari\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maoni yataonyeshwa kwenye kila ukurasa, ikiwa imezimwa hakuna maoni yataonyeshwa\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ufunguo wa faragha ni kama nenosiri, lakini hauwezi kuwekwa upya. Ilinde kwa uangalifu na usiwahi kuionyesha kwa mtu yeyote. Mtu akishapata ufunguo wako wa faragha, ataweza kufikia akaunti yako milele.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool hufanya kazi tu ikiwa unatumia mojawapo ya miunganisho ya pochi inayotumika (WebLN, LNC, LNDHub au Nostr Wallet Connect)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Message\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kwa sasa una viti \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" kwenye zap pool yako.\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Direct Messages\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watu unaowafuata\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker Haujatekelezwa\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repository state announcements\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jina la mtumiaji linapaswa kuwa na herufi ndogo na nambari pekee\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muda wake umeisha\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Short-form Portrait Video Event\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Na: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je, una uhakika unataka kufuta \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Vending Machines\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamisho\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading note: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permissions\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingiza pin kuweka funguo yako binafsi, unapaswa kuingiza pin hii kila wakati unapofungua \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tuma zap kwa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sasisha Anwani ya Umeme\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nunua Usajili\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular relays used by people you follow.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wakala wa Anwani ya LN\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay sets\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Problem Tracker\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weka alama kuwa zote zimesomwa\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Desturi\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Utaitwa nini?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lipa Sasa\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Application-specific Data\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mwandishi ametaja madokezo haya kama \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"mada nyeti\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays close to your geographic location.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maudhui katika madokezo yataonyeshwa kiotomatiki kwa watu waliochaguliwa, vinginevyo kiungo pekee ndicho kitakachoonyeshwa\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handler information\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onesha Mapema\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use Local Relay\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imemalizika\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingia kwa Upanuzi wa Nostr\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jifunze zaidi\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crypto\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interest sets\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar Events\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex chumvi..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watu\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"alipenda\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acha kusikiliza\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Definition\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ondoa kwenye relays yangu\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pokea\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Angalia saini zote za tukio zilizopokelewa kutoka kwenye relays\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gumzo Mpya\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watumiaji lazima wakubali onyo la maudhui ili kuonyesha maudhui ya dokezo lako.\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Server\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingia\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zuia\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maombi yako yanangojea\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Una akaunti ya iris.to iliyopo\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share a personalized invitation with friends!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Msimbo wako wa rufaa ni \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Labeling\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chagua huduma ya kupakia viambatisho\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ufunguo wa umma (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ndio tafadhali\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ili kuona orodha kamili ya mabadiliko, unaweza kuangalia mabadiliko \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"hapa\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" zimefanywa kimya\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Picha\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inaonekana huna usajili wowote, unaweza kupata moja \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zimezuiliwa\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Local\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rudisha sauti\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"From Server\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Issues\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tafsiri moja kwa moja madokezo kwa lugha yako ya asili\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / anwani ya Nostr\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingia kwa ufunguo\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemoniki\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tuma takwimu za matumizi\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wapangaji wa Faili\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uunganisho wa mkoba wa Alby\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afya za Ufuatiliaji\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Komboa\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vishazi Vya Kupanda\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Miitikio\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inatuma kutoka \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kiasi chako chaguo-msingi cha zap ni \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, thamani zilizopo zinakadiriwa kutoka hapo.\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL ya Huduma\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular media servers.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont follow enough people, take a look at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to discover people to follow!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hakuna ufunguo, hakuna \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", Hakuna njia ya kuzirejesha ikiwa haujafanya nakala rudufu. Inachukua dakika tu.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Chat\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Washa Mijibu\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unganisha pochi ili kutuma malipo ya papo hapo\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Try another relay\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Metadata\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weka maneno ya kuoanisha\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delegated Event Signing\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compose a note\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Washa Sasa\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wachangiaji\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tuma mgawanyo wa zap kwa\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jina la mtumiaji iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" limetengwa kwa ajili yako!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encrypted Direct Messages\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" amekualika kwenye \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media servers store media which you can share in notes as images and videos\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watengenezaji wa mfuko na mifumo inayotoa huduma za uthibitishaji wa NIP-05\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vidokezo vitatiririka kwa wakati halisi kwenye kichupo cha kimataifa cha madokezo\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jina au kifupisho\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vifaa Vinavyoungwa mkono\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imelipwa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, ada \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unganisha kwa nodi yako ya LND na Uunganisho wa Njia ya Umeme\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onyesha Zaidi\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite Friends\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemoniki\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nchi yako itafanya kama anwani ya umeme na itaelekeza kwenye LNURL uliyochagua au anwani ya Umeme\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wewe ni kiongozi wa jamii na unapata \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ya michango ya watumiaji waliotajwa!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mhudumu wa Huduma Unafanya Kazi\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hesabu Orodha ya Kupogoa\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pata Anwani\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Umeingia kwa upatikanaji wa kusoma tu\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maudhui Yanayofunuliwa\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ufunguo wa Umma\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hajulikani\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sasa Hivi\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kind mute sets\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hapana asante\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirects\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ikiwa una swali kuhusu agizo lako la NIP-05 tafadhali DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tangaza Tena\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je, unatumia Alby? Nenda kwenye \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" kupata usanidi wako wa NWC!\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muunganisho wa mkoba wa asili wa nostr\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ufotografia\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Direct Message\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ninafuata\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media Servers\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Funga Mijibu Yote\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unganisha Pochi\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Msaada wa Akaunti Nyingi\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jina limehifadhiwa\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Activities\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Rudi\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Orodha za kufuta sauti:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"WoT Filter\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hajajiandikisha kwa Piga\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anwani ya LN\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ufunguo wa umma ni kama jina lako la mtumiaji, unaweza kuushiriki na mtu yeyote.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jina la kuonyesha\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modular Article Header\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Hashtags\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jisajili\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kiasi katika sati\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Classified Listing\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mgawo wa default wa Zap Pool wa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" umewekwa kwa watengenezaji wa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", unaweza kuzima wakati wowote kwenye \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Aina\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inakuja hivi karibuni\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingiza pin kufuli funguo yako binafsi\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weka Alama Yote Yamesomwa\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tumia kiendelezi cha kusaini Nostr kuingia\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji ya majibu\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pata Kuthibitishwa\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap moja ya \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats itatenga \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats kwenye bwawa la zap.\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Feed\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mazungumzo ya Kikundi\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"window.nostr capability for web browsers\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" mwingine\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" wengine\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nyumbani\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poor\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Viongozi wa jamii ni watu binafsi wanaoendeleza mfumo wa nostr kwa kuwa na shughuli katika jamii zao za kienyeji na kusaidia kuwajumuisha watumiaji wapya. Kila mtu anaweza kuwa kiongozi wa jamii, lakini wachache wanashikilia cheo cha heshima cha sasa.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tupa\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Asante kwa kutumia \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", tafadhali fikiria kuchangia ikiwa unaweza.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort ni mradi wa chanzo huria uliojengwa na watu wenye shauku katika wakati wao wa bure, michango yako inathaminiwa sana\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Haiwezi kupiga kura kwa sababu huduma ya LNURL haitumii zaps\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onyesha machapisho yenye lebo ya onyo la yaliyomo\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imebandikwa\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chagua mada kadhaa za kuvutia\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Soma\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vifurushi vya Zawadi\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unafikiria nini?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Michango kwenye Mnyororo\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imehifadhiwa\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Attach Media\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tazama Tiririsha\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kuhusu\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Haiwezi kutuma kura\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji za kutuma unapojibu ujumbe kwa dokezo\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sio wateja wote wanaounga mkono hii bado\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jisajili\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" katika kumbukumbu)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inapakia...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Android Signer Application\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lists\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"User server list\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ushahidi wa Kazi\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Basic protocol flow description\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ina furaha zaidi pamoja!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beji\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"User Metadata\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pogoa Orodha ya Ufuatao\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sawazisha Akaunti\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ujumbe\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inasaidia\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onyesha majibu\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"hapa\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked relays list\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interaction\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Malipo uliyotuma na kupokea yataonekana hapa.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Maoni (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tafsiri za DeepL\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Afya ya Kufuatilia Ufuatao (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Admin\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" inafuata (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" nakala)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mpini\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Haiwezi kuingia kwa kutumia ufunguo wa faragha kwenye muunganisho usio salama, tafadhali tumia kiendelezi cha kidhibiti cha ufunguo wa Nostr badala yake\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Malipo\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"new users page\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fuata\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat Threaded Reply\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tengeneza ankara\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wasifu\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Acha kufuata\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tayari umefanya nakala rudufu\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usajili wako wa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" umekwisha\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Safisha chakula chako\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hitilafu ya ndani: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video Event\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hifadhi\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Maoni\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tumia Sasa\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Andika\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Huduma yetu wenyewe ya uthibitishaji wa NIP-05, inasaidia kusaidia uundaji wa tovuti hii na kupata beji maalum inayong'aa kwenye tovuti yetu!\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays which you have connected to before and appear to be reliable.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jisajili jina la mtumiaji wa Iris\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" alireposted\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" na wengine wkarepost\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Info\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidal login\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"sasa hivi\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mada\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Post Approval\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sanidi bwawa la zap\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" amependa\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" na wengine wamependa\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kila kitu katika \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Waalika marafiki zako\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Basic key derivation from mnemonic seed phrase\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nunua Sasa hivi\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lipa\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Matukio yangu: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anwani ya nostr ya Snort\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nenosiri la Wallet\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy link\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Isiyo ya Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"ukurasa wa akaunti\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Huduma ya wakala wa picha\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unafuata \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bofya ili kupakia maudhui kutoka kwa \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lipa ankara\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Request\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handler recommendation\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes have been muted\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inaonekana huna, angalia \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ili kununua!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Worker Relay\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fuata wote\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Huduma ya kupakia faili\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"one\": {\n          \"value\": []\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anza\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chaguo: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read Only\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badili\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Time-Based Calendar Event\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bid confirmation\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ondoa kizuizi\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alamisho\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ruhusu Arifa\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inatafuta shughuli za akaunti (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coinjoin Pool\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vyombo\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upya\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sikiliza makala hii\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" imezuiliwa\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sitaha\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"wafuasi \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hakuna kilichopatikana:/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Inafuata pekee\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hujambo, inaonekana kama bado huna Anwani ya Nostr, unapaswa kuipata! Angalia \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge Award\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pakia\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" wana relay (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reliable Relays\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hifadhi rudufu zinazoweza kupakuliwa kutoka kwa relay ya Snort\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Emoji\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Mute User\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bandika\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (for resilient marketplaces)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wafuasi\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent Comment\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Date-Based Calendar Event\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Thread Reply\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Barua pepe <> Daraja la DM kwa anwani yako ya nostr ya Snort\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hitilafu isiyojulikana\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Badges\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Taarifa\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chaguo-msingi cha Zap\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imezuiwa\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fungua\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jiandikishie upya \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"API za Arifa zimelemazwa\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ufunguo wako wa Faragha Ni (usishiriki hii na mtu yeyote)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hii taarifa imezimwa\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ongeza kwa Wasifu\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tafsiri imeshindwa\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Penda\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onyesha kidogo\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sayansi\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin isiyo sahihi\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Programu\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ingiza nenosiri la pochi\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay List Metadata\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public chats list\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hifadhi nakala sasa\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Zaps\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ongeza Relay\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reporting\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Chaguo-msingi)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encrypted Direct Message\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 0,\n      \"value\": \"siku \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vituo vya Gumzo la Umma\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kiungo fupi\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark sets\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onyesha Vialamisho\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"mtumiaji\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imeshindwa kuchambua mgawanyo wa zap: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"The relay name shown is not the same as the full URL entered.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Event Deletion Request\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vidokezo vilivyonyamazishwa havitaonyeshwa\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connection Success:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interests list\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Release artifact sets\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video Events\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Giza\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Versioned Encryption\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video View Event\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Free\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tuma dokezo kwa kikundi kidogo cha relay zako za uandishi\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kuthibitishwa kwa NIP-05 kunaweza kusaidia:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sati\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Takwimu za Relay\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Beji ya Msaidizi\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Status\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imelipwa\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin list\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uptime\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Jina lazima liwe chini ya wahusika \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Je, tayari una akaunti?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"External Identities in Profiles\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay list to receive DMs\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Machapisho mapya yanahitaji kuthibitishwa mwenyewe\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tuma sats zilizogawanywa kwa\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imepata matukio \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Umma\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" taarifa\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badilisha Wasifu\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anzisha gumzo\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lazima iwe orodha ya mawasiliano au orodha ya pubkey\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Communities list\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pata ya bure\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zana hii itatafuta tukio la mwisho lililochapishwa na wafuatiliaji wako wote na kuondoa wale ambao hawajachapisha kwa miezi 6\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 ni uthibitishaji wa msingi wa DNS ambao husaidia kukuthibitisha kama mtumiaji halisi.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chaguo za Kura\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pata ya bure\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imefuatiliwa na marafiki\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kiasi cha kazi ya kuomba kwa matukio yote yaliyochapishwa\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Biashara\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hariri\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"File storage server list\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tuma\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media Attachments\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Gumzo la Umma\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"jina limezuiwa\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Patches\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usimamizi\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pata maelezo zaidi kuhusu \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" kwenye \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nakili ID\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"My Relays\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fundisha huduma unazotumia kwa kugawanya sehemu ya zap zako zote kwenye kundi la fedha!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nyamazisha\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kwa ajili yako\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kura za \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nenda kwa\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: URI scheme\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mtoa huduma\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pakia midia kiotomatiki\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muda wake unaisha\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Vigezo vingine:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tafuta\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"SHABIKI\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ruhusu\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lugha\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSatI\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL au Anwani ya Umeme\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Relays\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Native App\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Draft Long-form Content\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uzito\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wasiliana\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mmiliki\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Yote\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kiasi cha Zap katika seti\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chess (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" dakika kusoma\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Imeshindwa kupakia huduma ya LNURL\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Onyesha taarifa mpya kiotomatiki\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Participants\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/ta_IN.json",
    "content": "{\n  \"+D82kt\": \"நீங்கள் உறுதியாக மறுபதிவு செய்ய விரும்புகிறீர்களா: {id}\",\n  \"+PzQ9Y\": \"தொகையைச் செலுத்துக\",\n  \"+QM0PJ\": \"Sync all events for your profile into local cache\",\n  \"+QMdsy\": \"Relay Stats\",\n  \"+UjDmN\": \"Logged in with write access\",\n  \"+Vxixo\": \"ரகசிய குழு அரட்டை\",\n  \"+aZY2h\": \"ஜாப் வகை\",\n  \"+tShPg\": \"பின்தொடரப் படுவோர்\",\n  \"+vA//S\": \"உள்நுழைவுகள்\",\n  \"+vIQlC\": \"பிற்காலத்தில் உங்களது கணக்கை நிர்வகிக்க, கீழே உள்ள கடவுச்சொல்லைத் தவறாமல் சேமிக்கவும்\",\n  \"+vVZ/G\": \"இணை\",\n  \"+vj0U3\": \"தொகு\",\n  \"+xliwN\": \"{name} மறுபதிவு செய்தார்\",\n  \"/B8zwF\": \"நீங்கள் விரும்பியபடி உங்கள் இடம் 😌\",\n  \"/GCoTA\": \"அழி\",\n  \"/JE/X+\": \"கணக்கு உதவி\",\n  \"/T7HId\": \"HTTP File Storage Integration\",\n  \"/Xf4UW\": \"அடையாளம் காட்டாமல் பயன்பாட்டு புள்ளிவிவரங்களை அனுப்புக\",\n  \"/b1IHW\": \"Group Chat Message\",\n  \"/d6vEc\": \"உங்கள் சுயவிவரத்தை கண்டறிவதையும் பகிர்வதையும் எளிதாக்குங்கள்\",\n  \"/ioUrF\": \"From File\",\n  \"/n5KSF\": \"{n} மில்லி வினாடிகள்\",\n  \"00LcfG\": \"மேலும் காண்க\",\n  \"01iNut\": \"Nostr address does not belong to you\",\n  \"08zn6O\": \"Export Keys\",\n  \"0Azlrb\": \"நிர்வகி\",\n  \"0BUTMv\": \"தேடு...\",\n  \"0MndVW\": \"Generic LNDHub wallet (BTCPayServer / Alby / LNBits)\",\n  \"0jOEtS\": \"தவறான LNURL\",\n  \"0kOBMu\": \"Handling Mentions\",\n  \"0mch2Y\": \"பெயர் அங்கீகரிக்கப்படாத எழுத்துக்களைக் கொண்டுள்ளது\",\n  \"0siT4z\": \"அரசியல்\",\n  \"0uoY11\": \"சமுதாய நிலையைக் காட்டு\",\n  \"0yO7wF\": \"{n} வினாடிகள்\",\n  \"0zASjL\": \"Go\",\n  \"1/BFEj\": \"git stuff\",\n  \"1Mo59U\": \"இந்தக் குறிப்பைப் புக்மார்க்குகளிலிருந்து அகற்ற நிச்சயமாக விரும்புகிறீர்களா?\",\n  \"1R43+L\": \"நாஸ்டர் பணப்பை இணைப்புக் கட்டமைப்பை உள்ளிடவும்\",\n  \"1UWegE\": \"Be sure to back up your keys!\",\n  \"1c4YST\": \"{node} உடன் இணைக்கப் பட்டது 🎉\",\n  \"1nYUGC\": \"{n} பின்தொடரப் படுவோர்\",\n  \"1o2BgB\": \"கையெழுத்துக்களை சரிபார்\",\n  \"1ozeyg\": \"இயற்கை\",\n  \"1udzha\": \"உரையாடல்கள்\",\n  \"2/2yg+\": \"சேர்\",\n  \"25V4l1\": \"பதாகை\",\n  \"25WwxF\": \"கணக்கு இல்லையா?\",\n  \"28oKbu\": \"Moderated Communities\",\n  \"29sHFE\": \"Wallet Connect\",\n  \"2BBGxX\": \"Subject tag in text events\",\n  \"2HIqeO\": \"User emoji list\",\n  \"2IFGap\": \"நன்கொடை அளிக்க\",\n  \"2LbrkB\": \"கடவுச்சொல்லை உள்ளிடுக\",\n  \"2O2sfp\": \"முடிக்க\",\n  \"2Qsf9/\": \"Generic lists\",\n  \"2a2YiP\": \"{n} புத்தகக் குறிகள்\",\n  \"2k0Cv+\": \"விருப்பமின்மைகள் ({n})\",\n  \"2mcwT8\": \"New Note\",\n  \"2oCF7O\": \"Followed by friends of friends\",\n  \"2raFAu\": \"Application-specific data\",\n  \"2ukA4d\": \"{n} மணித்துளிகள்\",\n  \"2z7Kky\": \"Latest Articles\",\n  \"3/onCd\": \"Replies\",\n  \"39AHJm\": \"பதிவு செய்\",\n  \"3GWu6/\": \"User Statuses\",\n  \"3KNMbJ\": \"கட்டுரைகள்\",\n  \"3MKdAw\": \"Blobs stored on mediaservers\",\n  \"3QwfJR\": \"~{amount}\",\n  \"3adEeb\": \"{n} viewers\",\n  \"3cc4Ct\": \"ஒளி\",\n  \"3gOsZq\": \"மொழிபெயர்ப்பாளர்கள்\",\n  \"3kbIhS\": \"Untitled\",\n  \"3qnJlS\": \"{amount} சேட்களைக் கொண்டு நீங்கள் வாக்களிக்கிறீர்கள்\",\n  \"3t3kok\": \"{n,plural,=1{{n} புதிய குறிப்பு} other{{n} புதிய குறிப்புகள்}}\",\n  \"3tVy+Z\": \"{n} பின்தொடர்வோர்\",\n  \"3yk8fB\": \"Wallet\",\n  \"40VR6s\": \"Nostr Connect\",\n  \"41BSaT\": \"Total Events:\",\n  \"450Fty\": \"எதுவுமில்லை\",\n  \"47E53q\": \"Wiki\",\n  \"47FYwb\": \"ரத்துசெய்\",\n  \"48zn4v\": \"Bid\",\n  \"4IPzdn\": \"முதன்மை உருவாக்கி\",\n  \"4L2vUY\": \"உங்களது புதிய NIP-05 கணக்கு:\",\n  \"4MjsHk\": \"வாழ்க்கை\",\n  \"4OB335\": \"விருப்பமில்லை\",\n  \"4P/kKm\": \"Private Key Encryption\",\n  \"4Vmpt4\": \"Nostr Plebs முதல் NIP-05 வழங்குநர்களில் ஒன்றாகும். மேலும், இது நியாயமான விலையில் டொமைன்களின் நல்ல தொகுப்பை வழங்குகிறது\",\n  \"4Z3t5i\": \"படங்களை சுருக்க imgproxy உபயோகிக்கவும்\",\n  \"4emo2p\": \"Missing Relays\",\n  \"4rYCjn\": \"சுய குறிப்பு\",\n  \"4wgYpI\": \"Recommended Application Handlers\",\n  \"5BVs2e\": \"ஜாப்\",\n  \"5CB6zB\": \"ஜாப் பிரிப்புகள்\",\n  \"5PRWs7\": \"Notifications API Enabled\",\n  \"5dfmvv\": \"Zap Goal\",\n  \"5oTnfy\": \"பயனர் பெயரை வாங்கவும்\",\n  \"5qEWCr\": \"File Metadata\",\n  \"5u6iEc\": \"பொது சாவிக்கு பரிமாற்றவும்\",\n  \"5vMmmR\": \"நாஸ்டரில் உள்ள பயனர்பெயர்கள் உங்களுக்கு மட்டுமேயான தனிப்பட்ட பயனர்பெயர் கிடையாது. நாஸ்டர் முகவரி மட்டுமே மனிதர்களால் வாசிக்க இயலும் தனிப்பட்ட முகவரி ஆகும். அந்த முகவரி நீங்கள் நாஸ்டரில் பதிவு செய்யும்போது உங்களுக்கு வழங்கப்படும்.\",\n  \"5ykRmX\": \"ஜாப் அனுப்பு\",\n  \"6/hB3S\": \"மறு ஓட்டத்தைப் பார்க்கவும்\",\n  \"60kEE3\": \"Mute list\",\n  \"62nsdy\": \"மீண்டும் முயற்சிக்கவும்\",\n  \"634VVz\": \"Connection Failed:\",\n  \"6559gb\": \"New follow list length {length}\",\n  \"65BmHb\": \"{host} இல் இருந்து படத்தைப் பதிலி செய்ய முடியவில்லை, நேரடியாகப் பெற இங்கு கிளிக் செய்யவும்\",\n  \"6D4Hhn\": \"Recommend Relay\",\n  \"6KGebm\": \"Seal\",\n  \"6OSOXl\": \"காரணம்: <i>{reason}</i>\",\n  \"6WWD34\": \"Looking for: {noteId}\",\n  \"6bgpn+\": \"எல்லா நாஸ்டர் மென்பொருட்களும் இதை இன்னும் ஆதரிக்கவில்லை, ஜாப் பிரிப்புகள் கட்டமைக்காததைப் போல நீங்கள் சில ஜாப்களை பெற வாய்ப்பு உள்ளது\",\n  \"6ewQqw\": \"விருப்பங்கள் ({n})\",\n  \"6mr8WU\": \"Followed by\",\n  \"6pdxsi\": \"Extra metadata fields and tags\",\n  \"6uMqL1\": \"கட்டணம் செலுத்தப்படாத\",\n  \"6xNr8c\": \"Switch accounts\",\n  \"6xap9L\": \"Good\",\n  \"7+Domh\": \"குறிப்புகள்\",\n  \"712i26\": \"Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node\",\n  \"753yX5\": \"Label\",\n  \"769A8p\": \"Wiki article\",\n  \"77nkEO\": \"Relay Information Document\",\n  \"7LFU8U\": \"Search Capability\",\n  \"7UOvbT\": \"அகல்நிலை\",\n  \"7YkSA2\": \"Community Leader\",\n  \"7gMmSL\": \"Reaction\",\n  \"7hp70g\": \"NIP-05\",\n  \"7jfPsW\": \"Modular Article Content\",\n  \"7nAz/z\": \"Mute notes from people who are outside your web of trust\",\n  \"7pFGAQ\": \"Close Relays\",\n  \"8/vBbP\": \"மறுபதிவுகள் ({n})\",\n  \"89q5wc\": \"மறுப்பதிவுகளை உறுதி செய்யவும்\",\n  \"8BDFvJ\": \"Conventions for clients' use of e and p tags in text events\",\n  \"8ED/4u\": \"இவருக்கு பதிலளி\",\n  \"8HJxXG\": \"Sign up\",\n  \"8QDesP\": \"{n} ஸாட்கள் ஜாப் செய்\",\n  \"8Rkoyb\": \"பெறுநர்\",\n  \"8Y6bZQ\": \"தவறான zap பிளவு: {input}\",\n  \"8ZGqWl\": \"Group Thread\",\n  \"8g2vyB\": \"பெயர் மிக நீளமாக உள்ளது\",\n  \"8jmwT8\": \"bech32-encoded entities\",\n  \"8v1NN+\": \"ஜோடிக்கும் சொற்றொடர்\",\n  \"8xdDLn\": \"Follow sets\",\n  \"8za9Pq\": \"Draft Classified Listing\",\n  \"9+Ddtu\": \"அடுத்து\",\n  \"9HU8vw\": \"பதில்\",\n  \"9SvQep\": \"பின்தொடர்வுகள் {n}\",\n  \"9V0wg3\": \"Calendar Event RSVP\",\n  \"9WRlF4\": \"அனுப்பு\",\n  \"9kO0VQ\": \"Hide muted notes\",\n  \"9kSari\": \"வெளியிட மீண்டும் முயற்சிக்கவும்\",\n  \"9pMqYs\": \"நாஸ்டர் முகவரி\",\n  \"9wO4wJ\": \"லைட்னிங் விலைப்பட்டியல்\",\n  \"A86fJ+\": \"Generic Repost\",\n  \"ADmfQT\": \"பெற்றோர்\",\n  \"ALdW69\": \"Note by {name}\",\n  \"AN0Z7Q\": \"முடக்கப்பட்ட வார்த்தைகள்\",\n  \"ASRK0S\": \"இந்தப் பதிவாளர் முடக்கப் பட்டுள்ளார்\",\n  \"AedFVZ\": \"Create or update a product\",\n  \"Ai8VHU\": \"ஸ்நார்ட் ரிலேயில் வரம்பற்ற குறிப்புகளை வைத்திரு\",\n  \"AkCxS/\": \"காரணம்\",\n  \"AktAk2\": \"Great\",\n  \"Am8glJ\": \"விளையாட்டு\",\n  \"AqGfF4\": \"Channel Creation\",\n  \"Aujn2T\": \"Count\",\n  \"Awq32I\": \"Push notifications\",\n  \"AxDOiG\": \"மாதங்கள்\",\n  \"AyGauy\": \"உள்நுழை\",\n  \"B4C47Y\": \"பெயர் மிகச் சிறியதாக உள்ளது\",\n  \"B6+XJy\": \"ஜாப் செய்தார்\",\n  \"B6H7eJ\": \"nsec, npub, nip-05, hex\",\n  \"B7wvUM\": \"You can add a single or multiple relays, one per line.\",\n  \"BGCM48\": \"1 வருட நிகழ்வு தக்கவைப்புடன், ஸ்நார்ட் ரிலேக்கான எழுதும் உரிமை\",\n  \"BGGacK\": \"AI Embeddings / Vector lists\",\n  \"BQW4gi\": \"Relay-based Groups\",\n  \"BWpuKl\": \"புதுப்பி\",\n  \"BfuAQ5\": \"Marketplace UI/UX\",\n  \"BjNwZW\": \"நாஸ்டர் முகவரி (nip05)\",\n  \"Blxcdx\": \"Relay\",\n  \"Bo+O//\": \"HTTP Auth\",\n  \"C1LjMx\": \"லைட்னிங் நன்கொடை\",\n  \"C6Lhhp\": \"Live Event\",\n  \"C7642/\": \"மேற்கோள் மறுபதிவு\",\n  \"C81/uG\": \"வெளியேறு\",\n  \"C8FsOr\": \"Popular Servers\",\n  \"C8HhVE\": \"பரிந்துரைக்கப்படும் பயனர்கள்\",\n  \"CA1efg\": \"Video sets\",\n  \"CHTbO3\": \"விலைப்பட்டியலை பெற முடியவில்லை\",\n  \"CJx5Nd\": \"Profile Zaps\",\n  \"CM+Cfj\": \"Follow List\",\n  \"CM0k0d\": \"Prune follow list\",\n  \"CVWeJ6\": \"டிரெண்டிங் நபர்கள்\",\n  \"CYkOCI\": \"and {count} others you follow\",\n  \"Cdxwi0\": \"Repository announcements\",\n  \"CmZ9ls\": \"{n} ஒலியடக்கப்பட்டவை\",\n  \"Coy6SH\": \"Calendar\",\n  \"CsCUYo\": \"{n} சாட்ஸ்\",\n  \"Cu/K85\": \"{lang} இல் இருந்து மொழிபெயர்க்கப் பட்டது\",\n  \"CzHZoc\": \"சமூக வரைபடம்\",\n  \"D++Njw\": \"Text Note References\",\n  \"D+KzKd\": \"கிடைக்கும் ஒவ்வொரு குறிப்புகளையும் தானாக ஜாப் செய்யவும்\",\n  \"D09wbg\": \"Badge Definition\",\n  \"D3idYv\": \"அமைப்புகள்\",\n  \"D9xTLE\": \"Channel Hide Message\",\n  \"DBiVK1\": \"தேக்ககம்\",\n  \"DKnriN\": \"ஸாட்கள் அனுப்பு\",\n  \"DZzCem\": \"சமீபத்திய {n} குறிப்புகளைக் காட்டு\",\n  \"Dh3hbq\": \"தானாக ஜாப்\",\n  \"Dn82AL\": \"நேரலை\",\n  \"DqUmXt\": \"Product sold as an auction\",\n  \"DrZqav\": \"About must be less than {limit} characters\",\n  \"DtYelJ\": \"பரிமாற்றம்\",\n  \"Dx4ey3\": \"அனைத்தையும் நிலைமாற்று\",\n  \"E3oB+t\": \"Browser\",\n  \"E5ZIPD\": \"<big>{amount}</big> <small>sats</small>\",\n  \"EHqHsu\": \"Invoice / Lightning Address\",\n  \"EJbFi7\": \"குறிப்புகளைத் தேடு\",\n  \"ELbg9p\": \"தரவு வழங்குநர்\",\n  \"EQKRE4\": \"சுயவிவரப் பக்கங்களில் பேட்ஜ்களைக் காட்டு\",\n  \"EWeVrH\": \"Reaction to a website\",\n  \"EWyQH5\": \"முழுதளாவிய\",\n  \"Ebl/B2\": \"{lang} இற்கு மொழிபெயர்க்கவும்\",\n  \"Ec+xLY\": \"Curation sets\",\n  \"EcZF24\": \"கஸ்டம் ரிலேஸ்\",\n  \"EcfIwB\": \"பயனர் பெயர் இருக்கிறது\",\n  \"EcglP9\": \"சாவி\",\n  \"EjFyoR\": \"ஆன்-செயின் நன்கொடை முகவரி\",\n  \"EnCOBJ\": \"வாங்கு\",\n  \"EsHX35\": \"Sorry, we dont understand this event kind ({name}), please try one of the following apps instead!\",\n  \"F/6VqP\": \"Server\",\n  \"F3l7xL\": \"கணக்கை சேர்\",\n  \"F4eJ/3\": \"Classified Listings\",\n  \"FDguSC\": \"{n} ஜாப்கள்\",\n  \"FHWpHC\": \"Wallet Response\",\n  \"FHvSk3\": \"Authentication of clients to relays\",\n  \"FMfjrl\": \"சுயவிவரப் பக்கங்களில் நிலை செய்திகளைக் காட்டு\",\n  \"FSYL8G\": \"பிரபலமான பயனர்கள்\",\n  \"FWJR1B\": \"User groups\",\n  \"FcNSft\": \"Redirect issues HTTP redirect to the supplied lightning address\",\n  \"FdhSU2\": \"இப்போது உரிமை கோரவும்\",\n  \"FfYsOb\": \"ஓரு பிழை நேர்ந்துவிட்டது!\",\n  \"FmXUJg\": \"உங்களைப் பின்தொடர்கிறார்\",\n  \"FvanT6\": \"Accounts\",\n  \"FzbSGg\": \"You dont have any media servers, try adding some.\",\n  \"G/yZLu\": \"நீக்கு\",\n  \"G1BGCg\": \"பணப்பை தேர்வு\",\n  \"G3A56c\": \"Subscribed to Push\",\n  \"GFOoEE\": \"உப்பு\",\n  \"GIqktu\": \"Supported NIPs\",\n  \"GL8aXW\": \"புக்மார்க்குகள் ({n})\",\n  \"GSye7T\": \"லைட்னிங் முகவரி\",\n  \"GUlSVG\": \"உங்கள் ஸ்நார்ட் நாஸ்டர் முகவரியைப் பெறவும்\",\n  \"Gcn9NQ\": \"மேக்னெட் இணைப்பு\",\n  \"GpkNYn\": \"Torrent\",\n  \"GqQeu/\": \"Invalid Lightning Address\",\n  \"GspYR7\": \"{n} விருப்பமின்மை\",\n  \"Gxcr08\": \"ஒளிபரப்பு நிகழ்வு\",\n  \"H+vHiz\": \"ஹெக்ஸ் சாவி..\",\n  \"H/oroO\": \"Dealing with Unknown Events\",\n  \"H0JBH6\": \"வெளியேறு\",\n  \"H0OG3T\": \"Leader Info\",\n  \"H1GTaC\": \"Bookmark list\",\n  \"H6/kLh\": \"ஆர்டர் செலுத்தப்பட்டது!\",\n  \"HAlOn1\": \"பெயர்\",\n  \"HFls6j\": \"பெயர் பின்னர் கிடைக்கப் பெறும்\",\n  \"HOzFdo\": \"ஒலியடக்கப்பட்டவை\",\n  \"HWbkEK\": \"தற்காலிக சேமிப்பை அழித்து மீண்டும் ஏற்றவும்\",\n  \"HbefNb\": \"திறந்த பணப்பை\",\n  \"HhcAVH\": \"நீங்கள் இவரைப் பின்தொடரவில்லை, மீடியாவை ஏற்ற இங்கே கிளிக் செய்யவும் <i>{link}</i>, அல்லது புதுப்பிக்கவும் <a><i>உங்கள் விருப்பங்களை</i></a> எல்லாரிடமிருந்தும் எப்போதும் மீடியாவை ஏற்றுவதற்கு.\",\n  \"HpAmQZ\": \"Relay reviews\",\n  \"HqRNN8\": \"Support\",\n  \"HzSFeV\": \"Expiration Timestamp\",\n  \"I0tYZf\": \"Create or update a stall\",\n  \"I1AoOu\": \"Last post {time}\",\n  \"IEwZvs\": \"இந்தக் குறிப்பின் நிலையான பொறுத்தத்தை நிச்சயமாக நீக்க விரும்புகிறீர்களா?\",\n  \"IIOul1\": \"Account Data\",\n  \"IKKHqV\": \"பின்தொடர்வுகள்\",\n  \"IOu4Xh\": \"You must be a {tier} subscriber to access {app} deck\",\n  \"IVbtTS\": \"{n} சாட்கள் ஜாப் செய்\",\n  \"IWz1ta\": \"தானியங்கு மொழிபெயர்ப்பு\",\n  \"IcHcWj\": \"Last Seen:\",\n  \"Ig9/a1\": \"{name} க்கு {n} சாட்ஸ் அனுப்பப்பட்டது\",\n  \"IgsWFG\": \"Not followed by anyone you follow\",\n  \"IoQq+a\": \"எப்படியும் ஏற்ற இங்கே கிளிக் செய்யவும்\",\n  \"IvjoDS\": \"Connected\",\n  \"Ix8l+B\": \"பிரபலமான குறிப்புகள்\",\n  \"J+dIsA\": \"சந்தாக்கள்\",\n  \"J1iLmb\": \"Notifications Not Allowed\",\n  \"J2HeQ+\": \"சொற்களைப் பிரிக்க காற்புள்ளிகளைப் பயன்படுத்தவும் எ.கா. சொல்1, சொல்2, சொல்3\",\n  \"J2Q92B\": \"Emoji sets\",\n  \"J6N9xl\": \"Sign in with Android signer\",\n  \"JCIgkj\": \"பயனர் பெயர்\",\n  \"JGrt9q\": \"{name} க்கு சாட்களை அனுப்பு\",\n  \"JHEHCk\": \"ஜாப்கள் ({n})\",\n  \"JIVWWA\": \"விளையாட்டு\",\n  \"JPFYIM\": \"லைட்னிங் முகவரி இல்லை\",\n  \"JSx7y9\": \"{price} க்கு {site_name} {plan} இல் குழுசேர்ந்து பின்வரும் வெகுமதிகளைப் பெறுங்கள்\",\n  \"JeoS4y\": \"மறுபதிவு\",\n  \"Jh5zKH\": \"Search relays list\",\n  \"JjGgXI\": \"பயனர்களைத் தேடுக\",\n  \"JkLHGw\": \"வலைத்தளம்\",\n  \"JmcxzF\": \"Relays are servers you connect to for sending and receiving events. Aim for 4-8 relays.\",\n  \"JymXbw\": \"தனிப்பட்ட சாவி\",\n  \"K1wl1/\": \"Average Latency:\",\n  \"K3r6DQ\": \"நீக்கு\",\n  \"K7AkdL\": \"காண்பி\",\n  \"K9zklU\": \"External Content IDs\",\n  \"KAhAcM\": \"LNDHub கட்டமைப்பை உள்ளிடவும்\",\n  \"KGmQjH\": \"Highlights\",\n  \"KJryGq\": \"Live Chat Message\",\n  \"KQvWvD\": \"நீக்கப்பட்டது\",\n  \"KT9nox\": \"Protected Events\",\n  \"KahimY\": \"அறிந்திராத நிகழ்வு வகை: {kind}\",\n  \"KipVeG\": \"Mapping Nostr keys to DNS-based internet identifiers\",\n  \"KtsyO0\": \"பின்னை உள்ளிடவும்\",\n  \"KyRp/q\": \"Wallet Request\",\n  \"LBAnc7\": \"View as user?\",\n  \"LEmxc8\": \"Zap Goals\",\n  \"LKw/ue\": \"Check out the code {link}\",\n  \"LR1XjT\": \"பின் மிகவும் சிறியது\",\n  \"LXxsbk\": \"பெயரிலா\",\n  \"LgbKvU\": \"கருத்து\",\n  \"LhLvRx\": \"Name must be between 8 and 15 characters\",\n  \"LmdPXO\": \"Cannot verify Nostr Address\",\n  \"Lu5/Bj\": \"Zapstr இல் திறக்கவும்\",\n  \"LuDBLj\": \"Torrents\",\n  \"Lw+I+J\": \"{n,plural,=0{{name} zapped} other{{{name} & {n} others zapped}}\",\n  \"LwYmVi\": \"இந்தக் குறிப்பில் உள்ள Zaps பின்வரும் பயனர்களுக்குப் பிரிக்கப்படும்.\",\n  \"M3Oirc\": \"மெனுக்களை பிழை திருத்தவும்\",\n  \"M6C/px\": \"Become a leader\",\n  \"MBAYRO\": \"ஒவ்வொரு செய்தியிலும் சூழல் மெனுவில் \\\"IDஐ நகலெடு\\\" மற்றும் \\\"நிகழ்வு JSONஐ நகலெடு\\\" ஆகியவற்றைக் காட்டுகிறது\",\n  \"MI2jkA\": \"கிடைக்கவில்லை:\",\n  \"MKDHEa\": \"Join Room\",\n  \"MP54GY\": \"பணப்பை கடவுச்சொல்\",\n  \"MWTx65\": \"இயல்புநிலை பக்கம்\",\n  \"MYBYdJ\": \"Short Text Note\",\n  \"MYUBaG\": \"Client Authentication\",\n  \"MiMipu\": \"முதன்மை Nostr முகவரியாக அமைக்கவும் (nip05)\",\n  \"MkQ4FX\": \"Proxy Tags\",\n  \"Ml7+RS\": \"Send this link to your friends and share the magic of the nostr.\",\n  \"Mrpkot\": \"சந்தாவுக்கு பணம் செலுத்துங்கள்\",\n  \"MuVeKe\": \"Buy nostr address\",\n  \"Muhna4\": \"Counting results\",\n  \"MzRYWH\": \"{item} வாங்கப் படுகிறது\",\n  \"Mzizei\": \"Iris.to account\",\n  \"N2IrpM\": \"உறுதிசெய்\",\n  \"NAidKb\": \"Notifications\",\n  \"NAuFNH\": \"உங்களிடம் ஏற்கனவே இந்த வகை சந்தா உள்ளது, புதுப்பிக்கவும் அல்லது பணம் செலுத்தவும்\",\n  \"NDTFsp\": \"Job Feedback\",\n  \"NepkXH\": \"{amount} ஸாட்களால் வாக்களிக்க இயலாது, தயவு செய்து வேறொரு இயல்புநிலை ஜாப் தொகையைத் தேர்வு செய்யவும்\",\n  \"NndBJE\": \"புதிய பயனர்கள் பக்கம்\",\n  \"Nr9Yyx\": \"Reposts\",\n  \"NxzeNU\": \"Dead\",\n  \"O3Jz4E\": \"Use your invite code to earn sats!\",\n  \"OEW7yJ\": \"ஜாப்கள்\",\n  \"OIqnZN\": \"OpenTimestamps Attestations for Events\",\n  \"OJHKIL\": \"Gift Wrap\",\n  \"OKhRC6\": \"பகிர்\",\n  \"OLEm6z\": \"அறியப்படாத உள்நுழைவு பிழை\",\n  \"OQSOJF\": \"Get a free nostr address\",\n  \"OQXnew\": \"உங்கள் சந்தா இன்னும் செயலில் உள்ளது, உங்களால் இன்னும் புதுப்பிக்க முடியாது\",\n  \"ORGv1Q\": \"உருவாக்கியது\",\n  \"ORa81+\": \"Merge Requests\",\n  \"OoZgbB\": \"Failed to update, please try again\",\n  \"OuProE\": \"Long-form Content\",\n  \"OxPdQ0\": \"Scanning {date}\",\n  \"P2o+ZZ\": \"Invalid Nostr Address\",\n  \"P61BTu\": \"நிகழ்வு JSONஐ நகலெடு\",\n  \"P7FD0F\": \"கணினி (இயல்புநிலை)\",\n  \"P7nJT9\": \"இன்றைய (UTC) மொத்தம்: {amount} சாட்கள்\",\n  \"P8JC58\": \"Distance\",\n  \"PCSt5T\": \"விருப்பங்கள்\",\n  \"PXQ0z0\": \"Receiving to <b>{wallet}</b>\",\n  \"PamNxw\": \"தெரியாத கோப்புத் தலைப்பு: {name}\",\n  \"Pe0ogR\": \"வண்ண அமைப்பு\",\n  \"PrsIg7\": \"ஒவ்வொரு பக்கத்திலும் எதிர்வினைகள் காண்பிக்கப்படும், முடக்கப்பட்டிருந்தால் எந்த எதிர்வினைகளும் காட்டப்படாது\",\n  \"QDFTjG\": \"{n} ரிலேகள்\",\n  \"QJfhKt\": \"The private key is like a password, but it cannot be reset. Guard it carefully and never show it to anyone. Once someone has your private key, they will have access to your account forever.\",\n  \"QWhotP\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\",\n  \"QpaLA3\": \"Channel Message\",\n  \"Qxv0B2\": \"You currently have {number} sats in your zap pool.\",\n  \"Qy6/Ft\": \"Private Direct Messages\",\n  \"R/6nsx\": \"Subscription\",\n  \"R81upa\": \"நீங்கள் பின்தொடர்வோர்\",\n  \"RDha9y\": \"Service Worker Not Running\",\n  \"RRz1cA\": \"Repository state announcements\",\n  \"RSr2uB\": \"Username must only contain lowercase letters and numbers\",\n  \"RahCRH\": \"காலாவதியாகிவிட்டது\",\n  \"RefZpK\": \"Short-form Portrait Video Event\",\n  \"RfhLwC\": \"எழுதியவர்: {author}\",\n  \"RhDAoS\": \"{id} ஐ நிச்சயமாக நீக்க விரும்புகிறீர்களா\",\n  \"RmxSZo\": \"Data Vending Machines\",\n  \"RoOyAh\": \"ரிலேகள்\",\n  \"Rs4kCE\": \"புக்மார்க்\",\n  \"S/NV2G\": \"Loading note: {id}\",\n  \"SFuk1v\": \"Permissions\",\n  \"SLZGPn\": \"Enter a pin to encrypt your private key, you must enter this pin every time you open {site}.\",\n  \"SMO+on\": \"Send zap to {name}\",\n  \"SOqbe9\": \"லைட்னிங் முகவரியை உள்ளிடவும்\",\n  \"SP0+yi\": \"Buy Subscription\",\n  \"SW3TFA\": \"Popular relays used by people you follow.\",\n  \"SYQtZ7\": \"LN முகவரி பதிலீடு\",\n  \"Sd0PKc\": \"Relay sets\",\n  \"SfwSIm\": \"Problem Tracker\",\n  \"ShdEie\": \"அனைத்தையும் படித்ததாகக் குறி\",\n  \"Sjo1P4\": \"தனிப்பயன்\",\n  \"SmuYUd\": \"What should we call you?\",\n  \"Ss0sWu\": \"தொகை செலுத்தவும்\",\n  \"SsUQnC\": \"Application-specific Data\",\n  \"StKzTE\": \"The author has marked this note as a <i>sensitive topic</i>\",\n  \"T83nqf\": \"Relays close to your geographic location.\",\n  \"TDR5ge\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\",\n  \"TGc5nI\": \"Handler information\",\n  \"TH1fFo\": \"Telegram\",\n  \"TJo5E6\": \"Preview\",\n  \"TOG64f\": \"Use Local Relay\",\n  \"TP/cMX\": \"Ended\",\n  \"TaeBqw\": \"Sign in with Nostr Extension\",\n  \"TdTXXf\": \"Learn more\",\n  \"TdtZQ5\": \"Crypto\",\n  \"Tdv6NY\": \"Interest sets\",\n  \"TgDKhI\": \"Calendar Events\",\n  \"TpgeGw\": \"Hex Salt..\",\n  \"Tpy00S\": \"People\",\n  \"TvKqBp\": \"liked\",\n  \"TwyMau\": \"Account\",\n  \"U1aPPi\": \"Stop listening\",\n  \"U30H69\": \"Community Definition\",\n  \"UJTWqI\": \"Remove from my relays\",\n  \"ULXFfP\": \"Receive\",\n  \"UNjfWJ\": \"Check all event signatures received from relays\",\n  \"UT7Nkj\": \"New Chat\",\n  \"UUPFlt\": \"உங்கள் குறிப்பின் உள்ளடக்கத்தைக் காட்ட, உள்ளடக்க எச்சரிக்கையைப் பயனர்கள் ஏற்க வேண்டும்.\",\n  \"UaCh1c\": \"Add Server\",\n  \"Ub+AGc\": \"Sign In\",\n  \"Up5U7K\": \"முடக்கு\",\n  \"Ups2/p\": \"Your application is pending\",\n  \"UrKTqQ\": \"You have an active iris.to account\",\n  \"UsCzPc\": \"Share a personalized invitation with friends!\",\n  \"UxgyeY\": \"Your referral code is {code}\",\n  \"V20Og0\": \"Labeling\",\n  \"VOjC1i\": \"எந்தப் பதிவேற்ற சேவையில் இணைப்புகளைப் பதிவேற்ற விரும்புகிறீர்கள் என்பதைத் தேர்ந்தெடுக்கவும்\",\n  \"VR5eHw\": \"பொது சாவி (npub/nprofile)\",\n  \"VcwrfF\": \"Yes please\",\n  \"VfhYxG\": \"To see a full list of changes you can view the changelog {here}\",\n  \"VlJkSk\": \"{n} ஒலியடக்கப்பட்டவை\",\n  \"VnXp8Z\": \"சுயவிவர படம்\",\n  \"W1yoZY\": \"உங்களிடம் சந்தாக்கள் எதுவும் இல்லை என்பது போல் தெரிகிறது, நீங்கள் ஒன்றைப் பெறலாம் {link}\",\n  \"W2PiAr\": \"{n} முடக்கப்பட்டவை\",\n  \"W4SaxY\": \"Local\",\n  \"W9355R\": \"ஒலியடக்கத்தை நீக்கு\",\n  \"WeLEuL\": \"From Server\",\n  \"Wj5TbN\": \"Issues\",\n  \"WmZhfL\": \"Automatically translate notes to your local language\",\n  \"WvGmZT\": \"npub / nprofile / nostr address\",\n  \"X6tipZ\": \"Sign in with key\",\n  \"X7xU8J\": \"nsec, npub, nip-05, hex, mnemonic\",\n  \"XECMfW\": \"Send usage metrics\",\n  \"XICsE8\": \"File hosts\",\n  \"XPB8VV\": \"Alby wallet connection\",\n  \"XQiFEl\": \"Follows Relay Health\",\n  \"XSdWHA\": \"Redeem\",\n  \"XXm7jJ\": \"Trending Hashtags\",\n  \"XgWvGA\": \"எதிர்வினைகள்\",\n  \"Xnimz0\": \"Sending from <b>{wallet}</b>\",\n  \"Xopqkl\": \"Your default zap amount is {number} sats, example values are calculated from this.\",\n  \"YDMrKK\": \"Users\",\n  \"YDURw6\": \"சேவை URL\",\n  \"YH2RKk\": \"Popular media servers.\",\n  \"YQZY/S\": \"It looks like you dont follow enough people, take a look at {newUsersPage} to discover people to follow!\",\n  \"YR2I9M\": \"No keys, no {app}, There is no way to reset it if you don't back up. It only takes a minute.\",\n  \"YU7ZYp\": \"Public Chat\",\n  \"YXA3AH\": \"எதிர்வினைகளை அனுமதி\",\n  \"Yf3DwC\": \"Connect a wallet to send instant payments\",\n  \"YuoEb9\": \"Try another relay\",\n  \"Z48UEo\": \"Channel Metadata\",\n  \"Z4BMCZ\": \"இணைத்தல் சொற்றொடரை உள்ளிடவும்\",\n  \"Z7kkeJ\": \"Delegated Event Signing\",\n  \"ZFe9tl\": \"Compose a note\",\n  \"ZKORll\": \"இப்போது செயல்படுத்துக\",\n  \"ZLmyG9\": \"பங்களிப்பாளர்கள்\",\n  \"ZS+jRE\": \"Send zap splits to\",\n  \"Zff6lu\": \"Username iris.to/<b>{name}</b> is reserved for you!\",\n  \"ZlIh4/\": \"Encrypted Direct Messages\",\n  \"ZlmK/p\": \"{name} invited you to {app}\",\n  \"a1x4gD\": \"Media servers store media which you can share in notes as images and videos\",\n  \"a5UPxh\": \"NIP-05 சரிபார்ப்பு சேவைகளை வழங்கும் டெவலப்பர்கள் மற்றும் தளங்களுக்கு நிதி உதவி செய்யுங்கள்\",\n  \"a7TDNm\": \"Notes will stream in real time into global and notes tab\",\n  \"aHje0o\": \"Name or nym\",\n  \"aMaLBK\": \"Supported Extensions\",\n  \"aRex7h\": \"Paid {amount} sats, fee {fee} sats\",\n  \"aSGz4J\": \"Connect to your own LND node with Lightning Node Connect\",\n  \"aWpBzj\": \"மேலும் காட்டு\",\n  \"abbGKq\": \"{n} km\",\n  \"ak3MTf\": \"Invite Friends\",\n  \"b12Goz\": \"நினைவூட்டி\",\n  \"b5vAk0\": \"உங்கள் பயனர் அடையாளம் மின்னல் முகவரிபோல் செயல்படும் மற்றும் நீங்கள் தேர்ந்தெடுத்த LNURL அல்லது மின்னல் முகவரிக்குத் திருப்பிவிடும்\",\n  \"bF1MYT\": \"You are a community leader and are earning <b>{percent}</b> of referred users subscriptions!\",\n  \"bG00/W\": \"Service Worker Running\",\n  \"bJ+wrA\": \"Compute prune list\",\n  \"bLZL5a\": \"Get Address\",\n  \"bMphls\": \"Logged in with read-only access\",\n  \"bQdA2k\": \"உணர்திறன் மிக்க உள்ளடக்கம்\",\n  \"bep9C3\": \"பொது சாவி\",\n  \"bfvyfs\": \"Anon\",\n  \"bxv59V\": \"இப்போது\",\n  \"c+1p0i\": \"Kind mute sets\",\n  \"c+JYNI\": \"No thanks\",\n  \"c2T+1B\": \"Redirects\",\n  \"c35bj2\": \"உங்களின் NIP-05 ஆர்டரைப் பற்றி விசாரணை இருந்தால், {link} க்கு DM செய்யவும்\",\n  \"c3LlRO\": \"{n}KiB\",\n  \"c3g2hL\": \"Broadcast Again\",\n  \"cFbU1B\": \"Using Alby? Go to {link} to get your NWC config!\",\n  \"cG/bKQ\": \"Native nostr wallet connection\",\n  \"cHCwbF\": \"Photography\",\n  \"cKbMRX\": \"Direct Message\",\n  \"cPIKU2\": \"பின்தொடரப் படுவோர்\",\n  \"cQfLWb\": \"URL..\",\n  \"cVcgLJ\": \"Media Servers\",\n  \"cWx9t8\": \"அனைத்தையும் ஒலிநிறுத்து\",\n  \"cg1VJ2\": \"பணப்பையை இணைக்கவும்\",\n  \"cnwHgH\": \"OpenTimestamps\",\n  \"cuP16y\": \"பல கணக்கு ஆதரவு\",\n  \"cuV2gK\": \"பெயர் பதிவு செய்யப்பட்டுள்ளது\",\n  \"cw1Ftc\": \"Live Activities\",\n  \"cyR7Kh\": \"பின்\",\n  \"d+6YsV\": \"Lists to mute:\",\n  \"d0qim7\": \"WoT Filter\",\n  \"d2ebEu\": \"Not Subscribed to Push\",\n  \"d7d0/x\": \"LN முகவரி\",\n  \"dK2CcV\": \"The public key is like your username, you can share it with anyone.\",\n  \"dOQCL8\": \"காட்சி பெயர்\",\n  \"dZZIGe\": \"Modular Article Header\",\n  \"ddd3JX\": \"Popular Hashtags\",\n  \"deEeEI\": \"Register\",\n  \"djLctd\": \"Amount in sats\",\n  \"dmcsBA\": \"Classified Listing\",\n  \"dmsiLv\": \"A default Zap Pool split of {n} has been configured for {site} developers, you can disable it at any time in {link}\",\n  \"e5x8FT\": \"Kind\",\n  \"e61Jf3\": \"விரைவில் வருகிறது\",\n  \"e7VmYP\": \"Enter pin to unlock your private key\",\n  \"e7qqly\": \"அனைத்தையும் படித்ததாகக் குறிக்கவும்\",\n  \"eF0Re7\": \"Use a nostr signer extension to sign in\",\n  \"eHAneD\": \"எதிர்வினை ஈமோஜி\",\n  \"eJj8HD\": \"உங்கள் கணக்கைச் சரிபார்க்கப் பட்டதாக்கவும்\",\n  \"eSzf2G\": \"A single zap of {nIn} sats will allocate {nOut} sats to the zap pool.\",\n  \"eW/Bj9\": \"Feed\",\n  \"eXT2QQ\": \"குழு அரட்டை\",\n  \"eZtOxB\": \"window.nostr capability for web browsers\",\n  \"egib+2\": \"{n,plural,=1{& {n} other} other{& {n} others}}\",\n  \"ejEGdx\": \"Home\",\n  \"eoV49s\": \"Poor\",\n  \"f1OxTe\": \"Community leaders are individuals who grow the nostr ecosystem by being active in their local communities and helping onboard new users. Anyone can become a community leader, but few hold the current honorary title.\",\n  \"f2CAxA\": \"Dump\",\n  \"fBI91o\": \"Zap\",\n  \"fBlba3\": \"Thanks for using {site}, please consider donating if you can.\",\n  \"fLIvbC\": \"Snort is an open source project built by passionate people in their free time, your donations are greatly appreciated\",\n  \"fOksnD\": \"LNURL சேவை ஜாப்களை ஆதரிக்காததால் வாக்களிக்க இயலாது\",\n  \"fQN+tq\": \"Show posts that have a content warning tag\",\n  \"fWZYP5\": \"நிலையாகப் பொருத்தப் பட்டவை\",\n  \"fX5RYm\": \"Pick a few topics of interest\",\n  \"filwqD\": \"படி\",\n  \"fjAcWo\": \"Gift Wraps\",\n  \"flnGvv\": \"உங்கள் மனதில் என்ன இருக்கிறது?\",\n  \"fqwcJ1\": \"On-chain Donation\",\n  \"fr+XYA\": \"Lightning Pub RPC\",\n  \"fsB/4p\": \"சேமிக்கப்பட்டது\",\n  \"fucxlm\": \"Attach Media\",\n  \"furjvW\": \"Watch Stream\",\n  \"g5pX+a\": \"தகவல்\",\n  \"g985Wp\": \"வாக்கை அனுப்ப முடியவில்லை\",\n  \"gDzDRs\": \"குறிப்புக்கு எதிர்வினையாற்றும்போது அனுப்ப வேண்டிய ஈமோஜி\",\n  \"gXgY3+\": \"எல்லா நாஸ்டர் மென்பொருட்களும் இதை இன்னும் ஆதரிக்கவில்லை\",\n  \"gczcC5\": \"சந்தா\",\n  \"geppt8\": \"{count} ({count2} in memory)\",\n  \"gjBiyj\": \"ஏற்றுகிறது...\",\n  \"gkMmvC\": \"Android Signer Application\",\n  \"gl1NeW\": \"Lists\",\n  \"go2/QF\": \"User server list\",\n  \"grQ+mI\": \"Proof of Work\",\n  \"gtNjNP\": \"Basic protocol flow description\",\n  \"h7jvCs\": \"{site} is more fun together!\",\n  \"h8XMJL\": \"பேட்ஜ்கள்\",\n  \"h9M0rW\": \"User Metadata\",\n  \"hF6IN2\": \"Prune Follow List\",\n  \"hMQmIw\": \"Sync Account\",\n  \"hMzcSq\": \"அஞ்சல்கள்\",\n  \"hRTfTR\": \"PRO\",\n  \"hY4lzx\": \"ஆதரவு\",\n  \"hYOE+U\": \"Invite\",\n  \"hicxcO\": \"பதில்களைக் காட்டு\",\n  \"hmZ3Bz\": \"Media\",\n  \"hniz8Z\": \"இங்கே\",\n  \"hv/eRj\": \"Blocked relays list\",\n  \"hvFRBo\": \"Interaction\",\n  \"i/dBAR\": \"Zap Pool\",\n  \"i5gBFz\": \"Your sent and received payments will show up here.\",\n  \"iCqGww\": \"எதிர்வினைகள் ({n})\",\n  \"iEoXYx\": \"DeepL மொழிபெயர்ப்புகள்\",\n  \"iGT1eE\": \"போலி கணக்குகள் உங்களைப் போல் நடிப்பதை தடுக்கவும்\",\n  \"iHN12u\": \"Admin\",\n  \"iICVoL\": \"{x} follows ({y} duplicates)\",\n  \"iNWbVV\": \"பயனர்பெயர்\",\n  \"iXPL0Z\": \"பாதுகாப்பற்ற இணைப்பில் தனிப்பட்ட சாவியுடன் உள்நுழைய முடியாது, அதற்குப் பதிலாக நாஸ்டர் விசை மேலாளர் நீட்டிப்பைப் பயன்படுத்தவும்\",\n  \"iYc3Ld\": \"Payments\",\n  \"icCxlA\": \"new users page\",\n  \"ieGrWo\": \"பின்தொடர்\",\n  \"igUUst\": \"Group Chat Threaded Reply\",\n  \"ipHVx5\": \"Generate Invoice\",\n  \"itPgxd\": \"சுயவிவரம்\",\n  \"izWS4J\": \"பின்தொடர்வதை நிறுத்துக\",\n  \"j9xbzF\": \"Already backed up\",\n  \"jA3OE/\": \"{n,plural,=1{{n} ஸாட்} other{{n} ஸாட்கள்}}\",\n  \"jAmfGl\": \"Your {site_name} subscription is expired\",\n  \"jHa/ko\": \"Clean up your feed\",\n  \"jMzO1S\": \"உள் பிழை: {msg}\",\n  \"jiAVXu\": \"Video Event\",\n  \"jvo0vs\": \"சேமி\",\n  \"jzgQ2z\": \"{n} எதிர்வினைகள்\",\n  \"k0kCJp\": \"Apply Now\",\n  \"k2veDA\": \"எழுது\",\n  \"k7sKNy\": \"இது எங்களின் சொந்த NIP-05 சரிபார்ப்புச் சேவை. இந்தத் தளத்தின் வளர்ச்சிக்கு உதவுவதோடு, எங்கள் தளத்தில் பளபளப்பான சிறப்புப் பேட்ஜைப் பெறவும்!\",\n  \"k9SQm1\": \"Relays which you have connected to before and appear to be reliable.\",\n  \"kEZUR8\": \"Register an Iris username\",\n  \"kJYo0u\": \"{n,plural,=0{{name} reposted} other{{name} & {n} others reposted}}\",\n  \"kKC9ya\": \"Wallet Info\",\n  \"kNd2FL\": \"Tidal login\",\n  \"kQAf2d\": \"Select\",\n  \"kaaf1E\": \"இப்போது\",\n  \"kc79d3\": \"Topics\",\n  \"klCm96\": \"Community Post Approval\",\n  \"kqPQJD\": \"Configure zap pool\",\n  \"kuPHYE\": \"{n,plural,=0{{name} liked} other{{name} & {n} others liked}}\",\n  \"l+ikU1\": \"{plan} இல் உள்ள அனைத்தும்\",\n  \"l3H1EK\": \"Invite your friends\",\n  \"l3nTjd\": \"Basic key derivation from mnemonic seed phrase\",\n  \"lCILNz\": \"இப்போது வாங்கு\",\n  \"lD3+8a\": \"பணம் செலுத்து\",\n  \"lEnclp\": \"My events: {n}\",\n  \"lPWASz\": \"ஸ்நார்ட் நாஸ்டர் முகவரி\",\n  \"lTbT3s\": \"பணப்பை கடவுச்சொல்\",\n  \"lbr3Lq\": \"Copy link\",\n  \"lfOesV\": \"Non-Zap\",\n  \"lgg1KN\": \"கணக்குப் பக்கம்\",\n  \"ll3xBp\": \"பட பதிலீடு சேவை\",\n  \"lnaT9F\": \"பின்தொடரப் படுவோர் {n}\",\n  \"lsNFM1\": \"{link} இலிருந்து உள்ளடக்கத்தை ஏற்ற கிளிக் செய்யவும்\",\n  \"lvlPhZ\": \"விலை பட்டியலை செலுத்தவும்\",\n  \"m/59y2\": \"Zap Request\",\n  \"m6h2Eg\": \"Handler recommendation\",\n  \"mCEKiZ\": \"{n} notes have been muted\",\n  \"mErPop\": \"உங்களிடம் எதுவும் இல்லை என்பது போல் தெரிகிறது, ஒன்றை வாங்க {link} ஐப் பார்க்கவும்!\",\n  \"mFtdYh\": \"{type} Worker Relay\",\n  \"mKAr6h\": \"அனைத்தையும் பின்பற்றவும்\",\n  \"mKh2HS\": \"கோப்பு பதிவேற்ற சேவை\",\n  \"mKhgP9\": \"{n,plural,=0{} =1{ஜாப் செய்தார்} other{ஜாப் செய்தனர்}}\",\n  \"mOFG3K\": \"Start\",\n  \"mfe8RW\": \"விருப்பம்: {n}\",\n  \"mmPSWH\": \"Read Only\",\n  \"n1Whvj\": \"மாற்று\",\n  \"n5l7tP\": \"Time-Based Calendar Event\",\n  \"n8k1SG\": \"{n}MiB\",\n  \"nD4frR\": \"Bid confirmation\",\n  \"nDejmx\": \"முடக்கத்தை நீக்கு\",\n  \"nGBrvw\": \"புக்மார்க்குகள்\",\n  \"nGGDsi\": \"Notifications Allowed\",\n  \"nIchMQ\": \"Searching for account activity ({progress})\",\n  \"nPHrqp\": \"Coinjoin Pool\",\n  \"nUT0Lv\": \"Tools\",\n  \"nWQFic\": \"Renew\",\n  \"nihgfo\": \"Listen to this article\",\n  \"nwZXeh\": \"{n} முடக்கப்பட்டவை\",\n  \"o/gK53\": \"Deck\",\n  \"o7e+nJ\": \"{n} பின்தொடர்பவர்கள்\",\n  \"oJ+JJN\": \"எதுவும் கிடைக்கவில்லை :/\",\n  \"odFwjL\": \"பின்பற்றுபவை மட்டும்\",\n  \"ojzbwv\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out {link}\",\n  \"ozZ2Cj\": \"Badge Award\",\n  \"p4N05H\": \"Upload\",\n  \"p9Ps2l\": \"{x}/{y} have relays ({percent})\",\n  \"pEEBFk\": \"Reliable Relays\",\n  \"pI+77w\": \"ஸ்நார்ட் ரிலேயிலிருந்து பதிவிறக்கக்கூடிய காப்புப்பிரதிகள்\",\n  \"pRess9\": \"ZapPool\",\n  \"plOM0t\": \"Custom Emoji\",\n  \"plg2Ua\": \"Channel Mute User\",\n  \"puLNUJ\": \"நிலையாக பொறுத்து\",\n  \"pyjJ5f\": \"Nostr Marketplace (for resilient marketplaces)\",\n  \"pzTOmv\": \"பின்தொடர்வோர்\",\n  \"q3OuMw\": \"Torrent Comment\",\n  \"qAY40L\": \"Date-Based Calendar Event\",\n  \"qBYNMb\": \"Group Thread Reply\",\n  \"qD9EUF\": \"உங்கள் ஸ்நார்ட் நாஸ்டர் முகவரிக்கு மின்னஞ்சல் <> DM பாலம்\",\n  \"qDwvZ4\": \"அறியப்படாத பிழை\",\n  \"qFIVx4\": \"Profile Badges\",\n  \"qMePPG\": \"Note\",\n  \"qMx1sA\": \"இயல்புநிலை ஜாப் தொகை\",\n  \"qUJTsT\": \"முடக்கப்பட்டவை\",\n  \"qXCbgZ\": \"Unlock\",\n  \"qZsKBR\": \"Renew {tier}\",\n  \"qcJFEJ\": \"Notifications API Disabled\",\n  \"qdGuQo\": \"உங்கள் தனிப்பட்ட சாவி (இதை யாருடனும் பகிர வேண்டாம்)\",\n  \"qfmMQh\": \"This note has been muted\",\n  \"qkvYUb\": \"சுயவிவரத்தில் சேர்க்கவும்\",\n  \"qmJ8kD\": \"மொழிபெயர்ப்பு தோல்வியடைந்தது\",\n  \"qtWLmt\": \"Like\",\n  \"qyJtWy\": \"Show less\",\n  \"qydxOd\": \"Science\",\n  \"qz9fty\": \"Incorrect pin\",\n  \"r3C4x/\": \"மென்பொருள்\",\n  \"r5srDR\": \"பணப்பையின் கடவுச்சொல்லை உள்ளிடவும்\",\n  \"rAQG0X\": \"Relay List Metadata\",\n  \"rIsVe+\": \"Public chats list\",\n  \"rMgF34\": \"Back up now\",\n  \"rRRXtB\": \"Lightning Zaps\",\n  \"rT14Ow\": \"ரிலேகளைச் சேர்க்கவும்\",\n  \"reFEEC\": \"Reporting\",\n  \"rfuMjE\": \"(இயல்புநிலை)\",\n  \"rkM7l8\": \"Encrypted Direct Message\",\n  \"rmdsT4\": \"{n} நாட்கள்\",\n  \"rn52n9\": \"Public Chat Channels\",\n  \"rx1i0i\": \"Short link\",\n  \"sFUkSN\": \"Bookmark sets\",\n  \"sKDn4e\": \"Show Badges\",\n  \"sUNhQE\": \"user\",\n  \"sZQzjQ\": \"Failed to parse zap split: {input}\",\n  \"saInmO\": \"The relay name shown is not the same as the full URL entered.\",\n  \"saorw+\": \"Event Deletion Request\",\n  \"sfL/O+\": \"Muted notes will not be shown\",\n  \"t79a6U\": \"Connection Success:\",\n  \"tDDiRL\": \"Interests list\",\n  \"tFpT/O\": \"Release artifact sets\",\n  \"tO1oq9\": \"Video Events\",\n  \"tOdNiY\": \"இருள்\",\n  \"tRGdV1\": \"Versioned Encryption\",\n  \"tU0ADf\": \"Unknown NIP-{x}\",\n  \"tVuVg9\": \"Video View Event\",\n  \"tf1lIh\": \"Free\",\n  \"th5lxp\": \"Send note to a subset of your write relays\",\n  \"thnRpU\": \"NIP-05 மூலம் சரிபார்த்துக் கொள்வது கீழ்க்கண்டவற்றில் உதவலாம்:\",\n  \"tj6kdX\": \"{sign} {amount} sats\",\n  \"tjpYlr\": \"Relay Metrics\",\n  \"ttxS0b\": \"ஆதரவாளர் பேட்ஜ்\",\n  \"tzMNF3\": \"Status\",\n  \"u/vOPu\": \"கட்டணத்திற்கு உரியது\",\n  \"u4I8q8\": \"Pin list\",\n  \"u81G9+\": \"Uptime\",\n  \"u9NoC1\": \"Name must be less than {limit} characters\",\n  \"uCk8r+\": \"Already have an account?\",\n  \"uD7Els\": \"External Identities in Profiles\",\n  \"uJaMkO\": \"Relay list to receive DMs\",\n  \"uSV4Ti\": \"மறுபதிவுகள் கைமுறையாக உறுதிப்படுத்தப்பட வேண்டும்\",\n  \"uc0din\": \"Send sats splits to\",\n  \"ufvXH1\": \"Found {n} events\",\n  \"uhu5aG\": \"Public\",\n  \"un1nGw\": \"{n} notes\",\n  \"usAvMr\": \"சுயவிவரத்தைத் திருத்து\",\n  \"v8lolG\": \"பேசத் தொடங்குக\",\n  \"vB3oQ/\": \"Must be a contact list or pubkey list\",\n  \"vBsZhD\": \"Communities list\",\n  \"vN5UH8\": \"Profile Image\",\n  \"vU/Q5i\": \"This tool will search for the last event published by all of your follows and remove those who have not posted in 6 months\",\n  \"vZ4quW\": \"NIP-05 என்பது DNS அடிப்படையிலான சரிபார்ப்பு விவரக்குறிப்பாகும், இது உங்களை உண்மையான பயனராகச் சரிபார்க்க உதவுகிறது.\",\n  \"vhlWFg\": \"வாக்கெடுப்பு விருப்பங்கள்\",\n  \"vlbWtt\": \"விலையின்றிப் பெறுக\",\n  \"voxBKC\": \"Followed by friends\",\n  \"vxwnbh\": \"அனைத்து பதியப்பட்ட நிகழ்வுகளிலும் மாற்றம் செய்யத் தேவைப்படும் பணிச் சுமை\",\n  \"w1Fanr\": \"Business\",\n  \"w6qrwX\": \"NSFW\",\n  \"wEQDC6\": \"திருத்து\",\n  \"wOyDTB\": \"File storage server list\",\n  \"wSZR47\": \"Submit\",\n  \"wc9st7\": \"Media Attachments\",\n  \"whSrs+\": \"Nostr Public Chat\",\n  \"wih7iJ\": \"பெயர் முடக்கப் பட்டுள்ளது\",\n  \"wlWMuh\": \"Patches\",\n  \"wofVHy\": \"Moderation\",\n  \"wqyN/i\": \"{link} இல் {service} பற்றிய கூடுதல் தகவலைக் கண்டறியவும்\",\n  \"wtLjP6\": \"IDஐ நகல் எடு\",\n  \"x+3fl6\": \"My Relays\",\n  \"x/Fx2P\": \"நீங்கள் பயன்படுத்தும் சேவைக்குக் நன்கொடை அளிக்கலாம் - உங்கள் zap-களின் ஒரு பகுதியை நிதியத்தில் சேர்ப்பதன் வழியாக!\",\n  \"x82IOl\": \"ஒலியடக்கு\",\n  \"xEjBS7\": \"For you\",\n  \"xIcAOU\": \"Votes by {type}\",\n  \"xIoGG9\": \"செல்\",\n  \"xPCyu+\": \"nostr: URI scheme\",\n  \"xaj9Ba\": \"வழங்குநர்\",\n  \"xbVgIm\": \"மீடியாவை தானாகக் காட்டவும்\",\n  \"xhQMeQ\": \"காலாவதியாகிறது\",\n  \"xl4s/X\": \"Additional Terms:\",\n  \"xmcVZ0\": \"தேடு\",\n  \"xybOUv\": \"FAN\",\n  \"y/bmsG\": \"Allow\",\n  \"y1Z3or\": \"மொழி\",\n  \"yAztTU\": \"{n} eSats\",\n  \"yCLnBC\": \"LNURL அல்லது லைட்னிங் முகவரி\",\n  \"yLzgxH\": \"Popular Relays\",\n  \"yeX8yA\": \"Native App\",\n  \"z3UjXR\": \"Debug\",\n  \"z3Ukvq\": \"Draft Long-form Content\",\n  \"zCb8fX\": \"Weight\",\n  \"zFegDD\": \"தொடர்பு\",\n  \"zINlao\": \"உரிமையாளர்\",\n  \"zQvVDJ\": \"அனைத்தும்\",\n  \"zcaOTs\": \"ஜாப் தொகை ஸாட்களில்\",\n  \"zi9MdS\": \"Chess (PGN)\",\n  \"zm6qS1\": \"{n} mins to read\",\n  \"zonsdq\": \"LNURL சேவையை ஏற்றுவதில் தோல்வி\",\n  \"zvCDao\": \"சமீபத்திய குறிப்புகளைத் தானாகக் காட்டு\",\n  \"zx0myy\": \"Participants\"\n}\n"
  },
  {
    "path": "packages/app/src/translations/th_TH.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"คุณแน่ใจหรือไม่ว่าต้องการจะรีโพสต์: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"จ่ายเลยตอนนี้\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sync all events for your profile into local cache\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Stats\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logged in with write access\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"รูปแบบการ Zap\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"กำลังติดตาม\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"เข้าสู่ระบบ\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"โปรดตรวจสอบให้แน่ใจว่าคุณได้ทำการบันทึกรหัสผ่านต่อไปนี้ไว้เรียบร้อยแล้ว เพื่อให้สะดวกต่อจัดการในอนาคต\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"เชื่อมต่อ\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"แก้ไข\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your space the way you want it 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"ล้าง\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"การสนับสนุนบัญชี\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP File Storage Integration\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send anonymous usage metrics\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat Message\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"ทำให้ค้นหาและแบ่งปันโปรไฟล์ได้ง่ายขึ้น\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"From File\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr address does not belong to you\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"จัดการ\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"ค้นหา...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic LNDHub wallet (BTCPayServer / Alby / LNBits)\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL ไม่ถูกต้อง\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handling Mentions\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"ชื่อมีอักขระที่ไม่อนุญาตให้ใช้\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Politics\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show Status\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" วินาที\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"git stuff\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"คุณแน่ใจหรือว่าต้องการลบโน้ตนี้ออกจากบุ๊คมาร์ค?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"ใส่ Nostr Wallet Connect config\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Be sure to back up your keys!\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"เชื่อมต่อกับ: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 0,\n      \"value\": \"กำลังติดตาม \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check Signatures\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nature\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"การสนทนา\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"เพิ่ม\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"แบนเนอร์\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Don't have an account?\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderated Communities\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Connect\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subject tag in text events\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"User emoji list\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"โดเนท\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"ป้อนรหัสผ่าน\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Finish\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic lists\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 0,\n      \"value\": \"บุ๊คมาร์ค \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่ถูกใจ (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Note\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed by friends of friends\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Application-specific data\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ชั่วโมง\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"Latest Articles\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Replies\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign Up\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"User Statuses\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Articles\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blobs stored on mediaservers\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" viewers\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"สว่าง\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"แปลภาษา\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Untitled\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"คุณกำลังลงคะแนนด้วย \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" โน้ตใหม่\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" โน้ตใหม่\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"ผู้ติดตาม \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total Events:\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่มี\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"ยกเลิก\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bid\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"นักพัฒนาหลัก\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 ใหม่ของคุณคือ:\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Life\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่ถูกใจ\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key Encryption\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs เป็นหนึ่งในผู้ให้บริการ NIP-05 รายแรก ๆ ในพื้นที่นี้ และเสนอชุดโดเมนที่ดีในราคาที่สมเหตุสมผล\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"ใช้ imgproxy เพื่อบีบอัดรูปภาพ\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Missing Relays\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"หมายเหตุถึงตนเอง\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recommended Application Handlers\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zaps\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Splits\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications API Enabled\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Goal\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"รหัสการซื้อ\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"File Metadata\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"แปลงเป็น Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"ส่ง zap\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Replay\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute list\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retry\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connection Failed:\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"New follow list length \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"อิมเมจพร็อกซีจาก \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ไม่สำเร็จ คลิกที่นี่เพื่อโหลดโดยตรง\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recommend Relay\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Seal\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Looking for: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this, you may still receive some zaps as if zap splits was not configured\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"ถูกใจ (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed by\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Extra metadata fields and tags\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"ยังไม่ได้ชำระ\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch accounts\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Good\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"โน้ต\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Label\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wiki article\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Information Document\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search Capability\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Offline\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Leader\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modular Article Content\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute notes from people who are outside your web of trust\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Close Relays\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"รีโพสต์ (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"ยืนยันรีโพสต์\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conventions for clients' use of e and p tags in text events\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply To\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign up\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recipient\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid zap split: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Thread\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"ชื่อยาวเกินไป\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"bech32-encoded entities\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow sets\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Draft Classified Listing\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"ถัดไป\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"ตอบกลับ\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"ติดตาม \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar Event RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"ส่ง\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hide muted notes\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"Retry publishing\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generic Repost\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"ตอบกลับจาก\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted Words\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"ผู้เขียนถูกปิดการมองเห็น\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create or update a product\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"สามารถเก็บโน้ตได้อย่างไม่จำกัดบน Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"เหตุผล\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Great\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Game\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Creation\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Count\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"Push notifications\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Months\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"เข้าสู่ระบบ\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"ชื่อสั้นเกินไป\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap เรียบร้อยแล้ว\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can add a single or multiple relays, one per line.\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write ไปยัง Snort relay จะเก็บรักษา event ให้เป็นเวลา 1 ปี\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AI Embeddings / Vector lists\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay-based Groups\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"อัปเดต\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Marketplace UI/UX\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr address (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP Auth\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"บริจาคด้วย Linghtning\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Event\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Quote Repost\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"ออกจากระบบ\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Servers\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"แนะนำให้ติดตาม\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video sets\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่สามารถโหลด invoice\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow List\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prune follow list\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"บุตคลที่กำลังมาแรง\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"and \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" others you follow\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repository announcements\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 0,\n      \"value\": \"ปิดการมองเห็น \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" บัญชี\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"แปลจาก \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Social Graph\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Text Note References\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap ให้ทุกโน้ตที่โหลดโดยอัตโนมัติ\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge Definition\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"การตั้งค่า\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Hide Message\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cache\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"ส่งซาโตชิ\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"แสดงโน้ตล่าสุด \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" รายการ\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap โดยอัตโนมัติ\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Product sold as an auction\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"About must be less than \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" characters\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"โอนย้าย\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle all\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Browser\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sats\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invoice / Lightning Address\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search notes\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"ผู้ให้บริการข้อมูล\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show badges on profile pages\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction to a website\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"แปลจาก \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Curation sets\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"รีเลย์ที่กำหนดเอง\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username is available\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain Donation Address\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ซื้อ\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sorry, we dont understand this event kind (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"), please try one of the following apps instead!\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Server\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"เพิ่มบัญชี\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Classified Listings\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Response\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Authentication of clients to relays\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show status messages on profile pages\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"User groups\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirect issues HTTP redirect to the supplied lightning address\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"รับทันที\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"พบข้อผิดพลาด!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"ได้ติดตามคุณ\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Accounts\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"You dont have any media servers, try adding some.\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"ลบ\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"เลือก wallet\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribed to Push\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supported NIPs\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"บุ๊คมาร์ค (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"รับ Snort nostr address ของคุณ\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid Lightning Address\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ไม่ถูกใจ\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Event\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dealing with Unknown Events\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"ออกจากระบบ\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Leader Info\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark list\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"ได้รับการชำระเงินเรียบร้อย!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"ชื่อ\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"ชื่อจะสามารถใช้ได้ในภายหลัง\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"ปิดการมองเห็น\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"ล้างแคชและดาวน์โหลดใหม่อีกครั้ง\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"เปิด Wallet\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You don't follow this person, click here to load media from \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", or update \"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"your preferences\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to always load media from everybody.\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay reviews\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Support\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expiration Timestamp\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create or update a stall\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Last post \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"คุณแน่ใจแล้วใช่มั้ยว่าต้องการลบโน้ตนี้?\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Data\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"You must be a \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" subscriber to access \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" deck\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap all \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Translate\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Last Seen:\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"ส่ง \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats ถึง \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not followed by anyone you follow\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click here to load anyway\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"โน๊ตที่กำลังมาแรง\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"การสมัครสมาชิก\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications Not Allowed\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use commas to separate words e.g. word1, word2, word3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji sets\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"ชื่อผู้ใช้\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sport\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่มี lightning address นี้\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search relays list\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"เว็บไซต์\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays are servers you connect to for sending and receiving events. Aim for 4-8 relays.\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Average Latency:\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ลบ\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"แสดง\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"External Content IDs\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"ใส่ LNDHub config\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Highlights\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Chat Message\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"ลบทิ้งแล้ว\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"Protected Events\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่รู้จัก event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mapping Nostr keys to DNS-based internet identifiers\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Pin\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Request\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"View as user?\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Goals\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin too short\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่ระบุตัวตน\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"ความคิดเห็น\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name must be between 8 and 15 characters\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cannot verify Nostr Address\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"เปิด Zapstr\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrents\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps on this note will be split to the following users.\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"เมนูการแก้ปัญหา\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"Become a leader\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"แสดง \\\"Copy ID\\\" และ \\\"Copy Event JSON\\\" ในเมนูของแต่ละข้อความ\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่พร้อมใช้งาน:\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"Join Room\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"รหัสผ่าน wallet\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"หน้าเริ่มต้น\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Short Text Note\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Client Authentication\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Set as primary Nostr address (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proxy Tags\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send this link to your friends and share the magic of the nostr.\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"จ่ายเพื่อสมัครสมาชิก\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Counting results\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"กำลังซื้อ \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.to account\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"ยืนยัน\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"คุณได้สมัครสมาชิกประเภทนี้แล้ว โปรดต่ออายุหรือชำระเงิน\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Job Feedback\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่สามารถโหวตด้วย \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats โปรดตั้งค่าจำนวน zap เริ่มต้นใหม่\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"หน้าต่างสำหรับผู้ใช้ใหม่\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dead\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use your invite code to earn sats!\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps Attestations for Events\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gift Wrap\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"แชร์\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"พบข้อผิดพลาดการเข้าสู่ระบบที่ไม่ทราบสาเหตุ\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free nostr address\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"การสมัครสมาชิกของคุณยังคงใช้งานได้ คุณยังไม่จำเป็นต้องต่ออายุ\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"สร้าง\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Merge Requests\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to update, please try again\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Long-form Content\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Scanning \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid Nostr Address\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"คัดลอก Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"ระบบ (ค่าเริ่มต้น)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ยอดรวมวันนี้ (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"Distance\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"การตั้งค่า\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Receiving to \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"ส่วนต้นของไฟล์ที่ไม่รู้จัก: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"ธีม\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions จะแสดงในทุกหน้า หากปิดใช้งาน จะไม่แสดง Reactions ใด ๆ\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" รีเลย์\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"The private key is like a password, but it cannot be reset. Guard it carefully and never show it to anyone. Once someone has your private key, they will have access to your account forever.\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool ใช้งานได้เฉพาะเมื่อคุณใช้การเชื่อมต่อ wallet ที่รองรับ (WebLN, LNC, LNDHub หรือ Nostr Wallet Connect)\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Message\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"ขณะนี้มี \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats ใน zappool ของคุณ\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Direct Messages\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker Not Running\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repository state announcements\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username must only contain lowercase letters and numbers\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"หมดอายุแล้ว\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Short-form Portrait Video Event\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"โดย \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"คุณแน่ใจหรือไม่ ว่าต้องการลบ \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Vending Machines\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"รีเลย์\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"บุ๊คมาร์ก\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading note: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Permissions\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter a pin to encrypt your private key, you must enter this pin every time you open \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \".\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"อัพเดต Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"ซื้อการสมัครสมาชิก\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular relays used by people you follow.\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay sets\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Problem Tracker\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"ปรับแต่งเอง\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"What should we call you?\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"ชำระเงินทันที\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Application-specific Data\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"The author has marked this note as a \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"sensitive topic\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays close to your geographic location.\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"สื่อในโน้ตจะแสดงโดยอัตโนมัติสำหรับบุคคลที่เลือกเท่านั้น คนอื่น ๆ จะแสดงเฉพาะลิงก์\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handler information\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use Local Relay\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Ended\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Nostr Extension\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Learn more\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Crypto\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interest sets\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Calendar Events\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"ผู้คน\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"liked\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Stop listening\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Definition\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove from my relays\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Receive\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check all event signatures received from relays\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"ผู้ใช้จะต้องยอมรับคำเตือนเพื่อแสดงเนื้อหาในโน้ตของคุณ\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Server\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign In\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"บล็อก\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your application is pending\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"You have an active iris.to account\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share a personalized invitation with friends!\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your referral code is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Labeling\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"เลือกบริการอัปโหลดที่คุณต้องการอัปโหลดไฟล์แนบ\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Yes please\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"To see a full list of changes you can view the changelog \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 0,\n      \"value\": \"ปิดการมองเห็น \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" บัญชี\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"อวตาร\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"ดูเหมือนว่าคุณไม่มีการสมัครสมาชิกใด ๆ คุณสามารถสมัครรับข้อมูลได้ \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" บล็อค\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Local\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"เปิดการมองเห็น\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"From Server\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Issues\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically translate notes to your local language\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / nostr address\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with key\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send usage metrics\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"สถานที่เก็บไฟล์\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alby wallet connection\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows Relay Health\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Hashtags\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sending from \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"จํานวน zap เริ่มต้นของคุณคือ \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats ค่าตัวอย่างคํานวณจากสิ่งนี้\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular media servers.\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont follow enough people, take a look at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to discover people to follow!\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"No keys, no \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", There is no way to reset it if you don't back up. It only takes a minute.\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Chat\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"เปิดใช้งาน reactions\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect a wallet to send instant payments\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Try another relay\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Metadata\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ใส่ pairing phrase\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delegated Event Signing\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compose a note\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"เปิดใช้งานทันที\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ผู้มีส่วนร่วม\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap splits to\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" is reserved for you!\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encrypted Direct Messages\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" invited you to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media servers store media which you can share in notes as images and videos\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"สนับสนุนนักพัฒนาและแฟลตฟอร์มที่ให้บริการ NIP-05\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"โน้ตจะแสดงแบบเรียลไทม์บนหน้า global และ โน้ต\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name or nym\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supported Extensions\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, fee \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect to your own LND node with Lightning Node Connect\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"ดูเพิ่มเติม\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" km\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite Friends\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"สิ่งนี้เหมือนกับ Lightning Address และจะเปลี่ยนการเชื่อมต่อไปที่ LNURL หรือ Lightning Addresses ที่คุณเลือก\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are a community leader and are earning \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" of referred users subscriptions!\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service Worker Running\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Compute prune list\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Address\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logged in with read-only access\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"เนื้อหาที่ละเอียดอ่อน\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่ระบุชื่อ\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"เมื่อสักครู่\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kind mute sets\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"No thanks\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redirects\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"หากคุณมีคําถามใด ๆ เกี่ยวกับคําสั่งซื้อ NIP-05 ของคุณ โปรดติดต่อที่ \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"เผยแพร่อีกครั้ง\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"ใช้ Alby? ไปที่\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" เพื่อรับ NWC config ของคุณ\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Native nostr wallet connection\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Photography\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Direct Message\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"กำลังติดตาม\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media Servers\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"ปิดการโต้ตอบทั้งหมด\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"เชื่อมต่อ Wallet\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"รับรองการใช้งานหลายบัญชี\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"ชื่อนี้ถูกใช้งานแล้ว\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Live Activities\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"ย้อนกลับ\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lists to mute:\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"WoT Filter\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not Subscribed to Push\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN address\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"The public key is like your username, you can share it with anyone.\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"ชื่อที่แสดง\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Modular Article Header\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Hashtags\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Register\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount in sats\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Classified Listing\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"A default Zap Pool split of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" has been configured for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" developers, you can disable it at any time in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Kind\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"เร็ว ๆ นี้\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pin to unlock your private key\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"ทำเครื่องหมายเป็นอ่านแล้วทั้งหมด\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use a nostr signer extension to sign in\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"รับการยืนยัน!\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap จำนวน \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats จะจัดสรร \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats ให้กับ zap pool\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Feed\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"window.nostr capability for web browsers\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Home\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poor\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community leaders are individuals who grow the nostr ecosystem by being active in their local communities and helping onboard new users. Anyone can become a community leader, but few hold the current honorary title.\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dump\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", please consider donating if you can.\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time, your donations are greatly appreciated\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่สามารถโหวตได้เนื่องจากบริการ LNURL ไม่รองรับ zaps\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show posts that have a content warning tag\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"ปักหมุดข้อความแล้ว\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a few topics of interest\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"อ่าน\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Gift Wraps\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"คุณกำลังคิดอะไรอยู่?\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"On-chain Donation\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"บันทึกแล้ว\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Attach Media\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Stream\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"เกี่ยวกับ\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"การโหวตไม่สำเร็จ\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji ที่ต้องการส่งเมื่อ reaction บนโน้ต\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"ยังไม่มี client ไหนรับรองสิ่งนี้\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"สมัครสมาชิก\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" in memory)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"กำลังโหลด...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Android Signer Application\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lists\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"User server list\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Basic protocol flow description\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" is more fun together!\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"เหรียญตรา\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"User Metadata\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prune Follow List\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sync Account\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"ข้อความ\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"สนับสนุน\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"แสดงการตอบกลับ\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"ที่นี่\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked relays list\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interaction\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your sent and received payments will show up here.\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"แปล DeepL\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"ป้องกันไม่ให้บัญชีปลอมเลียนแบบคุณ\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"Admin\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" follows (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" duplicates)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"จัดการ\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่สามารถเข้าสู่ระบบด้วย private key ในการเชื่อมต่อที่ไม่ปลอดภัย โปรดใช้ Nostr key manager extension ในการจัดการ\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payments\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"new users page\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"ติดตาม\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat Threaded Reply\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Generate Invoice\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"โปรไฟล์\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"เลิกติดตาม\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Already backed up\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" subscription is expired\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clean up your feed\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"ข้อผิดพลาดภายใน: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video Event\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"บันทึก\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Apply Now\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"เขียน\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"บริการตรวจสอบ NIP-05 เป็นของเรา ช่วยสนับสนุนการพัฒนาของเว็บไซต์ และรับเหรียญตราที่สวยงามบนเว็บไซต์ของเรา\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays which you have connected to before and appear to be reliable.\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Register an Iris username\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet Info\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tidal login\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"ตอนนี้\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Topics\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"Community Post Approval\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Configure zap pool\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"ทุกสิ่งทุกอย่างใน \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invite your friends\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Basic key derivation from mnemonic seed phrase\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"ซื้อตอนนี้\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"ชำระเงิน\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"My events: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"รหัสผ่าน wallet\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy link\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"หน้าต่างบัญชี\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"บริการ Image proxy\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"กำลังติดตาม \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"คลิกเพื่อโหลดเนื้อหาจาก \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"จ่าย invoice\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Request\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handler recommendation\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes have been muted\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"เหมือนว่าคุณจะยังไม่มีนะ เช็ค \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" เพื่อซื้อสักอันสิ!\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Worker Relay\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"ติดตามทั้งหมด\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"บริการอัพโหลดไฟล์\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"ตัวเลือก: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read Only\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"สลับ\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Time-Based Calendar Event\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bid confirmation\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"ยกเลิกการบล็อค\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"บุ๊คมาร์ค\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications Allowed\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Searching for account activity (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coinjoin Pool\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Tools\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Listen to this article\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" บล็อค\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deck\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ผู้ติดตาม \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่พบสิ่งใด :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"เฉพาะที่ติดตามเท่านั้น\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badge Award\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" have relays (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reliable Relays\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"ดาวน์โหลดข้อมูลสำรองจากรีเลย์ของ Snort\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ZapPool\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Emoji\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"Channel Mute User\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ปักหมุด\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (for resilient marketplaces)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"ผู้ติดตาม\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent Comment\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Date-Based Calendar Event\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Thread Reply\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge ของคุณจาก Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"ข้อผิดพลาดที่ไม่รู้จัก\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Badges\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"จำนวน zap พื้นฐาน\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"บล็อค\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notifications API Disabled\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private key ของคุณคือ(อย่าส่งข้อมูลนี้ให้ผู้อื่น)\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been muted\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"เพิ่มไปยังโปรไฟล์\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"แปลล้มเหลว\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show less\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Science\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"Incorrect pin\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"ซอฟต์แวร์\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"โปรดใส่รหัส wallet\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay List Metadata\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public chats list\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back up now\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Zaps\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"เพิ่มรีเลย์\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reporting\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(ค่าเริ่มต้น)\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Encrypted Direct Message\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Chat Channels\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Short link\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark sets\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show Badges\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to parse zap split: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"The relay name shown is not the same as the full URL entered.\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Event Deletion Request\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted notes will not be shown\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connection Success:\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Interests list\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Release artifact sets\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video Events\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"มืด\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Versioned Encryption\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Video View Event\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Free\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"ส่งโน้ตของคุณไปยังชุดของรีเลย์ที่คุณอนุญาติให้เขียน\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"การได้รับการยืนยัน NIP-05 สามารถช่วย:\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay Metrics\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"เหรียญตราของผู้สนับสนุน\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Status\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"ชำระเงินแล้ว\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin list\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Uptime\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name must be less than \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" characters\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Already have an account?\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"External Identities in Profiles\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relay list to receive DMs\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"การรีโพสจะต้องได้รับการยืนยันด้วยตนเอง\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats splits to\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Found \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" events\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"แก้ไขโปร์ไฟล์\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Must be a contact list or pubkey list\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Communities list\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile Image\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"This tool will search for the last event published by all of your follows and remove those who have not posted in 6 months\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"จ่ายด้วย \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"ตัวเลือกโพลล์\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followed by friends\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Business\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"แก้ไข\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"File storage server list\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"Submit\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media Attachments\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Public Chat\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ชื่อนี้ถูกบล๊อค\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Patches\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Moderation\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"ค้นหาข้อมูลเพิ่มเติมเกี่ยวกับ \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ได้ที่ \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"คัดลอก ID\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"My Relays\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"จัดหาเงินทุนให้กับบริการที่คุณใช้โดยแบ่งส่วนของ zaps ทั้งหมดของคุณออกเป็นกองทุน!\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"ปิดการมองเห็น\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"For you\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไปยัง\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr: URI scheme\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"ผู้ให้บริการ\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"โหลดสื่อโดยอัตโนมัติ\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"หมดอายุ\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"Additional Terms:\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"ค้นหา\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"FAN\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Allow\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"ภาษา\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" eSats\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL หรือ Lightning Address\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular Relays\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Native App\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Draft Long-form Content\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Weight\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"รายชื่อผู้ติดต่อ\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"เจ้าของ\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"ทั้งหมด\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"จำนวน zap ในหน่วย sats\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Chess (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" mins to read\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"ไม่สามารถโหลดบริการ LNURL\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"โชว์โน้ตแบบย่ออัตโนมัติ\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Participants\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/tr_TR.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/uk_UA.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/vi_VN.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to repost: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Payout Now\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Secret Group Chat\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Type\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logins\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Please make sure to save the following password in order to manage your handle in the future\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" reposted\"\n    }\n  ],\n  \"/4tOwT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Skip\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Support\"\n    }\n  ],\n  \"/PCavi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public\"\n    }\n  ],\n  \"/RD0e2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr uses digital signature technology to provide tamper proof notes which can safely be replicated to many relays to provide redundant storage of your content.\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Make your profile easier to find and share\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" ms\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Load more\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Export Keys\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Manage\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search...\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Invalid LNURL\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name has disallowed characters\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" secs\"\n    }\n  ],\n  \"1A7TZk\": [\n    {\n      \"type\": 0,\n      \"value\": \"What is Snort and how does it work?\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to remove this note from bookmarks?\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter Nostr Wallet Connect config\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connected to: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1iQ8GN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Toggle Preview\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Following\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"Conversations\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Banner\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"Donate\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter password\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Bookmarks\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislikes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" hours\"\n    }\n  ],\n  \"3Rx6Qo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Advanced\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"Light\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translators\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"You are voting with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new note\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" new notes\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Followers\"\n    }\n  ],\n  \"3xCwbZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"OR\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"None\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cancel\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Primary Developers\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your new NIP-05 handle is:\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dislike\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs is one of the first NIP-05 providers in the space and offers a good collection of domains at reasonable prices\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Use imgproxy to compress images\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"Note to Self\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"zap\"\n    }\n  ],\n  \"5JcXdV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Create Account\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Handle\"\n    }\n  ],\n  \"5rOdPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Once you setup your key manager extension and generated a key, you can follow our new users flow to setup your profile and help you find some interesting people on Nostr to follow.\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer to Pubkey\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Usernames are not unique on Nostr. The nostr address is your unique human-readable address that is unique to you upon registration.\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send zap\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to proxy image from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \", click here to load directly\"\n    }\n  ],\n  \"6Yfvvp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get an identifier\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Likes (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unpaid\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes\"\n    }\n  ],\n  \"7BX/yC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Account Switcher\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7xzTiH\": [\n    {\n      \"type\": 1,\n      \"value\": \"action\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm Reposts\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too long\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pairing phrase\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Next\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reply\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send\"\n    }\n  ],\n  \"9gqH2W\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Address\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Invoice\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Parent\"\n    }\n  ],\n  \"AGNz71\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap All \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"This author has been muted\"\n    }\n  ],\n  \"Adk34V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup your Profile\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlimited note retention on Snort relay\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason\"\n    }\n  ],\n  \"AnLrRC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Non-Zap\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"name too short\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"zapped\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write access to Snort relay, with 1 year of event retention\"\n    }\n  ],\n  \"BOUMjw\": [\n    {\n      \"type\": 0,\n      \"value\": \"No nostr users found for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"twitterUsername\"\n    }\n  ],\n  \"BOr9z/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is an open source project built by passionate people in their free time\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update\"\n    }\n  ],\n  \"BcGMo+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes hold text content, the most popular usage of these notes is to store \\\"tweet like\\\" messages.\"\n    }\n  ],\n  \"C5xzTC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Premium\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Logout\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Suggested Follows\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load invoice\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending People\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Muted\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translated from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically zap every note when loaded\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Settings\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send sats\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show latest \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" notes\"\n    }\n  ],\n  \"DcL8P+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Auto Zap\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Transfer\"\n    }\n  ],\n  \"E8a4yq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow some popular accounts\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Data Providers\"\n    }\n  ],\n  \"EPYwm7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key is your password. If you lose this key, you will lose access to your account! Copy it and keep it in a safe place. There is no way to reset your private key.\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Global\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translate to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom Relays\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy\"\n    }\n  ],\n  \"Eqjl5K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only Snort and our integration partner identifier gives you a colorful domain name, but you are welcome to use other services too.\"\n    }\n  ],\n  \"F+B3x1\": [\n    {\n      \"type\": 0,\n      \"value\": \"We have also partnered with nostrplebs.com to give you more options\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Account\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Zaps\"\n    }\n  ],\n  \"FP+D3H\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL to forward zaps to\"\n    }\n  ],\n  \"FS3b54\": [\n    {\n      \"type\": 0,\n      \"value\": \"Done!\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Users\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim Now\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"An error has occured!\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"follows you\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Remove\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Select Wallet\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Salt\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Address\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Claim your included Snort nostr address\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Magnet Link\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Dislike\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Key..\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Log Out\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Order Paid!\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name\"\n    }\n  ],\n  \"HF4YnO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Watch Live!\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"name will be available later\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Muted\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"Clear cache and reload\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open Wallet\"\n    }\n  ],\n  \"IDjHJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Thanks for using Snort, please consider donating if you can.\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to unpin this note?\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows\"\n    }\n  ],\n  \"INSqIz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username...\"\n    }\n  ],\n  \"IUZC+0\": [\n    {\n      \"type\": 0,\n      \"value\": \"This means that nobody can modify notes which you have created and everybody can easily verify that the notes they are reading are created by you.\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sent \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Trending Notes\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscriptions\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Username\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"No lightning address\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Repost\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search users\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Website\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Private Key\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Delete\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter LNDHub config\"\n    }\n  ],\n  \"KLo3SP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reason: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"reason\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Deleted\"\n    }\n  ],\n  \"KWuDfz\": [\n    {\n      \"type\": 0,\n      \"value\": \"I have saved my keys, continue\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown event kind: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KoFlZg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter mint URL\"\n    }\n  ],\n  \"LF5kYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Other Connections\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anonymous\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Comment\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Open on Zapstr\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Debug Menus\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Shows \\\"Copy ID\\\" and \\\"Copy Event JSON\\\" in the context menu on each message\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not available:\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"MRp6Ly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Twitter username\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Page\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay for subscription\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy nostr address\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buying \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Confirm\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"You already have a subscription of this type, please renew or pay\"\n    }\n  ],\n  \"NNSu3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Import Twitter Follows\"\n    }\n  ],\n  \"NdOYJJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm nothing here.. Checkout \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to follow some recommended nostrich's!\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, please set a different default zap amount\"\n    }\n  ],\n  \"NfNk2V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your private key\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"New users page\"\n    }\n  ],\n  \"O9GTIc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile picture\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zaps\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown login error\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"You subscription is still active, you can't renew yet\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"Created\"\n    }\n  ],\n  \"P04gQm\": [\n    {\n      \"type\": 0,\n      \"value\": \"All zaps sent to this note will be received by the following LNURL\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy Event JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"System (Default)\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Total today (UTC): \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preferences\"\n    }\n  ],\n  \"PLSbmL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your mnemonic phrase\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown file header: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Theme\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions will be shown on every page, if disabled no reactions will be shown\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Relays\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool only works if you use one of the supported wallet connections (WebLN, LNC, LNDHub or Nostr Wallet Connect)\"\n    }\n  ],\n  \"QawghE\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can change your username at any point.\"\n    }\n  ],\n  \"QxCuTo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Art by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"You currently have \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats in your zap pool.\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscription\"\n    }\n  ],\n  \"R1fEdZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Forward Zaps\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"People you follow\"\n    }\n  ],\n  \"RDZVQL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expired\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"By: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"Are you sure you want to delete \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RjpoYG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Recent\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Relays\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmark\"\n    }\n  ],\n  \"RwFaYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sort\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Update Lightning Address\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Subscription\"\n    }\n  ],\n  \"SX58hM\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address Proxy\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark all read\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Custom\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Now\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"Media in notes will automatically be shown for selected people, otherwise only the link will show\"\n    }\n  ],\n  \"TMfYfY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Cashu token\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hex Salt..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"People\"\n    }\n  ],\n  \"UDYlxu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pending Subscriptions\"\n    }\n  ],\n  \"ULotH9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"New Chat\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Users must accept the content warning to show the content of your note.\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"Block\"\n    }\n  ],\n  \"VBadwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hmm, can't find a key manager extension.. try reloading the page.\"\n    }\n  ],\n  \"VN0+Fz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Balance: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick which upload service you want to upload attachments to\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public key (npub/nprofile)\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" muted\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Avatar\"\n    }\n  ],\n  \"VtPV/B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login with Extension (NIP-07)\"\n    }\n  ],\n  \"VvaJst\": [\n    {\n      \"type\": 0,\n      \"value\": \"View Wallets\"\n    }\n  ],\n  \"Vx7Zm2\": [\n    {\n      \"type\": 0,\n      \"value\": \"How do keys work?\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any subscriptions, you can get one \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Blocked\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unmute\"\n    }\n  ],\n  \"WONP5O\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find your twitter follows on nostr (Data provided by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"provider\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"WxthCV\": [\n    {\n      \"type\": 0,\n      \"value\": \"e.g. Jack\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec, npub, nip-05, hex, mnemonic\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"File hosts\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your default zap amount is \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats, example values are calculated from this.\"\n    }\n  ],\n  \"XrSk2j\": [\n    {\n      \"type\": 0,\n      \"value\": \"Redeem\"\n    }\n  ],\n  \"XzF0aC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Key manager extensions are more secure and allow you to easily login to any Nostr client, here are some well known extensions:\"\n    }\n  ],\n  \"Y31HTH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Help fund the development of Snort\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Service URL\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enable reactions\"\n    }\n  ],\n  \"Z0FDj+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe to Snort \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" and receive the following rewards\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter pairing phrase\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"Activate Now\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contributors\"\n    }\n  ],\n  \"ZUZedV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Donation:\"\n    }\n  ],\n  \"Zr5TMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup profile\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund developers and platforms providing NIP-05 verification services\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Notes will stream in real time into global and notes tab\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show more\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mnemonic\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your handle will act like a lightning address and will redirect to your chosen LNURL or Lightning address\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sensitive Content\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Public Key\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"brAXSu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pick a username\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"Just now\"\n    }\n  ],\n  \"c+oiJe\": [\n    {\n      \"type\": 0,\n      \"value\": \"Install Extension\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you have an enquiry about your NIP-05 order please DM \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Broadcast Again\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Using Alby? Go to \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to get your NWC config!\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute all\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Connect Wallet\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"Multi account support\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is registered\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"d6CyG5\": [\n    {\n      \"type\": 0,\n      \"value\": \"History\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"LN Address\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Display name\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coming soon\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mark All Read\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reaction emoji\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get Verified\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"A single zap of \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats will allocate \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats to the zap pool.\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Group Chat\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't vote because LNURL service does not support zaps\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pinned\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"What's on your mind?\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"Saved\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"About\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to send vote\"\n    }\n  ],\n  \"gBdUXk\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save your keys!\"\n    }\n  ],\n  \"gDZkld\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is a Nostr UI, nostr is a decentralised protocol for saving and distributing \\\"notes\\\".\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Emoji to send when reactiong to a note\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Not all clients support this yet\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"Subscribe\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Loading...\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"Proof of Work\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Badges\"\n    }\n  ],\n  \"hK5ZDk\": [\n    {\n      \"type\": 0,\n      \"value\": \"the world\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Messages\"\n    }\n  ],\n  \"hWSp+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect (NIP-46)\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supports\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"Show replies\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"here\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap Pool\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reactions (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"iDGAbc\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a Snort identifier\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL translations\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"Prevent fake accounts from imitating you\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Handle\"\n    }\n  ],\n  \"iUsU2x\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mint: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"url\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"Can't login with private key on an insecure connection, please use a Nostr key manager extension instead\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Profile\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unfollow\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sat\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" sats\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jCA7Cw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Preview on snort\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"Internal error: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jfV8Wr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Back\"\n    }\n  ],\n  \"juhqvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Improve login security with browser extensions\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Save\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" Reactions\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Write\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Our very own NIP-05 verification service, help support the development of this site and get a shiny special badge on our site!\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" reposted\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others reposted\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"now\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" liked\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" & \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others liked\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Everything in \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    }\n  ],\n  \"lBboHo\": [\n    {\n      \"type\": 0,\n      \"value\": \"If you want to try out some others, check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" for more!\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Buy Now\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr address\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Wallet password\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"account page\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Image proxy service\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"Following \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"Click to load content from \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pay Invoice\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"It looks like you dont have any, check \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" to buy one!\"\n    }\n  ],\n  \"mH91FY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Each contributor will get paid a percentage of all donations and NIP-05 orders, you can see the split amounts below\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follow all\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"File upload service\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"zapped\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mTJFgF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Popular\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Option: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"Switch\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unblock\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Bookmarks\"\n    }\n  ],\n  \"nN9XTz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Share your thoughts with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"nOaArs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Setup Profile\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"Renew\"\n    }\n  ],\n  \"nn1qb3\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your donations are greatly appreciated\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" blocked\"\n    }\n  ],\n  \"o6Uy3d\": [\n    {\n      \"type\": 0,\n      \"value\": \"Only the secret key can be used to publish (sign events), everything else logs you in read-only mode.\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" followers\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nothing found :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"Follows only\"\n    }\n  ],\n  \"odhABf\": [\n    {\n      \"type\": 0,\n      \"value\": \"Login\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Hey, it looks like you dont have a Nostr Address yet, you should get one! Check out \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"osUr8O\": [\n    {\n      \"type\": 0,\n      \"value\": \"You can also use these extensions to login to most Nostr sites.\"\n    }\n  ],\n  \"oxCa4R\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting an identifier helps confirm the real you to people who know you. Many people can have a username @jack, but there is only one jack@cash.app.\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"Upload\"\n    }\n  ],\n  \"p85Uwy\": [\n    {\n      \"type\": 0,\n      \"value\": \"Active Subscriptions\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"Downloadable backups from Snort relay\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Pin\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Followers\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Email <> DM bridge for your Snort nostr address\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unknown error\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Default Zap amount\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"Blocked\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your Private Key Is (do not share this with anyone)\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add to Profile\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Translation failed\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Like\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"Software\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Enter wallet password\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"Add Relays\"\n    }\n  ],\n  \"reJ6SM\": [\n    {\n      \"type\": 0,\n      \"value\": \"It is recommended to use one of the following browser extensions if you are on a desktop computer to secure your key:\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"(Default)\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" days\"\n    }\n  ],\n  \"rrfdTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"This is the same technology which is used by Bitcoin and has been proven to be extremely secure.\"\n    }\n  ],\n  \"rudscU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load follows, please try again later\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"user\"\n    }\n  ],\n  \"sWnYKw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort is designed to have a similar experience to Twitter.\"\n    }\n  ],\n  \"svOoEH\": [\n    {\n      \"type\": 0,\n      \"value\": \"Name-squatting and impersonation is not allowed. Snort and our partners reserve the right to terminate your handle (not your account - nobody can take that away) for violating this rule.\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"Dark\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Send note to a subset of your write relays\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Getting NIP-05 verified can help:\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"Supporter Badge\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paid\"\n    }\n  ],\n  \"u4bHcR\": [\n    {\n      \"type\": 0,\n      \"value\": \"Check out the code here: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"uD/N6c\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"target\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"Reposts need to be manually confirmed\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit Profile\"\n    }\n  ],\n  \"ut+2Cd\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a partner identifier\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"Start chat\"\n    }\n  ],\n  \"vOKedj\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" other\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" others\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"vU71Ez\": [\n    {\n      \"type\": 0,\n      \"value\": \"Paying with \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"wallet\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 is a DNS based verification spec which helps to validate you as a real user.\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"Poll Options\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"Get a free one\"\n    }\n  ],\n  \"vrTOHJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" sats\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Amount of work to apply to all published events\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Edit\"\n    }\n  ],\n  \"wLtRCF\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your key\"\n    }\n  ],\n  \"wWLwvh\": [\n    {\n      \"type\": 0,\n      \"value\": \"Anon\"\n    }\n  ],\n  \"wYSD2L\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Adddress\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"name is blocked\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"Find out more info about \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" at \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"Copy ID\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"Fund the services that you use by splitting a portion of all your zaps into a pool of funds!\"\n    }\n  ],\n  \"x/q8d5\": [\n    {\n      \"type\": 0,\n      \"value\": \"This note has been marked as sensitive, click here to reveal\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Mute\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Votes by \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"Go to\"\n    }\n  ],\n  \"xJ9n2N\": [\n    {\n      \"type\": 0,\n      \"value\": \"Your public key\"\n    }\n  ],\n  \"xKflGN\": [\n    {\n      \"type\": 1,\n      \"value\": \"username\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"'s Follows on Nostr\"\n    }\n  ],\n  \"xQtL3v\": [\n    {\n      \"type\": 0,\n      \"value\": \"Unlock\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"Provider\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically load media\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Expires\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"Search\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"Language\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL or Lightning Address\"\n    }\n  ],\n  \"yCmnnm\": [\n    {\n      \"type\": 0,\n      \"value\": \"Read global from\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"Contact\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Owner\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"All\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap amount in sats\"\n    }\n  ],\n  \"zjJZBd\": [\n    {\n      \"type\": 0,\n      \"value\": \"You're ready!\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"Failed to load LNURL service\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"Automatically show latest notes\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/zh_CN.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"是否确定要转发：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即支出\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"将您个人资料的所有事件同步到本地缓存\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"接力统计\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"已使用写入权限登录\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"秘密群聊\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"打闪种类\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"已关注\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"登录\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"请确保将以下密码妥善保存以便将来管理你的代号\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"连接\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"编辑\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 转发了\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"如你所愿的空间 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"清空\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"帐户支持\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP 文件存储集成\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"发送匿名使用资料\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"群聊信息\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"使你的帐号可更方便地被找到及分享\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"来自文件\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 毫秒\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"加载更多\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 地址不属于你\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"导出密钥\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"管理\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"搜索...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"通用 LNDHub 钱包（BTCPayServer / Alby / LNBits）\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL无效\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"处理提及\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"名称中有禁用字符\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"政治\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"显示状态\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 秒\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"开始\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"git的东西\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"是否确定要从收藏中移除此条笔记？\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"输入 Nostr Wallet Connect 配置\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"请务必备份你的密钥！\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"已连接到：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 个关注\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"检查签名\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"自然\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"聊天\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"添加\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"横幅\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"没有账户？\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"主持社区\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"钱包连接\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"文本事件中的主题标签\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"用户表情符号列表\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"捐赠\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"输入密码\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"完成\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"通用清单\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 个收藏\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"踩 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"新笔记\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"被好友的好友关注\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"特定应用数据\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 小时\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"最新文章\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"答复\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"注册\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"用户状态\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"文章\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"存储在媒体服务器上的 Blob\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 观众\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"浅色\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"翻译人员\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"无标题\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"你正在用 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聪投票\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"条新笔记\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"条新笔记\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 个粉丝\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"钱包\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"活动总数\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"无\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"维基\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"取消\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"投标\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"主要开发人员\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的新 NIP-05 代号是：\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"生活\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"踩\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"私钥加密\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs 是该领域首批 NIP-05 提供商之一，以合理的价格提供大量域名\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用 imgproxy 压缩图片\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"缺少中继器\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"自用笔记\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"推荐的应用程序处理程序\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"打闪\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"打闪拆分\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"通知 API 已启用\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"斩获目标\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"购买代号\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"文件元数据\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"转移到公钥\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"在 nostr 上，用户名不是独特的。Nostr 地址是你的独特的人类可读的地址。\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"发送打闪\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"观看重播\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"静音列表\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"重试\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"连接失败：\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"新关注列表长度 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"从 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 代理图像失败，点击此处直接加载\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"推荐继电器\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"密封\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"原因：\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"寻找 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"并非所有客户端都支持，就算已配置了打闪拆分，你仍然可能会收到一些打闪\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"赞 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"被这些人关注\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"额外的元数据字段和标记\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"未付款\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"切换账户\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"良好\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"笔记\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"代理使用 HODL 发票转发付款，从而隐藏了你的节点的公钥\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"标签\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"维基文章\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"中继信息文件\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"搜索功能\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"离线\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"社区领袖\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"反应\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"模块化文章内容\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"将信任网络之外的人发来的信息静音\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"关闭继电器\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"转发 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"确认转发\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"客户在文本事件中使用 e 和 p 标记的规范\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"回复\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"注册\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"打闪 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聪\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"接收方\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"无效打闪拆分：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"小组主题\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"名称过长\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"bech32编码实体\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"配对词句\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"按照套数\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"分类目录草案\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"下一步\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"回复\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"关注 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"日历 活动 RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"发送\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"隐藏静音笔记\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"重试发布\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 地址\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"闪电发票\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"通用转贴\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"上一层\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 的笔记\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"已被静音的关键词\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"该作者已被静音\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"创建或更新产品\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort 中继器上无限制笔记保留\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"原因\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"伟大\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"游戏\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"创建频道\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"总计\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"推送通知\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"月\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"登录\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"名称过短\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"已打闪\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec、npub、nip-05、十六进制\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"您可以添加单个或多个继电器，每行一个。\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"写入 Snort 中继器的权限，1年的事件保留\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"人工智能嵌入/矢量列表\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"中继群组\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"更新\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"市场用户界面/用户体验\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 地址 (nip05)\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"继电器\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP Auth\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"闪电捐款\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"现场活动\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"引用转贴\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"登出\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"热门服务器\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"推荐关注\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"视频集\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"加载发票失败\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"简介 Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"关注列表\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"清理关注列表\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"热门用户\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"和 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 个你关注的其他人\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"存储库公告\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 已静音\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"日历\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聪\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"翻译自 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"社交图表\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"文字说明 参考资料\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"加载时自动打闪每条笔记\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"徽章定义\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"设置\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"频道隐藏信息\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"缓存\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"发送聪\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"显示最新的 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 条笔记\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"自动打闪\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"直播\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"作为拍卖品出售的产品\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"介绍必须少于 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 个字符\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"转移\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"全部切换\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"浏览器\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"聪\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"发票 / 闪电地址\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"搜索笔记\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"数据提供方\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"在个人档案页面上显示徽章\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"对网站的反应\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"全球\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"翻译成 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"成套的策划\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"自定义中继器\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"用户名可用\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"密钥\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"链上捐赠地址\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"购买\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"很抱歉，我们不了解此事件类型 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")，请尝试以下应用程序！\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"服务器\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"添加帐户\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"分类列表\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 次打闪\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"钱包响应\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"客户端与中继器之间的身份验证\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"在个人档案页面上显示状态消息\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"热门用户\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"用户组\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"重定向将 HTTP 重定向到所提供的闪电地址\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即领取\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"发生错误！\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"正在关注你\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"帐户\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"您没有任何媒体服务器，请尝试添加一些。\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"移除\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"选择钱包\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"已订阅推送通知\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"盐\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"支持的国家实施计划\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"收藏 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"闪电地址\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"认领你包含的 Snort nostr 地址\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"磁力链接\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"下载\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"闪电地址无效\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 踩\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"广播事件\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"十六进制密钥...\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"处理未知事件\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"登出\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"领袖信息\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"书签列表\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"订单已支付！\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"名称\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"名称稍后可用\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"已静音\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"清除缓存并重新加载\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"打开钱包\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"你不关注这个用户，点击此处从\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"加载多媒体，或更新\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"你的选项\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"来自动加载来自任何人的多媒体。\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"继电器评论\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"支持\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"到期时间戳\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"创建或更新摊位\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"最近发布 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"是否确定要取消置顶此条笔记？\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"账户数据\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"关注\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"你必须是 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 订阅者，才能访问 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 面板\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"打闪所有 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聪\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"自动翻译\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"最后一次露面\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"向 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 发送了 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聪\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"未被你关注的任何人关注\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"仍然要加载点击这里\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"已连接\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"热门笔记\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"订阅\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"未允许通知\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用逗号分隔单词，如 word1, word2, word3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"表情符号集\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"用户名\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"将聪发送到 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"打闪 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"体育\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"没有闪电地址\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"以 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 订阅 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 并获得以下奖励\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"转发\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"搜索继电器列表\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"搜索用户\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"网站\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"中继器是您连接的服务器，用于发送和接收事件。目标是 4-8 个中继器。\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"私钥\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"平均延迟：\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"删除\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"显示\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"外部内容 ID\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"输入 LNDHub 配置\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"亮点\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"即时聊天信息\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"已删除\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"受保护事件\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"未知事件类型：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"将 Nostr 密钥映射到基于 DNS 的互联网标识符\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"输入 PIN 码\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"钱包申请\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"以用户身份查看？\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"斩获目标\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"在此处查看代码：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"PIN 码太短了\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"匿名\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"评论\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"名称长度必须介于8~15个字符\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"无法验证 Nostr 地址\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"在 Zapstr 上打开\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"下载\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"已打闪\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"和\"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"个其他用户已打闪\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"此笔记上的打闪将被拆分给以下用户。\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"调试菜单\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"成为领袖\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"在每条消息的上下文菜单中显示“复制 ID”和“复制事件 JSON”\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"无法使用：\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"加盟房间\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"钱包密码\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"默认页面\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"简短文字说明\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"客户端验证\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"设置为主要 Nostr 地址 (nip05)\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"代理标签\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"将此链接发送给你的好友，分享 Nostr 的魅力。\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"支付订阅\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"购买 nostr 地址\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"计算结果\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"购买\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.to 帐户\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"确认\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"通知\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"你已经有此类型的订阅，请续订或支付\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"工作反馈\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"无法用\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"聪投票，请设置一个不同的默认打闪金额\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"新用户页面\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"转贴\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"死亡\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用你的邀请码赚取聪！\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"打闪\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"事件的 OpenTimestamps 证明\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"礼品包装\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"分享\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"未知登录错误\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"获取一个免费的 nostr 地址\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的订阅仍然活跃，你还不能续订\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"已创建\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"合并请求\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"更新失败，请重试\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"长篇内容\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"扫描 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 地址无效\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"复制事件 JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"系统（默认）\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"今天总计 (UTC)：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聪\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"距离\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"选项\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"接收至 \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"未知文件标头：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"主题\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"回应将在每个页面上显示，如果禁用则不会显示任何回应\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 个中继器\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"私钥就像密码，但无法重置。请小心保管，千万不要给任何人看。一旦有人拿到了你的私钥，他们就可以永远访问你的账户。\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"打闪池只有当你使用支持的钱包连接（WebLN、LNC、LNDHub 或 Nostr Wallet Connect）时才能启用\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"频道信息\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"目前你的打闪池中有 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聪。\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"私人直接信息\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"订阅\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"你关注的用户\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"服务工作程序未运行\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"存储库状态公告\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"用户名必须只包含小写字母和数字\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"已过期\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"短篇肖像视频活动\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"作者：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"是否确定要删除 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"数据自动售货机\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"中继器\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"收藏\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"加载说明： \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"权限\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"输入密码来加密私人密钥，每次打开 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"时都必须输入该密码。\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"将打闪发送到 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"更新闪电地址\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"购买订阅\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"您关注的人使用的热门中继器。\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"闪电地址代理\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"继电器组\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"问题跟踪器\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"全标已读\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"自定义\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"我们该怎么称呼你？\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即支付\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"特定应用数据\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"作者已将此笔记标记为\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"敏感主题\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"地理位置附近的中继站\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"笔记中的媒体将自动显示给选定的人，否则只会显示链接\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"处理程序信息\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"预览\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用本地中继器\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"已结束\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用 Nostr 扩展登录\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"了解更多\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"加密货币\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"兴趣小组\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"日历活动\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"十六进制盐..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"用户\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"已点赞\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"账户\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"停止收听\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"社区定义\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"从我的中继器中移除\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"接收\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"检查从中继站收到的所有赛事签名\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"新聊天\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"用户必须接受内容警告才能显示你的笔记的内容。\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"添加服务器\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"登录\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"屏蔽\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的申请正在处理中\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"你有一个活跃的 iris.to 帐户\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"与朋友分享个性化邀请函！\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的邀请代码是 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"标签\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"选择你要将附件上传到哪个上传服务\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"公钥 (npub/nprofile)\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"好的\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"要查看全部更改列表，请在此查看更新日志： \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 已静音\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"头像\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"看起来你没有任何订阅，你可以获取一个\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 已屏蔽\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"当地\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"解除静音\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"来自服务器\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"问题\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"自动将笔记翻译成你的本地语言\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / nostr 地址\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用密钥登录\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec、npub、NIP-05、十六进制、助记词句\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"发送使用资料\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"文件主机\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alby 钱包连接\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"关注中继器健康\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"兑换\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"热门话题标签\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"回应\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"从 \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 发送\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的默认打闪金额是 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聪，示例值是以此计算的。\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"用户\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"服务网址\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"流行的媒体服务器。\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"看起来你关注的人还不够多，请访问 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 发掘要关注的人！\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"没有密钥，就没有 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"，如果不备份，就无法重置。这只需要一分钟。\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"公开聊天\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"启用回应\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"连接钱包以发送即时付款\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"尝试另一个继电器\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"频道元数据\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"输入配对词句\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"委托活动签署\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"撰写便条\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即激活\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"贡献者\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"将打闪拆分发送到\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"用户名 iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 已为你保留！\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"加密直接消息\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 邀请你访问 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"媒体服务器存储媒体，您可以在笔记中分享图片和视频\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"资助提供 NIP-05 验证服务的开发人员和平台\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"笔记将实时流式传输到全球和帖子选项卡\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"姓名\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"支持的扩展\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"支付 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聪，付费 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聪\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用 Lightning Node Connect 连接你自己的 LND 节点\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"显示更多\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 公里\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"邀请朋友\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"助记词\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的代号将像闪电地址一样重定向至你所选的 LNURL 或闪电地址\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"你已成为社区领袖，并可从邀请用户的订阅中赚取 \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"！\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"服务工作程序正在运行\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"计算剪枝列表\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"获取地址\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"以只读权限登录\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"敏感内容\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"公钥\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"匿名\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"刚刚\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"善意静音套\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"不，谢谢\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"重定向\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"如果你对 NIP-05 订单有任何疑问，请私信 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"再次广播\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用 Alby？前往 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 来配置你的 NWC！\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"原生 nostr 钱包连接\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"摄影\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"直接留言\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"关注\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"网址..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"媒体服务器\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"全部静音\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"连接钱包\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"打开时间戳\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"多帐户支持\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"名称已被注册\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"现场活动\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"返回\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"应静音的列表：\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"WoT 过滤器\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"未订阅推送\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"闪电地址\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"公钥就像你的用户名，你可以分享给任何人。\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"显示名称\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"模块化文章标题\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"热门标签\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"注册\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"聪金额\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"分类列表\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"已为 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 开发人员配置了 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 的默认打闪池分割，你随时可以在 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"中禁用它。\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"类别\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"即将上线\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"输入 PIN 码解锁你的私钥\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"全标已读\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用 nostr 签名器扩展登录\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"回应表情符号\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"获取验证\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"一个 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聪的打闪将分配 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聪给打闪池。\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"喂食\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"群聊\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"网络浏览器的 window.nostr 功能\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 个其他\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 个其他\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"首页\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"贫穷\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"社区领袖是指通过活跃于当地社区并帮助新用户加入而发展 nostr 生态系统的个人。任何人都可以成为社区领袖，但目前拥有这一荣誉称号的人寥寥无几。\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"转储\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"打闪\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"感谢你使用 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"，请考虑捐赠。\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort 是一个开放源码项目，由热心人士利用业余时间创建，我们非常欢迎你的捐赠。\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"无法投票，因为LNURL 服务不支持打闪\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"显示有内容警告标签的帖子\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"已置顶\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"选择几个感兴趣的主题\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"读\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"礼品包装\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"你在想些什么？\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"链上捐款\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"已保存\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"附加媒体\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"观看直播\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"介绍\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"发送投票失败\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"回应笔记时发送的表情符号\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"并非所有客户端都支持此功能\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"订阅\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" in memory)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"加载中...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"安卓签名应用程序\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"列表\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"用户服务器列表\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"工作量证明\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"基本协议流程说明\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 在一起更有趣！\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"徽章\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"用户元数据\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"修剪关注列表\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"同步账户\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"消息\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"专业\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"支持\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"邀请\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"显示回复\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"多媒体\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"这里\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"受阻中继列表\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"互动\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"打闪池\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"你已发送和收到的付款将显示在此处。\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"回应（\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"）\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL 翻译\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"防止虚假帐户冒充你\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"管理员\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 个关注 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 个重复)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"代号\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"无法在不安全的连接上使用私钥登录，请使用Nostr密钥管理器扩展程序\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"付款\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"新用户页面\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"关注\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"群组聊天主题回复\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"生成发票\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"个人档案\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"取消关注\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"已备份\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"聪\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"聪\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 订阅已过期\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"清理你的订阅\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"内部错误: \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"视频活动\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"保存\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 个回应\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即申请\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"写\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"我们自己的 NIP-05 验证服务，帮助支持本站的发展，并在我们的网站上获得闪亮的特殊徽章！\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"您以前连接过并且看起来可靠的继电器。\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"注册 Iris 用户名\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"已转发\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"和\"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"个其他用户已转发\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"钱包信息\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"潮汐登录\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"选择\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"现在\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"话题\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"社区职位审批\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"配置打闪池\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"已点赞\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"和\"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"个其他用户已点赞\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"提供\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"邀请你的好友\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"从记忆性种子短语导出基本密钥\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即购买\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"付款\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"我的活动 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort 的 Nostr 地址\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"钱包密码\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"复制链接\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"非斩击\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"帐户页面\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"图片代理服务\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"关注 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"点击以从 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 加载内容\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"支付发票\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"扎普请求\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"处理人建议\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 音符已经哑了\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"看起来你没有 nostr 地址，查看 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 以购买！\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 工人接力\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"关注所有\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"文件上传服务\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"已打闪\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"已打闪\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"开始\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"选项：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"只读\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"切换\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"基于时间的日历事件\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"米字节\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"投标确认\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"解除屏蔽\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"收藏\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"已允许通知\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"正在搜索帐户活动 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"共同加入游泳池\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"工具\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"更新\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"聆听本文\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 已屏蔽\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"面板\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 个粉丝\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"什么都没找到 :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"仅关注\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"嘿，看起来你还没有 Nostr 地址，你应该去获取一个！查看 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"徽章奖\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"上传\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 有中继器 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"可靠的继电器\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"可从 Snort 中继器下载备份\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"打闪池\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"自定义表情符号\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"频道静音用户\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"置顶\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace（用于弹性市场）\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"粉丝\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"转播评论\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"基于日期的日历事件\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"小组主题回复\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"给你的 Snort Nostr 地址建立电子邮件 <> 私信桥\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"未知错误\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"简介徽章\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"笔记\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"默认打闪金额\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"已屏蔽\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"解锁\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"更新 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"通知 API 已禁用\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的私钥是（不要与任何人分享）\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"该笔记已被静音\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"添加至个人档案\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"翻译失败\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"点赞\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"显示更少\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"科学\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"PIN 码不正确\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"软件\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"输入钱包密码\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"中继列表元数据\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"公开聊天列表\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即备份\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"闪电斩击\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"添加中继\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"报告\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"（默认）\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"加密直接信息\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 天\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"公开聊天频道\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"短链接\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"书签集\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"显示徽章\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"用户\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"解析打闪拆分失败了：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"显示的中继名称与输入的完整 URL 不一致。\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"事件删除请求\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"已静音笔记将不显示\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"连接成功：\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"兴趣列表\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"发布人工制品集\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"视频活动\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"深色\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"版本化加密\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"未知 NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"视频观看活动\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"免费\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"将笔记发送到你的写入中继器的子集\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"验证 NIP-05 可以帮助：\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聪\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"中继器指标\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"支持者徽章\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"现状\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"已付款\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"针脚列表\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"正常运行时间\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"名称必须少于 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 个字符\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"已有账户？\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"档案中的外部身份\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"接收 DM 的中继列表\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"转发需要人工确认\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"将聪拆分发送到\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"发现 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 个事件\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"公众\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 条笔记\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"编辑个人档案\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"开始聊天\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"必须是一个联系人列表或公钥列表\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"社区名单\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"简介图片\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"该工具将搜索所有关注最近发布的事件，并删除6个月内未发布事件的关注。\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 是一种基于 DNS 的验证规范，可帮助验证你是真实用户。\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"投票选项\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"获取免费的\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"好友关注\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"适用于所有发布事件的工作量\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"商业\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"NSFW\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"编辑\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"文件存储服务器列表\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"提交\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"媒体附件\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 公开聊天\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"名称已被屏蔽\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"补丁\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"审核\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"在 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 了解有关 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 的更多信息\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"复制 ID\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"我的继电器\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"将部分打闪分配到资金库来资助你使用的服务！\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"静音\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"为你推荐\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"根据 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 的投票\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"前往\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr：URI 方案\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"提供方\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"自动加载媒体\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"有效期\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"附加条款：\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"搜索\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"粉丝\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"允许\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"语言\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 电子卫星\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL 或闪电地址\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"热门继电器\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"本地应用程序\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"调试\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"起草长篇内容\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"权重\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"联系人\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"所有者\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"全部\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"以聪为单位的打闪金额\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"国际象棋 (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 分钟阅读时间\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"加载 LNURL 服务失败\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"自动显示最新笔记\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"与会者\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/translations/zh_TW.json",
    "content": "{\n  \"+D82kt\": [\n    {\n      \"type\": 0,\n      \"value\": \"是否確定要轉發：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"+PzQ9Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即支出\"\n    }\n  ],\n  \"+QM0PJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"將你的個人檔案的所有事件同步至本機快取\"\n    }\n  ],\n  \"+QMdsy\": [\n    {\n      \"type\": 0,\n      \"value\": \"接力統計\"\n    }\n  ],\n  \"+UjDmN\": [\n    {\n      \"type\": 0,\n      \"value\": \"已使用寫入權限登錄\"\n    }\n  ],\n  \"+Vxixo\": [\n    {\n      \"type\": 0,\n      \"value\": \"祕密羣聊\"\n    }\n  ],\n  \"+aZY2h\": [\n    {\n      \"type\": 0,\n      \"value\": \"打閃種類\"\n    }\n  ],\n  \"+tShPg\": [\n    {\n      \"type\": 0,\n      \"value\": \"已關注\"\n    }\n  ],\n  \"+vA//S\": [\n    {\n      \"type\": 0,\n      \"value\": \"登錄\"\n    }\n  ],\n  \"+vIQlC\": [\n    {\n      \"type\": 0,\n      \"value\": \"請確保將以下密碼妥善保存以便將來管理你的代號\"\n    }\n  ],\n  \"+vVZ/G\": [\n    {\n      \"type\": 0,\n      \"value\": \"連接\"\n    }\n  ],\n  \"+vj0U3\": [\n    {\n      \"type\": 0,\n      \"value\": \"編輯\"\n    }\n  ],\n  \"+xliwN\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 轉發了\"\n    }\n  ],\n  \"/B8zwF\": [\n    {\n      \"type\": 0,\n      \"value\": \"如你所願的空間 😌\"\n    }\n  ],\n  \"/GCoTA\": [\n    {\n      \"type\": 0,\n      \"value\": \"清除\"\n    }\n  ],\n  \"/JE/X+\": [\n    {\n      \"type\": 0,\n      \"value\": \"帳戶支持\"\n    }\n  ],\n  \"/T7HId\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP 檔案儲存整合\"\n    }\n  ],\n  \"/Xf4UW\": [\n    {\n      \"type\": 0,\n      \"value\": \"傳送匿名使用資料\"\n    }\n  ],\n  \"/b1IHW\": [\n    {\n      \"type\": 0,\n      \"value\": \"群聊訊息\"\n    }\n  ],\n  \"/d6vEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"使你的帳號可更方便地被找到及分享\"\n    }\n  ],\n  \"/ioUrF\": [\n    {\n      \"type\": 0,\n      \"value\": \"從檔案\"\n    }\n  ],\n  \"/n5KSF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 毫秒\"\n    }\n  ],\n  \"00LcfG\": [\n    {\n      \"type\": 0,\n      \"value\": \"加載更多\"\n    }\n  ],\n  \"01iNut\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 地址不屬於你\"\n    }\n  ],\n  \"08zn6O\": [\n    {\n      \"type\": 0,\n      \"value\": \"導出密鑰\"\n    }\n  ],\n  \"0Azlrb\": [\n    {\n      \"type\": 0,\n      \"value\": \"管理\"\n    }\n  ],\n  \"0BUTMv\": [\n    {\n      \"type\": 0,\n      \"value\": \"搜索...\"\n    }\n  ],\n  \"0MndVW\": [\n    {\n      \"type\": 0,\n      \"value\": \"通用 LNDHub 錢包（BTCPayServer / Alby / LNBits）\"\n    }\n  ],\n  \"0jOEtS\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL 無效\"\n    }\n  ],\n  \"0kOBMu\": [\n    {\n      \"type\": 0,\n      \"value\": \"處理提及\"\n    }\n  ],\n  \"0mch2Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"名稱中有禁用字符\"\n    }\n  ],\n  \"0siT4z\": [\n    {\n      \"type\": 0,\n      \"value\": \"政治\"\n    }\n  ],\n  \"0uoY11\": [\n    {\n      \"type\": 0,\n      \"value\": \"顯示狀態\"\n    }\n  ],\n  \"0yO7wF\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 秒\"\n    }\n  ],\n  \"0zASjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"開始\"\n    }\n  ],\n  \"1/BFEj\": [\n    {\n      \"type\": 0,\n      \"value\": \"git 的東西\"\n    }\n  ],\n  \"1Mo59U\": [\n    {\n      \"type\": 0,\n      \"value\": \"是否確定要從收藏中移除此條筆記？\"\n    }\n  ],\n  \"1R43+L\": [\n    {\n      \"type\": 0,\n      \"value\": \"輸入 Nostr Wallet Connect 配置\"\n    }\n  ],\n  \"1UWegE\": [\n    {\n      \"type\": 0,\n      \"value\": \"請務必備份你的密鑰！\"\n    }\n  ],\n  \"1c4YST\": [\n    {\n      \"type\": 0,\n      \"value\": \"已連接到：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"node\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 🎉\"\n    }\n  ],\n  \"1nYUGC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 個關注\"\n    }\n  ],\n  \"1o2BgB\": [\n    {\n      \"type\": 0,\n      \"value\": \"檢查簽名\"\n    }\n  ],\n  \"1ozeyg\": [\n    {\n      \"type\": 0,\n      \"value\": \"自然\"\n    }\n  ],\n  \"1udzha\": [\n    {\n      \"type\": 0,\n      \"value\": \"對話\"\n    }\n  ],\n  \"2/2yg+\": [\n    {\n      \"type\": 0,\n      \"value\": \"添加\"\n    }\n  ],\n  \"25V4l1\": [\n    {\n      \"type\": 0,\n      \"value\": \"橫幅\"\n    }\n  ],\n  \"25WwxF\": [\n    {\n      \"type\": 0,\n      \"value\": \"沒有帳戶？\"\n    }\n  ],\n  \"28oKbu\": [\n    {\n      \"type\": 0,\n      \"value\": \"管理的社群\"\n    }\n  ],\n  \"29sHFE\": [\n    {\n      \"type\": 0,\n      \"value\": \"錢包連線\"\n    }\n  ],\n  \"2BBGxX\": [\n    {\n      \"type\": 0,\n      \"value\": \"文字事件中的主題標籤\"\n    }\n  ],\n  \"2HIqeO\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用者表情符號清單\"\n    }\n  ],\n  \"2IFGap\": [\n    {\n      \"type\": 0,\n      \"value\": \"捐贈\"\n    }\n  ],\n  \"2LbrkB\": [\n    {\n      \"type\": 0,\n      \"value\": \"輸入密碼\"\n    }\n  ],\n  \"2O2sfp\": [\n    {\n      \"type\": 0,\n      \"value\": \"完成\"\n    }\n  ],\n  \"2Qsf9/\": [\n    {\n      \"type\": 0,\n      \"value\": \"通用清單\"\n    }\n  ],\n  \"2a2YiP\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 個收藏\"\n    }\n  ],\n  \"2k0Cv+\": [\n    {\n      \"type\": 0,\n      \"value\": \"踩 （\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"）\"\n    }\n  ],\n  \"2mcwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"新筆記\"\n    }\n  ],\n  \"2oCF7O\": [\n    {\n      \"type\": 0,\n      \"value\": \"被好友的好友關注\"\n    }\n  ],\n  \"2raFAu\": [\n    {\n      \"type\": 0,\n      \"value\": \"應用程式特定資料\"\n    }\n  ],\n  \"2ukA4d\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"小時\"\n    }\n  ],\n  \"2z7Kky\": [\n    {\n      \"type\": 0,\n      \"value\": \"最新文章\"\n    }\n  ],\n  \"3/onCd\": [\n    {\n      \"type\": 0,\n      \"value\": \"回覆\"\n    }\n  ],\n  \"39AHJm\": [\n    {\n      \"type\": 0,\n      \"value\": \"註冊\"\n    }\n  ],\n  \"3GWu6/\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用者狀態\"\n    }\n  ],\n  \"3KNMbJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"文章\"\n    }\n  ],\n  \"3MKdAw\": [\n    {\n      \"type\": 0,\n      \"value\": \"儲存在媒體伺服器上的 Blob\"\n    }\n  ],\n  \"3QwfJR\": [\n    {\n      \"type\": 0,\n      \"value\": \"~\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    }\n  ],\n  \"3adEeb\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 觀眾\"\n    }\n  ],\n  \"3cc4Ct\": [\n    {\n      \"type\": 0,\n      \"value\": \"淺色\"\n    }\n  ],\n  \"3gOsZq\": [\n    {\n      \"type\": 0,\n      \"value\": \"翻譯人員\"\n    }\n  ],\n  \"3kbIhS\": [\n    {\n      \"type\": 0,\n      \"value\": \"無題\"\n    }\n  ],\n  \"3qnJlS\": [\n    {\n      \"type\": 0,\n      \"value\": \"你正在用\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"聰投票\"\n    }\n  ],\n  \"3t3kok\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"條新筆記\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"條新筆記\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"3tVy+Z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 個粉絲\"\n    }\n  ],\n  \"3yk8fB\": [\n    {\n      \"type\": 0,\n      \"value\": \"錢包\"\n    }\n  ],\n  \"40VR6s\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Connect\"\n    }\n  ],\n  \"41BSaT\": [\n    {\n      \"type\": 0,\n      \"value\": \"活動總數：\"\n    }\n  ],\n  \"450Fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"無\"\n    }\n  ],\n  \"47E53q\": [\n    {\n      \"type\": 0,\n      \"value\": \"維基\"\n    }\n  ],\n  \"47FYwb\": [\n    {\n      \"type\": 0,\n      \"value\": \"取消\"\n    }\n  ],\n  \"48zn4v\": [\n    {\n      \"type\": 0,\n      \"value\": \"出價\"\n    }\n  ],\n  \"4IPzdn\": [\n    {\n      \"type\": 0,\n      \"value\": \"主要開發人員\"\n    }\n  ],\n  \"4L2vUY\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的新 NIP-05 代號是：\"\n    }\n  ],\n  \"4MjsHk\": [\n    {\n      \"type\": 0,\n      \"value\": \"生活\"\n    }\n  ],\n  \"4OB335\": [\n    {\n      \"type\": 0,\n      \"value\": \"踩\"\n    }\n  ],\n  \"4P/kKm\": [\n    {\n      \"type\": 0,\n      \"value\": \"私密金鑰加密\"\n    }\n  ],\n  \"4Vmpt4\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Plebs 是該領域首批 NIP-05 供應商之一，以合理的價格提供大量域名\"\n    }\n  ],\n  \"4Z3t5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用 imgproxy 壓縮圖片\"\n    }\n  ],\n  \"4emo2p\": [\n    {\n      \"type\": 0,\n      \"value\": \"缺少中繼器\"\n    }\n  ],\n  \"4rYCjn\": [\n    {\n      \"type\": 0,\n      \"value\": \"自用筆記\"\n    }\n  ],\n  \"4wgYpI\": [\n    {\n      \"type\": 0,\n      \"value\": \"推薦的應用處理程式\"\n    }\n  ],\n  \"5BVs2e\": [\n    {\n      \"type\": 0,\n      \"value\": \"打閃\"\n    }\n  ],\n  \"5CB6zB\": [\n    {\n      \"type\": 0,\n      \"value\": \"打閃拆分\"\n    }\n  ],\n  \"5PRWs7\": [\n    {\n      \"type\": 0,\n      \"value\": \"已啟用通知 API\"\n    }\n  ],\n  \"5dfmvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap 目標\"\n    }\n  ],\n  \"5oTnfy\": [\n    {\n      \"type\": 0,\n      \"value\": \"購買代號\"\n    }\n  ],\n  \"5qEWCr\": [\n    {\n      \"type\": 0,\n      \"value\": \"檔案元資料\"\n    }\n  ],\n  \"5u6iEc\": [\n    {\n      \"type\": 0,\n      \"value\": \"轉移到公鑰\"\n    }\n  ],\n  \"5vMmmR\": [\n    {\n      \"type\": 0,\n      \"value\": \"在 nostr 上，用戶名不是獨特的。Nostr 地址是你的獨特的人類可讀的地址。\"\n    }\n  ],\n  \"5ykRmX\": [\n    {\n      \"type\": 0,\n      \"value\": \"發送打閃\"\n    }\n  ],\n  \"6/hB3S\": [\n    {\n      \"type\": 0,\n      \"value\": \"觀看重播\"\n    }\n  ],\n  \"60kEE3\": [\n    {\n      \"type\": 0,\n      \"value\": \"靜音清單\"\n    }\n  ],\n  \"62nsdy\": [\n    {\n      \"type\": 0,\n      \"value\": \"重試\"\n    }\n  ],\n  \"634VVz\": [\n    {\n      \"type\": 0,\n      \"value\": \"連線失敗：\"\n    }\n  ],\n  \"6559gb\": [\n    {\n      \"type\": 0,\n      \"value\": \"新關注列表長度 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"length\"\n    }\n  ],\n  \"65BmHb\": [\n    {\n      \"type\": 0,\n      \"value\": \"從 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"host\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 代理圖像失敗，點擊此處直接加載\"\n    }\n  ],\n  \"6D4Hhn\": [\n    {\n      \"type\": 0,\n      \"value\": \"推薦繼電器\"\n    }\n  ],\n  \"6KGebm\": [\n    {\n      \"type\": 0,\n      \"value\": \"密封\"\n    }\n  ],\n  \"6OSOXl\": [\n    {\n      \"type\": 0,\n      \"value\": \"原因：\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"reason\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"6WWD34\": [\n    {\n      \"type\": 0,\n      \"value\": \"尋找 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"noteId\"\n    }\n  ],\n  \"6bgpn+\": [\n    {\n      \"type\": 0,\n      \"value\": \"並非所有客戶端都支持，就算已配置了打閃拆分，你仍然可能會收到一些打閃\"\n    }\n  ],\n  \"6ewQqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"贊（\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"）\"\n    }\n  ],\n  \"6mr8WU\": [\n    {\n      \"type\": 0,\n      \"value\": \"被這些人關注\"\n    }\n  ],\n  \"6pdxsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"額外的元資料欄位和標籤\"\n    }\n  ],\n  \"6uMqL1\": [\n    {\n      \"type\": 0,\n      \"value\": \"未付款\"\n    }\n  ],\n  \"6xNr8c\": [\n    {\n      \"type\": 0,\n      \"value\": \"切換帳戶\"\n    }\n  ],\n  \"6xap9L\": [\n    {\n      \"type\": 0,\n      \"value\": \"良好\"\n    }\n  ],\n  \"7+Domh\": [\n    {\n      \"type\": 0,\n      \"value\": \"筆記\"\n    }\n  ],\n  \"712i26\": [\n    {\n      \"type\": 0,\n      \"value\": \"代理使用 HODL 發票轉發付款，從而隱藏了你的節點的公鑰\"\n    }\n  ],\n  \"753yX5\": [\n    {\n      \"type\": 0,\n      \"value\": \"標籤\"\n    }\n  ],\n  \"769A8p\": [\n    {\n      \"type\": 0,\n      \"value\": \"維基文章\"\n    }\n  ],\n  \"77nkEO\": [\n    {\n      \"type\": 0,\n      \"value\": \"中繼資訊文件\"\n    }\n  ],\n  \"7LFU8U\": [\n    {\n      \"type\": 0,\n      \"value\": \"搜尋能力\"\n    }\n  ],\n  \"7UOvbT\": [\n    {\n      \"type\": 0,\n      \"value\": \"離線\"\n    }\n  ],\n  \"7YkSA2\": [\n    {\n      \"type\": 0,\n      \"value\": \"社區領袖\"\n    }\n  ],\n  \"7gMmSL\": [\n    {\n      \"type\": 0,\n      \"value\": \"反應\"\n    }\n  ],\n  \"7hp70g\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05\"\n    }\n  ],\n  \"7jfPsW\": [\n    {\n      \"type\": 0,\n      \"value\": \"模組化文章內容\"\n    }\n  ],\n  \"7nAz/z\": [\n    {\n      \"type\": 0,\n      \"value\": \"將不屬於您信任網的人的筆記設定為靜音\"\n    }\n  ],\n  \"7pFGAQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"關閉繼電器\"\n    }\n  ],\n  \"8/vBbP\": [\n    {\n      \"type\": 0,\n      \"value\": \"轉發（\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"）\"\n    }\n  ],\n  \"89q5wc\": [\n    {\n      \"type\": 0,\n      \"value\": \"確認轉發\"\n    }\n  ],\n  \"8BDFvJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"客戶在文字事件中使用 e 和 p 標籤的慣例\"\n    }\n  ],\n  \"8ED/4u\": [\n    {\n      \"type\": 0,\n      \"value\": \"回覆\"\n    }\n  ],\n  \"8HJxXG\": [\n    {\n      \"type\": 0,\n      \"value\": \"註冊\"\n    }\n  ],\n  \"8QDesP\": [\n    {\n      \"type\": 0,\n      \"value\": \"打閃 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聰\"\n    }\n  ],\n  \"8Rkoyb\": [\n    {\n      \"type\": 0,\n      \"value\": \"接收方\"\n    }\n  ],\n  \"8Y6bZQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"無效打閃拆分：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"8ZGqWl\": [\n    {\n      \"type\": 0,\n      \"value\": \"群組主題\"\n    }\n  ],\n  \"8g2vyB\": [\n    {\n      \"type\": 0,\n      \"value\": \"名稱過長\"\n    }\n  ],\n  \"8jmwT8\": [\n    {\n      \"type\": 0,\n      \"value\": \"bech32 編碼的實體\"\n    }\n  ],\n  \"8v1NN+\": [\n    {\n      \"type\": 0,\n      \"value\": \"配對詞句\"\n    }\n  ],\n  \"8xdDLn\": [\n    {\n      \"type\": 0,\n      \"value\": \"遵循套裝\"\n    }\n  ],\n  \"8za9Pq\": [\n    {\n      \"type\": 0,\n      \"value\": \"分類列表草案\"\n    }\n  ],\n  \"9+Ddtu\": [\n    {\n      \"type\": 0,\n      \"value\": \"下一步\"\n    }\n  ],\n  \"9HU8vw\": [\n    {\n      \"type\": 0,\n      \"value\": \"回覆\"\n    }\n  ],\n  \"9SvQep\": [\n    {\n      \"type\": 0,\n      \"value\": \"關注 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"9V0wg3\": [\n    {\n      \"type\": 0,\n      \"value\": \"日曆活動 RSVP\"\n    }\n  ],\n  \"9WRlF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"發送\"\n    }\n  ],\n  \"9kO0VQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"隱藏已靜音筆記\"\n    }\n  ],\n  \"9kSari\": [\n    {\n      \"type\": 0,\n      \"value\": \"重試發布\"\n    }\n  ],\n  \"9pMqYs\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 地址\"\n    }\n  ],\n  \"9wO4wJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"閃電發票\"\n    }\n  ],\n  \"A86fJ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"通用轉貼\"\n    }\n  ],\n  \"ADmfQT\": [\n    {\n      \"type\": 0,\n      \"value\": \"上一層\"\n    }\n  ],\n  \"ALdW69\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 的筆記\"\n    }\n  ],\n  \"AN0Z7Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"已被靜音的關鍵詞\"\n    }\n  ],\n  \"ASRK0S\": [\n    {\n      \"type\": 0,\n      \"value\": \"该作者已被静音\"\n    }\n  ],\n  \"AedFVZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"建立或更新產品\"\n    }\n  ],\n  \"Ai8VHU\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort 中繼器上無限制筆記保留\"\n    }\n  ],\n  \"AkCxS/\": [\n    {\n      \"type\": 0,\n      \"value\": \"原因\"\n    }\n  ],\n  \"AktAk2\": [\n    {\n      \"type\": 0,\n      \"value\": \"偉大\"\n    }\n  ],\n  \"Am8glJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"遊戲\"\n    }\n  ],\n  \"AqGfF4\": [\n    {\n      \"type\": 0,\n      \"value\": \"頻道建立\"\n    }\n  ],\n  \"Aujn2T\": [\n    {\n      \"type\": 0,\n      \"value\": \"總計\"\n    }\n  ],\n  \"Awq32I\": [\n    {\n      \"type\": 0,\n      \"value\": \"推送通知\"\n    }\n  ],\n  \"AxDOiG\": [\n    {\n      \"type\": 0,\n      \"value\": \"月\"\n    }\n  ],\n  \"AyGauy\": [\n    {\n      \"type\": 0,\n      \"value\": \"登錄\"\n    }\n  ],\n  \"B4C47Y\": [\n    {\n      \"type\": 0,\n      \"value\": \"名稱過短\"\n    }\n  ],\n  \"B6+XJy\": [\n    {\n      \"type\": 0,\n      \"value\": \"已打閃\"\n    }\n  ],\n  \"B6H7eJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec、npub、nip-05、十六進制\"\n    }\n  ],\n  \"B7wvUM\": [\n    {\n      \"type\": 0,\n      \"value\": \"您可以新增單一或多個繼電器，每行一個。\"\n    }\n  ],\n  \"BGCM48\": [\n    {\n      \"type\": 0,\n      \"value\": \"寫入 Snort 中繼器到權限，1年的事件保留\"\n    }\n  ],\n  \"BGGacK\": [\n    {\n      \"type\": 0,\n      \"value\": \"AI 嵌入/向量清單\"\n    }\n  ],\n  \"BQW4gi\": [\n    {\n      \"type\": 0,\n      \"value\": \"中繼群組\"\n    }\n  ],\n  \"BWpuKl\": [\n    {\n      \"type\": 0,\n      \"value\": \"更新\"\n    }\n  ],\n  \"BfuAQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"市場 UI/UX\"\n    }\n  ],\n  \"BjNwZW\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 地址（NIP-05）\"\n    }\n  ],\n  \"Blxcdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"繼電器\"\n    }\n  ],\n  \"Bo+O//\": [\n    {\n      \"type\": 0,\n      \"value\": \"HTTP Auth\"\n    }\n  ],\n  \"C1LjMx\": [\n    {\n      \"type\": 0,\n      \"value\": \"閃電捐款\"\n    }\n  ],\n  \"C6Lhhp\": [\n    {\n      \"type\": 0,\n      \"value\": \"現場活動\"\n    }\n  ],\n  \"C7642/\": [\n    {\n      \"type\": 0,\n      \"value\": \"引用轉帖\"\n    }\n  ],\n  \"C81/uG\": [\n    {\n      \"type\": 0,\n      \"value\": \"登出\"\n    }\n  ],\n  \"C8FsOr\": [\n    {\n      \"type\": 0,\n      \"value\": \"熱門伺服器\"\n    }\n  ],\n  \"C8HhVE\": [\n    {\n      \"type\": 0,\n      \"value\": \"推薦關注\"\n    }\n  ],\n  \"CA1efg\": [\n    {\n      \"type\": 0,\n      \"value\": \"視訊套件\"\n    }\n  ],\n  \"CHTbO3\": [\n    {\n      \"type\": 0,\n      \"value\": \"加載發票失敗\"\n    }\n  ],\n  \"CJx5Nd\": [\n    {\n      \"type\": 0,\n      \"value\": \"簡介 Zaps\"\n    }\n  ],\n  \"CM+Cfj\": [\n    {\n      \"type\": 0,\n      \"value\": \"關注列表\"\n    }\n  ],\n  \"CM0k0d\": [\n    {\n      \"type\": 0,\n      \"value\": \"修剪關注列表\"\n    }\n  ],\n  \"CVWeJ6\": [\n    {\n      \"type\": 0,\n      \"value\": \"熱門用戶\"\n    }\n  ],\n  \"CYkOCI\": [\n    {\n      \"type\": 0,\n      \"value\": \"和 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 個你關注的人\"\n    }\n  ],\n  \"Cdxwi0\": [\n    {\n      \"type\": 0,\n      \"value\": \"儲存庫公告\"\n    }\n  ],\n  \"CmZ9ls\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 已静音\"\n    }\n  ],\n  \"Coy6SH\": [\n    {\n      \"type\": 0,\n      \"value\": \"行事曆\"\n    }\n  ],\n  \"CsCUYo\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聰\"\n    }\n  ],\n  \"Cu/K85\": [\n    {\n      \"type\": 0,\n      \"value\": \"翻譯自 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"CzHZoc\": [\n    {\n      \"type\": 0,\n      \"value\": \"社交圖表\"\n    }\n  ],\n  \"D++Njw\": [\n    {\n      \"type\": 0,\n      \"value\": \"文字說明 參考資料\"\n    }\n  ],\n  \"D+KzKd\": [\n    {\n      \"type\": 0,\n      \"value\": \"加載時自動打閃每條筆記\"\n    }\n  ],\n  \"D09wbg\": [\n    {\n      \"type\": 0,\n      \"value\": \"徽章定義\"\n    }\n  ],\n  \"D3idYv\": [\n    {\n      \"type\": 0,\n      \"value\": \"設置\"\n    }\n  ],\n  \"D9xTLE\": [\n    {\n      \"type\": 0,\n      \"value\": \"頻道隱藏訊息\"\n    }\n  ],\n  \"DBiVK1\": [\n    {\n      \"type\": 0,\n      \"value\": \"緩存\"\n    }\n  ],\n  \"DKnriN\": [\n    {\n      \"type\": 0,\n      \"value\": \"發送聰\"\n    }\n  ],\n  \"DZzCem\": [\n    {\n      \"type\": 0,\n      \"value\": \"顯示最新的 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 條筆記\"\n    }\n  ],\n  \"Dh3hbq\": [\n    {\n      \"type\": 0,\n      \"value\": \"自動打閃\"\n    }\n  ],\n  \"Dn82AL\": [\n    {\n      \"type\": 0,\n      \"value\": \"直播\"\n    }\n  ],\n  \"DqUmXt\": [\n    {\n      \"type\": 0,\n      \"value\": \"以拍賣方式出售的產品\"\n    }\n  ],\n  \"DrZqav\": [\n    {\n      \"type\": 0,\n      \"value\": \"關於必須少於 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 個字符\"\n    }\n  ],\n  \"DtYelJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"轉移\"\n    }\n  ],\n  \"Dx4ey3\": [\n    {\n      \"type\": 0,\n      \"value\": \"切換全部\"\n    }\n  ],\n  \"E3oB+t\": [\n    {\n      \"type\": 0,\n      \"value\": \"瀏覽器\"\n    }\n  ],\n  \"E5ZIPD\": [\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"amount\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"big\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"聰\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"small\"\n    }\n  ],\n  \"EHqHsu\": [\n    {\n      \"type\": 0,\n      \"value\": \"發票 / 閃電地址\"\n    }\n  ],\n  \"EJbFi7\": [\n    {\n      \"type\": 0,\n      \"value\": \"搜索筆記\"\n    }\n  ],\n  \"ELbg9p\": [\n    {\n      \"type\": 0,\n      \"value\": \"數據提供方\"\n    }\n  ],\n  \"EQKRE4\": [\n    {\n      \"type\": 0,\n      \"value\": \"在個人檔案頁面上顯示徽章\"\n    }\n  ],\n  \"EWeVrH\": [\n    {\n      \"type\": 0,\n      \"value\": \"對網站的反應\"\n    }\n  ],\n  \"EWyQH5\": [\n    {\n      \"type\": 0,\n      \"value\": \"全球\"\n    }\n  ],\n  \"Ebl/B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"翻譯成 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"lang\"\n    }\n  ],\n  \"Ec+xLY\": [\n    {\n      \"type\": 0,\n      \"value\": \"編輯套件\"\n    }\n  ],\n  \"EcZF24\": [\n    {\n      \"type\": 0,\n      \"value\": \"自定義中繼器\"\n    }\n  ],\n  \"EcfIwB\": [\n    {\n      \"type\": 0,\n      \"value\": \"用戶名可用。\"\n    }\n  ],\n  \"EcglP9\": [\n    {\n      \"type\": 0,\n      \"value\": \"密鑰\"\n    }\n  ],\n  \"EjFyoR\": [\n    {\n      \"type\": 0,\n      \"value\": \"鏈上捐款地址\"\n    }\n  ],\n  \"EnCOBJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"購買\"\n    }\n  ],\n  \"EsHX35\": [\n    {\n      \"type\": 0,\n      \"value\": \"抱歉，我們不瞭解此事件類型 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")，請嘗試以下其中一個應用程式！\"\n    }\n  ],\n  \"F/6VqP\": [\n    {\n      \"type\": 0,\n      \"value\": \"伺服器\"\n    }\n  ],\n  \"F3l7xL\": [\n    {\n      \"type\": 0,\n      \"value\": \"添加帳戶\"\n    }\n  ],\n  \"F4eJ/3\": [\n    {\n      \"type\": 0,\n      \"value\": \"分類列表\"\n    }\n  ],\n  \"FDguSC\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 打閃\"\n    }\n  ],\n  \"FHWpHC\": [\n    {\n      \"type\": 0,\n      \"value\": \"錢包回復\"\n    }\n  ],\n  \"FHvSk3\": [\n    {\n      \"type\": 0,\n      \"value\": \"用戶端對中繼器的驗證\"\n    }\n  ],\n  \"FMfjrl\": [\n    {\n      \"type\": 0,\n      \"value\": \"在個人檔案頁面上顯示狀態消息\"\n    }\n  ],\n  \"FSYL8G\": [\n    {\n      \"type\": 0,\n      \"value\": \"熱門用戶\"\n    }\n  ],\n  \"FWJR1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用者群組\"\n    }\n  ],\n  \"FcNSft\": [\n    {\n      \"type\": 0,\n      \"value\": \"重定向將 HTTP 重定向到所提供的閃電地址\"\n    }\n  ],\n  \"FdhSU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即領取\"\n    }\n  ],\n  \"FfYsOb\": [\n    {\n      \"type\": 0,\n      \"value\": \"發生錯誤！\"\n    }\n  ],\n  \"FmXUJg\": [\n    {\n      \"type\": 0,\n      \"value\": \"正在關注你\"\n    }\n  ],\n  \"FvanT6\": [\n    {\n      \"type\": 0,\n      \"value\": \"帳戶\"\n    }\n  ],\n  \"FzbSGg\": [\n    {\n      \"type\": 0,\n      \"value\": \"你沒有任何媒體伺服器，請嘗試新增一些。\"\n    }\n  ],\n  \"G/yZLu\": [\n    {\n      \"type\": 0,\n      \"value\": \"移除\"\n    }\n  ],\n  \"G1BGCg\": [\n    {\n      \"type\": 0,\n      \"value\": \"選擇錢包\"\n    }\n  ],\n  \"G3A56c\": [\n    {\n      \"type\": 0,\n      \"value\": \"已訂閱推送通知\"\n    }\n  ],\n  \"GFOoEE\": [\n    {\n      \"type\": 0,\n      \"value\": \"鹽\"\n    }\n  ],\n  \"GIqktu\": [\n    {\n      \"type\": 0,\n      \"value\": \"支援的 NIP\"\n    }\n  ],\n  \"GL8aXW\": [\n    {\n      \"type\": 0,\n      \"value\": \"收藏 （\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"）\"\n    }\n  ],\n  \"GSye7T\": [\n    {\n      \"type\": 0,\n      \"value\": \"閃電地址\"\n    }\n  ],\n  \"GUlSVG\": [\n    {\n      \"type\": 0,\n      \"value\": \"認領你包含的 Snort nostr 地址\"\n    }\n  ],\n  \"Gcn9NQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"磁力鏈接\"\n    }\n  ],\n  \"GpkNYn\": [\n    {\n      \"type\": 0,\n      \"value\": \"傳輸\"\n    }\n  ],\n  \"GqQeu/\": [\n    {\n      \"type\": 0,\n      \"value\": \"閃電地址無效\"\n    }\n  ],\n  \"GspYR7\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 踩\"\n    }\n  ],\n  \"Gxcr08\": [\n    {\n      \"type\": 0,\n      \"value\": \"廣播事件\"\n    }\n  ],\n  \"H+vHiz\": [\n    {\n      \"type\": 0,\n      \"value\": \"十六進制密鑰...\"\n    }\n  ],\n  \"H/oroO\": [\n    {\n      \"type\": 0,\n      \"value\": \"處理未知事件\"\n    }\n  ],\n  \"H0JBH6\": [\n    {\n      \"type\": 0,\n      \"value\": \"登出\"\n    }\n  ],\n  \"H0OG3T\": [\n    {\n      \"type\": 0,\n      \"value\": \"領袖信息\"\n    }\n  ],\n  \"H1GTaC\": [\n    {\n      \"type\": 0,\n      \"value\": \"書籤清單\"\n    }\n  ],\n  \"H6/kLh\": [\n    {\n      \"type\": 0,\n      \"value\": \"訂單已支付！\"\n    }\n  ],\n  \"HAlOn1\": [\n    {\n      \"type\": 0,\n      \"value\": \"名稱\"\n    }\n  ],\n  \"HFls6j\": [\n    {\n      \"type\": 0,\n      \"value\": \"名稱稍後可用\"\n    }\n  ],\n  \"HOzFdo\": [\n    {\n      \"type\": 0,\n      \"value\": \"已静音\"\n    }\n  ],\n  \"HWbkEK\": [\n    {\n      \"type\": 0,\n      \"value\": \"清除緩存並重新加載\"\n    }\n  ],\n  \"HbefNb\": [\n    {\n      \"type\": 0,\n      \"value\": \"打開錢包\"\n    }\n  ],\n  \"HhcAVH\": [\n    {\n      \"type\": 0,\n      \"value\": \"你不關注此用戶，點擊此處從\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"link\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"加載多媒體，或更新\"\n    },\n    {\n      \"children\": [\n        {\n          \"children\": [\n            {\n              \"type\": 0,\n              \"value\": \"你的選項\"\n            }\n          ],\n          \"type\": 8,\n          \"value\": \"i\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"a\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"來自動加載來自任何人的多媒體。\"\n    }\n  ],\n  \"HpAmQZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"繼電器回顧\"\n    }\n  ],\n  \"HqRNN8\": [\n    {\n      \"type\": 0,\n      \"value\": \"支持\"\n    }\n  ],\n  \"HzSFeV\": [\n    {\n      \"type\": 0,\n      \"value\": \"到期時間戳記\"\n    }\n  ],\n  \"I0tYZf\": [\n    {\n      \"type\": 0,\n      \"value\": \"建立或更新檔位\"\n    }\n  ],\n  \"I1AoOu\": [\n    {\n      \"type\": 0,\n      \"value\": \"最近發佈 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"time\"\n    }\n  ],\n  \"IEwZvs\": [\n    {\n      \"type\": 0,\n      \"value\": \"是否確定要取消置頂此條筆記？\"\n    }\n  ],\n  \"IIOul1\": [\n    {\n      \"type\": 0,\n      \"value\": \"帳戶數據\"\n    }\n  ],\n  \"IKKHqV\": [\n    {\n      \"type\": 0,\n      \"value\": \"關注\"\n    }\n  ],\n  \"IOu4Xh\": [\n    {\n      \"type\": 0,\n      \"value\": \"你必須是 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 訂閱者，才能訪問 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 面板\"\n    }\n  ],\n  \"IVbtTS\": [\n    {\n      \"type\": 0,\n      \"value\": \"打閃所有 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聰\"\n    }\n  ],\n  \"IWz1ta\": [\n    {\n      \"type\": 0,\n      \"value\": \"自動翻譯\"\n    }\n  ],\n  \"IcHcWj\": [\n    {\n      \"type\": 0,\n      \"value\": \"最後一次見到\"\n    }\n  ],\n  \"Ig9/a1\": [\n    {\n      \"type\": 0,\n      \"value\": \"向 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 發送了 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聰\"\n    }\n  ],\n  \"IgsWFG\": [\n    {\n      \"type\": 0,\n      \"value\": \"未被你關注的任何人關注\"\n    }\n  ],\n  \"IoQq+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"仍然要加載點擊這裡\"\n    }\n  ],\n  \"IvjoDS\": [\n    {\n      \"type\": 0,\n      \"value\": \"連接\"\n    }\n  ],\n  \"Ix8l+B\": [\n    {\n      \"type\": 0,\n      \"value\": \"熱門筆記\"\n    }\n  ],\n  \"J+dIsA\": [\n    {\n      \"type\": 0,\n      \"value\": \"訂閱\"\n    }\n  ],\n  \"J1iLmb\": [\n    {\n      \"type\": 0,\n      \"value\": \"未允許通知\"\n    }\n  ],\n  \"J2HeQ+\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用逗号分隔单词，如 word1, word2, word3\"\n    }\n  ],\n  \"J2Q92B\": [\n    {\n      \"type\": 0,\n      \"value\": \"表情符號套裝\"\n    }\n  ],\n  \"J6N9xl\": [\n    {\n      \"type\": 0,\n      \"value\": \"Sign in with Android signer\"\n    }\n  ],\n  \"JCIgkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"用戶名\"\n    }\n  ],\n  \"JGrt9q\": [\n    {\n      \"type\": 0,\n      \"value\": \"將聰發送到 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"JHEHCk\": [\n    {\n      \"type\": 0,\n      \"value\": \"打閃（\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"）\"\n    }\n  ],\n  \"JIVWWA\": [\n    {\n      \"type\": 0,\n      \"value\": \"體育\"\n    }\n  ],\n  \"JPFYIM\": [\n    {\n      \"type\": 0,\n      \"value\": \"沒有閃電地址\"\n    }\n  ],\n  \"JSx7y9\": [\n    {\n      \"type\": 0,\n      \"value\": \"以 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"price\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 訂閱 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 並獲得以下獎勵\"\n    }\n  ],\n  \"JeoS4y\": [\n    {\n      \"type\": 0,\n      \"value\": \"轉發\"\n    }\n  ],\n  \"Jh5zKH\": [\n    {\n      \"type\": 0,\n      \"value\": \"搜尋繼電器清單\"\n    }\n  ],\n  \"JjGgXI\": [\n    {\n      \"type\": 0,\n      \"value\": \"搜索用戶\"\n    }\n  ],\n  \"JkLHGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"網站\"\n    }\n  ],\n  \"JmcxzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"繼電器是您連接的伺服器，用於傳送和接收事件。以 4-8 個中繼為目標。\"\n    }\n  ],\n  \"JymXbw\": [\n    {\n      \"type\": 0,\n      \"value\": \"私鑰\"\n    }\n  ],\n  \"K1wl1/\": [\n    {\n      \"type\": 0,\n      \"value\": \"平均延遲時間：\"\n    }\n  ],\n  \"K3r6DQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"刪除\"\n    }\n  ],\n  \"K7AkdL\": [\n    {\n      \"type\": 0,\n      \"value\": \"顯示\"\n    }\n  ],\n  \"K9zklU\": [\n    {\n      \"type\": 0,\n      \"value\": \"外部內容 ID\"\n    }\n  ],\n  \"KAhAcM\": [\n    {\n      \"type\": 0,\n      \"value\": \"輸入 LNDHub 配置\"\n    }\n  ],\n  \"KGmQjH\": [\n    {\n      \"type\": 0,\n      \"value\": \"重點介紹\"\n    }\n  ],\n  \"KJryGq\": [\n    {\n      \"type\": 0,\n      \"value\": \"即時聊天訊息\"\n    }\n  ],\n  \"KQvWvD\": [\n    {\n      \"type\": 0,\n      \"value\": \"已刪除\"\n    }\n  ],\n  \"KT9nox\": [\n    {\n      \"type\": 0,\n      \"value\": \"受保護事件\"\n    }\n  ],\n  \"KahimY\": [\n    {\n      \"type\": 0,\n      \"value\": \"未知事件類型：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"kind\"\n    }\n  ],\n  \"KipVeG\": [\n    {\n      \"type\": 0,\n      \"value\": \"將 Nostr 金鑰對應到基於 DNS 的網際網路識別碼\"\n    }\n  ],\n  \"KtsyO0\": [\n    {\n      \"type\": 0,\n      \"value\": \"輸入 PIN 碼\"\n    }\n  ],\n  \"KyRp/q\": [\n    {\n      \"type\": 0,\n      \"value\": \"錢包需求\"\n    }\n  ],\n  \"LBAnc7\": [\n    {\n      \"type\": 0,\n      \"value\": \"以用戶身份查看？\"\n    }\n  ],\n  \"LEmxc8\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap 目標\"\n    }\n  ],\n  \"LKw/ue\": [\n    {\n      \"type\": 0,\n      \"value\": \"在此處查看代碼：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"LR1XjT\": [\n    {\n      \"type\": 0,\n      \"value\": \"PIN 碼太短了\"\n    }\n  ],\n  \"LXxsbk\": [\n    {\n      \"type\": 0,\n      \"value\": \"匿名\"\n    }\n  ],\n  \"LgbKvU\": [\n    {\n      \"type\": 0,\n      \"value\": \"評論\"\n    }\n  ],\n  \"LhLvRx\": [\n    {\n      \"type\": 0,\n      \"value\": \"名稱長度必須介於 8 到 15 個字符之間\"\n    }\n  ],\n  \"LmdPXO\": [\n    {\n      \"type\": 0,\n      \"value\": \"無法驗證 Nostr 地址\"\n    }\n  ],\n  \"Lu5/Bj\": [\n    {\n      \"type\": 0,\n      \"value\": \"在 Zapstr 上打開\"\n    }\n  ],\n  \"LuDBLj\": [\n    {\n      \"type\": 0,\n      \"value\": \"下載\"\n    }\n  ],\n  \"Lw+I+J\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"已打閃\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"和\"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"個其他用戶已打閃\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"LwYmVi\": [\n    {\n      \"type\": 0,\n      \"value\": \"此筆記上的打閃將被拆分給以下的用戶。\"\n    }\n  ],\n  \"M3Oirc\": [\n    {\n      \"type\": 0,\n      \"value\": \"調試選單\"\n    }\n  ],\n  \"M6C/px\": [\n    {\n      \"type\": 0,\n      \"value\": \"成爲領袖\"\n    }\n  ],\n  \"MBAYRO\": [\n    {\n      \"type\": 0,\n      \"value\": \"每條消息的上下文菜單中顯示“複製 ID”和“複製事件 JSON”\"\n    }\n  ],\n  \"MI2jkA\": [\n    {\n      \"type\": 0,\n      \"value\": \"無法使用：\"\n    }\n  ],\n  \"MKDHEa\": [\n    {\n      \"type\": 0,\n      \"value\": \"加入房間\"\n    }\n  ],\n  \"MP54GY\": [\n    {\n      \"type\": 0,\n      \"value\": \"錢包密碼\"\n    }\n  ],\n  \"MWTx65\": [\n    {\n      \"type\": 0,\n      \"value\": \"默認頁面\"\n    }\n  ],\n  \"MYBYdJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"簡短文字說明\"\n    }\n  ],\n  \"MYUBaG\": [\n    {\n      \"type\": 0,\n      \"value\": \"用戶端驗證\"\n    }\n  ],\n  \"MiMipu\": [\n    {\n      \"type\": 0,\n      \"value\": \"設置為主要 Nostr 地址（NIP-05）\"\n    }\n  ],\n  \"MkQ4FX\": [\n    {\n      \"type\": 0,\n      \"value\": \"代理標籤\"\n    }\n  ],\n  \"Ml7+RS\": [\n    {\n      \"type\": 0,\n      \"value\": \"將此鏈接發送給你的好友，分享 Nostr 的魅力。\"\n    }\n  ],\n  \"Mrpkot\": [\n    {\n      \"type\": 0,\n      \"value\": \"支付訂閱\"\n    }\n  ],\n  \"MuVeKe\": [\n    {\n      \"type\": 0,\n      \"value\": \"購買 nostr 地址\"\n    }\n  ],\n  \"Muhna4\": [\n    {\n      \"type\": 0,\n      \"value\": \"計數結果\"\n    }\n  ],\n  \"MzRYWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"購買 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"item\"\n    }\n  ],\n  \"Mzizei\": [\n    {\n      \"type\": 0,\n      \"value\": \"Iris.to 帳戶\"\n    }\n  ],\n  \"N2IrpM\": [\n    {\n      \"type\": 0,\n      \"value\": \"確認\"\n    }\n  ],\n  \"NAidKb\": [\n    {\n      \"type\": 0,\n      \"value\": \"通知\"\n    }\n  ],\n  \"NAuFNH\": [\n    {\n      \"type\": 0,\n      \"value\": \"你已經有此類型的訂閱，請續訂或支付\"\n    }\n  ],\n  \"NDTFsp\": [\n    {\n      \"type\": 0,\n      \"value\": \"工作反饋\"\n    }\n  ],\n  \"NepkXH\": [\n    {\n      \"type\": 0,\n      \"value\": \"無法用\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"聰投票，請設置一個不同的默認打閃金額\"\n    }\n  ],\n  \"NndBJE\": [\n    {\n      \"type\": 0,\n      \"value\": \"新用戶頁面\"\n    }\n  ],\n  \"Nr9Yyx\": [\n    {\n      \"type\": 0,\n      \"value\": \"轉貼\"\n    }\n  ],\n  \"NxzeNU\": [\n    {\n      \"type\": 0,\n      \"value\": \"死亡\"\n    }\n  ],\n  \"O3Jz4E\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用你的邀請碼賺取聰！\"\n    }\n  ],\n  \"OEW7yJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"打閃\"\n    }\n  ],\n  \"OIqnZN\": [\n    {\n      \"type\": 0,\n      \"value\": \"事件的 OpenTimestamps 驗證\"\n    }\n  ],\n  \"OJHKIL\": [\n    {\n      \"type\": 0,\n      \"value\": \"禮品包裝\"\n    }\n  ],\n  \"OKhRC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"分享\"\n    }\n  ],\n  \"OLEm6z\": [\n    {\n      \"type\": 0,\n      \"value\": \"未知登錄錯誤\"\n    }\n  ],\n  \"OQSOJF\": [\n    {\n      \"type\": 0,\n      \"value\": \"獲取一個免費的 Nostr 地址\"\n    }\n  ],\n  \"OQXnew\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的訂閱仍然活躍，你還不能續訂\"\n    }\n  ],\n  \"ORGv1Q\": [\n    {\n      \"type\": 0,\n      \"value\": \"已創建\"\n    }\n  ],\n  \"ORa81+\": [\n    {\n      \"type\": 0,\n      \"value\": \"合併請求\"\n    }\n  ],\n  \"OoZgbB\": [\n    {\n      \"type\": 0,\n      \"value\": \"無法更新, 請重試。\"\n    }\n  ],\n  \"OuProE\": [\n    {\n      \"type\": 0,\n      \"value\": \"長篇內容\"\n    }\n  ],\n  \"OxPdQ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"掃描 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"date\"\n    }\n  ],\n  \"P2o+ZZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 地址無效\"\n    }\n  ],\n  \"P61BTu\": [\n    {\n      \"type\": 0,\n      \"value\": \"複製事件 JSON\"\n    }\n  ],\n  \"P7FD0F\": [\n    {\n      \"type\": 0,\n      \"value\": \"系統（默認）\"\n    }\n  ],\n  \"P7nJT9\": [\n    {\n      \"type\": 0,\n      \"value\": \"今天總計（UTC）：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聰\"\n    }\n  ],\n  \"P8JC58\": [\n    {\n      \"type\": 0,\n      \"value\": \"距離\"\n    }\n  ],\n  \"PCSt5T\": [\n    {\n      \"type\": 0,\n      \"value\": \"選項\"\n    }\n  ],\n  \"PXQ0z0\": [\n    {\n      \"type\": 0,\n      \"value\": \"接收至 \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    }\n  ],\n  \"PamNxw\": [\n    {\n      \"type\": 0,\n      \"value\": \"未知文件標頭：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"Pe0ogR\": [\n    {\n      \"type\": 0,\n      \"value\": \"主題\"\n    }\n  ],\n  \"PrsIg7\": [\n    {\n      \"type\": 0,\n      \"value\": \"回應將在每個頁面上顯示，如果禁用則不會顯示任何回應\"\n    }\n  ],\n  \"QDFTjG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 中繼器\"\n    }\n  ],\n  \"QJfhKt\": [\n    {\n      \"type\": 0,\n      \"value\": \"私鑰就像密碼一樣，但無法重設。請小心保管，切勿給任何人看。一旦有人擁有你的私鑰，他們將永遠擁有你帳戶的掌控權。\"\n    }\n  ],\n  \"QWhotP\": [\n    {\n      \"type\": 0,\n      \"value\": \"打閃池只有當你使用支持的錢包（WebLN、LNC、LNDHub 或 Nostr Wallet Connect）時才能啟用\"\n    }\n  ],\n  \"QpaLA3\": [\n    {\n      \"type\": 0,\n      \"value\": \"頻道訊息\"\n    }\n  ],\n  \"Qxv0B2\": [\n    {\n      \"type\": 0,\n      \"value\": \"目前你的打閃池中有 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聰。\"\n    }\n  ],\n  \"Qy6/Ft\": [\n    {\n      \"type\": 0,\n      \"value\": \"私人直接訊息\"\n    }\n  ],\n  \"R/6nsx\": [\n    {\n      \"type\": 0,\n      \"value\": \"訂閱\"\n    }\n  ],\n  \"R81upa\": [\n    {\n      \"type\": 0,\n      \"value\": \"你關注的用戶\"\n    }\n  ],\n  \"RDha9y\": [\n    {\n      \"type\": 0,\n      \"value\": \"服務工作程式未運行\"\n    }\n  ],\n  \"RRz1cA\": [\n    {\n      \"type\": 0,\n      \"value\": \"儲存庫狀態公告\"\n    }\n  ],\n  \"RSr2uB\": [\n    {\n      \"type\": 0,\n      \"value\": \"用戶名只能含有小寫字母和數字\"\n    }\n  ],\n  \"RahCRH\": [\n    {\n      \"type\": 0,\n      \"value\": \"已過期\"\n    }\n  ],\n  \"RefZpK\": [\n    {\n      \"type\": 0,\n      \"value\": \"人像短片活動\"\n    }\n  ],\n  \"RfhLwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"作者：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"author\"\n    }\n  ],\n  \"RhDAoS\": [\n    {\n      \"type\": 0,\n      \"value\": \"是否確定要刪除 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"RmxSZo\": [\n    {\n      \"type\": 0,\n      \"value\": \"資料販賣機\"\n    }\n  ],\n  \"RoOyAh\": [\n    {\n      \"type\": 0,\n      \"value\": \"中繼器\"\n    }\n  ],\n  \"Rs4kCE\": [\n    {\n      \"type\": 0,\n      \"value\": \"收藏\"\n    }\n  ],\n  \"S/NV2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"載入注意事項： \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"id\"\n    }\n  ],\n  \"SFuk1v\": [\n    {\n      \"type\": 0,\n      \"value\": \"權限\"\n    }\n  ],\n  \"SLZGPn\": [\n    {\n      \"type\": 0,\n      \"value\": \"輸入一個 PIN 碼來加密你的私鑰，每次開啟 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 時都必須輸入此 PIN 碼。\"\n    }\n  ],\n  \"SMO+on\": [\n    {\n      \"type\": 0,\n      \"value\": \"將打閃發送到 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    }\n  ],\n  \"SOqbe9\": [\n    {\n      \"type\": 0,\n      \"value\": \"更新閃電地址\"\n    }\n  ],\n  \"SP0+yi\": [\n    {\n      \"type\": 0,\n      \"value\": \"購買訂閱\"\n    }\n  ],\n  \"SW3TFA\": [\n    {\n      \"type\": 0,\n      \"value\": \"您追隨的人所使用的熱門繼電器。\"\n    }\n  ],\n  \"SYQtZ7\": [\n    {\n      \"type\": 0,\n      \"value\": \"閃電地址代理\"\n    }\n  ],\n  \"Sd0PKc\": [\n    {\n      \"type\": 0,\n      \"value\": \"繼電器組\"\n    }\n  ],\n  \"SfwSIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"問題追蹤\"\n    }\n  ],\n  \"ShdEie\": [\n    {\n      \"type\": 0,\n      \"value\": \"全標已讀\"\n    }\n  ],\n  \"Sjo1P4\": [\n    {\n      \"type\": 0,\n      \"value\": \"自定義\"\n    }\n  ],\n  \"SmuYUd\": [\n    {\n      \"type\": 0,\n      \"value\": \"我們應該怎麼樣稱呼你？\"\n    }\n  ],\n  \"Ss0sWu\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即支付\"\n    }\n  ],\n  \"SsUQnC\": [\n    {\n      \"type\": 0,\n      \"value\": \"應用程式特定資料\"\n    }\n  ],\n  \"StKzTE\": [\n    {\n      \"type\": 0,\n      \"value\": \"作者已將此筆記標記為\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 0,\n          \"value\": \"敏感主題\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"i\"\n    }\n  ],\n  \"T83nqf\": [\n    {\n      \"type\": 0,\n      \"value\": \"鄰近您地理位置的繼電器。\"\n    }\n  ],\n  \"TDR5ge\": [\n    {\n      \"type\": 0,\n      \"value\": \"帖子中的媒體將自動顯示給選定的人，否則只會顯示鏈接\"\n    }\n  ],\n  \"TGc5nI\": [\n    {\n      \"type\": 0,\n      \"value\": \"處理者資訊\"\n    }\n  ],\n  \"TH1fFo\": [\n    {\n      \"type\": 0,\n      \"value\": \"Telegram\"\n    }\n  ],\n  \"TJo5E6\": [\n    {\n      \"type\": 0,\n      \"value\": \"預覽\"\n    }\n  ],\n  \"TOG64f\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用本地中繼\"\n    }\n  ],\n  \"TP/cMX\": [\n    {\n      \"type\": 0,\n      \"value\": \"已結束\"\n    }\n  ],\n  \"TaeBqw\": [\n    {\n      \"type\": 0,\n      \"value\": \"通過 Nostr 擴展程式登錄\"\n    }\n  ],\n  \"TdTXXf\": [\n    {\n      \"type\": 0,\n      \"value\": \"瞭解更多\"\n    }\n  ],\n  \"TdtZQ5\": [\n    {\n      \"type\": 0,\n      \"value\": \"加密貨幣\"\n    }\n  ],\n  \"Tdv6NY\": [\n    {\n      \"type\": 0,\n      \"value\": \"興趣集\"\n    }\n  ],\n  \"TgDKhI\": [\n    {\n      \"type\": 0,\n      \"value\": \"日曆活動\"\n    }\n  ],\n  \"TpgeGw\": [\n    {\n      \"type\": 0,\n      \"value\": \"十六進制鹽..\"\n    }\n  ],\n  \"Tpy00S\": [\n    {\n      \"type\": 0,\n      \"value\": \"用戶\"\n    }\n  ],\n  \"TvKqBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"已點贊\"\n    }\n  ],\n  \"TwyMau\": [\n    {\n      \"type\": 0,\n      \"value\": \"帳戶\"\n    }\n  ],\n  \"U1aPPi\": [\n    {\n      \"type\": 0,\n      \"value\": \"停止收聽\"\n    }\n  ],\n  \"U30H69\": [\n    {\n      \"type\": 0,\n      \"value\": \"社群定義\"\n    }\n  ],\n  \"UJTWqI\": [\n    {\n      \"type\": 0,\n      \"value\": \"從我的中繼器中移除\"\n    }\n  ],\n  \"ULXFfP\": [\n    {\n      \"type\": 0,\n      \"value\": \"收款\"\n    }\n  ],\n  \"UNjfWJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"检查从中继收到的所有事件签名\"\n    }\n  ],\n  \"UT7Nkj\": [\n    {\n      \"type\": 0,\n      \"value\": \"新聊天\"\n    }\n  ],\n  \"UUPFlt\": [\n    {\n      \"type\": 0,\n      \"value\": \"用戶必須接受內容警告才能顯示你的筆記的內容。\"\n    }\n  ],\n  \"UaCh1c\": [\n    {\n      \"type\": 0,\n      \"value\": \"新增伺服器\"\n    }\n  ],\n  \"Ub+AGc\": [\n    {\n      \"type\": 0,\n      \"value\": \"登錄\"\n    }\n  ],\n  \"Up5U7K\": [\n    {\n      \"type\": 0,\n      \"value\": \"屏蔽\"\n    }\n  ],\n  \"Ups2/p\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的申請正在處理中\"\n    }\n  ],\n  \"UrKTqQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"你有一個活躍的 iris.to 帳戶\"\n    }\n  ],\n  \"UsCzPc\": [\n    {\n      \"type\": 0,\n      \"value\": \"與朋友分享個人化邀請函！\"\n    }\n  ],\n  \"UxgyeY\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的邀請代碼是 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"code\"\n    }\n  ],\n  \"V20Og0\": [\n    {\n      \"type\": 0,\n      \"value\": \"標籤\"\n    }\n  ],\n  \"VOjC1i\": [\n    {\n      \"type\": 0,\n      \"value\": \"選擇你要將附件上傳到哪個上傳服務\"\n    }\n  ],\n  \"VR5eHw\": [\n    {\n      \"type\": 0,\n      \"value\": \"公鑰（npub/nprofile）\"\n    }\n  ],\n  \"VcwrfF\": [\n    {\n      \"type\": 0,\n      \"value\": \"好的\"\n    }\n  ],\n  \"VfhYxG\": [\n    {\n      \"type\": 0,\n      \"value\": \"要查看全部更改列表，請在此查看更新日誌：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"here\"\n    }\n  ],\n  \"VlJkSk\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 已静音\"\n    }\n  ],\n  \"VnXp8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"頭像\"\n    }\n  ],\n  \"W1yoZY\": [\n    {\n      \"type\": 0,\n      \"value\": \"看起來你沒有任何訂閱，你可以獲取一個\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"W2PiAr\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 已屏蔽\"\n    }\n  ],\n  \"W4SaxY\": [\n    {\n      \"type\": 0,\n      \"value\": \"當地\"\n    }\n  ],\n  \"W9355R\": [\n    {\n      \"type\": 0,\n      \"value\": \"解除静音\"\n    }\n  ],\n  \"WeLEuL\": [\n    {\n      \"type\": 0,\n      \"value\": \"來自伺服器\"\n    }\n  ],\n  \"Wj5TbN\": [\n    {\n      \"type\": 0,\n      \"value\": \"問題\"\n    }\n  ],\n  \"WmZhfL\": [\n    {\n      \"type\": 0,\n      \"value\": \"自動將筆記翻譯成你的本地語言\"\n    }\n  ],\n  \"WvGmZT\": [\n    {\n      \"type\": 0,\n      \"value\": \"npub / nprofile / nostr 地址\"\n    }\n  ],\n  \"X6tipZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用密鑰登錄\"\n    }\n  ],\n  \"X7xU8J\": [\n    {\n      \"type\": 0,\n      \"value\": \"nsec、nsec、NIP-05、十六進制、助記詞句\"\n    }\n  ],\n  \"XECMfW\": [\n    {\n      \"type\": 0,\n      \"value\": \"傳送使用資料\"\n    }\n  ],\n  \"XICsE8\": [\n    {\n      \"type\": 0,\n      \"value\": \"文件主機\"\n    }\n  ],\n  \"XPB8VV\": [\n    {\n      \"type\": 0,\n      \"value\": \"Alby 錢包連接\"\n    }\n  ],\n  \"XQiFEl\": [\n    {\n      \"type\": 0,\n      \"value\": \"關注中繼器健康\"\n    }\n  ],\n  \"XSdWHA\": [\n    {\n      \"type\": 0,\n      \"value\": \"兌現\"\n    }\n  ],\n  \"XXm7jJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"熱門主題標籤\"\n    }\n  ],\n  \"XgWvGA\": [\n    {\n      \"type\": 0,\n      \"value\": \"回應\"\n    }\n  ],\n  \"Xnimz0\": [\n    {\n      \"type\": 0,\n      \"value\": \"從 \"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"wallet\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 發送\"\n    }\n  ],\n  \"Xopqkl\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的默認打閃金額是 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"number\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聰，示例值是以此計算的。\"\n    }\n  ],\n  \"YDMrKK\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用者\"\n    }\n  ],\n  \"YDURw6\": [\n    {\n      \"type\": 0,\n      \"value\": \"服務 URL\"\n    }\n  ],\n  \"YH2RKk\": [\n    {\n      \"type\": 0,\n      \"value\": \"受歡迎的媒體伺服器。\"\n    }\n  ],\n  \"YQZY/S\": [\n    {\n      \"type\": 0,\n      \"value\": \"看起來您追隨的人還不夠多，請瀏覽 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"newUsersPage\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 發掘要追隨的人！\"\n    }\n  ],\n  \"YR2I9M\": [\n    {\n      \"type\": 0,\n      \"value\": \"沒有密鑰，就沒有 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"，如果不備份，就無法重置。這只需要一分鐘。\"\n    }\n  ],\n  \"YU7ZYp\": [\n    {\n      \"type\": 0,\n      \"value\": \"公開聊天\"\n    }\n  ],\n  \"YXA3AH\": [\n    {\n      \"type\": 0,\n      \"value\": \"启用回應\"\n    }\n  ],\n  \"Yf3DwC\": [\n    {\n      \"type\": 0,\n      \"value\": \"連接錢包以發送即時付款\"\n    }\n  ],\n  \"YuoEb9\": [\n    {\n      \"type\": 0,\n      \"value\": \"嘗試另一個繼電器\"\n    }\n  ],\n  \"Z48UEo\": [\n    {\n      \"type\": 0,\n      \"value\": \"頻道元資料\"\n    }\n  ],\n  \"Z4BMCZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"輸入配對詞句\"\n    }\n  ],\n  \"Z7kkeJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"委託活動簽署\"\n    }\n  ],\n  \"ZFe9tl\": [\n    {\n      \"type\": 0,\n      \"value\": \"撰寫筆記\"\n    }\n  ],\n  \"ZKORll\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即激活\"\n    }\n  ],\n  \"ZLmyG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"貢獻者\"\n    }\n  ],\n  \"ZS+jRE\": [\n    {\n      \"type\": 0,\n      \"value\": \"將打閃拆分發送到\"\n    }\n  ],\n  \"Zff6lu\": [\n    {\n      \"type\": 0,\n      \"value\": \"用戶名 iris.to/\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"name\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 已為你保留！\"\n    }\n  ],\n  \"ZlIh4/\": [\n    {\n      \"type\": 0,\n      \"value\": \"加密的直接訊息\"\n    }\n  ],\n  \"ZlmK/p\": [\n    {\n      \"type\": 1,\n      \"value\": \"name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 邀請你訪問 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"app\"\n    }\n  ],\n  \"a1x4gD\": [\n    {\n      \"type\": 0,\n      \"value\": \"媒體伺服器儲存你可以在筆記中以圖像和視訊形式共享的媒體\"\n    }\n  ],\n  \"a5UPxh\": [\n    {\n      \"type\": 0,\n      \"value\": \"資助提供 NIP-05 驗證服務的開發人員和平台\"\n    }\n  ],\n  \"a7TDNm\": [\n    {\n      \"type\": 0,\n      \"value\": \"筆記將實時流式傳輸到全球和帖子選項卡\"\n    }\n  ],\n  \"aHje0o\": [\n    {\n      \"type\": 0,\n      \"value\": \"名稱\"\n    }\n  ],\n  \"aMaLBK\": [\n    {\n      \"type\": 0,\n      \"value\": \"支持的擴展\"\n    }\n  ],\n  \"aRex7h\": [\n    {\n      \"type\": 0,\n      \"value\": \"支付 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聰，付費 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"fee\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聰\"\n    }\n  ],\n  \"aSGz4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用 Lightning Node Connect 連接你自己的 LND 節點\"\n    }\n  ],\n  \"aWpBzj\": [\n    {\n      \"type\": 0,\n      \"value\": \"顯示更多\"\n    }\n  ],\n  \"abbGKq\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 公里\"\n    }\n  ],\n  \"ak3MTf\": [\n    {\n      \"type\": 0,\n      \"value\": \"邀請朋友\"\n    }\n  ],\n  \"b12Goz\": [\n    {\n      \"type\": 0,\n      \"value\": \"助記詞\"\n    }\n  ],\n  \"b5vAk0\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的代號將像閃電地址一樣重定向至你所選的 LNURL 或閃電地址\"\n    }\n  ],\n  \"bF1MYT\": [\n    {\n      \"type\": 0,\n      \"value\": \"你已成爲社區領袖，並可從邀請用戶的訂閱中賺取\"\n    },\n    {\n      \"children\": [\n        {\n          \"type\": 1,\n          \"value\": \"percent\"\n        }\n      ],\n      \"type\": 8,\n      \"value\": \"b\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"！\"\n    }\n  ],\n  \"bG00/W\": [\n    {\n      \"type\": 0,\n      \"value\": \"服務工作程式正在運行\"\n    }\n  ],\n  \"bJ+wrA\": [\n    {\n      \"type\": 0,\n      \"value\": \"計算修剪列表\"\n    }\n  ],\n  \"bLZL5a\": [\n    {\n      \"type\": 0,\n      \"value\": \"獲取地址\"\n    }\n  ],\n  \"bMphls\": [\n    {\n      \"type\": 0,\n      \"value\": \"已使用只讀權限登錄\"\n    }\n  ],\n  \"bQdA2k\": [\n    {\n      \"type\": 0,\n      \"value\": \"敏感內容\"\n    }\n  ],\n  \"bep9C3\": [\n    {\n      \"type\": 0,\n      \"value\": \"公鑰\"\n    }\n  ],\n  \"bfvyfs\": [\n    {\n      \"type\": 0,\n      \"value\": \"匿名\"\n    }\n  ],\n  \"bxv59V\": [\n    {\n      \"type\": 0,\n      \"value\": \"剛剛\"\n    }\n  ],\n  \"c+1p0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"親切的靜音套裝\"\n    }\n  ],\n  \"c+JYNI\": [\n    {\n      \"type\": 0,\n      \"value\": \"不，謝謝\"\n    }\n  ],\n  \"c2T+1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"重定向\"\n    }\n  ],\n  \"c35bj2\": [\n    {\n      \"type\": 0,\n      \"value\": \"如果你對 NIP-05 訂單有任何疑問，請私信 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"c3LlRO\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"KiB\"\n    }\n  ],\n  \"c3g2hL\": [\n    {\n      \"type\": 0,\n      \"value\": \"再次廣播\"\n    }\n  ],\n  \"cFbU1B\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用 Alby？前往 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 來配置你的 NWC！\"\n    }\n  ],\n  \"cG/bKQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"原生 nostr 錢包連接\"\n    }\n  ],\n  \"cHCwbF\": [\n    {\n      \"type\": 0,\n      \"value\": \"攝影\"\n    }\n  ],\n  \"cKbMRX\": [\n    {\n      \"type\": 0,\n      \"value\": \"直接訊息\"\n    }\n  ],\n  \"cPIKU2\": [\n    {\n      \"type\": 0,\n      \"value\": \"關注\"\n    }\n  ],\n  \"cQfLWb\": [\n    {\n      \"type\": 0,\n      \"value\": \"URL..\"\n    }\n  ],\n  \"cVcgLJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"媒體伺服器\"\n    }\n  ],\n  \"cWx9t8\": [\n    {\n      \"type\": 0,\n      \"value\": \"全部靜音\"\n    }\n  ],\n  \"cg1VJ2\": [\n    {\n      \"type\": 0,\n      \"value\": \"連接錢包\"\n    }\n  ],\n  \"cnwHgH\": [\n    {\n      \"type\": 0,\n      \"value\": \"OpenTimestamps\"\n    }\n  ],\n  \"cuP16y\": [\n    {\n      \"type\": 0,\n      \"value\": \"多帳戶支持\"\n    }\n  ],\n  \"cuV2gK\": [\n    {\n      \"type\": 0,\n      \"value\": \"名稱已被註冊\"\n    }\n  ],\n  \"cw1Ftc\": [\n    {\n      \"type\": 0,\n      \"value\": \"現場活動\"\n    }\n  ],\n  \"cyR7Kh\": [\n    {\n      \"type\": 0,\n      \"value\": \"返回\"\n    }\n  ],\n  \"d+6YsV\": [\n    {\n      \"type\": 0,\n      \"value\": \"應靜音的列表：\"\n    }\n  ],\n  \"d0qim7\": [\n    {\n      \"type\": 0,\n      \"value\": \"WoT 過濾器\"\n    }\n  ],\n  \"d2ebEu\": [\n    {\n      \"type\": 0,\n      \"value\": \"未訂閱推送\"\n    }\n  ],\n  \"d7d0/x\": [\n    {\n      \"type\": 0,\n      \"value\": \"閃電地址\"\n    }\n  ],\n  \"dK2CcV\": [\n    {\n      \"type\": 0,\n      \"value\": \"公鑰就像你的用戶名，你可以與任何人分享。\"\n    }\n  ],\n  \"dOQCL8\": [\n    {\n      \"type\": 0,\n      \"value\": \"顯示名稱\"\n    }\n  ],\n  \"dZZIGe\": [\n    {\n      \"type\": 0,\n      \"value\": \"模組化文章標題\"\n    }\n  ],\n  \"ddd3JX\": [\n    {\n      \"type\": 0,\n      \"value\": \"熱門標籤\"\n    }\n  ],\n  \"deEeEI\": [\n    {\n      \"type\": 0,\n      \"value\": \"註冊\"\n    }\n  ],\n  \"djLctd\": [\n    {\n      \"type\": 0,\n      \"value\": \"聰金額\"\n    }\n  ],\n  \"dmcsBA\": [\n    {\n      \"type\": 0,\n      \"value\": \"分類列表\"\n    }\n  ],\n  \"dmsiLv\": [\n    {\n      \"type\": 0,\n      \"value\": \"已為 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 開發人員配置了 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 的默認打閃池分割，你隨時可以在 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 中禁用它。\"\n    }\n  ],\n  \"e5x8FT\": [\n    {\n      \"type\": 0,\n      \"value\": \"類別\"\n    }\n  ],\n  \"e61Jf3\": [\n    {\n      \"type\": 0,\n      \"value\": \"即將上線\"\n    }\n  ],\n  \"e7VmYP\": [\n    {\n      \"type\": 0,\n      \"value\": \"輸入 PIN 碼解鎖你的私鑰\"\n    }\n  ],\n  \"e7qqly\": [\n    {\n      \"type\": 0,\n      \"value\": \"全標已讀\"\n    }\n  ],\n  \"eF0Re7\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用 Nostr 簽名擴展登錄\"\n    }\n  ],\n  \"eHAneD\": [\n    {\n      \"type\": 0,\n      \"value\": \"回應表情符號\"\n    }\n  ],\n  \"eJj8HD\": [\n    {\n      \"type\": 0,\n      \"value\": \"獲取驗證\"\n    }\n  ],\n  \"eSzf2G\": [\n    {\n      \"type\": 0,\n      \"value\": \"一個 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nIn\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聰的打閃將分配 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"nOut\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聰給打閃池。\"\n    }\n  ],\n  \"eW/Bj9\": [\n    {\n      \"type\": 0,\n      \"value\": \"飼料\"\n    }\n  ],\n  \"eXT2QQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"羣聊\"\n    }\n  ],\n  \"eZtOxB\": [\n    {\n      \"type\": 0,\n      \"value\": \"網頁瀏覽器的 window.nostr 功能\"\n    }\n  ],\n  \"egib+2\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 个其他\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"& \"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 个其他\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"ejEGdx\": [\n    {\n      \"type\": 0,\n      \"value\": \"主頁\"\n    }\n  ],\n  \"eoV49s\": [\n    {\n      \"type\": 0,\n      \"value\": \"貧窮\"\n    }\n  ],\n  \"f1OxTe\": [\n    {\n      \"type\": 0,\n      \"value\": \"社區領袖是指通過活躍於當地社區並幫助新用戶加入而發展 nostr 生態系統的個人。任何人都可以成爲社區領袖，但目前擁有這一榮譽稱號的人寥寥無幾。\"\n    }\n  ],\n  \"f2CAxA\": [\n    {\n      \"type\": 0,\n      \"value\": \"轉儲\"\n    }\n  ],\n  \"fBI91o\": [\n    {\n      \"type\": 0,\n      \"value\": \"打閃\"\n    }\n  ],\n  \"fBlba3\": [\n    {\n      \"type\": 0,\n      \"value\": \"感謝你使用 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"，請考慮捐贈。\"\n    }\n  ],\n  \"fLIvbC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort 是一個開放代碼項目，由熱心人士利用業餘時間創建，我們非常歡迎你的捐贈。\"\n    }\n  ],\n  \"fOksnD\": [\n    {\n      \"type\": 0,\n      \"value\": \"無法投票，因為 LNURL 服務不支持打閃\"\n    }\n  ],\n  \"fQN+tq\": [\n    {\n      \"type\": 0,\n      \"value\": \"顯示含有內容警告標籤的帖子\"\n    }\n  ],\n  \"fWZYP5\": [\n    {\n      \"type\": 0,\n      \"value\": \"置頂\"\n    }\n  ],\n  \"fX5RYm\": [\n    {\n      \"type\": 0,\n      \"value\": \"挑選幾個感興趣的主題\"\n    }\n  ],\n  \"filwqD\": [\n    {\n      \"type\": 0,\n      \"value\": \"讀\"\n    }\n  ],\n  \"fjAcWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"禮品包裝\"\n    }\n  ],\n  \"flnGvv\": [\n    {\n      \"type\": 0,\n      \"value\": \"你在想些什麼？\"\n    }\n  ],\n  \"fqwcJ1\": [\n    {\n      \"type\": 0,\n      \"value\": \"鏈上捐款\"\n    }\n  ],\n  \"fr+XYA\": [\n    {\n      \"type\": 0,\n      \"value\": \"Lightning Pub RPC\"\n    }\n  ],\n  \"fsB/4p\": [\n    {\n      \"type\": 0,\n      \"value\": \"已保存\"\n    }\n  ],\n  \"fucxlm\": [\n    {\n      \"type\": 0,\n      \"value\": \"附加媒體\"\n    }\n  ],\n  \"furjvW\": [\n    {\n      \"type\": 0,\n      \"value\": \"觀看直播\"\n    }\n  ],\n  \"g5pX+a\": [\n    {\n      \"type\": 0,\n      \"value\": \"關於\"\n    }\n  ],\n  \"g985Wp\": [\n    {\n      \"type\": 0,\n      \"value\": \"發送投票失敗\"\n    }\n  ],\n  \"gDzDRs\": [\n    {\n      \"type\": 0,\n      \"value\": \"回應筆記時發送的表情符號\"\n    }\n  ],\n  \"gXgY3+\": [\n    {\n      \"type\": 0,\n      \"value\": \"並非所有客戶端都支持此功能\"\n    }\n  ],\n  \"gczcC5\": [\n    {\n      \"type\": 0,\n      \"value\": \"訂閱\"\n    }\n  ],\n  \"geppt8\": [\n    {\n      \"type\": 1,\n      \"value\": \"count\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"count2\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" in memory)\"\n    }\n  ],\n  \"gjBiyj\": [\n    {\n      \"type\": 0,\n      \"value\": \"加載中...\"\n    }\n  ],\n  \"gkMmvC\": [\n    {\n      \"type\": 0,\n      \"value\": \"Android Signer 應用程式\"\n    }\n  ],\n  \"gl1NeW\": [\n    {\n      \"type\": 0,\n      \"value\": \"清單\"\n    }\n  ],\n  \"go2/QF\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用者伺服器清單\"\n    }\n  ],\n  \"grQ+mI\": [\n    {\n      \"type\": 0,\n      \"value\": \"工作量證明\"\n    }\n  ],\n  \"gtNjNP\": [\n    {\n      \"type\": 0,\n      \"value\": \"基本通訊協定流程說明\"\n    }\n  ],\n  \"h7jvCs\": [\n    {\n      \"type\": 1,\n      \"value\": \"site\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 一起使用更好玩！\"\n    }\n  ],\n  \"h8XMJL\": [\n    {\n      \"type\": 0,\n      \"value\": \"徽章\"\n    }\n  ],\n  \"h9M0rW\": [\n    {\n      \"type\": 0,\n      \"value\": \"使用者元資料\"\n    }\n  ],\n  \"hF6IN2\": [\n    {\n      \"type\": 0,\n      \"value\": \"修剪關注列表\"\n    }\n  ],\n  \"hMQmIw\": [\n    {\n      \"type\": 0,\n      \"value\": \"同步帳戶\"\n    }\n  ],\n  \"hMzcSq\": [\n    {\n      \"type\": 0,\n      \"value\": \"消息\"\n    }\n  ],\n  \"hRTfTR\": [\n    {\n      \"type\": 0,\n      \"value\": \"PRO\"\n    }\n  ],\n  \"hY4lzx\": [\n    {\n      \"type\": 0,\n      \"value\": \"支持\"\n    }\n  ],\n  \"hYOE+U\": [\n    {\n      \"type\": 0,\n      \"value\": \"邀請\"\n    }\n  ],\n  \"hicxcO\": [\n    {\n      \"type\": 0,\n      \"value\": \"顯示回覆\"\n    }\n  ],\n  \"hmZ3Bz\": [\n    {\n      \"type\": 0,\n      \"value\": \"多媒體\"\n    }\n  ],\n  \"hniz8Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"這裡\"\n    }\n  ],\n  \"hv/eRj\": [\n    {\n      \"type\": 0,\n      \"value\": \"封鎖的繼電器清單\"\n    }\n  ],\n  \"hvFRBo\": [\n    {\n      \"type\": 0,\n      \"value\": \"互動\"\n    }\n  ],\n  \"i/dBAR\": [\n    {\n      \"type\": 0,\n      \"value\": \"打閃池\"\n    }\n  ],\n  \"i5gBFz\": [\n    {\n      \"type\": 0,\n      \"value\": \"你已發送和收到的付款將顯示在此處。\"\n    }\n  ],\n  \"iCqGww\": [\n    {\n      \"type\": 0,\n      \"value\": \"回應（\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"）\"\n    }\n  ],\n  \"iEoXYx\": [\n    {\n      \"type\": 0,\n      \"value\": \"DeepL 翻譯\"\n    }\n  ],\n  \"iGT1eE\": [\n    {\n      \"type\": 0,\n      \"value\": \"防止虛假帳戶冒充你\"\n    }\n  ],\n  \"iHN12u\": [\n    {\n      \"type\": 0,\n      \"value\": \"管理員\"\n    }\n  ],\n  \"iICVoL\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 個關注 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 個重複)\"\n    }\n  ],\n  \"iNWbVV\": [\n    {\n      \"type\": 0,\n      \"value\": \"代號\"\n    }\n  ],\n  \"iXPL0Z\": [\n    {\n      \"type\": 0,\n      \"value\": \"無法在不安全的連接上使用私鑰登錄，請使用 nostr 密鑰管理器擴展程序\"\n    }\n  ],\n  \"iYc3Ld\": [\n    {\n      \"type\": 0,\n      \"value\": \"付款\"\n    }\n  ],\n  \"icCxlA\": [\n    {\n      \"type\": 0,\n      \"value\": \"新使用者頁面\"\n    }\n  ],\n  \"ieGrWo\": [\n    {\n      \"type\": 0,\n      \"value\": \"關注\"\n    }\n  ],\n  \"igUUst\": [\n    {\n      \"type\": 0,\n      \"value\": \"群聊主題回覆\"\n    }\n  ],\n  \"ipHVx5\": [\n    {\n      \"type\": 0,\n      \"value\": \"生成發票\"\n    }\n  ],\n  \"itPgxd\": [\n    {\n      \"type\": 0,\n      \"value\": \"個人檔案\"\n    }\n  ],\n  \"izWS4J\": [\n    {\n      \"type\": 0,\n      \"value\": \"取消關注\"\n    }\n  ],\n  \"j9xbzF\": [\n    {\n      \"type\": 0,\n      \"value\": \"已备份\"\n    }\n  ],\n  \"jA3OE/\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 聰\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \" 聰\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"jAmfGl\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"site_name\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 訂閱已過期了\"\n    }\n  ],\n  \"jHa/ko\": [\n    {\n      \"type\": 0,\n      \"value\": \"清理你的訂閱\"\n    }\n  ],\n  \"jMzO1S\": [\n    {\n      \"type\": 0,\n      \"value\": \"內部錯誤：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"msg\"\n    }\n  ],\n  \"jiAVXu\": [\n    {\n      \"type\": 0,\n      \"value\": \"視訊活動\"\n    }\n  ],\n  \"jvo0vs\": [\n    {\n      \"type\": 0,\n      \"value\": \"保存\"\n    }\n  ],\n  \"jzgQ2z\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 個回應\"\n    }\n  ],\n  \"k0kCJp\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即申請\"\n    }\n  ],\n  \"k2veDA\": [\n    {\n      \"type\": 0,\n      \"value\": \"寫\"\n    }\n  ],\n  \"k7sKNy\": [\n    {\n      \"type\": 0,\n      \"value\": \"我們自己的 NIP-05 驗證服務，幫助支持本站的發展，並在我們的網站上獲得閃亮的特殊徽章。\"\n    }\n  ],\n  \"k9SQm1\": [\n    {\n      \"type\": 0,\n      \"value\": \"您之前連接過且看起來可靠的繼電器。\"\n    }\n  ],\n  \"kEZUR8\": [\n    {\n      \"type\": 0,\n      \"value\": \"註冊一個 Iris 用戶名\"\n    }\n  ],\n  \"kJYo0u\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"已轉發\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"和\"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"個其他用戶已轉發\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"kKC9ya\": [\n    {\n      \"type\": 0,\n      \"value\": \"錢包資訊\"\n    }\n  ],\n  \"kNd2FL\": [\n    {\n      \"type\": 0,\n      \"value\": \"潮汐登錄\"\n    }\n  ],\n  \"kQAf2d\": [\n    {\n      \"type\": 0,\n      \"value\": \"選擇\"\n    }\n  ],\n  \"kaaf1E\": [\n    {\n      \"type\": 0,\n      \"value\": \"現在\"\n    }\n  ],\n  \"kc79d3\": [\n    {\n      \"type\": 0,\n      \"value\": \"话题\"\n    }\n  ],\n  \"klCm96\": [\n    {\n      \"type\": 0,\n      \"value\": \"社區職位核准\"\n    }\n  ],\n  \"kqPQJD\": [\n    {\n      \"type\": 0,\n      \"value\": \"設置打閃池\"\n    }\n  ],\n  \"kuPHYE\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"已點贊\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 1,\n              \"value\": \"name\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"和\"\n            },\n            {\n              \"type\": 1,\n              \"value\": \"n\"\n            },\n            {\n              \"type\": 0,\n              \"value\": \"個其他用戶已點贊\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"l+ikU1\": [\n    {\n      \"type\": 1,\n      \"value\": \"plan\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"提供\"\n    }\n  ],\n  \"l3H1EK\": [\n    {\n      \"type\": 0,\n      \"value\": \"邀請你的好友\"\n    }\n  ],\n  \"l3nTjd\": [\n    {\n      \"type\": 0,\n      \"value\": \"從記憶種子詞組衍生出基本金鑰\"\n    }\n  ],\n  \"lCILNz\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即購買\"\n    }\n  ],\n  \"lD3+8a\": [\n    {\n      \"type\": 0,\n      \"value\": \"付款\"\n    }\n  ],\n  \"lEnclp\": [\n    {\n      \"type\": 0,\n      \"value\": \"我的事件:  \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lPWASz\": [\n    {\n      \"type\": 0,\n      \"value\": \"Snort nostr 地址\"\n    }\n  ],\n  \"lTbT3s\": [\n    {\n      \"type\": 0,\n      \"value\": \"錢包密碼\"\n    }\n  ],\n  \"lbr3Lq\": [\n    {\n      \"type\": 0,\n      \"value\": \"複製連結\"\n    }\n  ],\n  \"lfOesV\": [\n    {\n      \"type\": 0,\n      \"value\": \"非打閃\"\n    }\n  ],\n  \"lgg1KN\": [\n    {\n      \"type\": 0,\n      \"value\": \"帳戶頁面\"\n    }\n  ],\n  \"ll3xBp\": [\n    {\n      \"type\": 0,\n      \"value\": \"圖片代理服務\"\n    }\n  ],\n  \"lnaT9F\": [\n    {\n      \"type\": 0,\n      \"value\": \"關注 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"lsNFM1\": [\n    {\n      \"type\": 0,\n      \"value\": \"點擊以從 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 加載內容\"\n    }\n  ],\n  \"lvlPhZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"支付發票\"\n    }\n  ],\n  \"m/59y2\": [\n    {\n      \"type\": 0,\n      \"value\": \"Zap 請求\"\n    }\n  ],\n  \"m6h2Eg\": [\n    {\n      \"type\": 0,\n      \"value\": \"處理者建議\"\n    }\n  ],\n  \"mCEKiZ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 音符已被靜音\"\n    }\n  ],\n  \"mErPop\": [\n    {\n      \"type\": 0,\n      \"value\": \"看起來你還沒有 nostr 地址，查看 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 以購買！\"\n    }\n  ],\n  \"mFtdYh\": [\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 工人繼電器\"\n    }\n  ],\n  \"mKAr6h\": [\n    {\n      \"type\": 0,\n      \"value\": \"全部關注\"\n    }\n  ],\n  \"mKh2HS\": [\n    {\n      \"type\": 0,\n      \"value\": \"文件上傳服務\"\n    }\n  ],\n  \"mKhgP9\": [\n    {\n      \"offset\": 0,\n      \"options\": {\n        \"=0\": {\n          \"value\": []\n        },\n        \"=1\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"已打閃\"\n            }\n          ]\n        },\n        \"other\": {\n          \"value\": [\n            {\n              \"type\": 0,\n              \"value\": \"已打閃\"\n            }\n          ]\n        }\n      },\n      \"pluralType\": \"cardinal\",\n      \"type\": 6,\n      \"value\": \"n\"\n    }\n  ],\n  \"mOFG3K\": [\n    {\n      \"type\": 0,\n      \"value\": \"開始\"\n    }\n  ],\n  \"mfe8RW\": [\n    {\n      \"type\": 0,\n      \"value\": \"選項：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    }\n  ],\n  \"mmPSWH\": [\n    {\n      \"type\": 0,\n      \"value\": \"僅讀\"\n    }\n  ],\n  \"n1Whvj\": [\n    {\n      \"type\": 0,\n      \"value\": \"切換\"\n    }\n  ],\n  \"n5l7tP\": [\n    {\n      \"type\": 0,\n      \"value\": \"基於時間的日曆事件\"\n    }\n  ],\n  \"n8k1SG\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"MiB\"\n    }\n  ],\n  \"nD4frR\": [\n    {\n      \"type\": 0,\n      \"value\": \"出價確認\"\n    }\n  ],\n  \"nDejmx\": [\n    {\n      \"type\": 0,\n      \"value\": \"解除屏蔽\"\n    }\n  ],\n  \"nGBrvw\": [\n    {\n      \"type\": 0,\n      \"value\": \"收藏\"\n    }\n  ],\n  \"nGGDsi\": [\n    {\n      \"type\": 0,\n      \"value\": \"以允許通知\"\n    }\n  ],\n  \"nIchMQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"正在搜索帳戶活動（\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"progress\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"）\"\n    }\n  ],\n  \"nPHrqp\": [\n    {\n      \"type\": 0,\n      \"value\": \"Coinjoin Pool\"\n    }\n  ],\n  \"nUT0Lv\": [\n    {\n      \"type\": 0,\n      \"value\": \"工具\"\n    }\n  ],\n  \"nWQFic\": [\n    {\n      \"type\": 0,\n      \"value\": \"續訂\"\n    }\n  ],\n  \"nihgfo\": [\n    {\n      \"type\": 0,\n      \"value\": \"聆聽本文\"\n    }\n  ],\n  \"nwZXeh\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 已屏蔽\"\n    }\n  ],\n  \"o/gK53\": [\n    {\n      \"type\": 0,\n      \"value\": \"面板\"\n    }\n  ],\n  \"o7e+nJ\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 個粉絲\"\n    }\n  ],\n  \"oJ+JJN\": [\n    {\n      \"type\": 0,\n      \"value\": \"什麼都沒找到 :/\"\n    }\n  ],\n  \"odFwjL\": [\n    {\n      \"type\": 0,\n      \"value\": \"僅關注\"\n    }\n  ],\n  \"ojzbwv\": [\n    {\n      \"type\": 0,\n      \"value\": \"嘿，看起來你還沒有 nostr 地址，你應該去獲取一個！查看 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    }\n  ],\n  \"ozZ2Cj\": [\n    {\n      \"type\": 0,\n      \"value\": \"徽章獎\"\n    }\n  ],\n  \"p4N05H\": [\n    {\n      \"type\": 0,\n      \"value\": \"上傳\"\n    }\n  ],\n  \"p9Ps2l\": [\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"/\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"y\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 有中繼器 (\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"percent\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \")\"\n    }\n  ],\n  \"pEEBFk\": [\n    {\n      \"type\": 0,\n      \"value\": \"可靠的繼電器\"\n    }\n  ],\n  \"pI+77w\": [\n    {\n      \"type\": 0,\n      \"value\": \"可從 Snort 中繼器下載備份\"\n    }\n  ],\n  \"pRess9\": [\n    {\n      \"type\": 0,\n      \"value\": \"打閃池\"\n    }\n  ],\n  \"plOM0t\": [\n    {\n      \"type\": 0,\n      \"value\": \"自訂表情符號\"\n    }\n  ],\n  \"plg2Ua\": [\n    {\n      \"type\": 0,\n      \"value\": \"頻道靜音使用者\"\n    }\n  ],\n  \"puLNUJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"置頂\"\n    }\n  ],\n  \"pyjJ5f\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr Marketplace (適用於彈性市場)\"\n    }\n  ],\n  \"pzTOmv\": [\n    {\n      \"type\": 0,\n      \"value\": \"粉絲\"\n    }\n  ],\n  \"q3OuMw\": [\n    {\n      \"type\": 0,\n      \"value\": \"Torrent 評論\"\n    }\n  ],\n  \"qAY40L\": [\n    {\n      \"type\": 0,\n      \"value\": \"基於日期的日曆事件\"\n    }\n  ],\n  \"qBYNMb\": [\n    {\n      \"type\": 0,\n      \"value\": \"群組主題回覆\"\n    }\n  ],\n  \"qD9EUF\": [\n    {\n      \"type\": 0,\n      \"value\": \"給你的 Snort nostr 地址建立電子郵件 <> 私信橋\"\n    }\n  ],\n  \"qDwvZ4\": [\n    {\n      \"type\": 0,\n      \"value\": \"未知錯誤\"\n    }\n  ],\n  \"qFIVx4\": [\n    {\n      \"type\": 0,\n      \"value\": \"個人資料徽章\"\n    }\n  ],\n  \"qMePPG\": [\n    {\n      \"type\": 0,\n      \"value\": \"筆記\"\n    }\n  ],\n  \"qMx1sA\": [\n    {\n      \"type\": 0,\n      \"value\": \"默認打閃金額\"\n    }\n  ],\n  \"qUJTsT\": [\n    {\n      \"type\": 0,\n      \"value\": \"已屏蔽\"\n    }\n  ],\n  \"qXCbgZ\": [\n    {\n      \"type\": 0,\n      \"value\": \"解鎖\"\n    }\n  ],\n  \"qZsKBR\": [\n    {\n      \"type\": 0,\n      \"value\": \"更新 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"tier\"\n    }\n  ],\n  \"qcJFEJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"已停用通知 API\"\n    }\n  ],\n  \"qdGuQo\": [\n    {\n      \"type\": 0,\n      \"value\": \"你的私鑰是（不要與任何人分享）\"\n    }\n  ],\n  \"qfmMQh\": [\n    {\n      \"type\": 0,\n      \"value\": \"该筆記已被静音\"\n    }\n  ],\n  \"qkvYUb\": [\n    {\n      \"type\": 0,\n      \"value\": \"添加至個人檔案\"\n    }\n  ],\n  \"qmJ8kD\": [\n    {\n      \"type\": 0,\n      \"value\": \"翻譯失敗\"\n    }\n  ],\n  \"qtWLmt\": [\n    {\n      \"type\": 0,\n      \"value\": \"點贊\"\n    }\n  ],\n  \"qyJtWy\": [\n    {\n      \"type\": 0,\n      \"value\": \"顯示更少\"\n    }\n  ],\n  \"qydxOd\": [\n    {\n      \"type\": 0,\n      \"value\": \"科學\"\n    }\n  ],\n  \"qz9fty\": [\n    {\n      \"type\": 0,\n      \"value\": \"PIN 碼不正確\"\n    }\n  ],\n  \"r3C4x/\": [\n    {\n      \"type\": 0,\n      \"value\": \"軟件\"\n    }\n  ],\n  \"r5srDR\": [\n    {\n      \"type\": 0,\n      \"value\": \"輸入錢包密碼\"\n    }\n  ],\n  \"rAQG0X\": [\n    {\n      \"type\": 0,\n      \"value\": \"中繼清單元資料\"\n    }\n  ],\n  \"rIsVe+\": [\n    {\n      \"type\": 0,\n      \"value\": \"公開聊天清單\"\n    }\n  ],\n  \"rMgF34\": [\n    {\n      \"type\": 0,\n      \"value\": \"立即備份\"\n    }\n  ],\n  \"rRRXtB\": [\n    {\n      \"type\": 0,\n      \"value\": \"電擊\"\n    }\n  ],\n  \"rT14Ow\": [\n    {\n      \"type\": 0,\n      \"value\": \"添加中繼器\"\n    }\n  ],\n  \"reFEEC\": [\n    {\n      \"type\": 0,\n      \"value\": \"報告\"\n    }\n  ],\n  \"rfuMjE\": [\n    {\n      \"type\": 0,\n      \"value\": \"（默認）\"\n    }\n  ],\n  \"rkM7l8\": [\n    {\n      \"type\": 0,\n      \"value\": \"加密直接訊息\"\n    }\n  ],\n  \"rmdsT4\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \"天\"\n    }\n  ],\n  \"rn52n9\": [\n    {\n      \"type\": 0,\n      \"value\": \"公開聊天頻道\"\n    }\n  ],\n  \"rx1i0i\": [\n    {\n      \"type\": 0,\n      \"value\": \"短鏈接\"\n    }\n  ],\n  \"sFUkSN\": [\n    {\n      \"type\": 0,\n      \"value\": \"書籤集\"\n    }\n  ],\n  \"sKDn4e\": [\n    {\n      \"type\": 0,\n      \"value\": \"顯示徽章\"\n    }\n  ],\n  \"sUNhQE\": [\n    {\n      \"type\": 0,\n      \"value\": \"用戶\"\n    }\n  ],\n  \"sZQzjQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"解析打閃拆分失敗了：\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"input\"\n    }\n  ],\n  \"saInmO\": [\n    {\n      \"type\": 0,\n      \"value\": \"顯示的中繼名稱與輸入的完整 URL 不相同。\"\n    }\n  ],\n  \"saorw+\": [\n    {\n      \"type\": 0,\n      \"value\": \"事件刪除請求\"\n    }\n  ],\n  \"sfL/O+\": [\n    {\n      \"type\": 0,\n      \"value\": \"已靜音筆記將不顯示\"\n    }\n  ],\n  \"t79a6U\": [\n    {\n      \"type\": 0,\n      \"value\": \"連接成功：\"\n    }\n  ],\n  \"tDDiRL\": [\n    {\n      \"type\": 0,\n      \"value\": \"興趣清單\"\n    }\n  ],\n  \"tFpT/O\": [\n    {\n      \"type\": 0,\n      \"value\": \"釋放工件集\"\n    }\n  ],\n  \"tO1oq9\": [\n    {\n      \"type\": 0,\n      \"value\": \"視訊活動\"\n    }\n  ],\n  \"tOdNiY\": [\n    {\n      \"type\": 0,\n      \"value\": \"深色\"\n    }\n  ],\n  \"tRGdV1\": [\n    {\n      \"type\": 0,\n      \"value\": \"版本化加密\"\n    }\n  ],\n  \"tU0ADf\": [\n    {\n      \"type\": 0,\n      \"value\": \"未知 NIP-\"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"x\"\n    }\n  ],\n  \"tVuVg9\": [\n    {\n      \"type\": 0,\n      \"value\": \"視訊觀賞活動\"\n    }\n  ],\n  \"tf1lIh\": [\n    {\n      \"type\": 0,\n      \"value\": \"免費\"\n    }\n  ],\n  \"th5lxp\": [\n    {\n      \"type\": 0,\n      \"value\": \"將筆記發送到你的寫入中繼器的子集\"\n    }\n  ],\n  \"thnRpU\": [\n    {\n      \"type\": 0,\n      \"value\": \"驗證 NIP-05 可以幫助：\"\n    }\n  ],\n  \"tj6kdX\": [\n    {\n      \"type\": 1,\n      \"value\": \"sign\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"amount\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 聰\"\n    }\n  ],\n  \"tjpYlr\": [\n    {\n      \"type\": 0,\n      \"value\": \"中繼器指標\"\n    }\n  ],\n  \"ttxS0b\": [\n    {\n      \"type\": 0,\n      \"value\": \"支持者徽章\"\n    }\n  ],\n  \"tzMNF3\": [\n    {\n      \"type\": 0,\n      \"value\": \"狀態\"\n    }\n  ],\n  \"u/vOPu\": [\n    {\n      \"type\": 0,\n      \"value\": \"已支付\"\n    }\n  ],\n  \"u4I8q8\": [\n    {\n      \"type\": 0,\n      \"value\": \"針腳清單\"\n    }\n  ],\n  \"u81G9+\": [\n    {\n      \"type\": 0,\n      \"value\": \"正常運行時間\"\n    }\n  ],\n  \"u9NoC1\": [\n    {\n      \"type\": 0,\n      \"value\": \"名稱必須少於 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"limit\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 個字符\"\n    }\n  ],\n  \"uCk8r+\": [\n    {\n      \"type\": 0,\n      \"value\": \"已經有帳戶？\"\n    }\n  ],\n  \"uD7Els\": [\n    {\n      \"type\": 0,\n      \"value\": \"檔案中的外部身分\"\n    }\n  ],\n  \"uJaMkO\": [\n    {\n      \"type\": 0,\n      \"value\": \"接收 DM 的中繼清單\"\n    }\n  ],\n  \"uSV4Ti\": [\n    {\n      \"type\": 0,\n      \"value\": \"轉發需要人工確認\"\n    }\n  ],\n  \"uc0din\": [\n    {\n      \"type\": 0,\n      \"value\": \"將聰拆分發送到\"\n    }\n  ],\n  \"ufvXH1\": [\n    {\n      \"type\": 0,\n      \"value\": \"發現 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 個事件\"\n    }\n  ],\n  \"uhu5aG\": [\n    {\n      \"type\": 0,\n      \"value\": \"公開\"\n    }\n  ],\n  \"un1nGw\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 條筆記\"\n    }\n  ],\n  \"usAvMr\": [\n    {\n      \"type\": 0,\n      \"value\": \"編輯個人檔案\"\n    }\n  ],\n  \"v8lolG\": [\n    {\n      \"type\": 0,\n      \"value\": \"開始聊天\"\n    }\n  ],\n  \"vB3oQ/\": [\n    {\n      \"type\": 0,\n      \"value\": \"必須是一個聯繫人列表或公鑰列表\"\n    }\n  ],\n  \"vBsZhD\": [\n    {\n      \"type\": 0,\n      \"value\": \"社群清單\"\n    }\n  ],\n  \"vN5UH8\": [\n    {\n      \"type\": 0,\n      \"value\": \"頭像\"\n    }\n  ],\n  \"vU/Q5i\": [\n    {\n      \"type\": 0,\n      \"value\": \"該工具將搜索所有關注最近發佈的事件，並刪除6個月內未發佈事件的關注。\"\n    }\n  ],\n  \"vZ4quW\": [\n    {\n      \"type\": 0,\n      \"value\": \"NIP-05 是一種基於 DNS 的驗證規範，可幫助驗證你是真實用戶。\"\n    }\n  ],\n  \"vhlWFg\": [\n    {\n      \"type\": 0,\n      \"value\": \"投票選項\"\n    }\n  ],\n  \"vlbWtt\": [\n    {\n      \"type\": 0,\n      \"value\": \"獲取免費的\"\n    }\n  ],\n  \"voxBKC\": [\n    {\n      \"type\": 0,\n      \"value\": \"好友關注\"\n    }\n  ],\n  \"vxwnbh\": [\n    {\n      \"type\": 0,\n      \"value\": \"適用於所有發佈事件的工作量\"\n    }\n  ],\n  \"w1Fanr\": [\n    {\n      \"type\": 0,\n      \"value\": \"商業\"\n    }\n  ],\n  \"w6qrwX\": [\n    {\n      \"type\": 0,\n      \"value\": \"敏感內容\"\n    }\n  ],\n  \"wEQDC6\": [\n    {\n      \"type\": 0,\n      \"value\": \"編輯\"\n    }\n  ],\n  \"wOyDTB\": [\n    {\n      \"type\": 0,\n      \"value\": \"檔案儲存伺服器清單\"\n    }\n  ],\n  \"wSZR47\": [\n    {\n      \"type\": 0,\n      \"value\": \"提交\"\n    }\n  ],\n  \"wc9st7\": [\n    {\n      \"type\": 0,\n      \"value\": \"媒體附件\"\n    }\n  ],\n  \"whSrs+\": [\n    {\n      \"type\": 0,\n      \"value\": \"Nostr 公開聊天\"\n    }\n  ],\n  \"wih7iJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"名稱已被屏蔽\"\n    }\n  ],\n  \"wlWMuh\": [\n    {\n      \"type\": 0,\n      \"value\": \"補丁\"\n    }\n  ],\n  \"wofVHy\": [\n    {\n      \"type\": 0,\n      \"value\": \"審核\"\n    }\n  ],\n  \"wqyN/i\": [\n    {\n      \"type\": 0,\n      \"value\": \"在 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"link\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 瞭解有關 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"service\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 的更多信息\"\n    }\n  ],\n  \"wtLjP6\": [\n    {\n      \"type\": 0,\n      \"value\": \"複製ID\"\n    }\n  ],\n  \"x+3fl6\": [\n    {\n      \"type\": 0,\n      \"value\": \"我的繼電器\"\n    }\n  ],\n  \"x/Fx2P\": [\n    {\n      \"type\": 0,\n      \"value\": \"將部份打閃分配到資金庫來資助你使用的服務！\"\n    }\n  ],\n  \"x82IOl\": [\n    {\n      \"type\": 0,\n      \"value\": \"静音\"\n    }\n  ],\n  \"xEjBS7\": [\n    {\n      \"type\": 0,\n      \"value\": \"爲你推薦\"\n    }\n  ],\n  \"xIcAOU\": [\n    {\n      \"type\": 0,\n      \"value\": \"根據 \"\n    },\n    {\n      \"type\": 1,\n      \"value\": \"type\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 的投票\"\n    }\n  ],\n  \"xIoGG9\": [\n    {\n      \"type\": 0,\n      \"value\": \"前往\"\n    }\n  ],\n  \"xPCyu+\": [\n    {\n      \"type\": 0,\n      \"value\": \"nostr：URI 方案\"\n    }\n  ],\n  \"xaj9Ba\": [\n    {\n      \"type\": 0,\n      \"value\": \"供應方\"\n    }\n  ],\n  \"xbVgIm\": [\n    {\n      \"type\": 0,\n      \"value\": \"自動加載媒體\"\n    }\n  ],\n  \"xhQMeQ\": [\n    {\n      \"type\": 0,\n      \"value\": \"有效期\"\n    }\n  ],\n  \"xl4s/X\": [\n    {\n      \"type\": 0,\n      \"value\": \"附加條款：\"\n    }\n  ],\n  \"xmcVZ0\": [\n    {\n      \"type\": 0,\n      \"value\": \"搜索\"\n    }\n  ],\n  \"xybOUv\": [\n    {\n      \"type\": 0,\n      \"value\": \"粉絲\"\n    }\n  ],\n  \"y/bmsG\": [\n    {\n      \"type\": 0,\n      \"value\": \"允許\"\n    }\n  ],\n  \"y1Z3or\": [\n    {\n      \"type\": 0,\n      \"value\": \"語言\"\n    }\n  ],\n  \"yAztTU\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" e聰\"\n    }\n  ],\n  \"yCLnBC\": [\n    {\n      \"type\": 0,\n      \"value\": \"LNURL 或閃電地址\"\n    }\n  ],\n  \"yLzgxH\": [\n    {\n      \"type\": 0,\n      \"value\": \"熱門繼電器\"\n    }\n  ],\n  \"yeX8yA\": [\n    {\n      \"type\": 0,\n      \"value\": \"原生應用程式\"\n    }\n  ],\n  \"z3UjXR\": [\n    {\n      \"type\": 0,\n      \"value\": \"除錯\"\n    }\n  ],\n  \"z3Ukvq\": [\n    {\n      \"type\": 0,\n      \"value\": \"草擬長篇內容\"\n    }\n  ],\n  \"zCb8fX\": [\n    {\n      \"type\": 0,\n      \"value\": \"權重\"\n    }\n  ],\n  \"zFegDD\": [\n    {\n      \"type\": 0,\n      \"value\": \"聯絡\"\n    }\n  ],\n  \"zINlao\": [\n    {\n      \"type\": 0,\n      \"value\": \"所有者\"\n    }\n  ],\n  \"zQvVDJ\": [\n    {\n      \"type\": 0,\n      \"value\": \"全部\"\n    }\n  ],\n  \"zcaOTs\": [\n    {\n      \"type\": 0,\n      \"value\": \"以聰為單位的打閃金額\"\n    }\n  ],\n  \"zi9MdS\": [\n    {\n      \"type\": 0,\n      \"value\": \"國際象棋 (PGN)\"\n    }\n  ],\n  \"zm6qS1\": [\n    {\n      \"type\": 1,\n      \"value\": \"n\"\n    },\n    {\n      \"type\": 0,\n      \"value\": \" 分鐘閱讀時間\"\n    }\n  ],\n  \"zonsdq\": [\n    {\n      \"type\": 0,\n      \"value\": \"加載 LNURL 服務失敗\"\n    }\n  ],\n  \"zvCDao\": [\n    {\n      \"type\": 0,\n      \"value\": \"自動顯示最新筆記\"\n    }\n  ],\n  \"zx0myy\": [\n    {\n      \"type\": 0,\n      \"value\": \"參與者\"\n    }\n  ]\n}\n"
  },
  {
    "path": "packages/app/src/tz.json",
    "content": "{\n  \"Africa/Abidjan\": [\"CI\", \"+0519-00402\"],\n  \"Africa/Accra\": [\"GH\", \"+0533-00013\"],\n  \"Africa/Addis_Ababa\": [\"ET\", \"+0902+03842\"],\n  \"Africa/Algiers\": [\"DZ\", \"+3647+00303\"],\n  \"Africa/Asmara\": [\"ER\", \"+1520+03853\"],\n  \"Africa/Bamako\": [\"ML\", \"+1239-00800\"],\n  \"Africa/Bangui\": [\"CF\", \"+0422+01835\"],\n  \"Africa/Banjul\": [\"GM\", \"+1328-01639\"],\n  \"Africa/Bissau\": [\"GW\", \"+1151-01535\"],\n  \"Africa/Blantyre\": [\"MW\", \"-1547+03500\"],\n  \"Africa/Brazzaville\": [\"CG\", \"-0416+01517\"],\n  \"Africa/Bujumbura\": [\"BI\", \"-0323+02922\"],\n  \"Africa/Cairo\": [\"EG\", \"+3003+03115\"],\n  \"Africa/Casablanca\": [\"MA\", \"+3339-00735\"],\n  \"Africa/Ceuta\": [\"ES\", \"+3553-00519\"],\n  \"Africa/Conakry\": [\"GN\", \"+0931-01343\"],\n  \"Africa/Dakar\": [\"SN\", \"+1440-01726\"],\n  \"Africa/Dar_es_Salaam\": [\"TZ\", \"-0648+03917\"],\n  \"Africa/Djibouti\": [\"DJ\", \"+1136+04309\"],\n  \"Africa/Douala\": [\"CM\", \"+0403+00942\"],\n  \"Africa/El_Aaiun\": [\"EH\", \"+2709-01312\"],\n  \"Africa/Freetown\": [\"SL\", \"+0830-01315\"],\n  \"Africa/Gaborone\": [\"BW\", \"-2439+02555\"],\n  \"Africa/Harare\": [\"ZW\", \"-1750+03103\"],\n  \"Africa/Johannesburg\": [\"ZA\", \"-2615+02800\"],\n  \"Africa/Juba\": [\"SS\", \"+0451+03137\"],\n  \"Africa/Kampala\": [\"UG\", \"+0019+03225\"],\n  \"Africa/Khartoum\": [\"SD\", \"+1536+03232\"],\n  \"Africa/Kigali\": [\"RW\", \"-0157+03004\"],\n  \"Africa/Kinshasa\": [\"CD\", \"-0418+01518\"],\n  \"Africa/Lagos\": [\"NG\", \"+0627+00324\"],\n  \"Africa/Libreville\": [\"GA\", \"+0023+00927\"],\n  \"Africa/Lome\": [\"TG\", \"+0608+00113\"],\n  \"Africa/Luanda\": [\"AO\", \"-0848+01314\"],\n  \"Africa/Lubumbashi\": [\"CD\", \"-1140+02728\"],\n  \"Africa/Lusaka\": [\"ZM\", \"-1525+02817\"],\n  \"Africa/Malabo\": [\"GQ\", \"+0345+00847\"],\n  \"Africa/Maputo\": [\"MZ\", \"-2558+03235\"],\n  \"Africa/Maseru\": [\"LS\", \"-2928+02730\"],\n  \"Africa/Mbabane\": [\"SZ\", \"-2618+03106\"],\n  \"Africa/Mogadishu\": [\"SO\", \"+0204+04522\"],\n  \"Africa/Monrovia\": [\"LR\", \"+0618-01047\"],\n  \"Africa/Nairobi\": [\"KE\", \"-0117+03649\"],\n  \"Africa/Ndjamena\": [\"TD\", \"+1207+01503\"],\n  \"Africa/Niamey\": [\"NE\", \"+1331+00207\"],\n  \"Africa/Nouakchott\": [\"MR\", \"+1806-01557\"],\n  \"Africa/Ouagadougou\": [\"BF\", \"+1222-00131\"],\n  \"Africa/Porto-Novo\": [\"BJ\", \"+0629+00237\"],\n  \"Africa/Sao_Tome\": [\"ST\", \"+0020+00644\"],\n  \"Africa/Tripoli\": [\"LY\", \"+3254+01311\"],\n  \"Africa/Tunis\": [\"TN\", \"+3648+01011\"],\n  \"Africa/Windhoek\": [\"NA\", \"-2234+01706\"],\n  \"America/Adak\": [\"US\", \"+515248-1763929\"],\n  \"America/Anchorage\": [\"US\", \"+611305-1495401\"],\n  \"America/Anguilla\": [\"AI\", \"+1812-06304\"],\n  \"America/Antigua\": [\"AG\", \"+1703-06148\"],\n  \"America/Araguaina\": [\"BR\", \"-0712-04812\"],\n  \"America/Argentina/Buenos_Aires\": [\"AR\", \"-3436-05827\"],\n  \"America/Argentina/Catamarca\": [\"AR\", \"-2828-06547\"],\n  \"America/Argentina/Cordoba\": [\"AR\", \"-3124-06411\"],\n  \"America/Argentina/Jujuy\": [\"AR\", \"-2411-06518\"],\n  \"America/Argentina/La_Rioja\": [\"AR\", \"-2926-06651\"],\n  \"America/Argentina/Mendoza\": [\"AR\", \"-3253-06849\"],\n  \"America/Argentina/Rio_Gallegos\": [\"AR\", \"-5138-06913\"],\n  \"America/Argentina/Salta\": [\"AR\", \"-2447-06525\"],\n  \"America/Argentina/San_Juan\": [\"AR\", \"-3132-06831\"],\n  \"America/Argentina/San_Luis\": [\"AR\", \"-3319-06621\"],\n  \"America/Argentina/Tucuman\": [\"AR\", \"-2649-06513\"],\n  \"America/Argentina/Ushuaia\": [\"AR\", \"-5448-06818\"],\n  \"America/Aruba\": [\"AW\", \"+1230-06958\"],\n  \"America/Asuncion\": [\"PY\", \"-2516-05740\"],\n  \"America/Atikokan\": [\"CA\", \"+484531-0913718\"],\n  \"America/Bahia\": [\"BR\", \"-1259-03831\"],\n  \"America/Bahia_Banderas\": [\"MX\", \"+2048-10515\"],\n  \"America/Barbados\": [\"BB\", \"+1306-05937\"],\n  \"America/Belem\": [\"BR\", \"-0127-04829\"],\n  \"America/Belize\": [\"BZ\", \"+1730-08812\"],\n  \"America/Blanc-Sablon\": [\"CA\", \"+5125-05707\"],\n  \"America/Boa_Vista\": [\"BR\", \"+0249-06040\"],\n  \"America/Bogota\": [\"CO\", \"+0436-07405\"],\n  \"America/Boise\": [\"US\", \"+433649-1161209\"],\n  \"America/Cambridge_Bay\": [\"CA\", \"+690650-1050310\"],\n  \"America/Campo_Grande\": [\"BR\", \"-2027-05437\"],\n  \"America/Cancun\": [\"MX\", \"+2105-08646\"],\n  \"America/Caracas\": [\"VE\", \"+1030-06656\"],\n  \"America/Cayenne\": [\"GF\", \"+0456-05220\"],\n  \"America/Cayman\": [\"KY\", \"+1918-08123\"],\n  \"America/Chicago\": [\"US\", \"+415100-0873900\"],\n  \"America/Chihuahua\": [\"MX\", \"+2838-10605\"],\n  \"America/Ciudad_Juarez\": [\"MX\", \"+3144-10629\"],\n  \"America/Costa_Rica\": [\"CR\", \"+0956-08405\"],\n  \"America/Creston\": [\"CA\", \"+4906-11631\"],\n  \"America/Cuiaba\": [\"BR\", \"-1535-05605\"],\n  \"America/Curacao\": [\"CW\", \"+1211-06900\"],\n  \"America/Danmarkshavn\": [\"GL\", \"+7646-01840\"],\n  \"America/Dawson\": [\"CA\", \"+6404-13925\"],\n  \"America/Dawson_Creek\": [\"CA\", \"+5546-12014\"],\n  \"America/Denver\": [\"US\", \"+394421-1045903\"],\n  \"America/Detroit\": [\"US\", \"+421953-0830245\"],\n  \"America/Dominica\": [\"DM\", \"+1518-06124\"],\n  \"America/Edmonton\": [\"CA\", \"+5333-11328\"],\n  \"America/Eirunepe\": [\"BR\", \"-0640-06952\"],\n  \"America/El_Salvador\": [\"SV\", \"+1342-08912\"],\n  \"America/Fort_Nelson\": [\"CA\", \"+5848-12242\"],\n  \"America/Fortaleza\": [\"BR\", \"-0343-03830\"],\n  \"America/Glace_Bay\": [\"CA\", \"+4612-05957\"],\n  \"America/Goose_Bay\": [\"CA\", \"+5320-06025\"],\n  \"America/Grand_Turk\": [\"TC\", \"+2128-07108\"],\n  \"America/Grenada\": [\"GD\", \"+1203-06145\"],\n  \"America/Guadeloupe\": [\"GP\", \"+1614-06132\"],\n  \"America/Guatemala\": [\"GT\", \"+1438-09031\"],\n  \"America/Guayaquil\": [\"EC\", \"-0210-07950\"],\n  \"America/Guyana\": [\"GY\", \"+0648-05810\"],\n  \"America/Halifax\": [\"CA\", \"+4439-06336\"],\n  \"America/Havana\": [\"CU\", \"+2308-08222\"],\n  \"America/Hermosillo\": [\"MX\", \"+2904-11058\"],\n  \"America/Indiana/Indianapolis\": [\"US\", \"+394606-0860929\"],\n  \"America/Indiana/Knox\": [\"US\", \"+411745-0863730\"],\n  \"America/Indiana/Marengo\": [\"US\", \"+382232-0862041\"],\n  \"America/Indiana/Petersburg\": [\"US\", \"+382931-0871643\"],\n  \"America/Indiana/Tell_City\": [\"US\", \"+375711-0864541\"],\n  \"America/Indiana/Vevay\": [\"US\", \"+384452-0850402\"],\n  \"America/Indiana/Vincennes\": [\"US\", \"+384038-0873143\"],\n  \"America/Indiana/Winamac\": [\"US\", \"+410305-0863611\"],\n  \"America/Inuvik\": [\"CA\", \"+682059-1334300\"],\n  \"America/Iqaluit\": [\"CA\", \"+6344-06828\"],\n  \"America/Jamaica\": [\"JM\", \"+175805-0764736\"],\n  \"America/Juneau\": [\"US\", \"+581807-1342511\"],\n  \"America/Kentucky/Louisville\": [\"US\", \"+381515-0854534\"],\n  \"America/Kentucky/Monticello\": [\"US\", \"+364947-0845057\"],\n  \"America/Kralendijk\": [\"BQ\", \"+120903-0681636\"],\n  \"America/La_Paz\": [\"BO\", \"-1630-06809\"],\n  \"America/Lima\": [\"PE\", \"-1203-07703\"],\n  \"America/Los_Angeles\": [\"US\", \"+340308-1181434\"],\n  \"America/Lower_Princes\": [\"SX\", \"+180305-0630250\"],\n  \"America/Maceio\": [\"BR\", \"-0940-03543\"],\n  \"America/Managua\": [\"NI\", \"+1209-08617\"],\n  \"America/Manaus\": [\"BR\", \"-0308-06001\"],\n  \"America/Marigot\": [\"MF\", \"+1804-06305\"],\n  \"America/Martinique\": [\"MQ\", \"+1436-06105\"],\n  \"America/Matamoros\": [\"MX\", \"+2550-09730\"],\n  \"America/Mazatlan\": [\"MX\", \"+2313-10625\"],\n  \"America/Menominee\": [\"US\", \"+450628-0873651\"],\n  \"America/Merida\": [\"MX\", \"+2058-08937\"],\n  \"America/Metlakatla\": [\"US\", \"+550737-1313435\"],\n  \"America/Mexico_City\": [\"MX\", \"+1924-09909\"],\n  \"America/Miquelon\": [\"PM\", \"+4703-05620\"],\n  \"America/Moncton\": [\"CA\", \"+4606-06447\"],\n  \"America/Monterrey\": [\"MX\", \"+2540-10019\"],\n  \"America/Montevideo\": [\"UY\", \"-345433-0561245\"],\n  \"America/Montserrat\": [\"MS\", \"+1643-06213\"],\n  \"America/Nassau\": [\"BS\", \"+2505-07721\"],\n  \"America/New_York\": [\"US\", \"+404251-0740023\"],\n  \"America/Nome\": [\"US\", \"+643004-1652423\"],\n  \"America/Noronha\": [\"BR\", \"-0351-03225\"],\n  \"America/North_Dakota/Beulah\": [\"US\", \"+471551-1014640\"],\n  \"America/North_Dakota/Center\": [\"US\", \"+470659-1011757\"],\n  \"America/North_Dakota/New_Salem\": [\"US\", \"+465042-1012439\"],\n  \"America/Nuuk\": [\"GL\", \"+6411-05144\"],\n  \"America/Ojinaga\": [\"MX\", \"+2934-10425\"],\n  \"America/Panama\": [\"PA\", \"+0858-07932\"],\n  \"America/Paramaribo\": [\"SR\", \"+0550-05510\"],\n  \"America/Phoenix\": [\"US\", \"+332654-1120424\"],\n  \"America/Port-au-Prince\": [\"HT\", \"+1832-07220\"],\n  \"America/Port_of_Spain\": [\"TT\", \"+1039-06131\"],\n  \"America/Porto_Velho\": [\"BR\", \"-0846-06354\"],\n  \"America/Puerto_Rico\": [\"PR\", \"+182806-0660622\"],\n  \"America/Punta_Arenas\": [\"CL\", \"-5309-07055\"],\n  \"America/Rankin_Inlet\": [\"CA\", \"+624900-0920459\"],\n  \"America/Recife\": [\"BR\", \"-0803-03454\"],\n  \"America/Regina\": [\"CA\", \"+5024-10439\"],\n  \"America/Resolute\": [\"CA\", \"+744144-0944945\"],\n  \"America/Rio_Branco\": [\"BR\", \"-0958-06748\"],\n  \"America/Santarem\": [\"BR\", \"-0226-05452\"],\n  \"America/Santiago\": [\"CL\", \"-3327-07040\"],\n  \"America/Santo_Domingo\": [\"DO\", \"+1828-06954\"],\n  \"America/Sao_Paulo\": [\"BR\", \"-2332-04637\"],\n  \"America/Scoresbysund\": [\"GL\", \"+7029-02158\"],\n  \"America/Sitka\": [\"US\", \"+571035-1351807\"],\n  \"America/St_Barthelemy\": [\"BL\", \"+1753-06251\"],\n  \"America/St_Johns\": [\"CA\", \"+4734-05243\"],\n  \"America/St_Kitts\": [\"KN\", \"+1718-06243\"],\n  \"America/St_Lucia\": [\"LC\", \"+1401-06100\"],\n  \"America/St_Thomas\": [\"VI\", \"+1821-06456\"],\n  \"America/St_Vincent\": [\"VC\", \"+1309-06114\"],\n  \"America/Swift_Current\": [\"CA\", \"+5017-10750\"],\n  \"America/Tegucigalpa\": [\"HN\", \"+1406-08713\"],\n  \"America/Thule\": [\"GL\", \"+7634-06847\"],\n  \"America/Tijuana\": [\"MX\", \"+3232-11701\"],\n  \"America/Toronto\": [\"CA\", \"+4339-07923\"],\n  \"America/Tortola\": [\"VG\", \"+1827-06437\"],\n  \"America/Vancouver\": [\"CA\", \"+4916-12307\"],\n  \"America/Whitehorse\": [\"CA\", \"+6043-13503\"],\n  \"America/Winnipeg\": [\"CA\", \"+4953-09709\"],\n  \"America/Yakutat\": [\"US\", \"+593249-1394338\"],\n  \"Antarctica/Casey\": [\"AQ\", \"-6617+11031\"],\n  \"Antarctica/Davis\": [\"AQ\", \"-6835+07758\"],\n  \"Antarctica/DumontDUrville\": [\"AQ\", \"-6640+14001\"],\n  \"Antarctica/Macquarie\": [\"AU\", \"-5430+15857\"],\n  \"Antarctica/Mawson\": [\"AQ\", \"-6736+06253\"],\n  \"Antarctica/McMurdo\": [\"AQ\", \"-7750+16636\"],\n  \"Antarctica/Palmer\": [\"AQ\", \"-6448-06406\"],\n  \"Antarctica/Rothera\": [\"AQ\", \"-6734-06808\"],\n  \"Antarctica/Syowa\": [\"AQ\", \"-690022+0393524\"],\n  \"Antarctica/Troll\": [\"AQ\", \"-720041+0023206\"],\n  \"Antarctica/Vostok\": [\"AQ\", \"-7824+10654\"],\n  \"Arctic/Longyearbyen\": [\"SJ\", \"+7800+01600\"],\n  \"Asia/Aden\": [\"YE\", \"+1245+04512\"],\n  \"Asia/Almaty\": [\"KZ\", \"+4315+07657\"],\n  \"Asia/Amman\": [\"JO\", \"+3157+03556\"],\n  \"Asia/Anadyr\": [\"RU\", \"+6445+17729\"],\n  \"Asia/Aqtau\": [\"KZ\", \"+4431+05016\"],\n  \"Asia/Aqtobe\": [\"KZ\", \"+5017+05710\"],\n  \"Asia/Ashgabat\": [\"TM\", \"+3757+05823\"],\n  \"Asia/Atyrau\": [\"KZ\", \"+4707+05156\"],\n  \"Asia/Baghdad\": [\"IQ\", \"+3321+04425\"],\n  \"Asia/Bahrain\": [\"BH\", \"+2623+05035\"],\n  \"Asia/Baku\": [\"AZ\", \"+4023+04951\"],\n  \"Asia/Bangkok\": [\"TH\", \"+1345+10031\"],\n  \"Asia/Barnaul\": [\"RU\", \"+5322+08345\"],\n  \"Asia/Beirut\": [\"LB\", \"+3353+03530\"],\n  \"Asia/Bishkek\": [\"KG\", \"+4254+07436\"],\n  \"Asia/Brunei\": [\"BN\", \"+0456+11455\"],\n  \"Asia/Chita\": [\"RU\", \"+5203+11328\"],\n  \"Asia/Choibalsan\": [\"MN\", \"+4804+11430\"],\n  \"Asia/Colombo\": [\"LK\", \"+0656+07951\"],\n  \"Asia/Damascus\": [\"SY\", \"+3330+03618\"],\n  \"Asia/Dhaka\": [\"BD\", \"+2343+09025\"],\n  \"Asia/Dili\": [\"TL\", \"-0833+12535\"],\n  \"Asia/Dubai\": [\"AE\", \"+2518+05518\"],\n  \"Asia/Dushanbe\": [\"TJ\", \"+3835+06848\"],\n  \"Asia/Famagusta\": [\"CY\", \"+3507+03357\"],\n  \"Asia/Gaza\": [\"PS\", \"+3130+03428\"],\n  \"Asia/Hebron\": [\"PS\", \"+313200+0350542\"],\n  \"Asia/Ho_Chi_Minh\": [\"VN\", \"+1045+10640\"],\n  \"Asia/Hong_Kong\": [\"HK\", \"+2217+11409\"],\n  \"Asia/Hovd\": [\"MN\", \"+4801+09139\"],\n  \"Asia/Irkutsk\": [\"RU\", \"+5216+10420\"],\n  \"Asia/Jakarta\": [\"ID\", \"-0610+10648\"],\n  \"Asia/Jayapura\": [\"ID\", \"-0232+14042\"],\n  \"Asia/Jerusalem\": [\"IL\", \"+314650+0351326\"],\n  \"Asia/Kabul\": [\"AF\", \"+3431+06912\"],\n  \"Asia/Kamchatka\": [\"RU\", \"+5301+15839\"],\n  \"Asia/Karachi\": [\"PK\", \"+2452+06703\"],\n  \"Asia/Kathmandu\": [\"NP\", \"+2743+08519\"],\n  \"Asia/Khandyga\": [\"RU\", \"+623923+1353314\"],\n  \"Asia/Kolkata\": [\"IN\", \"+2232+08822\"],\n  \"Asia/Krasnoyarsk\": [\"RU\", \"+5601+09250\"],\n  \"Asia/Kuala_Lumpur\": [\"MY\", \"+0310+10142\"],\n  \"Asia/Kuching\": [\"MY\", \"+0133+11020\"],\n  \"Asia/Kuwait\": [\"KW\", \"+2920+04759\"],\n  \"Asia/Macau\": [\"MO\", \"+221150+1133230\"],\n  \"Asia/Magadan\": [\"RU\", \"+5934+15048\"],\n  \"Asia/Makassar\": [\"ID\", \"-0507+11924\"],\n  \"Asia/Manila\": [\"PH\", \"+1435+12100\"],\n  \"Asia/Muscat\": [\"OM\", \"+2336+05835\"],\n  \"Asia/Nicosia\": [\"CY\", \"+3510+03322\"],\n  \"Asia/Novokuznetsk\": [\"RU\", \"+5345+08707\"],\n  \"Asia/Novosibirsk\": [\"RU\", \"+5502+08255\"],\n  \"Asia/Omsk\": [\"RU\", \"+5500+07324\"],\n  \"Asia/Oral\": [\"KZ\", \"+5113+05121\"],\n  \"Asia/Phnom_Penh\": [\"KH\", \"+1133+10455\"],\n  \"Asia/Pontianak\": [\"ID\", \"-0002+10920\"],\n  \"Asia/Pyongyang\": [\"KP\", \"+3901+12545\"],\n  \"Asia/Qatar\": [\"QA\", \"+2517+05132\"],\n  \"Asia/Qostanay\": [\"KZ\", \"+5312+06337\"],\n  \"Asia/Qyzylorda\": [\"KZ\", \"+4448+06528\"],\n  \"Asia/Riyadh\": [\"SA\", \"+2438+04643\"],\n  \"Asia/Sakhalin\": [\"RU\", \"+4658+14242\"],\n  \"Asia/Samarkand\": [\"UZ\", \"+3940+06648\"],\n  \"Asia/Seoul\": [\"KR\", \"+3733+12658\"],\n  \"Asia/Shanghai\": [\"CN\", \"+3114+12128\"],\n  \"Asia/Singapore\": [\"SG\", \"+0117+10351\"],\n  \"Asia/Srednekolymsk\": [\"RU\", \"+6728+15343\"],\n  \"Asia/Taipei\": [\"TW\", \"+2503+12130\"],\n  \"Asia/Tashkent\": [\"UZ\", \"+4120+06918\"],\n  \"Asia/Tbilisi\": [\"GE\", \"+4143+04449\"],\n  \"Asia/Tehran\": [\"IR\", \"+3540+05126\"],\n  \"Asia/Thimphu\": [\"BT\", \"+2728+08939\"],\n  \"Asia/Tokyo\": [\"JP\", \"+353916+1394441\"],\n  \"Asia/Tomsk\": [\"RU\", \"+5630+08458\"],\n  \"Asia/Ulaanbaatar\": [\"MN\", \"+4755+10653\"],\n  \"Asia/Urumqi\": [\"CN\", \"+4348+08735\"],\n  \"Asia/Ust-Nera\": [\"RU\", \"+643337+1431336\"],\n  \"Asia/Vientiane\": [\"LA\", \"+1758+10236\"],\n  \"Asia/Vladivostok\": [\"RU\", \"+4310+13156\"],\n  \"Asia/Yakutsk\": [\"RU\", \"+6200+12940\"],\n  \"Asia/Yangon\": [\"MM\", \"+1647+09610\"],\n  \"Asia/Yekaterinburg\": [\"RU\", \"+5651+06036\"],\n  \"Asia/Yerevan\": [\"AM\", \"+4011+04430\"],\n  \"Atlantic/Azores\": [\"PT\", \"+3744-02540\"],\n  \"Atlantic/Bermuda\": [\"BM\", \"+3217-06446\"],\n  \"Atlantic/Canary\": [\"ES\", \"+2806-01524\"],\n  \"Atlantic/Cape_Verde\": [\"CV\", \"+1455-02331\"],\n  \"Atlantic/Faroe\": [\"FO\", \"+6201-00646\"],\n  \"Atlantic/Madeira\": [\"PT\", \"+3238-01654\"],\n  \"Atlantic/Reykjavik\": [\"IS\", \"+6409-02151\"],\n  \"Atlantic/South_Georgia\": [\"GS\", \"-5416-03632\"],\n  \"Atlantic/St_Helena\": [\"SH\", \"-1555-00542\"],\n  \"Atlantic/Stanley\": [\"FK\", \"-5142-05751\"],\n  \"Australia/Adelaide\": [\"AU\", \"-3455+13835\"],\n  \"Australia/Brisbane\": [\"AU\", \"-2728+15302\"],\n  \"Australia/Broken_Hill\": [\"AU\", \"-3157+14127\"],\n  \"Australia/Darwin\": [\"AU\", \"-1228+13050\"],\n  \"Australia/Eucla\": [\"AU\", \"-3143+12852\"],\n  \"Australia/Hobart\": [\"AU\", \"-4253+14719\"],\n  \"Australia/Lindeman\": [\"AU\", \"-2016+14900\"],\n  \"Australia/Lord_Howe\": [\"AU\", \"-3133+15905\"],\n  \"Australia/Melbourne\": [\"AU\", \"-3749+14458\"],\n  \"Australia/Perth\": [\"AU\", \"-3157+11551\"],\n  \"Australia/Sydney\": [\"AU\", \"-3352+15113\"],\n  \"Europe/Amsterdam\": [\"NL\", \"+5222+00454\"],\n  \"Europe/Andorra\": [\"AD\", \"+4230+00131\"],\n  \"Europe/Astrakhan\": [\"RU\", \"+4621+04803\"],\n  \"Europe/Athens\": [\"GR\", \"+3758+02343\"],\n  \"Europe/Belgrade\": [\"RS\", \"+4450+02030\"],\n  \"Europe/Berlin\": [\"DE\", \"+5230+01322\"],\n  \"Europe/Bratislava\": [\"SK\", \"+4809+01707\"],\n  \"Europe/Brussels\": [\"BE\", \"+5050+00420\"],\n  \"Europe/Bucharest\": [\"RO\", \"+4426+02606\"],\n  \"Europe/Budapest\": [\"HU\", \"+4730+01905\"],\n  \"Europe/Busingen\": [\"DE\", \"+4742+00841\"],\n  \"Europe/Chisinau\": [\"MD\", \"+4700+02850\"],\n  \"Europe/Copenhagen\": [\"DK\", \"+5540+01235\"],\n  \"Europe/Dublin\": [\"IE\", \"+5320-00615\"],\n  \"Europe/Gibraltar\": [\"GI\", \"+3608-00521\"],\n  \"Europe/Guernsey\": [\"GG\", \"+492717-0023210\"],\n  \"Europe/Helsinki\": [\"FI\", \"+6010+02458\"],\n  \"Europe/Isle_of_Man\": [\"IM\", \"+5409-00428\"],\n  \"Europe/Istanbul\": [\"TR\", \"+4101+02858\"],\n  \"Europe/Jersey\": [\"JE\", \"+491101-0020624\"],\n  \"Europe/Kaliningrad\": [\"RU\", \"+5443+02030\"],\n  \"Europe/Kirov\": [\"RU\", \"+5836+04939\"],\n  \"Europe/Kyiv\": [\"UA\", \"+5026+03031\"],\n  \"Europe/Lisbon\": [\"PT\", \"+3843-00908\"],\n  \"Europe/Ljubljana\": [\"SI\", \"+4603+01431\"],\n  \"Europe/London\": [\"GB\", \"+513030-0000731\"],\n  \"Europe/Luxembourg\": [\"LU\", \"+4936+00609\"],\n  \"Europe/Madrid\": [\"ES\", \"+4024-00341\"],\n  \"Europe/Malta\": [\"MT\", \"+3554+01431\"],\n  \"Europe/Mariehamn\": [\"AX\", \"+6006+01957\"],\n  \"Europe/Minsk\": [\"BY\", \"+5354+02734\"],\n  \"Europe/Monaco\": [\"MC\", \"+4342+00723\"],\n  \"Europe/Moscow\": [\"RU\", \"+554521+0373704\"],\n  \"Europe/Oslo\": [\"NO\", \"+5955+01045\"],\n  \"Europe/Paris\": [\"FR\", \"+4852+00220\"],\n  \"Europe/Podgorica\": [\"ME\", \"+4226+01916\"],\n  \"Europe/Prague\": [\"CZ\", \"+5005+01426\"],\n  \"Europe/Riga\": [\"LV\", \"+5657+02406\"],\n  \"Europe/Rome\": [\"IT\", \"+4154+01229\"],\n  \"Europe/Samara\": [\"RU\", \"+5312+05009\"],\n  \"Europe/San_Marino\": [\"SM\", \"+4355+01228\"],\n  \"Europe/Sarajevo\": [\"BA\", \"+4352+01825\"],\n  \"Europe/Saratov\": [\"RU\", \"+5134+04602\"],\n  \"Europe/Simferopol\": [\"UA\", \"+4457+03406\"],\n  \"Europe/Skopje\": [\"MK\", \"+4159+02126\"],\n  \"Europe/Sofia\": [\"BG\", \"+4241+02319\"],\n  \"Europe/Stockholm\": [\"SE\", \"+5920+01803\"],\n  \"Europe/Tallinn\": [\"EE\", \"+5925+02445\"],\n  \"Europe/Tirane\": [\"AL\", \"+4120+01950\"],\n  \"Europe/Ulyanovsk\": [\"RU\", \"+5420+04824\"],\n  \"Europe/Vaduz\": [\"LI\", \"+4709+00931\"],\n  \"Europe/Vatican\": [\"VA\", \"+415408+0122711\"],\n  \"Europe/Vienna\": [\"AT\", \"+4813+01620\"],\n  \"Europe/Vilnius\": [\"LT\", \"+5441+02519\"],\n  \"Europe/Volgograd\": [\"RU\", \"+4844+04425\"],\n  \"Europe/Warsaw\": [\"PL\", \"+5215+02100\"],\n  \"Europe/Zagreb\": [\"HR\", \"+4548+01558\"],\n  \"Europe/Zurich\": [\"CH\", \"+4723+00832\"],\n  \"Indian/Antananarivo\": [\"MG\", \"-1855+04731\"],\n  \"Indian/Chagos\": [\"IO\", \"-0720+07225\"],\n  \"Indian/Christmas\": [\"CX\", \"-1025+10543\"],\n  \"Indian/Cocos\": [\"CC\", \"-1210+09655\"],\n  \"Indian/Comoro\": [\"KM\", \"-1141+04316\"],\n  \"Indian/Kerguelen\": [\"TF\", \"-492110+0701303\"],\n  \"Indian/Mahe\": [\"SC\", \"-0440+05528\"],\n  \"Indian/Maldives\": [\"MV\", \"+0410+07330\"],\n  \"Indian/Mauritius\": [\"MU\", \"-2010+05730\"],\n  \"Indian/Mayotte\": [\"YT\", \"-1247+04514\"],\n  \"Indian/Reunion\": [\"RE\", \"-2052+05528\"],\n  \"Pacific/Apia\": [\"WS\", \"-1350-17144\"],\n  \"Pacific/Auckland\": [\"NZ\", \"-3652+17446\"],\n  \"Pacific/Bougainville\": [\"PG\", \"-0613+15534\"],\n  \"Pacific/Chatham\": [\"NZ\", \"-4357-17633\"],\n  \"Pacific/Chuuk\": [\"FM\", \"+0725+15147\"],\n  \"Pacific/Easter\": [\"CL\", \"-2709-10926\"],\n  \"Pacific/Efate\": [\"VU\", \"-1740+16825\"],\n  \"Pacific/Fakaofo\": [\"TK\", \"-0922-17114\"],\n  \"Pacific/Fiji\": [\"FJ\", \"-1808+17825\"],\n  \"Pacific/Funafuti\": [\"TV\", \"-0831+17913\"],\n  \"Pacific/Galapagos\": [\"EC\", \"-0054-08936\"],\n  \"Pacific/Gambier\": [\"PF\", \"-2308-13457\"],\n  \"Pacific/Guadalcanal\": [\"SB\", \"-0932+16012\"],\n  \"Pacific/Guam\": [\"GU\", \"+1328+14445\"],\n  \"Pacific/Honolulu\": [\"US\", \"+211825-1575130\"],\n  \"Pacific/Kanton\": [\"KI\", \"-0247-17143\"],\n  \"Pacific/Kiritimati\": [\"KI\", \"+0152-15720\"],\n  \"Pacific/Kosrae\": [\"FM\", \"+0519+16259\"],\n  \"Pacific/Kwajalein\": [\"MH\", \"+0905+16720\"],\n  \"Pacific/Majuro\": [\"MH\", \"+0709+17112\"],\n  \"Pacific/Marquesas\": [\"PF\", \"-0900-13930\"],\n  \"Pacific/Midway\": [\"UM\", \"+2813-17722\"],\n  \"Pacific/Nauru\": [\"NR\", \"-0031+16655\"],\n  \"Pacific/Niue\": [\"NU\", \"-1901-16955\"],\n  \"Pacific/Norfolk\": [\"NF\", \"-2903+16758\"],\n  \"Pacific/Noumea\": [\"NC\", \"-2216+16627\"],\n  \"Pacific/Pago_Pago\": [\"AS\", \"-1416-17042\"],\n  \"Pacific/Palau\": [\"PW\", \"+0720+13429\"],\n  \"Pacific/Pitcairn\": [\"PN\", \"-2504-13005\"],\n  \"Pacific/Pohnpei\": [\"FM\", \"+0658+15813\"],\n  \"Pacific/Port_Moresby\": [\"PG\", \"-0930+14710\"],\n  \"Pacific/Rarotonga\": [\"CK\", \"-2114-15946\"],\n  \"Pacific/Saipan\": [\"MP\", \"+1512+14545\"],\n  \"Pacific/Tahiti\": [\"PF\", \"-1732-14934\"],\n  \"Pacific/Tarawa\": [\"KI\", \"+0125+17300\"],\n  \"Pacific/Tongatapu\": [\"TO\", \"-210800-1751200\"],\n  \"Pacific/Wake\": [\"UM\", \"+1917+16637\"],\n  \"Pacific/Wallis\": [\"WF\", \"-1318-17610\"]\n}\n"
  },
  {
    "path": "packages/app/tests/Utils.test.ts",
    "content": "import { magnetURIDecode, getRelayName } from \"../src/Utils\"\nimport { describe, test, expect } from \"bun:test\"\n\ndescribe(\"magnet\", () => {\n  test(\"should parse magnet link\", () => {\n    const book =\n      \"magnet:?xt=urn:btih:d2474e86c95b19b8bcfdb92bc12c9d44667cfa36&xt=urn:btmh:1220d2474e86c95b19b8bcfdb92bc12c9d44667cfa36d2474e86c95b19b8bcfdb92b&dn=Leaves+of+Grass+by+Walt+Whitman.epub&tr=udp%3A%2F%2Ftracker.example4.com%3A80&tr=udp%3A%2F%2Ftracker.example5.com%3A80&tr=udp%3A%2F%2Ftracker.example3.com%3A6969&tr=udp%3A%2F%2Ftracker.example2.com%3A80&tr=udp%3A%2F%2Ftracker.example1.com%3A1337\"\n    const output = magnetURIDecode(book)\n    expect(output).not.toBeUndefined()\n    expect(output!.dn).toEqual(\"Leaves of Grass by Walt Whitman.epub\")\n    expect(output!.infoHash).toEqual(\"d2474e86c95b19b8bcfdb92bc12c9d44667cfa36\")\n    expect(output!.tr).toEqual([\n      \"udp://tracker.example4.com:80\",\n      \"udp://tracker.example5.com:80\",\n      \"udp://tracker.example3.com:6969\",\n      \"udp://tracker.example2.com:80\",\n      \"udp://tracker.example1.com:1337\",\n    ])\n  })\n})\n\ndescribe(\"getRelayName\", () => {\n  test(\"should return relay name\", () => {\n    const url = \"wss://relay.snort.social/\"\n    const output = getRelayName(url)\n    expect(output).toEqual(\"relay.snort.social\")\n  })\n  test(\"should return relay name with search property\", () => {\n    const url = \"wss://relay.example1.com/?lang=en\"\n    const output = getRelayName(url)\n    expect(output).toEqual(\"relay.example1.com?lang=en\")\n  })\n  test(\"should return relay name without pathname\", () => {\n    const url =\n      \"wss://relay.example2.com/npub1sn0rtcjcf543gj4wsg7fa59s700d5ztys5ctj0g69g2x6802npjqhjjtws?broadcast=true\"\n    const output = getRelayName(url)\n    expect(output).toEqual(\"relay.example2.com?broadcast=true\")\n  })\n})\n"
  },
  {
    "path": "packages/app/tests/worker-cached.test.ts",
    "content": "/**\n * Tests for WorkerBaseCache:\n *   - update() timestamp guard: newer created wins, stale events are rejected\n *   - subscribe(): O(1) per-key notifications\n *   - set() / bulkSet() fire per-key listeners\n */\n\nimport { describe, expect, test } from \"bun:test\"\nimport type { CachedBase, CacheRelay, NostrEvent, OkResponse, ReqCommand, TaggedNostrEvent } from \"@snort/system\"\nimport { WorkerBaseCache } from \"../src/Cache/worker-cached\"\n\n// ---------------------------------------------------------------------------\n// Minimal CacheRelay mock — returns empty arrays for queries\n// ---------------------------------------------------------------------------\n\nconst mockRelay: CacheRelay = {\n  async event(ev: TaggedNostrEvent): Promise<OkResponse> {\n    return { ok: true, id: \"\", relay: \"\", event: ev }\n  },\n  async query(_req: ReqCommand): Promise<TaggedNostrEvent[]> {\n    return []\n  },\n  async delete(_req: ReqCommand): Promise<string[]> {\n    return []\n  },\n}\n\n// ---------------------------------------------------------------------------\n// Concrete WorkerBaseCache for testing\n// ---------------------------------------------------------------------------\n\ntype TestEntry = CachedBase & { name: string }\n\nclass TestWorkerCache extends WorkerBaseCache<TestEntry> {\n  constructor() {\n    super(0, mockRelay)\n  }\n\n  name() {\n    return \"TestWorkerCache\"\n  }\n  maxSize() {\n    return 1000\n  }\n\n  mapper(ev: NostrEvent): TestEntry | undefined {\n    return undefined\n  }\n}\n\nfunction entry(pubkey: string, created: number, loaded: number, name = \"alice\"): TestEntry {\n  return { pubkey, created, loaded, name }\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe(\"WorkerBaseCache.update() — timestamp guard\", () => {\n  test('first entry is stored and returns \"new\"', async () => {\n    const cache = new TestWorkerCache()\n    const result = await cache.update(entry(\"pk1\", 100, 1000))\n    expect(result).toBe(\"new\")\n    expect(cache.getFromCache(\"pk1\")?.created).toBe(100)\n  })\n\n  test('entry with newer created timestamp overwrites and returns \"updated\"', async () => {\n    const cache = new TestWorkerCache()\n    await cache.update(entry(\"pk1\", 100, 1000, \"old\"))\n    const result = await cache.update(entry(\"pk1\", 200, 2000, \"new\"))\n    expect(result).toBe(\"updated\")\n    expect(cache.getFromCache(\"pk1\")?.name).toBe(\"new\")\n  })\n\n  test('entry with older created timestamp is rejected and returns \"no_change\"', async () => {\n    const cache = new TestWorkerCache()\n    await cache.update(entry(\"pk1\", 200, 2000, \"newer\"))\n    const result = await cache.update(entry(\"pk1\", 100, 1000, \"older\"))\n    expect(result).toBe(\"no_change\")\n    // Value should remain the newer entry\n    expect(cache.getFromCache(\"pk1\")?.name).toBe(\"newer\")\n  })\n\n  test(\"entry with same created but older loaded is rejected\", async () => {\n    const cache = new TestWorkerCache()\n    await cache.update(entry(\"pk1\", 100, 2000, \"newer-load\"))\n    const result = await cache.update(entry(\"pk1\", 100, 1000, \"older-load\"))\n    expect(result).toBe(\"no_change\")\n    expect(cache.getFromCache(\"pk1\")?.name).toBe(\"newer-load\")\n  })\n\n  test(\"entry with same created and same loaded is treated as no_change\", async () => {\n    const cache = new TestWorkerCache()\n    await cache.update(entry(\"pk1\", 100, 1000, \"first\"))\n    const result = await cache.update(entry(\"pk1\", 100, 1000, \"duplicate\"))\n    expect(result).toBe(\"no_change\")\n    expect(cache.getFromCache(\"pk1\")?.name).toBe(\"first\")\n  })\n})\n\ndescribe(\"WorkerBaseCache.subscribe()\", () => {\n  test(\"subscriber is called when key is set\", async () => {\n    const cache = new TestWorkerCache()\n    let callCount = 0\n\n    cache.subscribe(\"pk-a\", () => {\n      callCount++\n    })\n    await cache.set(entry(\"pk-a\", 1, 1))\n\n    expect(callCount).toBe(1)\n  })\n\n  test(\"subscriber is NOT called for a different key\", async () => {\n    const cache = new TestWorkerCache()\n    let callCount = 0\n\n    cache.subscribe(\"pk-a\", () => {\n      callCount++\n    })\n    await cache.set(entry(\"pk-b\", 1, 1))\n\n    expect(callCount).toBe(0)\n  })\n\n  test(\"unsubscribe prevents further notifications\", async () => {\n    const cache = new TestWorkerCache()\n    let callCount = 0\n\n    const unsub = cache.subscribe(\"pk-a\", () => {\n      callCount++\n    })\n    await cache.set(entry(\"pk-a\", 1, 1)) // fires\n    unsub()\n    await cache.set(entry(\"pk-a\", 2, 2)) // should not fire\n\n    expect(callCount).toBe(1)\n  })\n\n  test(\"bulkSet fires subscriber for each relevant key\", async () => {\n    const cache = new TestWorkerCache()\n    let countA = 0\n    let countB = 0\n\n    cache.subscribe(\"pa\", () => {\n      countA++\n    })\n    cache.subscribe(\"pb\", () => {\n      countB++\n    })\n\n    await cache.bulkSet([\n      entry(\"pa\", 1, 1, \"a\"),\n      entry(\"pb\", 1, 1, \"b\"),\n      entry(\"pc\", 1, 1, \"c\"), // no subscriber\n    ])\n\n    expect(countA).toBe(1)\n    expect(countB).toBe(1)\n  })\n\n  test(\"update() with new data triggers subscriber\", async () => {\n    const cache = new TestWorkerCache()\n    let callCount = 0\n\n    cache.subscribe(\"pk-u\", () => {\n      callCount++\n    })\n    await cache.update(entry(\"pk-u\", 1, 1, \"first\")) // new\n    await cache.update(entry(\"pk-u\", 2, 2, \"second\")) // updated\n\n    expect(callCount).toBe(2)\n  })\n\n  test(\"update() with stale data does NOT trigger subscriber\", async () => {\n    const cache = new TestWorkerCache()\n    let callCount = 0\n\n    cache.subscribe(\"pk-u\", () => {\n      callCount++\n    })\n    await cache.update(entry(\"pk-u\", 10, 10, \"current\")) // new\n    await cache.update(entry(\"pk-u\", 5, 5, \"old\")) // rejected — stale\n\n    expect(callCount).toBe(1)\n  })\n})\n"
  },
  {
    "path": "packages/app/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"target\": \"esnext\",\n    \"module\": \"esnext\",\n    \"jsx\": \"react-jsx\",\n    \"moduleResolution\": \"bundler\",\n    \"sourceMap\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"strict\": true,\n    \"skipLibCheck\": true,\n    \"resolveJsonModule\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"paths\": {\n      \"@/*\": [\"./src/*\"]\n    }\n  }\n}\n"
  },
  {
    "path": "packages/app/vite.config.ts",
    "content": "import basicSsl from \"@vitejs/plugin-basic-ssl\"\nimport react from \"@vitejs/plugin-react\"\nimport appConfig from \"config\"\nimport { visualizer } from \"rollup-plugin-visualizer\"\nimport { defineConfig } from \"vite\"\nimport { VitePWA } from \"vite-plugin-pwa\"\nimport { vitePluginVersionMark } from \"vite-plugin-version-mark\"\nimport tailwindcss from \"@tailwindcss/vite\"\n\nexport default defineConfig({\n  plugins: [\n    tailwindcss(),\n    //basicSsl(),\n    react({\n      babel: {\n        configFile: true,\n      },\n    }),\n    {\n      name: \"html-transform\",\n      transformIndexHtml(html: string) {\n        const hostname = appConfig.get(\"hostname\") as string\n        const appTitle = appConfig.get(\"appTitle\") as string\n        const appName = appConfig.get(\"appName\") as string\n        const icon = appConfig.get(\"icon\") as string\n\n        return html\n          .replace(/{{HOSTNAME}}/g, `https://${hostname}/`)\n          .replace(/{{APP_TITLE}}/g, appTitle)\n          .replace(/{{APP_NAME}}/g, appName)\n          .replace(/{{OG_IMAGE}}/g, `https://${hostname}${icon}`)\n      },\n    },\n    VitePWA({\n      strategies: \"injectManifest\",\n      injectRegister: \"script\",\n      srcDir: \"src\",\n      filename: \"service-worker.ts\",\n      registerType: \"autoUpdate\",\n      devOptions: {\n        enabled: false,\n        type: \"module\",\n      },\n    }),\n    visualizer({\n      open: false,\n      gzipSize: true,\n      filename: \"build/stats.html\",\n    }),\n    vitePluginVersionMark({\n      name: \"snort\",\n      ifGitSHA: true,\n      command: \"git describe --always --tags\",\n      ifMeta: true,\n      ifLog: false,\n      ifGlobal: false,\n    }),\n  ],\n  assetsInclude: [\"**/*.md\", \"**/*.wasm\"],\n  server: {\n    proxy: {},\n    watch: {\n      usePolling: true,\n    },\n  },\n  build: {\n    outDir: \"build\",\n    commonjsOptions: { transformMixedEsModules: true },\n    sourcemap: true,\n  },\n  clearScreen: false,\n  publicDir: appConfig.get(\"publicDir\"),\n  resolve: {\n    alias: {\n      \"@\": \"/src\",\n    },\n  },\n  define: {\n    CONFIG: JSON.stringify(appConfig),\n    global: {}, // needed for custom-event lib\n  },\n  worker: {\n    format: \"es\",\n  },\n})\n"
  },
  {
    "path": "packages/bot/README.md",
    "content": "# @snort/bot\n\nSimple live stream event chat bot (NIP-53)\n\n## Example\n\n```typescript\nimport { parseNostrLink } from \"@snort/system\";\nimport { SnortBot } from \"../src/index\";\n\n// listen to chat events on every NoGood live stream\nconst noGoodLink = parseNostrLink(\"npub12hcytyr8fumy3axde8wgeced523gyp6v6zczqktwuqeaztfc2xzsz3rdp4\");\n\n// Run a simple bot\nSnortBot.simple(\"example\")\n  .link(noGoodLink)\n  .relay(\"wss://relay.damus.io\")\n  .relay(\"wss://nos.lol\")\n  .relay(\"wss://relay.nostr.band\")\n  .profile({\n    name: \"PingBot\",\n    picture: \"https://nostr.download/572f5ff8286e8c719196f904fed24aef14586ec8181c14b09efa726682ef48ef\",\n    lud16: \"kieran@zap.stream\",\n    about: \"An example bot\",\n  })\n  .command(\"!ping\", h => {\n    h.reply(\"PONG!\");\n  })\n  .run();\n```\n"
  },
  {
    "path": "packages/bot/example/simple.ts",
    "content": "import { parseNostrLink } from \"@snort/system\"\nimport { SnortBot } from \"../src/index\"\n\nconst noGoodLink = parseNostrLink(\"npub12hcytyr8fumy3axde8wgeced523gyp6v6zczqktwuqeaztfc2xzsz3rdp4\")\n\nSnortBot.simple(\"example\")\n  .link(noGoodLink)\n  .relay(\"wss://relay.damus.io\")\n  .relay(\"wss://nos.lol\")\n  .relay(\"wss://relay.nostr.band\")\n  .profile({\n    name: \"PingBot\",\n    picture: \"https://nostr.download/572f5ff8286e8c719196f904fed24aef14586ec8181c14b09efa726682ef48ef\",\n    lud16: \"kieran@zap.stream\",\n    about: \"An example bot\",\n  })\n  .command(\"!ping\", h => {\n    h.reply(\"PONG!\")\n  })\n  .run()\n"
  },
  {
    "path": "packages/bot/package.json",
    "content": "{\n  \"name\": \"@snort/bot\",\n  \"version\": \"1.2.1\",\n  \"description\": \"Simple bot framework\",\n  \"type\": \"module\",\n  \"module\": \"src/index.ts\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"repository\": \"https://git.v0l.io/Kieran/snort\",\n  \"author\": \"Kieran\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"build\": \"rm -rf dist && bunx --bun tsc\"\n  },\n  \"dependencies\": {\n    \"@snort/system\": \"^1.5.2\",\n    \"eventemitter3\": \"^5.0.1\"\n  },\n  \"devDependencies\": {\n    \"@types/debug\": \"^4.1.12\",\n    \"typescript\": \"^5.9.3\"\n  }\n}\n"
  },
  {
    "path": "packages/bot/src/index.ts",
    "content": "import {\n  EventPublisher,\n  NostrLink,\n  RequestBuilder,\n  type NostrEvent,\n  type SystemInterface,\n  type EventKind,\n  type TaggedNostrEvent,\n  NostrSystem,\n  PrivateKeySigner,\n  type UserMetadata,\n  Nip10,\n  LinkScope,\n} from \"@snort/system\"\nimport { NostrPrefix } from \"@snort/shared\"\nimport EventEmitter from \"eventemitter3\"\n\nexport interface BotEvents {\n  message: (msg: BotMessage) => void\n  event: (ev: NostrEvent) => void\n}\n\nexport interface BotMessage {\n  /**\n   * Event which this message belongs to\n   */\n  link: NostrLink\n  /**\n   * Pubkey of the message author\n   */\n  from: string\n  /**\n   * Message content string\n   */\n  message: string\n  /**\n   * Original message event\n   */\n  event: NostrEvent\n  /**\n   * Reply handler for this message\n   */\n  reply: (msg: string) => Promise<void>\n}\n\nexport type CommandHandler = (msg: BotMessage) => void\n\nexport class SnortBot extends EventEmitter<BotEvents> {\n  #streams: Array<NostrLink> = []\n  #seen: Set<string> = new Set()\n  #activeStreamSub: Set<string> = new Set()\n\n  constructor(\n    readonly name: string,\n    readonly system: SystemInterface,\n    readonly publisher: EventPublisher,\n  ) {\n    super()\n  }\n\n  /**\n   * Create a new simple bot\n   */\n  static simple(name: string) {\n    const system = new NostrSystem({})\n    const signer = PrivateKeySigner.random()\n    return new SnortBot(name, system, new EventPublisher(signer, signer.getPubKey()))\n  }\n\n  get activeStreams() {\n    return (\n      this.system.GetQuery(\"streams\")?.snapshot?.filter(a => a.tags.find(b => b[0] === \"status\")?.at(1) === \"live\") ??\n      []\n    )\n  }\n\n  /**\n   * Add a stream to listen on\n   */\n  link(a: NostrLink) {\n    this.#streams.push(a)\n    return this\n  }\n\n  /**\n   * Add a relay for communication\n   */\n  relay(r: string) {\n    this.system.ConnectToRelay(r, { read: true, write: true })\n    return this\n  }\n\n  /**\n   * Create a profile\n   */\n  profile(p: UserMetadata) {\n    this.publisher.metadata(p).then(ev => this.system.BroadcastEvent(ev))\n    return this\n  }\n\n  /**\n   * Simple command handler\n   */\n  command(cmd: string, h: CommandHandler) {\n    this.on(\"message\", m => {\n      if (m.message.startsWith(cmd)) {\n        h(m)\n      }\n    })\n    return this\n  }\n\n  /**\n   * Start the bot\n   */\n  run() {\n    const req = new RequestBuilder(\"streams\")\n    req.withOptions({ leaveOpen: true })\n    for (const link of this.#streams) {\n      if (link.type === NostrPrefix.PublicKey || link.type === NostrPrefix.Profile) {\n        req.withFilter().authors([link.id]).kinds([30311])\n        req.withFilter().tag(\"p\", [link.id]).kinds([30311])\n      } else {\n        req.withFilter().link(link)\n      }\n    }\n\n    // requst streams by input links\n    const q = this.system.Query(req)\n    q.on(\"event\", evs => {\n      for (const e of evs) {\n        this.#handleEvent(e)\n      }\n    })\n    q.start()\n\n    // setup chat query, its empty for now\n    const rbChat = new RequestBuilder(\"stream-chat\")\n    rbChat.withOptions({ replaceable: true, leaveOpen: true })\n    const qChat = this.system.Query(rbChat)\n    qChat.on(\"event\", evs => {\n      for (const e of evs) {\n        this.#handleEvent(e)\n      }\n    })\n    qChat.start()\n\n    return this\n  }\n\n  /**\n   * Send a message to all active streams\n   */\n  async notify(msg: string) {\n    for (const stream of this.activeStreams) {\n      const ev = await this.publisher.reply(stream, msg, eb => {\n        return eb.kind(1311 as EventKind)\n      })\n      await this.system.BroadcastEvent(ev)\n    }\n  }\n\n  #handleEvent(e: TaggedNostrEvent) {\n    this.emit(\"event\", e)\n    if (e.kind === 30311) {\n      this.#checkActiveStreams(e)\n    } else if (e.kind === 1311) {\n      // skip my own messages\n      if (e.pubkey === this.publisher.pubKey) {\n        return\n      }\n      // skip already seen chat messages\n      if (this.#seen.has(e.id)) {\n        return\n      }\n      this.#seen.add(e.id)\n      const streamTag = e.tags.find(a => a[0] === \"a\" && a[1].startsWith(\"30311:\"))\n      if (streamTag) {\n        const link = NostrLink.fromTag(streamTag)\n        this.emit(\"message\", {\n          link,\n          from: e.pubkey,\n          message: e.content,\n          event: e,\n          reply: (msg: string) => this.#sendReplyTo(link, msg),\n        })\n      }\n    }\n  }\n\n  #checkActiveStreams(e: TaggedNostrEvent) {\n    const links = [e, ...this.activeStreams].map(v => NostrLink.fromEvent(v))\n    const linkStr = [...new Set(links.map(e => e.encode()))]\n    if (linkStr.every(a => this.#activeStreamSub.has(a))) {\n      return\n    }\n\n    const rb = new RequestBuilder(\"stream-chat\")\n    rb.withFilter()\n      .kinds([1311 as EventKind])\n      .replyToLink(links)\n      .since(Math.floor(new Date().getTime() / 1000))\n    const q = this.system.Query(rb)\n    q.start()\n\n    console.log(\"Looking for chat messages from: \", linkStr)\n    this.#activeStreamSub = new Set(linkStr)\n  }\n\n  async #sendReplyTo(link: NostrLink, msg: string) {\n    const ev = await this.publisher.generic(eb => {\n      eb.kind(1311 as EventKind)\n        .tag(Nip10.linkToTag(link, LinkScope.Root))\n        .content(msg)\n      return eb\n    })\n    await this.system.BroadcastEvent(ev)\n  }\n}\n"
  },
  {
    "path": "packages/bot/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \"src\",\n    \"target\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"esModuleInterop\": true,\n    \"noImplicitOverride\": true,\n    \"module\": \"ESNext\",\n    \"strict\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"inlineSourceMap\": true,\n    \"outDir\": \"dist\",\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"./src/**/*.ts\"],\n  \"exclude\": [\"src/**/*.test.ts\"]\n}\n"
  },
  {
    "path": "packages/bot/typedoc.json",
    "content": "{\n  \"entryPoints\": [\"src/index.ts\"]\n}\n"
  },
  {
    "path": "packages/shared/package.json",
    "content": "{\n  \"name\": \"@snort/shared\",\n  \"version\": \"2.0.0-pre.4\",\n  \"description\": \"Shared components for Snort\",\n  \"type\": \"module\",\n  \"module\": \"src/index.ts\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"repository\": \"https://git.v0l.io/Kieran/snort\",\n  \"author\": \"Kieran\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"build\": \"rm -rf dist && bunx --bun tsc\"\n  },\n  \"dependencies\": {\n    \"@noble/curves\": \"^2.0.1\",\n    \"@noble/hashes\": \"^2.0.1\",\n    \"@scure/base\": \"^2.0.0\",\n    \"debug\": \"^4.4.3\",\n    \"eventemitter3\": \"^5.0.1\",\n    \"light-bolt11-decoder\": \"^3.2.0\",\n    \"uuid\": \"^13.0.0\"\n  },\n  \"devDependencies\": {\n    \"@types/debug\": \"^4.1.12\",\n    \"typescript\": \"^5.9.3\"\n  }\n}\n"
  },
  {
    "path": "packages/shared/src/SortedMap/SortedMap.test.ts",
    "content": "import { describe, expect, test } from \"bun:test\"\nimport { SortedMap } from \"./SortedMap.js\"\n\nfunction runTestsForMap(MapConstructor: any, mapName: string) {\n  describe(mapName, () => {\n    test(\"should maintain order based on keys when no custom comparator is provided\", () => {\n      const map = new MapConstructor()\n      map.set(5, \"five\")\n      map.set(3, \"three\")\n      map.set(8, \"eight\")\n\n      const first = map.first()\n      const last = map.last()\n\n      expect(first).toEqual([3, \"three\"])\n      expect(last).toEqual([8, \"eight\"])\n    })\n\n    test(\"should maintain order based on custom comparator\", () => {\n      const comparator = (a: [string, number], b: [string, number]) => a[1] - b[1]\n      const map = new MapConstructor(undefined, comparator)\n\n      map.set(\"a\", 5)\n      map.set(\"b\", 3)\n      map.set(\"c\", 8)\n\n      const first = map.first()\n      const last = map.last()\n\n      expect(first).toEqual([\"b\", 3])\n      expect(last).toEqual([\"c\", 8])\n    })\n\n    test(\"should get correct value by key\", () => {\n      const map = new MapConstructor()\n      map.set(5, \"five\")\n\n      const value = map.get(5)\n\n      expect(value).toBe(\"five\")\n    })\n\n    test(\"should delete entry by key\", () => {\n      const map = new MapConstructor()\n      map.set(5, \"five\")\n      expect(map.has(5)).toBe(true)\n\n      map.delete(5)\n      expect(map.has(5)).toBe(false)\n    })\n\n    test(\"should iterate in order\", () => {\n      const map = new MapConstructor()\n      map.set(5, \"five\")\n      map.set(3, \"three\")\n      map.set(8, \"eight\")\n\n      const entries: [number, string][] = []\n      for (const entry of map.entries()) {\n        entries.push(entry)\n      }\n\n      expect(entries).toEqual([\n        [3, \"three\"],\n        [5, \"five\"],\n        [8, \"eight\"],\n      ])\n    })\n\n    test(\"should give correct size\", () => {\n      const map = new MapConstructor()\n      map.set(5, \"five\")\n      map.set(3, \"three\")\n\n      expect(map.size).toBe(2)\n    })\n  })\n}\n\n// Run the tests for SortedMap.\nrunTestsForMap(SortedMap, \"SortedMap\")\n"
  },
  {
    "path": "packages/shared/src/SortedMap/SortedMap.ts",
    "content": "type Comparator<K, V> = (a: [K, V], b: [K, V]) => number\n\nexport class SortedMap<K, V extends Record<string, any>> {\n  private map: Map<K, V>\n  private sortedKeys: K[]\n  private compare: Comparator<K, V>\n\n  constructor(initialEntries?: Iterable<readonly [K, V]>, compare?: string | Comparator<K, V>) {\n    this.map = new Map(initialEntries || [])\n\n    if (compare) {\n      if (typeof compare === \"string\") {\n        this.compare = (a, b) =>\n          (a[1] as any)[compare] > (b[1] as any)[compare] ? 1 : (a[1] as any)[compare] < (b[1] as any)[compare] ? -1 : 0\n      } else {\n        this.compare = compare\n      }\n    } else {\n      this.compare = (a, b) => (a[0] > b[0] ? 1 : a[0] < b[0] ? -1 : 0)\n    }\n\n    this.sortedKeys = initialEntries ? [...this.map.entries()].sort(this.compare).map(([key]) => key) : []\n  }\n\n  private binarySearch(key: K, value: V): number {\n    let left = 0\n    let right = this.sortedKeys.length\n    while (left < right) {\n      const mid = (left + right) >> 1\n      const midKey = this.sortedKeys[mid]\n      const midValue = this.map.get(midKey) as V\n\n      if (this.compare([key, value], [midKey, midValue]) < 0) {\n        right = mid\n      } else {\n        left = mid + 1\n      }\n    }\n    return left\n  }\n\n  set(key: K, value: V) {\n    const exists = this.map.has(key)\n    this.map.set(key, value)\n\n    if (exists) {\n      const index = this.sortedKeys.indexOf(key)\n      if (index !== -1) {\n        this.sortedKeys.splice(index, 1)\n      }\n    }\n\n    const insertAt = this.binarySearch(key, value)\n    this.sortedKeys.splice(insertAt, 0, key)\n  }\n\n  get(key: K): V | undefined {\n    return this.map.get(key)\n  }\n\n  last(): [K, V] | undefined {\n    if (this.sortedKeys.length === 0) {\n      return undefined\n    }\n    const key = this.sortedKeys[this.sortedKeys.length - 1]\n    return [key, this.map.get(key) as V]\n  }\n\n  first(): [K, V] | undefined {\n    if (this.sortedKeys.length === 0) {\n      return undefined\n    }\n    const key = this.sortedKeys[0]\n    return [key, this.map.get(key) as V]\n  }\n\n  *[Symbol.iterator](): Iterator<[K, V]> {\n    for (const key of this.sortedKeys) {\n      yield [key, this.map.get(key) as V]\n    }\n  }\n\n  *reverse(): Iterator<[K, V]> {\n    for (let i = this.sortedKeys.length - 1; i >= 0; i--) {\n      const key = this.sortedKeys[i]\n      yield [key, this.map.get(key) as V]\n    }\n  }\n\n  *keys(): IterableIterator<K> {\n    for (const key of this.sortedKeys) {\n      yield key\n    }\n  }\n\n  *values(): IterableIterator<V> {\n    for (const key of this.sortedKeys) {\n      yield this.map.get(key) as V\n    }\n  }\n\n  *entries(): IterableIterator<[K, V]> {\n    for (const key of this.sortedKeys) {\n      yield [key, this.map.get(key) as V]\n    }\n  }\n\n  *range(options: { gte?: K; lte?: K; direction?: \"asc\" | \"desc\" } = {}): IterableIterator<[K, V]> {\n    const { gte, lte, direction = \"asc\" } = options\n\n    const startIndex = gte ? this.binarySearch(gte, this.map.get(gte) as V) : 0\n    const endIndex = lte ? this.binarySearch(lte, this.map.get(lte) as V) : this.sortedKeys.length\n\n    if (direction === \"asc\") {\n      for (let i = startIndex; i < endIndex; i++) {\n        const key = this.sortedKeys[i]\n        yield [key, this.map.get(key) as V]\n      }\n    } else {\n      for (let i = endIndex - 1; i >= startIndex; i--) {\n        const key = this.sortedKeys[i]\n        yield [key, this.map.get(key) as V]\n      }\n    }\n  }\n\n  has(key: K): boolean {\n    return this.map.has(key)\n  }\n\n  delete(key: K): boolean {\n    if (this.map.delete(key)) {\n      const index = this.sortedKeys.indexOf(key)\n      if (index !== -1) {\n        this.sortedKeys.splice(index, 1)\n      }\n      return true\n    }\n    return false\n  }\n\n  clear(): void {\n    this.map.clear()\n    this.sortedKeys = []\n  }\n\n  get size(): number {\n    return this.map.size\n  }\n}\n"
  },
  {
    "path": "packages/shared/src/cache-store.ts",
    "content": "/**\n * Simple key-value store interface for caching\n * Can be implemented with IndexedDB, localStorage, in-memory Map, or any other storage backend\n */\nexport interface CacheStore<T = any> {\n  /**\n   * Get all keys in the store\n   */\n  keys(): Promise<Array<string>>\n\n  /**\n   * Get a single item by key\n   */\n  get(key: string): Promise<T | undefined>\n\n  /**\n   * Get multiple items by keys\n   */\n  bulkGet(keys: Array<string>): Promise<Array<T | undefined>>\n\n  /**\n   * Store a single item\n   */\n  put(item: T): Promise<void>\n\n  /**\n   * Store multiple items\n   */\n  bulkPut(items: readonly T[]): Promise<void>\n\n  /**\n   * Clear all items from the store\n   */\n  clear(): Promise<void>\n}\n"
  },
  {
    "path": "packages/shared/src/const.ts",
    "content": "/**\n * Regex to match email address\n */\nexport const EmailRegex =\n  // eslint-disable-next-line no-useless-escape\n  /^(([^<>()[\\]\\\\.,;:\\s@\"]+(\\.[^<>()[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/\n\n/**\n * Match any NIP-19 code\n */\nexport const Bech32Regex = /(n(?:pub|profile|event|ote|addr|req|relay|chat)1[acdefghjklmnpqrstuvwxyz023456789]+)/\n"
  },
  {
    "path": "packages/shared/src/custom.d.ts",
    "content": "declare module \"light-bolt11-decoder\" {\n  export function decode(pr?: string): ParsedInvoice\n\n  export interface ParsedInvoice {\n    paymentRequest: string\n    sections: Section[]\n  }\n\n  export interface Section {\n    name: string\n    value: string | Uint8Array | number | undefined\n  }\n}\n"
  },
  {
    "path": "packages/shared/src/external-store.ts",
    "content": "import { EventEmitter } from \"eventemitter3\"\n\ninterface ExternalStoreEvents {\n  change: () => void\n}\n\n/**\n * Simple hookable store with manual change notifications\n */\nexport abstract class ExternalStore<TSnapshot> extends EventEmitter<ExternalStoreEvents> {\n  #snapshot: TSnapshot = {} as TSnapshot\n  #changed = true\n\n  hook(cb: () => void) {\n    this.on(\"change\", cb)\n    return () => this.off(\"change\", cb)\n  }\n\n  snapshot(p?: any) {\n    if (this.#changed) {\n      this.#snapshot = this.takeSnapshot(p)\n      this.#changed = false\n    }\n    return this.#snapshot\n  }\n\n  protected notifyChange(sn?: TSnapshot) {\n    this.#changed = true\n    this.emit(\"change\")\n  }\n\n  abstract takeSnapshot(p?: any): TSnapshot\n}\n"
  },
  {
    "path": "packages/shared/src/feed-cache.ts",
    "content": "import debug from \"debug\"\nimport { EventEmitter } from \"eventemitter3\"\nimport type { CacheStore } from \"./cache-store\"\nimport { removeUndefined, unixNowMs } from \"./utils\"\n\ntype HookFn = () => void\n\nexport interface KeyedHookFilter {\n  key: string\n  fn: HookFn\n}\n\nexport interface CacheEvents<T> {\n  change: (keys: Array<string>) => void\n  update: (v: T) => void\n}\n\nexport type CachedTable<T> = {\n  preload(follows?: Array<string>): Promise<void>\n  keysOnTable(): Array<string>\n  getFromCache(key?: string): T | undefined\n  get(key?: string): Promise<T | undefined>\n  bulkGet(keys: Array<string>): Promise<Array<T>>\n  set(obj: T): Promise<void>\n  bulkSet(obj: Array<T> | Readonly<Array<T>>): Promise<void>\n\n  /**\n   * Try to update an entry where created values exists\n   * @param m Profile metadata\n   * @returns\n   */\n  update<TWithCreated extends T & { created: number; loaded: number }>(\n    m: TWithCreated,\n  ): Promise<\"new\" | \"refresh\" | \"updated\" | \"no_change\">\n\n  /**\n   * Loads a list of rows from disk cache\n   * @param keys List of ids to load\n   * @returns Keys that do not exist on disk cache\n   */\n  buffer(keys: Array<string>): Promise<Array<string>>\n  key(of: T): string\n  snapshot(): Array<T>\n  search(q: string): Promise<Array<T>>\n  clear(): Promise<void>\n\n  /**\n   * Subscribe to changes for a specific key only.\n   * More efficient than listening to the broad \"change\" event when only one key matters.\n   * Returns an unsubscribe function.\n   */\n  subscribe(key: string, cb: () => void): () => void\n} & EventEmitter<CacheEvents<T>>\n\n/**\n * Generic cache with optional persistent storage backend\n */\nexport abstract class FeedCache<TCached> extends EventEmitter<CacheEvents<TCached>> implements CachedTable<TCached> {\n  readonly name: string\n  #snapshot: Array<TCached> = []\n  protected log: ReturnType<typeof debug>\n  #hits = 0\n  #miss = 0\n  protected store?: CacheStore<TCached>\n  protected onTable: Set<string> = new Set()\n  protected cache: Map<string, TCached> = new Map()\n  /** Per-key subscribers for O(1) targeted notifications */\n  #keyListeners = new Map<string, Set<() => void>>()\n\n  constructor(name: string, store?: CacheStore<TCached>) {\n    super()\n    this.name = name\n    this.store = store\n    this.log = debug(name)\n    setInterval(() => {\n      this.log(\n        \"%d loaded, %d on-disk, %d hooks, %d% hit\",\n        this.cache.size,\n        this.onTable.size,\n        this.listenerCount(\"change\"),\n        ((this.#hits / (this.#hits + this.#miss)) * 100).toFixed(1),\n      )\n    }, 30_000)\n    this.on(\"change\", () => {\n      this.#snapshot = this.takeSnapshot()\n    })\n  }\n\n  async preload() {\n    // assume already preloaded if keys exist on table in memory\n    if (this.onTable.size === 0) {\n      const keys = (await this.store?.keys()) ?? []\n      this.onTable = new Set<string>(keys)\n    }\n  }\n\n  hook(fn: HookFn, key: string | undefined) {\n    const handle = (keys: Array<string>) => {\n      if (!key || keys.includes(key)) {\n        fn()\n      }\n    }\n    this.on(\"change\", handle)\n    return () => this.off(\"change\", handle)\n  }\n\n  /**\n   * Subscribe to changes for a specific key only.\n   * O(1) per notification — more efficient than listening to the broad \"change\" event.\n   * Returns an unsubscribe function.\n   */\n  subscribe(key: string, cb: () => void): () => void {\n    let listeners = this.#keyListeners.get(key)\n    if (!listeners) {\n      listeners = new Set()\n      this.#keyListeners.set(key, listeners)\n    }\n    listeners.add(cb)\n    return () => {\n      const s = this.#keyListeners.get(key)\n      if (s) {\n        s.delete(cb)\n        if (s.size === 0) {\n          this.#keyListeners.delete(key)\n        }\n      }\n    }\n  }\n\n  #notifyKeyListeners(key: string) {\n    const listeners = this.#keyListeners.get(key)\n    if (listeners) {\n      for (const cb of listeners) {\n        cb()\n      }\n    }\n  }\n\n  keysOnTable() {\n    return [...this.onTable]\n  }\n\n  getFromCache(key?: string) {\n    if (key) {\n      const ret = this.cache.get(key)\n      if (ret) {\n        this.#hits++\n      } else {\n        this.#miss++\n      }\n      return ret\n    }\n  }\n\n  async get(key?: string) {\n    if (key && !this.cache.has(key) && this.store) {\n      const cached = await this.store.get(key)\n      if (cached) {\n        this.cache.set(this.key(cached), cached)\n        this.emit(\"change\", [key])\n        return cached\n      }\n    }\n    return key ? this.cache.get(key) : undefined\n  }\n\n  async bulkGet(keys: Array<string>) {\n    const missing = keys.filter(a => !this.cache.has(a))\n    if (missing.length > 0 && this.store) {\n      const cached = await this.store.bulkGet(missing)\n      cached.forEach(a => {\n        if (a) {\n          this.cache.set(this.key(a), a)\n        }\n      })\n    }\n    return removeUndefined(keys.map(a => this.cache.get(a)))\n  }\n\n  async set(obj: TCached) {\n    const k = this.key(obj)\n    this.cache.set(k, obj)\n    if (this.store) {\n      try {\n        await this.store.put(obj)\n        this.onTable.add(k)\n      } catch (e) {\n        console.error(e)\n      }\n    }\n    this.emit(\"change\", [k])\n    this.#notifyKeyListeners(k)\n  }\n\n  async bulkSet(obj: Array<TCached> | Readonly<Array<TCached>>) {\n    if (this.store) {\n      try {\n        await this.store.bulkPut(obj)\n        obj.forEach(a => this.onTable.add(this.key(a)))\n      } catch (e) {\n        console.error(e)\n      }\n    }\n    obj.forEach(v => this.cache.set(this.key(v), v))\n    this.emit(\n      \"change\",\n      obj.map(a => this.key(a)),\n    )\n    for (const v of obj) {\n      this.#notifyKeyListeners(this.key(v))\n    }\n  }\n\n  async update<TCachedWithCreated extends TCached & { created: number; loaded: number }>(m: TCachedWithCreated) {\n    const k = this.key(m)\n    const existing = this.getFromCache(k) as TCachedWithCreated\n    const updateType = (() => {\n      if (!existing) {\n        return \"new\"\n      }\n      if (existing.created < m.created) {\n        return \"updated\"\n      }\n      if (existing && existing.loaded < m.loaded) {\n        return \"refresh\"\n      }\n      return \"no_change\"\n    })()\n    this.log(\"Updating %s %s %o\", k, updateType, m)\n    if (updateType !== \"no_change\") {\n      const updated = {\n        ...existing,\n        ...m,\n      }\n      await this.set(updated)\n    }\n    return updateType\n  }\n\n  async buffer(keys: Array<string>): Promise<Array<string>> {\n    const needsBuffer = keys.filter(a => !this.cache.has(a))\n    if (this.store && needsBuffer.length > 0) {\n      const mapped = needsBuffer.map(a => ({\n        has: this.onTable.has(a),\n        key: a,\n      }))\n      const keysToLoad = mapped.filter(a => a.has).map(a => a.key)\n\n      // Skip store query if no keys need loading\n      if (keysToLoad.length === 0) {\n        return mapped.filter(a => !a.has).map(a => a.key)\n      }\n\n      const start = unixNowMs()\n      const fromCache = removeUndefined(await this.store.bulkGet(keysToLoad))\n      if (fromCache.length > 0) {\n        fromCache.forEach(a => {\n          this.cache.set(this.key(a), a)\n        })\n        this.emit(\n          \"change\",\n          fromCache.map(a => this.key(a)),\n        )\n        this.log(`Loaded %d/%d in %d ms`, fromCache.length, keys.length, (unixNowMs() - start).toLocaleString())\n      }\n      return mapped.filter(a => !a.has).map(a => a.key)\n    }\n\n    // no persistent store, always return all keys\n    return needsBuffer\n  }\n\n  async clear() {\n    await this.store?.clear()\n    this.cache.clear()\n    this.onTable.clear()\n  }\n\n  snapshot() {\n    return this.#snapshot\n  }\n\n  abstract key(of: TCached): string\n  abstract takeSnapshot(): Array<TCached>\n  abstract search(q: string): Promise<Array<TCached>>\n}\n"
  },
  {
    "path": "packages/shared/src/imgproxy.ts",
    "content": "import { base64 } from \"@scure/base\"\nimport { hexToBytes } from \"@noble/hashes/utils.js\"\nimport { hmacSha256, unwrap } from \"./utils\"\n\nexport const DefaultImgProxy = {\n  url: \"https://imgproxy.v0l.io\",\n  key: \"a82fcf26aa0ccb55dfc6b4bd6a1c90744d3be0f38429f21a8828b43449ce7cebe6bdc2b09a827311bef37b18ce35cb1e6b1c60387a254541afa9e5b4264ae942\",\n  salt: \"a897770d9abf163de055e9617891214e75a9016d748f8ef865e6ffbcb9ed932295659549773a22a019a5f06d0b440c320be411e3fddfe784e199e4f03d74bd9b\",\n}\n\nexport interface ImgProxySettings {\n  url: string\n  key: string\n  salt: string\n}\n\nexport function proxyImg(url: string, settings?: ImgProxySettings, resize?: number, sha256?: string) {\n  const te = new TextEncoder()\n  function urlSafe(s: string) {\n    return s.replace(/=/g, \"\").replace(/\\+/g, \"-\").replace(/\\//g, \"_\")\n  }\n\n  function signUrl(u: string) {\n    const result = hmacSha256(hexToBytes(unwrap(settings).key), hexToBytes(unwrap(settings).salt), te.encode(u))\n    return urlSafe(base64.encode(result))\n  }\n  if (!settings) return url\n  if (url.startsWith(\"data:\") || url.startsWith(\"blob:\") || url.length == 0) return url\n  const opts = []\n  if (sha256) {\n    opts.push(`hs:sha256:${sha256}`)\n  }\n  if (resize) {\n    opts.push(`rs:fit:${resize}:${resize}`)\n    opts.push(`dpr:${window.devicePixelRatio}`)\n  }\n  const urlBytes = te.encode(url)\n  const urlEncoded = urlSafe(base64.encode(urlBytes))\n  const path = `/${opts.join(\"/\")}/${urlEncoded}`\n  const sig = signUrl(path)\n  return `${new URL(settings.url).toString()}${sig}${path}`\n}\n"
  },
  {
    "path": "packages/shared/src/index.ts",
    "content": "export * from \"./external-store\"\nexport * from \"./lnurl\"\nexport * from \"./utils\"\nexport * from \"./work-queue\"\nexport * from \"./feed-cache\"\nexport * from \"./invoices\"\nexport * from \"./cache-store\"\nexport * from \"./SortedMap/SortedMap\"\nexport * from \"./const\"\nexport * from \"./tlv\"\nexport * from \"./imgproxy\"\n\n/**\n * Well-known nostr entity HRP's\n */\nexport enum NostrPrefix {\n  PublicKey = \"npub\",\n  PrivateKey = \"nsec\",\n  Note = \"note\",\n\n  // TLV prefixes\n  Profile = \"nprofile\",\n  Event = \"nevent\",\n  Relay = \"nrelay\",\n  Address = \"naddr\",\n}\n\n/**\n * Is the TLV encoded type 0 (special) a decoded hex string\n */\nexport function isPrefixTlvIdHex(prefix: NostrPrefix) {\n  return [NostrPrefix.Event, NostrPrefix.Profile].includes(prefix)\n}\n"
  },
  {
    "path": "packages/shared/src/invoices.ts",
    "content": "import { bytesToHex } from \"@noble/hashes/utils.js\"\nimport { decode as invoiceDecode } from \"light-bolt11-decoder\"\n\nexport interface InvoiceDetails {\n  amount?: number\n  expire?: number\n  timestamp?: number\n  description?: string\n  descriptionHash?: string\n  paymentHash?: string\n  expired: boolean\n  pr: string\n}\n\nexport function decodeInvoice(pr: string): InvoiceDetails | undefined {\n  try {\n    const parsed = invoiceDecode(pr)\n\n    const amountSection = parsed.sections.find(a => a.name === \"amount\")\n    const amount = amountSection ? Number(amountSection.value as number | string) : undefined\n\n    const timestampSection = parsed.sections.find(a => a.name === \"timestamp\")\n    const timestamp = timestampSection ? Number(timestampSection.value as number | string) : undefined\n\n    const expirySection = parsed.sections.find(a => a.name === \"expiry\")\n    const expire = expirySection ? Number(expirySection.value as number | string) : undefined\n    const descriptionSection = parsed.sections.find(a => a.name === \"description\")?.value\n    const descriptionHashSection = parsed.sections.find(a => a.name === \"description_hash\")?.value\n    const paymentHashSection = parsed.sections.find(a => a.name === \"payment_hash\")?.value\n    const ret = {\n      pr,\n      amount: amount,\n      expire: timestamp && expire ? timestamp + expire : undefined,\n      timestamp: timestamp,\n      description: descriptionSection as string | undefined,\n      descriptionHash: descriptionHashSection\n        ? typeof descriptionHashSection === \"string\"\n          ? (descriptionHashSection as string)\n          : bytesToHex(descriptionHashSection as Uint8Array)\n        : undefined,\n      paymentHash: paymentHashSection\n        ? typeof paymentHashSection === \"string\"\n          ? (paymentHashSection as string)\n          : bytesToHex(paymentHashSection as Uint8Array)\n        : undefined,\n      expired: false,\n    }\n    if (ret.expire) {\n      ret.expired = ret.expire < new Date().getTime() / 1000\n    }\n    return ret\n  } catch (e) {\n    console.error(e)\n  }\n}\n"
  },
  {
    "path": "packages/shared/src/lnurl.ts",
    "content": "import { EmailRegex } from \"./const\"\nimport { bech32ToText, throwIfOffline, unwrap } from \"./utils\"\n\nconst PayServiceTag = \"payRequest\"\n\nexport enum LNURLErrorCode {\n  ServiceUnavailable = 1,\n  InvalidLNURL = 2,\n}\n\nexport class LNURLError extends Error {\n  code: LNURLErrorCode\n\n  constructor(code: LNURLErrorCode, msg: string) {\n    super(msg)\n    this.code = code\n  }\n}\n\nexport class LNURL {\n  #url: URL\n  #service?: LNURLService\n\n  /**\n   * Setup LNURL service\n   * @param lnurl bech32 lnurl / lightning address / https url\n   */\n  constructor(lnurl: string) {\n    lnurl = lnurl.toLowerCase().trim()\n    if (lnurl.startsWith(\"lnurl\")) {\n      const decoded = bech32ToText(lnurl)\n      if (!decoded.startsWith(\"http\")) {\n        throw new LNURLError(LNURLErrorCode.InvalidLNURL, \"Not a url\")\n      }\n      this.#url = new URL(decoded)\n    } else if (lnurl.match(EmailRegex)) {\n      const [handle, domain] = lnurl.split(\"@\")\n      this.#url = new URL(`https://${domain}/.well-known/lnurlp/${handle}`)\n    } else if (lnurl.startsWith(\"https:\")) {\n      this.#url = new URL(lnurl)\n    } else if (lnurl.startsWith(\"lnurlp:\")) {\n      const tmp = new URL(lnurl)\n      tmp.protocol = \"https:\"\n      this.#url = tmp\n    } else {\n      throw new LNURLError(LNURLErrorCode.InvalidLNURL, \"Could not determine service url\")\n    }\n  }\n\n  /**\n   * URL of this payService\n   */\n  get url() {\n    return this.#url\n  }\n\n  /**\n   * Return the optimal formatted LNURL\n   */\n  get lnurl() {\n    if (this.isLNAddress) {\n      return this.getLNAddress()\n    }\n    return this.#url.toString()\n  }\n\n  /**\n   * Human readable name for this service\n   */\n  get name() {\n    // LN Address formatted URL\n    if (this.isLNAddress) {\n      return this.getLNAddress()\n    }\n    // Generic LUD-06 url\n    return this.#url.hostname\n  }\n\n  /**\n   * Is this LNURL a LUD-16 Lightning Address\n   */\n  get isLNAddress() {\n    return this.#url.pathname.startsWith(\"/.well-known/lnurlp/\")\n  }\n\n  /**\n   * Get the LN Address for this LNURL\n   */\n  getLNAddress() {\n    const pathParts = this.#url.pathname.split(\"/\")\n    const username = pathParts[pathParts.length - 1]\n    return `${username}@${this.#url.hostname}`\n  }\n\n  async load() {\n    throwIfOffline()\n    const rsp = await fetch(this.#url)\n    if (rsp.ok) {\n      this.#service = await rsp.json()\n      this.#validateService()\n    }\n  }\n\n  /**\n   * Fetch an invoice from the LNURL service\n   * @param amount Amount in sats\n   * @param comment\n   * @param zap\n   * @returns\n   */\n  async getInvoice(amount: number, comment?: string, zap?: object) {\n    throwIfOffline()\n    const callback = new URL(unwrap(this.#service?.callback))\n    const query = new Map<string, string>()\n\n    if (callback.search.length > 0) {\n      callback.search\n        .slice(1)\n        .split(\"&\")\n        .forEach(a => {\n          const pSplit = a.split(\"=\")\n          query.set(pSplit[0], pSplit[1])\n        })\n    }\n    query.set(\"amount\", Math.floor(amount * 1000).toString())\n    if (comment && this.#service?.commentAllowed) {\n      query.set(\"comment\", comment)\n    }\n    if (this.#service?.nostrPubkey && zap) {\n      query.set(\"nostr\", JSON.stringify(zap))\n    }\n\n    const baseUrl = `${callback.protocol}//${callback.host}${callback.pathname}`\n    const queryJoined = [...query.entries()].map(v => `${v[0]}=${encodeURIComponent(v[1])}`).join(\"&\")\n    try {\n      const rsp = await fetch(`${baseUrl}?${queryJoined}`)\n      if (rsp.ok) {\n        const data: LNURLInvoice = await rsp.json()\n        if (data.status === \"ERROR\") {\n          throw new Error(data.reason)\n        } else {\n          return data\n        }\n      } else {\n        throw new LNURLError(LNURLErrorCode.ServiceUnavailable, `Failed to fetch invoice (${rsp.statusText})`)\n      }\n    } catch (e) {\n      throw new LNURLError(LNURLErrorCode.ServiceUnavailable, \"Failed to load callback\")\n    }\n  }\n\n  /**\n   * Are zaps (NIP-57) supported\n   */\n  get canZap() {\n    return this.#service?.nostrPubkey ? true : false\n  }\n\n  /**\n   * Return pubkey of zap service\n   */\n  get zapperPubkey() {\n    return this.#service?.nostrPubkey\n  }\n\n  /**\n   * Get the max allowed comment length\n   */\n  get maxCommentLength() {\n    return this.#service?.commentAllowed ?? 0\n  }\n\n  /**\n   * Min sendable in milli-sats\n   */\n  get min() {\n    return this.#service?.minSendable ?? 1_000 // 1 sat\n  }\n\n  /**\n   * Max sendable in milli-sats\n   */\n  get max() {\n    return this.#service?.maxSendable ?? 100e9 // 1 BTC in milli-sats\n  }\n\n  #validateService() {\n    if (this.#service?.tag !== PayServiceTag) {\n      throw new LNURLError(LNURLErrorCode.InvalidLNURL, \"Only LNURLp is supported\")\n    }\n    if (!this.#service?.callback) {\n      throw new LNURLError(LNURLErrorCode.InvalidLNURL, \"No callback url\")\n    }\n  }\n}\n\nexport interface LNURLService {\n  tag: string\n  nostrPubkey?: string\n  minSendable?: number\n  maxSendable?: number\n  metadata: string\n  callback: string\n  commentAllowed?: number\n}\n\nexport interface LNURLStatus {\n  status: \"SUCCESS\" | \"ERROR\"\n  reason?: string\n}\n\nexport interface LNURLInvoice extends LNURLStatus {\n  pr?: string\n  successAction?: LNURLSuccessAction\n}\n\nexport interface LNURLSuccessAction {\n  description?: string\n  url?: string\n}\n"
  },
  {
    "path": "packages/shared/src/tlv.ts",
    "content": "import { bytesToHex, hexToBytes, utf8ToBytes } from \"@noble/hashes/utils.js\"\nimport { bech32 } from \"@scure/base\"\nimport { NostrPrefix } from \".\"\n\nexport enum TLVEntryType {\n  Special = 0,\n  Relay = 1,\n  Author = 2,\n  Kind = 3,\n}\n\nexport interface TLVEntry {\n  type: TLVEntryType\n  length: number\n  value: string | number\n}\n\n// Max length of any nostr link in chars\nconst MaxLength = 10_000\n\nexport function encodeTLV(prefix: string, id: Uint8Array, relays?: string[], kind?: number, author?: string) {\n  const tl0 = [0, id.length, ...id]\n  const tl1 =\n    relays?.flatMap(a => {\n      const data = utf8ToBytes(a)\n      return [1, data.length, ...data]\n    }) ?? []\n\n  const tl2 = author ? [2, 32, ...hexToBytes(author)] : []\n  const tl3 = kind ? [3, 4, ...new Uint8Array(new Uint32Array([kind]).buffer).reverse()] : []\n\n  return bech32.encode(prefix, bech32.toWords(new Uint8Array([...tl0, ...tl1, ...tl2, ...tl3])), MaxLength)\n}\n\nexport function encodeTLVEntries(prefix: string, ...entries: Array<TLVEntry>) {\n  const enc = new TextEncoder()\n  const buffers: Array<number> = []\n\n  for (const v of entries) {\n    switch (v.type) {\n      case TLVEntryType.Special: {\n        const buf = prefix === NostrPrefix.Address ? enc.encode(v.value as string) : hexToBytes(v.value as string)\n        buffers.push(0, buf.length, ...buf)\n        break\n      }\n      case TLVEntryType.Relay: {\n        const data = enc.encode(v.value as string)\n        buffers.push(1, data.length, ...data)\n        break\n      }\n      case TLVEntryType.Author: {\n        if ((v.value as string).length !== 64) throw new Error(\"Author must be 32 bytes\")\n        buffers.push(2, 32, ...hexToBytes(v.value as string))\n        break\n      }\n      case TLVEntryType.Kind: {\n        if (typeof v.value !== \"number\") throw new Error(\"Kind must be a number\")\n        buffers.push(3, 4, ...new Uint8Array(new Uint32Array([v.value as number]).buffer).reverse())\n        break\n      }\n    }\n  }\n  return bech32.encode(prefix, bech32.toWords(new Uint8Array(buffers)), MaxLength)\n}\n\nexport function decodeTLV(str: string) {\n  const decoded = bech32.decode(str as `${string}1${string}`, MaxLength)\n  const data = bech32.fromWords(decoded.words)\n\n  const entries: TLVEntry[] = []\n  let x = 0\n  while (x < data.length) {\n    const t = data[x]\n    const l = data[x + 1]\n    const v = data.slice(x + 2, x + 2 + l)\n    entries.push({\n      type: t,\n      length: l,\n      value: decodeTLVEntry(t, decoded.prefix, new Uint8Array(v)),\n    })\n    x += 2 + l\n  }\n  return entries\n}\n\nfunction decodeTLVEntry(type: TLVEntryType, prefix: string, data: Uint8Array) {\n  switch (type) {\n    case TLVEntryType.Special: {\n      if (prefix === NostrPrefix.Address) {\n        return new TextDecoder().decode(data)\n      } else {\n        return bytesToHex(data)\n      }\n    }\n    case TLVEntryType.Author: {\n      return bytesToHex(data)\n    }\n    case TLVEntryType.Kind: {\n      return new Uint32Array(new Uint8Array(data.reverse()).buffer)[0]\n    }\n    case TLVEntryType.Relay: {\n      return new TextDecoder().decode(data)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/shared/src/utils.ts",
    "content": "import { hexToBytes, bytesToHex, concatBytes } from \"@noble/hashes/utils.js\"\nimport * as secp from \"@noble/curves/secp256k1.js\"\nimport { sha256 as sha2 } from \"@noble/hashes/sha2.js\"\nimport { bech32 } from \"@scure/base\"\nimport { hmac } from \"@noble/hashes/hmac.js\"\n\nexport function unwrap<T>(v: T | undefined | null): T {\n  if (v === undefined || v === null) {\n    throw new Error(\"missing value\")\n  }\n  return v\n}\n\nexport function sanitizeRelayUrl(url: string) {\n  try {\n    return new URL(url).toString()\n  } catch {\n    // ignore\n  }\n}\n\nexport function unixNow() {\n  return Math.floor(unixNowMs() / 1000)\n}\n\nexport function unixNowMs() {\n  return Date.now()\n}\n\nexport function jitter(n: number) {\n  return n * Math.random()\n}\n\nexport function deepClone<T>(obj: T) {\n  if (\"structuredClone\" in window) {\n    return structuredClone(obj)\n  } else {\n    return JSON.parse(JSON.stringify(obj))\n  }\n}\n\nexport function deepEqual(x: any, y: any): boolean {\n  const ok = Object.keys,\n    tx = typeof x,\n    ty = typeof y\n\n  return x && y && tx === \"object\" && tx === ty\n    ? ok(x).length === ok(y).length && ok(x).every(key => deepEqual(x[key], y[key]))\n    : x === y\n}\n\nexport function countMembers(a: any) {\n  let ret = 0\n  for (const [k, v] of Object.entries(a)) {\n    if (Array.isArray(v)) {\n      ret += v.length\n    }\n  }\n  return ret\n}\n\nexport function equalProp(\n  a: string | number | Array<string | number> | undefined,\n  b: string | number | Array<string | number> | undefined,\n) {\n  if ((a !== undefined && b === undefined) || (a === undefined && b !== undefined)) {\n    return false\n  }\n  if (Array.isArray(a) && Array.isArray(b)) {\n    if (a.length !== b.length) {\n      return false\n    }\n    if (!a.every(v => b.includes(v))) {\n      return false\n    }\n  }\n  return a === b\n}\n\n/**\n * Compute the \"distance\" between two objects by comparing their difference in properties\n * Missing/Added keys result in +10 distance\n * This is not recursive\n */\nexport function distance(a: any, b: any): number {\n  const keys1 = Object.keys(a)\n  const keys2 = Object.keys(b)\n  const maxKeys = keys1.length > keys2.length ? keys1 : keys2\n\n  let distance = 0\n  for (const key of maxKeys) {\n    if (key in a && key in b) {\n      if (Array.isArray(a[key]) && Array.isArray(b[key])) {\n        const aa = a[key] as Array<string | number>\n        const bb = b[key] as Array<string | number>\n        if (aa.length === bb.length) {\n          if (aa.some(v => !bb.includes(v))) {\n            distance++\n          }\n        } else {\n          distance++\n        }\n      } else if (a[key] !== b[key]) {\n        distance++\n      }\n    } else {\n      distance += 10\n    }\n  }\n\n  return distance\n}\n\nexport function dedupe<T>(v: Array<T>) {\n  return [...new Set(v)]\n}\n\nexport function appendDedupe<T>(a?: Array<T>, b?: Array<T>) {\n  return dedupe([...(a ?? []), ...(b ?? [])])\n}\n\nexport function dedupeBy<T>(v: Array<T>, mapper: (x: T) => string): Array<T> {\n  return [\n    ...v\n      .reduce((acc, v) => {\n        const k = mapper(v)\n        if (!acc.has(k)) {\n          acc.set(k, v)\n        }\n        return acc\n      }, new Map<string, T>())\n      .values(),\n  ]\n}\n\nexport const sha256 = (str: string | Uint8Array): string => {\n  const buf = typeof str === \"string\" ? new TextEncoder().encode(str) : str\n  return bytesToHex(sha2(buf))\n}\n\nexport function hmacSha256(key: Uint8Array, ...messages: Uint8Array[]) {\n  return hmac(sha2, key, concatBytes(...messages))\n}\n\nexport function getPublicKey(privKey: string | Uint8Array) {\n  const buf = typeof privKey === \"string\" ? hexToBytes(privKey) : privKey\n  return bytesToHex(secp.schnorr.getPublicKey(buf))\n}\n\nexport function bech32ToHex(str: string) {\n  const nKey = bech32.decode(str as `${string}1${string}`, 1_000)\n  const buff = bech32.fromWords(nKey.words)\n  return bytesToHex(Uint8Array.from(buff))\n}\n\n/**\n * Convert hex to bech32\n */\nexport function hexToBech32(hrp: string, id?: string) {\n  if (typeof id !== \"string\" || id.length === 0 || id.length % 2 !== 0 || !isHex(id)) {\n    return \"\"\n  }\n\n  try {\n    const buf = hexToBytes(id)\n    return bech32.encode(hrp, bech32.toWords(buf))\n  } catch (e) {\n    console.warn(\"Invalid hex\", id, e)\n    return \"\"\n  }\n}\n\n/**\n * Decode bech32 to string UTF-8\n * @param str bech32 encoded string\n * @returns\n */\nexport function bech32ToText(str: string) {\n  const decoded = bech32.decode(str as `${string}1${string}`, 1000)\n  const buf = bech32.fromWords(decoded.words)\n  return new TextDecoder().decode(Uint8Array.from(buf))\n}\n\nexport interface NostrJson {\n  names: Record<string, string>\n  relays?: Record<string, Array<string>>\n  nip46?: Record<string, Array<string>>\n}\n\nexport async function fetchNip05PubkeyWithThrow(name: string, domain: string, timeout?: number) {\n  const data = await fetchNostrAddressWithThrow(name, domain, timeout)\n  const match = Object.keys(data.names).find(n => {\n    return n.toLowerCase() === name.toLowerCase()\n  })\n  if (match) {\n    return data.names[match]\n  } else {\n    throw new Error(\"User not found, invalid\")\n  }\n}\n\nexport async function fetchNip05Pubkey(name: string, domain: string, timeout?: number) {\n  try {\n    return await fetchNip05PubkeyWithThrow(name, domain, timeout)\n  } catch {\n    // ignored\n  }\n  return undefined\n}\n\nexport async function fetchNostrAddress(name: string, domain: string, timeout?: number) {\n  if (!name || !domain) {\n    return undefined\n  }\n  try {\n    return await fetchNostrAddressWithThrow(name, domain, timeout)\n  } catch {\n    // ignored\n  }\n  return undefined\n}\n\nexport async function fetchNostrAddressWithThrow(name: string, domain: string, timeout = 5_000) {\n  if (!name || !domain) {\n    throw new Error(\"Name and Domain must be set\")\n  }\n  const u = new URL(`https://${domain}/.well-known/nostr.json?name=${encodeURIComponent(name)}`)\n  const res = await fetch(u, {\n    signal: AbortSignal.timeout(timeout),\n  })\n  const text = await res.text()\n  if (res.ok) {\n    const data = JSON.parse(text) as NostrJson\n    if (!(\"names\" in data)) {\n      throw new Error(`Invalid response, code=${res.status}, body=${text}`)\n    }\n    return data\n  } else {\n    throw new Error(`Invalid response, code=${res.status}, body=${text}`)\n  }\n}\n\nexport function removeUndefined<T>(v: Array<T | undefined>) {\n  return v.filter(a => a !== undefined).map(a => unwrap(a))\n}\n\n/**\n * Reaction types\n */\nexport enum Reaction {\n  Positive = \"+\",\n  Negative = \"-\",\n}\n\n/**\n * Return normalized reaction content\n */\nexport function normalizeReaction(content: string) {\n  switch (content) {\n    case \"-\":\n      return Reaction.Negative\n    case \"👎\":\n      return Reaction.Negative\n    default:\n      return Reaction.Positive\n  }\n}\n\nexport class OfflineError extends Error {}\n\nexport function throwIfOffline() {\n  if (isOffline()) {\n    throw new OfflineError(\"Offline\")\n  }\n}\n\nexport function isOffline() {\n  return !(\"navigator\" in globalThis && globalThis.navigator.onLine)\n}\n\nimport { v4 as uuidV4 } from \"uuid\"\n\nif (typeof globalThis.crypto?.randomUUID !== \"function\") {\n  const randomUUID: typeof crypto.randomUUID = () => uuidV4() as ReturnType<typeof crypto.randomUUID>\n  if (globalThis.crypto) {\n    globalThis.crypto.randomUUID = randomUUID\n  } else {\n    globalThis.crypto = { randomUUID } as unknown as Crypto\n  }\n}\n\nexport function isHex(s?: string) {\n  if (!s) return false\n  // 48-57 = 0-9\n  // 65-70 = A-F\n  // 97-102 = a-f\n  return (\n    s.length % 2 == 0 &&\n    [...s].map(v => v.charCodeAt(0)).every(v => (v >= 48 && v <= 57) || (v >= 65 && v <= 70) || (v >= 97 && v <= 102))\n  )\n}\n"
  },
  {
    "path": "packages/shared/src/work-queue.ts",
    "content": "export interface WorkQueueItem {\n  next: () => Promise<unknown>\n  resolve(v: unknown): void\n  reject(e: unknown): void\n}\n\nexport async function processWorkQueue(queue?: Array<WorkQueueItem>, queueDelay = 200) {\n  while (queue && queue.length > 0) {\n    const v = queue.shift()\n    if (v) {\n      try {\n        const ret = await v.next()\n        v.resolve(ret)\n      } catch (e) {\n        v.reject(e)\n      }\n    }\n  }\n  setTimeout(() => processWorkQueue(queue, queueDelay), queueDelay)\n}\n\nexport const barrierQueue = async <T>(queue: Array<WorkQueueItem>, then: () => Promise<T>): Promise<T> => {\n  return new Promise<T>((resolve, reject) => {\n    queue.push({\n      next: then,\n      resolve,\n      reject,\n    })\n  })\n}\n"
  },
  {
    "path": "packages/shared/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \"src\",\n    \"target\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"esModuleInterop\": true,\n    \"noImplicitOverride\": true,\n    \"module\": \"ESNext\",\n    \"strict\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"inlineSourceMap\": true,\n    \"outDir\": \"dist\",\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"./src/**/*.ts\"],\n  \"exclude\": [\"src/**/*.test.ts\"]\n}\n"
  },
  {
    "path": "packages/shared/typedoc.json",
    "content": "{\n  \"entryPoints\": [\"src/index.ts\"]\n}\n"
  },
  {
    "path": "packages/system/.npmignore",
    "content": "tests/\nsrc/\n*.tgz\nworker.ts\nyarn*"
  },
  {
    "path": "packages/system/AUDIT.md",
    "content": "# `@snort/system` — Comprehensive Audit & Review\n\n**Package**: `@snort/system` v2.0.0-pre.8\n**Date**: 2026-03-03\n**Scope**: 75 source files, ~9,880 lines of TypeScript across 8 subdirectories\n**Tests**: 149 tests, 338 assertions, 13 test files (~2,718 lines) — all passing, build clean\n\n---\n\n## 1. Architecture Overview\n\n`@snort/system` is a full-featured Nostr client library implementing a layered architecture:\n\n| Layer | Components | Responsibility |\n|-------|-----------|----------------|\n| **Transport** | `Connection`, `ConnectionPool` | WebSocket management, multiplexing |\n| **Protocol** | `event-kind.ts`, `nostr.ts`, `impl/nip*.ts` | Nostr types + 14 NIP implementations |\n| **Query Engine** | `RequestBuilder` → `QueryManager` → `Query` | Request lifecycle, trace-per-relay |\n| **Optimization** | `query-optimizer/` (expand, merge, diff, compress) | Filter algebra |\n| **Sync** | `SafeSync`, `DiffSyncTags`, `JsonEventSync`, `RangeSync`, `Negentropy` | State reconciliation |\n| **Caching** | `BackgroundLoader`, profile/relay/follows caches, `CacheRelay` | Background data loading |\n| **Signing** | `EventSigner`, `PrivateKeySigner`, NIP-07/46/55 signers | Pluggable signing |\n| **Encryption** | NIP-04 (AES-CBC), NIP-44 v1/v2 (ChaCha20+HMAC), PIN storage | Message encryption |\n| **State** | `UserState`, `NoteCollection` | User state management, event collections |\n| **Content** | `transformText` pipeline | Rich text fragment extraction |\n\nThe design is sound. The `SystemInterface` abstraction cleanly separates concerns, the `RequestRouter` interface enables the outbox model as a pluggable strategy, and the signer interface allows transparent switching between local keys, browser extensions, and remote bunkers.\n\n**Strengths of the architecture:**\n- Clean separation between transport, protocol, and application layers\n- Pluggable interfaces for signing, routing, caching, and optimization\n- The negentropy set reconciliation protocol is a sophisticated addition\n- `SafeSync` with `previous` tag chaining is a thoughtful approach to safe replaceable event updates\n- `UserState` provides a coherent high-level API for managing complex user data\n- The query trace system provides good observability (Perfetto-compatible export)\n\n---\n\n## 2. Security Findings\n\n### CRITICAL\n\n**2.1 — PIN Encryption Uses MAC-then-Encrypt (Wrong Order)**\n`src/encryption/pin-encrypted.ts:64-93`\n\nThe MAC is computed over the plaintext, then the plaintext is encrypted with XChaCha20. On decrypt, the ciphertext is decrypted first, then the MAC is verified. This is the reverse of the recommended encrypt-then-MAC pattern. With a stream cipher like XChaCha20, an attacker can perform trivial bit-flipping attacks on the ciphertext, and the tampered plaintext will be decrypted and processed before the MAC check detects it.\n\nAdditionally, the MAC comparison at line 71 uses `!==` (non-constant-time string comparison), which is vulnerable to timing attacks.\n\n**2.2 — Delegation Tags Accepted Without Signature Verification**\n`src/event-ext.ts:40-45`\n\n`getRootPubKey()` accepts NIP-26 delegation tags without verifying the delegation signature. There is a literal `// todo: verify sig` comment. Any event can claim delegation from any pubkey.\n\n**2.3 — NIP-46 Processes Unverified Events**\n`src/impl/nip46.ts:114`\n\nThe remote signer listens on `unverifiedEvent`, which only checks `EventExt.isValid()` — a method that merely confirms `sig !== undefined` without actually verifying the Schnorr signature. An attacker who can inject events into the relay (trivial on public relays) could potentially forge NIP-46 protocol messages.\n\n### HIGH\n\n| # | Finding | Location |\n|---|---------|----------|\n| 2.4 | `isValid()` does not verify signatures despite its name — only checks `sig !== undefined` | `event-ext.ts:163-169` |\n| 2.5 | NIP-46 debug logging exposes decrypted payloads including connect secrets | `nip46.ts:240,303` |\n| 2.6 | NIP-46 `#rpc()` fire-and-forgets `#sendCommand` (not awaited), no timeout on response promise | `nip46.ts:284-292` |\n| 2.7 | Same scrypt-derived key used for both XChaCha20 encryption and HMAC — violates key separation | `pin-encrypted.ts:65-70` |\n| 2.8 | `NotEncrypted` stores private keys as plaintext JSON (no PIN users) | `pin-encrypted.ts:97-122` |\n| 2.9 | `PrivateKeySigner` exposes raw private key via public getter | `signer.ts:56-58` |\n| 2.10 | NIP-44 v1 decrypt has no authentication — accepts any ciphertext silently | `encryption/nip44.ts:127-130` |\n\n### Positive Security Notes\n- NIP-44 v2 encrypt-then-MAC is implemented correctly\n- MAC verification in NIP-44 uses constant-time `equalBytes()`\n- Nonce generation uses CSPRNG (`randomBytes`)\n- HKDF key derivation with proper domain separation (`\"nip44-v2\"`)\n- scrypt parameters (N=2^20, r=8, p=1) are strong for passwords (but insufficient for short PINs)\n\n---\n\n## 3. Reliability & Error Handling Findings\n\n### Hanging Promises (No Timeout, No Reject Path)\n\nThese are the most operationally dangerous issues — they cause the UI to freeze with no error feedback:\n\n| Location | Scenario |\n|----------|----------|\n| `connection.ts:444` | Auth promise hangs if no auth handler is registered |\n| `nip46.ts:285` | RPC promise hangs if remote signer goes offline |\n| `nip55.ts:68` | Clipboard poll hangs forever (interval also leaks) |\n| `query-manager.ts:150` | `fetch()` hangs if query never emits EOSE |\n| `query-manager.ts:434` | Range sync fetcher hangs if connection drops mid-sync |\n\n### Unprotected JSON.parse\n\n11 of 14 `JSON.parse` calls lack try/catch. The most dangerous:\n\n| Location | Impact |\n|----------|--------|\n| `connection.ts:194` | A single malformed relay message crashes the entire connection message handler |\n| `nip46.ts:195,237` | Malformed bunker responses crash the signer |\n| `event-publisher.ts:329,359` | Gift wrap/seal decryption of non-JSON content crashes |\n| `sync/diff-sync.ts:60` | Corrupted encrypted tag data crashes sync |\n| `relays.ts:26` | Malformed kind 3 content crashes relay parsing |\n\n### Unhandled Async Errors\n\n| Location | Issue |\n|----------|-------|\n| `nostr-system.ts:53` | `pool.on(\"event\", async ...)` — cache relay errors become unhandled rejections |\n| `nip46.ts:114` | `on(\"unverifiedEvent\", async ...)` — JSON parse failures become unhandled rejections |\n| `event-publisher.ts` | Zero try/catch blocks in entire file (24 async methods) |\n\n---\n\n## 4. Performance Findings\n\n### CRITICAL\n\n**4.1 — Cartesian Product Explosion in Filter Expansion**\n`src/query-optimizer/request-expander.ts:8-47`\n\n`expandFilter()` computes the full cartesian product of array fields. A filter with `{authors: [100], kinds: [5], \"#p\": [10]}` produces 5,000 `FlatReqFilter` objects. Real-world filters can have hundreds of authors. The downstream `diffFilters` (O(n^2)) and `mergeSimilar` (O(n^2) to O(n^3)) compound this into pathological performance.\n\n### HIGH\n\n| # | Finding | Location |\n|---|---------|----------|\n| 4.2 | `NoteCollection.takeSnapshot()` copies all events on every addition — O(n^2) total GC pressure | `note-collection.ts:48,104` |\n| 4.3 | `BackgroundLoader.#blacklist` grows without bound, permanently blocks keys from loading | `background-loader.ts:9,119` |\n| 4.4 | `BackgroundLoader` polling loop has no stop/destroy mechanism — runs forever | `background-loader.ts:104-128` |\n| 4.5 | `QueryManager` cleanup interval never cleared, no destroy method | `query-manager.ts:60` |\n| 4.6 | Event listeners in `#syncRangeSync` never cleaned up — accumulate proportionally | `query-manager.ts:437-448` |\n| 4.7 | `Query.#tracing` map never pruned — grows on every reconnection for leave-open queries | `query.ts:157` |\n| 4.8 | `ConnectTimeout` doubles on every disconnect, never resets on reconnect success | `connection.ts:179` |\n\n### MEDIUM\n\n- Connection pool event listeners never removed on disconnect (`connection-pool.ts:187-198`)\n- `#connectionListeners` set leaks stale UUIDs after reconnections (`query-manager.ts:51,67,82`)\n- Ephemeral check interval not cleared on `close()` (`connection.ts:477-498`)\n- Busy-wait polling loop (100ms intervals) instead of event-based connection waiting (`connection-pool.ts:160-176`)\n- `#pendingTraces` array has no timeout or eviction (`query-manager.ts:41`)\n- `OutboxModel.forFlatRequest` mutates input filter objects (`outbox-model.ts:151-153`)\n\n---\n\n## 5. Type Safety Findings\n\n| Severity | Finding | Location |\n|----------|---------|----------|\n| HIGH | `as unknown as T` double cast bypasses type system entirely | `connection-pool.ts:138` |\n| HIGH | Non-null assertions on potentially undefined sync values + unprotected JSON.parse | `json-in-event-sync.ts:58,60` |\n| MEDIUM | `PinEncrypted.fromPayload` force-casts without runtime validation | `pin-encrypted.ts:37` |\n| MEDIUM | NIP-46 request/response types use `any` for params and results | `nip46.ts:28,33,272` |\n| MEDIUM | `simpleMerge` accumulator typed as `any`, cast to `ReqFilter` | `request-merger.ts:37,109` |\n\n---\n\n## 6. Test Coverage Assessment\n\n**Quantitative**: 13 test files / 75 source files = **17% file coverage**. 2,718 test LOC / 9,880 source LOC = **27% line ratio**.\n\n**What is well tested:**\n- NIP-10 thread parsing and reply construction (582 lines, thorough edge cases)\n- Text/content parsing (677 lines, comprehensive fragment types)\n- EventExt utilities (559 lines, good coverage of types/keys/signing/validation)\n- Filter expansion, merging, diffing (326 lines combined)\n- NostrLink encoding/decoding (201 lines)\n- NIP-18 quote tags (159 lines)\n\n**What has no tests at all:**\n\n| Module | Lines | Risk |\n|--------|-------|------|\n| `connection.ts` | 499 | HIGH — WebSocket handling, reconnection, auth flow |\n| `connection-pool.ts` | 286 | HIGH — pool lifecycle, broadcast logic |\n| `query-manager.ts` | 534 | HIGH — central orchestrator, sync pipeline |\n| `query.ts` | 411 | HIGH — query state machine, progress tracking |\n| `nostr-system.ts` | 203 | MEDIUM — system initialization, social graph |\n| `event-publisher.ts` | 361 | MEDIUM — all event creation methods |\n| `user-state.ts` | 557 | MEDIUM — user state management |\n| `encryption/nip44.ts` | 145 | HIGH — cryptographic correctness |\n| `encryption/pin-encrypted.ts` | 129 | HIGH — key protection |\n| `impl/nip46.ts` | 307 | HIGH — remote signer protocol |\n| `sync/*.ts` | ~558 | MEDIUM — all sync strategies |\n| `negentropy/*.ts` | ~628 | MEDIUM — set reconciliation |\n| `background-loader.ts` | 145 | MEDIUM — polling lifecycle |\n| `outbox/outbox-model.ts` | 224 | MEDIUM — relay routing logic |\n\nThe `negentropy.test.ts` file is a stub (empty test body, 6 lines).\n\n**Key gap**: The most complex and error-prone modules (connection management, query orchestration, encryption, sync) have zero unit tests. The tested modules are primarily pure functions and data transformations — important but not where the bugs live.\n\n---\n\n## 7. Code Quality Observations\n\n**Good practices observed:**\n- TypeScript strict mode enabled\n- ECMAScript private fields (`#field`) used consistently\n- Fluent builder APIs (`RequestBuilder`, `EventBuilder`, `DVMJobRequest`)\n- Event-driven architecture with typed EventEmitter\n- LRU caching for expensive operations (NIP-11, NIP-57, threads)\n- Proper NIP-19 TLV encoding/decoding\n- `SortedMap` for efficient ordered collections\n- Content processing pipeline is clean and extensible\n\n**Areas for improvement:**\n- No `dispose()`/`destroy()` lifecycle methods on any class — timers, intervals, and listeners leak when instances are discarded\n- Magic numbers scattered throughout (timeouts, intervals, buffer sizes) — should be named constants\n- `event-publisher.ts` has 24 async methods with zero error handling\n- Mixed mutation patterns — some methods return new objects, others mutate in-place (`EventExt.sign`, `OutboxModel.forFlatRequest`)\n- The `isValid` name is misleading — it performs structural validation, not cryptographic verification\n\n---\n\n## 8. Dependency Assessment\n\n| Dependency | Purpose | Assessment |\n|------------|---------|------------|\n| `@noble/curves`, `@noble/hashes`, `@noble/ciphers` | Crypto primitives | Excellent — audited, pure JS, maintained |\n| `@scure/base` | Encoding | Excellent — same family as noble |\n| `@stablelib/xchacha20` | XChaCha20 for PIN encryption | Good, but redundant — noble/ciphers has xchacha20 |\n| `eventemitter3` | Event emitting | Good — lightweight, well-maintained |\n| `isomorphic-ws` + `ws` | WebSocket | Necessary for Node compatibility |\n| `nostr-social-graph` | Social graph | External dependency for follow graph; version pinned |\n| `typescript-lru-cache` | LRU cache | Fine, though a simpler `Map`-based cache would reduce dependencies |\n| `uuid` | UUID generation | Heavy for generating random IDs — `crypto.randomUUID()` is native |\n| `debug` | Logging | Appropriate for library logging |\n\n**Note**: The `@stablelib/xchacha20` dependency is only used in `pin-encrypted.ts`. Since `@noble/ciphers` (already a dependency) provides `xchacha20`, this dependency could be consolidated.\n\n---\n\n## 9. Summary & Recommendations\n\n### Priority 1 — Security (fix before release)\n\n1. **Reverse MAC order in PIN encryption** — change to encrypt-then-MAC, use constant-time comparison, derive separate keys for encryption and MAC\n2. **Verify delegation signatures** or remove `getRootPubKey` delegation support entirely\n3. **Verify Schnorr signatures** on NIP-46 incoming events before processing\n4. **Rename `isValid` to `isWellFormed`** and create a real `isValid` that includes signature verification\n\n### Priority 2 — Reliability (fix soon)\n\n5. **Add timeouts to all promises** — auth, NIP-46 RPC, fetch EOSE, range sync, NIP-55 clipboard\n6. **Wrap all `JSON.parse` calls** in try/catch, especially `connection.ts:194`\n7. **Add `.catch()` to all async event handlers** or use synchronous wrappers\n8. **Add error handling to `event-publisher.ts`** — at minimum, wrap `JSON.parse` of decrypted content\n\n### Priority 3 — Performance (fix for scale)\n\n9. **Add lifecycle management** — `destroy()` methods on `QueryManager`, `BackgroundLoader`, `Connection`, `Query` that clear timers and listeners\n10. **Add eviction/TTL to `BackgroundLoader.#blacklist`** — keys should be retryable after a cooldown\n11. **Reset `ConnectTimeout` on successful reconnection**\n12. **Optimize `NoteCollection.takeSnapshot()`** — consider incremental snapshots or lazy evaluation\n13. **Add batching/chunking to `BackgroundLoader`** fetch requests to avoid oversized filters\n14. **Address cartesian explosion** in filter expansion — consider operating on compressed filters where possible\n\n### Priority 4 — Testing\n\n15. **Add unit tests for `connection.ts`** — reconnection, auth flow, message parsing errors\n16. **Add unit tests for encryption** — NIP-44 round-trip, PIN encrypt/decrypt, edge cases\n17. **Add unit tests for `query-manager.ts`** — send pipeline, cache relay interaction, cleanup\n18. **Add integration tests for NIP-46** — mock bunker communication, error scenarios\n19. **Fill in the negentropy test stub**\n\n### Priority 5 — Code Quality\n\n20. **Extract magic numbers to named constants** in `const.ts`\n21. **Remove redundant `@stablelib/xchacha20` dependency** — use `@noble/ciphers` instead\n22. **Consider replacing `uuid` with native `crypto.randomUUID()`**\n23. **Make mutation vs. immutability consistent** — `EventExt.sign` should either return a new event or be clearly documented as mutating\n\n---\n\n**Overall assessment**: The architecture is well-designed and the core Nostr protocol implementation is solid. The main concerns are (1) the MAC-then-encrypt pattern in PIN encryption, (2) missing signature verification in several trust-sensitive paths, (3) pervasive lack of error handling that could cause hanging UI or silent failures, and (4) missing lifecycle management causing memory/timer leaks in long-running sessions. The test coverage is thin relative to the complexity of the untested modules. The package is usable for its current purpose but needs hardening before wider library adoption.\n"
  },
  {
    "path": "packages/system/README.md",
    "content": "## @snort/system\n\nA collection of caching and querying techniquies used by https://snort.social to serve all content from the nostr protocol.\n\nSimple example:\n\n```js\nimport { NostrSystem, RequestBuilder, StoreSnapshot, NoteCollection } from \"@snort/system\";\n\n// Singleton instance to store all connections and access query fetching system\nconst System = new NostrSystem({});\n\n(async () => {\n  // Setup cache system\n  await System.Init();\n\n  // connec to one \"bootstrap\" relay to pull profiles/relay lists from\n  // also used as a fallback relay when gossip model doesnt know which relays to pick, or \"authors\" are not provided in the request\n  await System.ConnectToRelay(\"wss://relay.snort.social\", { read: true, write: false });\n\n  // ID should be unique to the use case, this is important as all data fetched from this ID will be merged into the same NoteStore\n  const rb = new RequestBuilder(\"get-posts\");\n  rb.withFilter()\n    .authors([\"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\"]) // Kieran pubkey\n    .kinds([1])\n    .limit(10);\n\n  const q = System.Query(rb);\n  // basic usage using \"onEvent\", fired every 100ms\n  q.on(\"event\", evs => {\n    console.log(evs);\n    // something else..\n  });\n})();\n```\n"
  },
  {
    "path": "packages/system/examples/simple.ts",
    "content": "import { NostrSystem, RequestBuilder, FlatNoteStore, StoreSnapshot, NoteCollection } from \"../src\"\n\n// Singleton instance to store all connections and access query fetching system\nconst System = new NostrSystem({})\n\n;(async () => {\n  // Setup cache system\n  await System.Init()\n\n  // connec to one \"bootstrap\" relay to pull profiles/relay lists from\n  // also used as a fallback relay when gossip model doesnt know which relays to pick, or \"authors\" are not provided in the request\n  await System.ConnectToRelay(\"wss://relay.snort.social\", { read: true, write: false })\n\n  // ID should be unique to the use case, this is important as all data fetched from this ID will be merged into the same NoteStore\n  const rb = new RequestBuilder(\"get-posts\")\n  rb.withFilter()\n    .authors([\"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\"]) // Kieran pubkey\n    .kinds([1])\n    .limit(10)\n\n  const q = System.Query(rb)\n  // basic usage using \"onEvent\", fired every 100ms\n  q.on(\"event\", evs => {\n    console.log(evs)\n    // something else..\n  })\n})()\n"
  },
  {
    "path": "packages/system/package.json",
    "content": "{\n  \"name\": \"@snort/system\",\n  \"version\": \"2.0.0-pre.11\",\n  \"description\": \"Snort nostr system package\",\n  \"type\": \"module\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"module\": \"src/index.ts\",\n  \"repository\": \"https://git.v0l.io/Kieran/snort\",\n  \"author\": \"v0l\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"build\": \"rm -rf dist && bunx --bun tsc\"\n  },\n  \"files\": [\"src\", \"dist\"],\n  \"devDependencies\": {\n    \"@peculiar/webcrypto\": \"^1.5.0\",\n    \"@types/debug\": \"^4.1.12\",\n    \"@types/node\": \"^24.8.1\",\n    \"@types/ws\": \"^8.18.1\",\n    \"typescript\": \"^5.9.3\"\n  },\n  \"dependencies\": {\n    \"@noble/ciphers\": \"^2.0.1\",\n    \"@noble/curves\": \"^2.0.1\",\n    \"@noble/hashes\": \"^2.0.1\",\n    \"@scure/base\": \"^2.0.0\",\n    \"@snort/shared\": \"^2.0.0-pre.4\",\n    \"debug\": \"^4.4.3\",\n    \"eventemitter3\": \"^5.0.1\",\n    \"isomorphic-ws\": \"^5.0.0\",\n    \"nostr-social-graph\": \"^1.0.33\",\n    \"typescript-lru-cache\": \"^2.0.0\",\n    \"ws\": \"^8.18.3\"\n  }\n}\n"
  },
  {
    "path": "packages/system/src/background-loader.ts",
    "content": "import { type CachedTable, isHex, removeUndefined } from \"@snort/shared\"\nimport debug from \"debug\"\nimport type { RequestBuilder, SystemInterface, TaggedNostrEvent } from \".\"\n\n/** How long a key stays blacklisted before being retried (ms) */\nconst BlacklistTtl = 5 * 60 * 1_000 // 5 minutes\n\n/** Maximum number of authors per relay filter to avoid relay rejections */\nconst ChunkSize = 100\n\n/** Debounce intervals (ms) per priority tier */\nconst FlushIntervals = {\n  high: 50,\n  normal: 500,\n  low: 5_000,\n} as const\n\nexport type ProfilePriority = keyof typeof FlushIntervals\n\n/**\n * Simple debounced flush scheduler.\n * Schedules a callback to fire after `delayMs` of inactivity.\n * Multiple `schedule()` calls within the window collapse into one flush.\n */\nclass DebouncedFlush {\n  #timer: ReturnType<typeof setTimeout> | undefined\n  readonly #delayMs: number\n  readonly #fn: () => void\n\n  constructor(delayMs: number, fn: () => void) {\n    this.#delayMs = delayMs\n    this.#fn = fn\n  }\n\n  schedule() {\n    if (this.#timer !== undefined) return\n    this.#timer = setTimeout(() => {\n      this.#timer = undefined\n      this.#fn()\n    }, this.#delayMs)\n  }\n\n  cancel() {\n    if (this.#timer !== undefined) {\n      clearTimeout(this.#timer)\n      this.#timer = undefined\n    }\n  }\n}\n\nexport abstract class BackgroundLoader<T extends { loaded: number; created: number }> {\n  #system: SystemInterface\n  readonly cache: CachedTable<T>\n  #log = debug(this.name())\n  /** Keys that returned no results, mapped to the timestamp (ms) they were blacklisted */\n  #blacklist = new Map<string, number>()\n  #destroyed = false\n\n  /**\n   * Per-priority sets of pubkeys to fetch.\n   * A key present in a higher-priority set will be promoted on the next flush.\n   */\n  #wantHigh = new Set<string>()\n  #wantNormal = new Set<string>()\n  #wantLow = new Set<string>()\n\n  /**\n   * Keys currently being fetched from relays.\n   * These are excluded from subsequent flush cycles until the fetch resolves.\n   */\n  #inFlight = new Set<string>()\n\n  /** Debounced flush schedulers per priority tier */\n  #flush: Record<ProfilePriority, DebouncedFlush>\n\n  /**\n   * Custom loader function for fetching data from alternative sources\n   */\n  loaderFn?: (pubkeys: Array<string>) => Promise<Array<T>>\n\n  constructor(system: SystemInterface, cache: CachedTable<T>) {\n    this.#system = system\n    this.cache = cache\n    this.#flush = {\n      high: new DebouncedFlush(FlushIntervals.high, () => this.#dispatch(\"high\")),\n      normal: new DebouncedFlush(FlushIntervals.normal, () => this.#dispatch(\"normal\")),\n      low: new DebouncedFlush(FlushIntervals.low, () => this.#dispatch(\"low\")),\n    }\n  }\n\n  /**\n   * Stop all pending flush timers.\n   * Call this when the loader is no longer needed to prevent timer leaks.\n   */\n  destroy() {\n    this.#destroyed = true\n    this.#flush.high.cancel()\n    this.#flush.normal.cancel()\n    this.#flush.low.cancel()\n  }\n\n  /**\n   * Name of this loader service\n   */\n  abstract name(): string\n\n  /**\n   * Handle fetched data\n   */\n  abstract onEvent(e: Readonly<TaggedNostrEvent>): T | undefined\n\n  /**\n   * Get expire time as unix milliseconds\n   */\n  abstract getExpireCutoff(): number\n\n  /**\n   * Build subscription for a chunk of missing keys\n   */\n  protected abstract buildSub(missing: Array<string>): RequestBuilder\n\n  /**\n   * Start requesting a set of keys to be loaded.\n   * @param pk One or more hex pubkeys\n   * @param priority Priority tier — higher tiers flush sooner (default: \"normal\")\n   */\n  TrackKeys(pk: string | Array<string>, priority: ProfilePriority = \"normal\") {\n    for (const p of Array.isArray(pk) ? pk : [pk]) {\n      if (!isHex(p) || p.length !== 64) continue\n      this.#wantSetFor(priority).add(p)\n    }\n    if (!this.#destroyed) {\n      this.#flush[priority].schedule()\n    }\n  }\n\n  /**\n   * Stop requesting a set of keys to be loaded\n   */\n  UntrackKeys(pk: string | Array<string>) {\n    for (const p of Array.isArray(pk) ? pk : [pk]) {\n      this.#wantHigh.delete(p)\n      this.#wantNormal.delete(p)\n      this.#wantLow.delete(p)\n    }\n  }\n\n  /**\n   * Get object from cache or fetch if missing\n   */\n  async fetch(key: string, timeoutMs = 30_000) {\n    const existing = await this.cache.get(key)\n    if (existing) {\n      return existing\n    } else {\n      return await new Promise<T>((resolve, reject) => {\n        this.TrackKeys(key, \"high\")\n        const timeout = setTimeout(() => {\n          unsub()\n          this.UntrackKeys(key)\n          reject(new Error(\"Fetch timeout\"))\n        }, timeoutMs)\n\n        const unsub = this.cache.subscribe(key, () => {\n          const found = this.cache.getFromCache(key)\n          if (found) {\n            clearTimeout(timeout)\n            unsub()\n            resolve(found)\n            this.UntrackKeys(key)\n          } else {\n            clearTimeout(timeout)\n            unsub()\n            reject(new Error(\"Not found\"))\n          }\n        })\n      })\n    }\n  }\n\n  /** Returns the want-set for the given priority tier */\n  #wantSetFor(priority: ProfilePriority): Set<string> {\n    switch (priority) {\n      case \"high\":\n        return this.#wantHigh\n      case \"normal\":\n        return this.#wantNormal\n      case \"low\":\n        return this.#wantLow\n    }\n  }\n\n  /** All tracked keys across all priority tiers, highest priority first */\n  get #allWanted(): Array<string> {\n    return [...this.#wantHigh, ...this.#wantNormal, ...this.#wantLow]\n  }\n\n  /**\n   * Dispatch a fetch cycle for all pending keys across all tiers.\n   * Called by the debounced flush scheduler.\n   */\n  async #dispatch(triggeredBy: ProfilePriority) {\n    if (this.#destroyed) return\n\n    const now = Date.now()\n    // Evict expired blacklist entries so keys are retried after BlacklistTtl\n    for (const [k, ts] of this.#blacklist) {\n      if (now - ts > BlacklistTtl) {\n        this.#blacklist.delete(k)\n      }\n    }\n\n    // Gather all keys that are not blacklisted and not currently in-flight\n    const candidates = this.#allWanted.filter(a => !this.#blacklist.has(a) && !this.#inFlight.has(a))\n\n    if (candidates.length === 0) {\n      this.#log(\"Dispatch triggered by %s — no candidates\", triggeredBy)\n      return\n    }\n\n    try {\n      // Buffer any keys not already in memory from persistent storage\n      const needsBuffer = candidates.filter(a => !this.cache.getFromCache(a))\n      if (needsBuffer.length > 0) {\n        await this.cache.buffer(needsBuffer)\n      }\n\n      // Determine which keys actually need fetching from relays (expired or never loaded)\n      const cutoff = this.getExpireCutoff()\n      const missing = candidates.filter(a => (this.cache.getFromCache(a)?.loaded ?? 0) < cutoff)\n\n      if (missing.length === 0) {\n        this.#log(\"Dispatch triggered by %s — all candidates fresh\", triggeredBy)\n        return\n      }\n\n      this.#log(\"Fetching %d keys (triggered by %s)\", missing.length, triggeredBy)\n\n      // Mark all as in-flight before dispatching to prevent re-entry\n      for (const k of missing) {\n        this.#inFlight.add(k)\n      }\n\n      // Chunk into groups of ChunkSize and dispatch each chunk independently\n      const chunks = chunk(missing, ChunkSize)\n      const results = await Promise.all(chunks.map((c, i) => this.#loadChunk(c, i)))\n      const found = results.flat()\n\n      // Blacklist keys that returned no data\n      const noResult = missing.filter(a => !found.some(b => a === this.cache.key(b)))\n      for (const k of noResult) {\n        this.#blacklist.set(k, Date.now())\n      }\n    } catch (e) {\n      this.#log(\"Dispatch error: %O\", e)\n    } finally {\n      // Release in-flight locks regardless of outcome\n      // (keys were added above; we clear them all here)\n      for (const k of this.#allWanted) {\n        this.#inFlight.delete(k)\n      }\n    }\n  }\n\n  async #loadChunk(keys: Array<string>, chunkIndex: number): Promise<Array<T>> {\n    this.#log(\"Loading chunk %d (%d keys)\", chunkIndex, keys.length)\n    const ret: Array<T> = []\n\n    // Use a unique ID per chunk to avoid QueryManager collisions\n    const req = this.#buildChunkSub(keys, chunkIndex)\n    req.withOptions({ leaveOpen: false, skipCache: true, useSyncModule: true })\n\n    await this.#system.Fetch(req, async x => {\n      const results = removeUndefined(x.map(e => this.onEvent(e)))\n      ret.push(...results)\n      await Promise.all(results.map(a => this.cache.update(a)))\n    })\n\n    this.#log(\"Chunk %d: got %d results\", chunkIndex, ret.length)\n    return ret\n  }\n\n  /**\n   * Wraps `buildSub` with a chunk-specific unique ID to prevent\n   * QueryManager from conflating concurrent chunk requests.\n   */\n  #buildChunkSub(keys: Array<string>, chunkIndex: number): RequestBuilder {\n    const req = this.buildSub(keys)\n    // Assign a unique ID so each chunk gets its own Query in the QueryManager\n    req.id = `${this.name()}-${Date.now()}-${chunkIndex}`\n    return req\n  }\n}\n\n/** Split an array into chunks of at most `size` elements */\nfunction chunk<T>(arr: Array<T>, size: number): Array<Array<T>> {\n  const out: Array<Array<T>> = []\n  for (let i = 0; i < arr.length; i += size) {\n    out.push(arr.slice(i, i + size))\n  }\n  return out\n}\n"
  },
  {
    "path": "packages/system/src/cache/index.ts",
    "content": "import type { FullRelaySettings, NostrEvent, UserMetadata } from \"..\"\nimport { unixNowMs } from \"@snort/shared\"\n\nexport interface CachedBase {\n  /**\n   * When the object was saved in cache\n   */\n  loaded: number\n\n  /**\n   * When the source data event was created\n   */\n  created: number\n\n  /**\n   * The pubkey of the owner of this data\n   */\n  pubkey: string\n}\n\nexport type CachedMetadata = CachedBase & UserMetadata\n\nexport type UsersRelays = {\n  relays: FullRelaySettings[]\n} & CachedBase\n\nexport type UsersFollows = {\n  follows: Array<Array<string>>\n} & CachedBase\n\nexport function mapEventToProfile(ev: NostrEvent) {\n  if (ev.kind !== 0 && ev.kind !== 31990) return\n  try {\n    const data: UserMetadata = JSON.parse(ev.content)\n    const ret = {\n      ...data,\n      pubkey: ev.pubkey,\n      created: ev.created_at,\n      loaded: unixNowMs(),\n    } as CachedMetadata\n\n    // sanitize non-string/number\n    for (const [k, v] of Object.entries(ret)) {\n      if (typeof v !== \"number\" && typeof v !== \"string\") {\n        ;(ret as any)[k] = undefined\n      }\n    }\n    return ret\n  } catch (e) {\n    console.error(\"Failed to parse JSON\", ev, e)\n  }\n}\n"
  },
  {
    "path": "packages/system/src/cache/user-follows-lists.ts",
    "content": "import type { UsersFollows } from \".\"\nimport { type CacheStore, FeedCache } from \"@snort/shared\"\n\nexport class UserFollowsCache extends FeedCache<UsersFollows> {\n  constructor(store?: CacheStore<UsersFollows>) {\n    super(\"UserFollowsCache\", store)\n  }\n\n  key(of: UsersFollows): string {\n    return of.pubkey\n  }\n\n  override async preload(follows?: Array<string>): Promise<void> {\n    await super.preload()\n    if (follows) {\n      await this.buffer(follows)\n    }\n  }\n\n  newest(): number {\n    let ret = 0\n    this.cache.forEach(v => (ret = v.created > ret ? v.created : ret))\n    return ret\n  }\n\n  takeSnapshot(): Array<UsersFollows> {\n    return [...this.cache.values()]\n  }\n\n  async search() {\n    return <Array<UsersFollows>>[]\n  }\n}\n"
  },
  {
    "path": "packages/system/src/cache/user-metadata.ts",
    "content": "import type { CachedMetadata } from \".\"\nimport { FeedCache, type CacheStore } from \"@snort/shared\"\n\nexport class UserProfileCache extends FeedCache<CachedMetadata> {\n  constructor(store?: CacheStore<CachedMetadata>) {\n    super(\"UserCache\", store)\n  }\n\n  key(of: CachedMetadata): string {\n    return of.pubkey\n  }\n\n  override async preload(follows?: Array<string>): Promise<void> {\n    await super.preload()\n    // load follows profiles\n    if (follows) {\n      await this.buffer(follows)\n    }\n  }\n\n  async search(q: string): Promise<Array<CachedMetadata>> {\n    const lowerQ = q.toLowerCase()\n    return [...this.cache.values()]\n      .filter(user => {\n        const profile = user as CachedMetadata\n        return (\n          profile.name?.toLowerCase().includes(lowerQ) ||\n          profile.display_name?.toLowerCase().includes(lowerQ) ||\n          profile.nip05?.toLowerCase().includes(lowerQ)\n        )\n      })\n      .slice(0, 5)\n  }\n\n  takeSnapshot(): CachedMetadata[] {\n    return [...this.cache.values()]\n  }\n}\n"
  },
  {
    "path": "packages/system/src/cache/user-relays.ts",
    "content": "import type { UsersRelays } from \".\"\nimport { type CacheStore, FeedCache } from \"@snort/shared\"\n\nexport class UserRelaysCache extends FeedCache<UsersRelays> {\n  constructor(store?: CacheStore<UsersRelays>) {\n    super(\"UserRelays\", store)\n  }\n\n  key(of: UsersRelays): string {\n    return of.pubkey\n  }\n\n  override async preload(follows?: Array<string>): Promise<void> {\n    await super.preload()\n    if (follows) {\n      await this.buffer(follows)\n    }\n  }\n\n  newest(): number {\n    let ret = 0\n    this.cache.forEach(v => (ret = v.created > ret ? v.created : ret))\n    return ret\n  }\n\n  takeSnapshot(): Array<UsersRelays> {\n    return [...this.cache.values()]\n  }\n\n  async search() {\n    return <Array<UsersRelays>>[]\n  }\n}\n"
  },
  {
    "path": "packages/system/src/cache-relay.ts",
    "content": "import type { OkResponse, ReqCommand, TaggedNostrEvent } from \"./nostr\"\n\n/**\n * A cache relay is an always available local (local network / browser worker) relay\n * Which should contain all of the content we're looking for and respond quickly.\n */\nexport interface CacheRelay {\n  /**\n   * Write event to cache relay\n   */\n  event(ev: TaggedNostrEvent): Promise<OkResponse>\n\n  /**\n   * Read event from cache relay\n   */\n  query(req: ReqCommand): Promise<Array<TaggedNostrEvent>>\n\n  /**\n   * Delete events by filter\n   */\n  delete(req: ReqCommand): Promise<Array<string>>\n}\n"
  },
  {
    "path": "packages/system/src/connection-cache-relay.ts",
    "content": "import type { NostrEvent, OkResponse, ReqCommand, ReqFilter, TaggedNostrEvent } from \"./nostr\"\nimport type { CacheRelay } from \"./cache-relay\"\nimport type { Connection } from \"./connection\"\nimport { NoteCollection } from \"./note-collection\"\n\n/**\n * Use a regular connection as a CacheRelay\n */\nexport class ConnectionCacheRelay implements CacheRelay {\n  #eventsSent = new Set<string>()\n\n  constructor(readonly connection: Connection) {}\n\n  async event(ev: NostrEvent): Promise<OkResponse> {\n    if (this.#eventsSent.has(ev.id))\n      return {\n        ok: true,\n        id: ev.id,\n        message: \"duplicate\",\n      } as OkResponse\n    this.#eventsSent.add(ev.id)\n    return await this.connection.publish(ev)\n  }\n\n  query(req: ReqCommand): Promise<Array<TaggedNostrEvent>> {\n    const id = crypto.randomUUID()\n    return new Promise((resolve, reject) => {\n      const results = new NoteCollection()\n      const evh = (s: string, e: TaggedNostrEvent) => {\n        if (s === id) {\n          results.add(e)\n        }\n      }\n      const eoh = (s: string) => {\n        if (s === id) {\n          resolve(results.snapshot)\n          this.connection.closeRequest(id)\n          this.connection.off(\"unverifiedEvent\", evh)\n          this.connection.off(\"eose\", eoh)\n          this.connection.off(\"closed\", eoh)\n        }\n      }\n      this.connection.on(\"unverifiedEvent\", evh)\n      this.connection.on(\"eose\", eoh)\n      this.connection.on(\"closed\", eoh)\n      this.connection.request([\"REQ\", id, ...(req.slice(2) as Array<ReqFilter>)])\n    })\n  }\n\n  delete(req: ReqCommand): Promise<string[]> {\n    // ignored\n    return Promise.resolve([])\n  }\n}\n"
  },
  {
    "path": "packages/system/src/connection-pool.ts",
    "content": "import { removeUndefined, sanitizeRelayUrl, unwrap } from \"@snort/shared\"\nimport debug from \"debug\"\nimport { EventEmitter } from \"eventemitter3\"\nimport type { RelayInfoDocument, SystemInterface } from \".\"\nimport { Connection, type RelaySettings } from \"./connection\"\nimport type { NostrEvent, OkResponse, ReqCommand, TaggedNostrEvent } from \"./nostr\"\n\n/**\n * Events which the ConnectionType must emit\n */\nexport interface ConnectionTypeEvents {\n  change: () => void\n  connected: (wasReconnect: boolean) => void\n  error: () => void\n  unverifiedEvent: (sub: string, e: TaggedNostrEvent) => void\n  eose: (sub: string) => void\n  closed: (sub: string, reason: string) => void\n  disconnect: (code: number) => void\n  auth: (challenge: string, relay: string, cb: (ev: NostrEvent) => void) => void\n  notice: (msg: string) => void\n  unknownMessage: (obj: Array<unknown>) => void\n}\n\nexport type ConnectionSubscription = Record<string, never>\n\n/**\n * Basic relay connection\n */\nexport type ConnectionType = {\n  readonly id: string\n  readonly address: string\n  readonly info: RelayInfoDocument | undefined\n  readonly isDown: boolean\n  readonly isOpen: boolean\n  readonly activeSubscriptions: number\n  readonly maxSubscriptions: number\n  settings: RelaySettings\n  ephemeral: boolean\n\n  /**\n   * Connect to relay\n   */\n  connect: () => Promise<void>\n\n  /**\n   * Disconnect relay\n   */\n  close: () => void\n\n  /**\n   * Publish an event to this relay\n   */\n  publish: (ev: NostrEvent, timeout?: number) => Promise<OkResponse>\n\n  /**\n   * Send request to relay\n   */\n  request: (req: ReqCommand, cbSent?: () => void) => void\n\n  /**\n   * Send raw json object on wire (used by negentropy sync)\n   */\n  sendRaw: (obj: object) => void\n\n  /**\n   * Close a request\n   */\n  closeRequest: (id: string) => void\n} & EventEmitter<ConnectionTypeEvents>\n\n/**\n * Events which are emitted by the connection pool\n */\nexport interface ConnectionPoolEvents {\n  connected: (address: string, wasReconnect: boolean) => void\n  connectFailed: (address: string) => void\n  event: (address: string, sub: string, e: TaggedNostrEvent) => void\n  eose: (address: string, sub: string) => void\n  disconnect: (address: string, code: number) => void\n  auth: (address: string, challenge: string, relay: string, cb: (ev: NostrEvent) => void) => void\n  notice: (address: string, msg: string) => void\n}\n\n/**\n * Base connection pool\n */\nexport type ConnectionPool = {\n  getConnection(id: string): ConnectionType | undefined\n  connect(address: string, options: RelaySettings, ephemeral: boolean): Promise<ConnectionType | undefined>\n  disconnect(address: string): void\n  broadcast(ev: NostrEvent, cb?: (rsp: OkResponse) => void): Promise<OkResponse[]>\n  broadcastTo(address: string, ev: NostrEvent): Promise<OkResponse>\n} & EventEmitter<ConnectionPoolEvents> &\n  Iterable<[string, ConnectionType]>\n\n/**\n * Function for building new connections\n */\nexport type ConnectionBuilder<T extends ConnectionType> = (\n  address: string,\n  options: RelaySettings,\n  ephemeral: boolean,\n) => Promise<T> | T\n\n/**\n * Simple connection pool containing connections to multiple nostr relays\n */\nexport class DefaultConnectionPool<T extends ConnectionType = Connection>\n  extends EventEmitter<ConnectionPoolEvents>\n  implements ConnectionPool\n{\n  #system: SystemInterface\n  #log = debug(\"ConnectionPool\")\n\n  /**\n   * Track if a connection request has started\n   */\n  #connectStarted = new Set<string>()\n\n  /**\n   * All currently connected websockets\n   */\n  #sockets = new Map<string, T>()\n\n  /**\n   * Builder function to create new sockets\n   */\n  #connectionBuilder: ConnectionBuilder<T>\n\n  constructor(system: SystemInterface, builder?: ConnectionBuilder<T>) {\n    super()\n    this.#system = system\n    if (builder) {\n      this.#connectionBuilder = builder\n    } else {\n      // Connection satisfies ConnectionType; the cast is safe when no custom builder is supplied.\n      this.#connectionBuilder = (addr, options, ephemeral) =>\n        new Connection(addr, options, ephemeral) as ConnectionType as T\n    }\n  }\n\n  /**\n   * Get a connection object from the pool\n   */\n  getConnection(id: string) {\n    const addr = sanitizeRelayUrl(id)\n    if (addr) {\n      return this.#sockets.get(addr)\n    }\n  }\n\n  /**\n   * Add a new relay to the pool\n   */\n  async connect(address: string, options: RelaySettings, ephemeral: boolean) {\n    const addr = unwrap(sanitizeRelayUrl(address))\n\n    // If connection is already being established, wait for it\n    if (this.#connectStarted.has(addr)) {\n      // Poll for the connection to be established\n      const maxWait = 10000 // 10 seconds\n      const pollInterval = 100 // 100ms\n      const startTime = Date.now()\n\n      while (this.#connectStarted.has(addr) && Date.now() - startTime < maxWait) {\n        await new Promise(resolve => setTimeout(resolve, pollInterval))\n        const existing = this.#sockets.get(addr)\n        if (existing) {\n          return existing\n        }\n      }\n\n      // If we get here, either connection failed or timed out\n      // Fall through to check sockets or start new connection\n    }\n\n    this.#connectStarted.add(addr)\n\n    try {\n      const existing = this.#sockets.get(addr)\n      if (!existing) {\n        const c = await this.#connectionBuilder(addr, options, ephemeral)\n        this.#sockets.set(addr, c)\n\n        // This is where we do check sigs.\n        // Events from a relay tend to arrive in bursts (one WebSocket frame per\n        // message, but many frames queued in the same microtask turn).  We\n        // accumulate them with queueMicrotask so that a single batchVerify call\n        // covers the whole burst, amortising the JS→WASM boundary overhead.\n        let pendingBatch: Array<{ sub: string; ev: TaggedNostrEvent }> = []\n        let batchScheduled = false\n\n        const flushBatch = () => {\n          batchScheduled = false\n          const batch = pendingBatch\n          pendingBatch = []\n\n          if (!this.#system.checkSigs) {\n            for (const { sub, ev } of batch) this.emit(\"event\", addr, sub, ev)\n            return\n          }\n\n          const results = this.#system.optimizer.batchVerify(batch.map(b => b.ev))\n          for (let i = 0; i < batch.length; i++) {\n            if (results[i]) {\n              this.emit(\"event\", addr, batch[i].sub, batch[i].ev)\n            } else {\n              this.#log(\"Reject invalid event %o\", batch[i].ev)\n            }\n          }\n        }\n\n        c.on(\"unverifiedEvent\", (s, e) => {\n          pendingBatch.push({ sub: s, ev: e })\n          if (!batchScheduled) {\n            batchScheduled = true\n            queueMicrotask(flushBatch)\n          }\n        })\n\n        c.on(\"eose\", s => this.emit(\"eose\", addr, s))\n        c.on(\"disconnect\", code => this.emit(\"disconnect\", addr, code))\n        c.on(\"connected\", r => this.emit(\"connected\", addr, r))\n        c.on(\"auth\", (cx, r, cb) => this.emit(\"auth\", addr, cx, r, cb))\n        await c.connect()\n        return c\n      } else {\n        // update settings if already connected\n        existing.settings = options\n        // upgrade to non-ephemeral, never downgrade\n        if (existing.ephemeral && !ephemeral) {\n          existing.ephemeral = ephemeral\n        }\n        // re-open if closed\n        if (existing.ephemeral && !existing.isOpen) {\n          await existing.connect()\n        }\n        return existing\n      }\n    } catch (e) {\n      console.error(e)\n      this.#log(\"%O\", e)\n      this.emit(\"connectFailed\", addr)\n      this.#sockets.delete(addr)\n    } finally {\n      this.#connectStarted.delete(addr)\n    }\n  }\n\n  /**\n   * Remove relay from pool\n   */\n  disconnect(address: string) {\n    const addr = unwrap(sanitizeRelayUrl(address))\n    const c = this.#sockets.get(addr)\n    if (c) {\n      this.#sockets.delete(addr)\n      c.close()\n    }\n  }\n\n  /**\n   * Broadcast event to all write relays.\n   * @remarks Also write event to read relays of those who are `p` tagged in the event (Inbox model)\n   */\n  async broadcast(ev: NostrEvent, cb?: (rsp: OkResponse) => void) {\n    const writeRelays = [...this.#sockets.values()].filter(a => !a.ephemeral && a.settings.write)\n    const replyRelays = (await this.#system.requestRouter?.forReply(ev)) ?? []\n    const oks = await Promise.all([\n      ...writeRelays.map(async s => {\n        try {\n          const rsp = await s.publish(ev)\n          cb?.(rsp)\n          return rsp\n        } catch (e) {\n          console.error(e)\n        }\n        return\n      }),\n      ...(replyRelays ?? [])\n        .filter(a => !this.#sockets.has(unwrap(sanitizeRelayUrl(a))))\n        .map(a => this.broadcastTo(a, ev)),\n    ])\n    return removeUndefined(oks)\n  }\n\n  /**\n   * Send event to specific relay\n   */\n  async broadcastTo(address: string, ev: NostrEvent): Promise<OkResponse> {\n    const addrClean = sanitizeRelayUrl(address)\n    if (!addrClean) {\n      throw new Error(\"Invalid relay address\")\n    }\n\n    const existing = this.#sockets.get(addrClean)\n    if (existing) {\n      return await existing.publish(ev)\n    } else {\n      // Use internal connect method to avoid duplicate connections\n      const c = await this.connect(address, { write: true, read: true }, true)\n      if (!c) {\n        throw new Error(\"Failed to connect to relay\")\n      }\n      return await c.publish(ev)\n    }\n  }\n\n  *[Symbol.iterator]() {\n    for (const kv of this.#sockets) {\n      yield kv\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/connection-stats.ts",
    "content": "/**\n * Stats class for tracking metrics per connection\n */\nexport class ConnectionStats {\n  /**\n   * Last n records of how long between REQ->EOSE\n   */\n  Latency: number[] = []\n\n  /**\n   * Total number of REQ's sent on this connection\n   */\n  Subs: number = 0\n\n  /**\n   * Count of REQ which took too long and where abandoned\n   */\n  SubsTimeout: number = 0\n\n  /**\n   * Total number of EVENT messages received\n   */\n  EventsReceived: number = 0\n\n  /**\n   * Total number of EVENT messages sent\n   */\n  EventsSent: number = 0\n\n  /**\n   * Total number of times this connection was lost\n   */\n  Disconnects: number = 0\n}\n"
  },
  {
    "path": "packages/system/src/connection.ts",
    "content": "import { unixNowMs } from \"@snort/shared\"\nimport debug from \"debug\"\nimport { EventEmitter } from \"eventemitter3\"\nimport WebSocket from \"isomorphic-ws\"\nimport type { ConnectionType, ConnectionTypeEvents } from \"./connection-pool\"\nimport { AuthTimeout, DefaultConnectTimeout } from \"./const\"\nimport { EventExt } from \"./event-ext\"\nimport EventKind from \"./event-kind\"\nimport { Nip11, type RelayInfoDocument } from \"./impl/nip11\"\nimport type { NostrEvent, OkResponse, ReqCommand, ReqFilter, TaggedNostrEvent } from \"./nostr\"\n\n/**\n * Relay settings\n */\nexport interface RelaySettings {\n  read: boolean\n  write: boolean\n}\n\nexport class Connection extends EventEmitter<ConnectionTypeEvents> implements ConnectionType {\n  #log: debug.Debugger\n  #ephemeralCheck?: ReturnType<typeof setInterval>\n  #activity: number = unixNowMs()\n  #expectAuth = false\n  #ephemeral: boolean\n  #closing = false\n  #downCount = 0\n  #activeRequests = new Map<string, ReqCommand>()\n  #connectStarted = false\n  #wasUp = false\n\n  id: string\n  readonly address: string\n  Socket: WebSocket | null = null\n\n  PendingRaw: Array<object> = []\n\n  settings: RelaySettings\n  info: RelayInfoDocument | undefined\n  ConnectTimeout: number = DefaultConnectTimeout\n  HasStateChange: boolean = true\n  ReconnectTimer?: ReturnType<typeof setTimeout>\n  EventsCallback: Map<string, (msg: Array<string | boolean>) => void>\n\n  AwaitingAuth: Map<string, boolean>\n  Authed = false\n\n  constructor(addr: string, options: RelaySettings, ephemeral: boolean = false) {\n    super()\n    this.id = crypto.randomUUID()\n    this.address = addr\n    this.settings = options\n    this.EventsCallback = new Map()\n    this.AwaitingAuth = new Map()\n    this.#ephemeral = ephemeral\n    this.#log = debug(\"Connection\").extend(addr)\n  }\n\n  get ephemeral() {\n    return this.#ephemeral\n  }\n\n  set ephemeral(v: boolean) {\n    this.#ephemeral = v\n    this.#setupEphemeral()\n  }\n\n  get isOpen() {\n    return this.Socket?.readyState === WebSocket.OPEN\n  }\n\n  get isConnecting() {\n    return this.Socket?.readyState === WebSocket.CONNECTING\n  }\n\n  get isDown() {\n    return this.#downCount > 0\n  }\n\n  get ActiveRequests() {\n    return [...this.#activeRequests.keys()]\n  }\n\n  async connect(awaitOpen = false) {\n    // already connected\n    if (this.isOpen || this.isConnecting) return\n    // wait for re-connect timer\n    if (this.ReconnectTimer) return\n    // prevent race condition\n    if (this.#connectStarted) return\n    this.#connectStarted = true\n\n    try {\n      if (this.info === undefined) {\n        this.info = await Nip11.loadRelayDocument(this.address)\n      }\n    } catch {\n      // ignored\n    }\n\n    try {\n      const wasReconnect = this.Socket !== null\n      if (this.Socket) {\n        this.id = crypto.randomUUID()\n        if (this.isOpen) {\n          this.Socket.close()\n        }\n        this.Socket.onopen = null\n        this.Socket.onmessage = null\n        this.Socket.onerror = null\n        this.Socket.onclose = null\n        this.Socket = null\n      }\n      this.Socket = new WebSocket(this.address)\n      this.Socket.onopen = () => this.#onOpen(wasReconnect)\n      this.Socket.onmessage = e => this.#onMessage(e)\n      this.Socket.onerror = e => this.#onError(e)\n      this.Socket.onclose = e => this.#onClose(e)\n      if (awaitOpen) {\n        await new Promise((resolve, reject) => {\n          this.once(\"connected\", resolve)\n          this.once(\"disconnect\", reject)\n        })\n      }\n    } catch (e) {\n      this.#connectStarted = false\n      throw e\n    }\n  }\n\n  close() {\n    this.#closing = true\n    this.Socket?.close()\n  }\n\n  #onOpen(wasReconnect: boolean) {\n    this.#downCount = 0\n    this.#connectStarted = false\n    this.#wasUp = true\n    // Reset backoff so the next disconnect starts from DefaultConnectTimeout again\n    this.ConnectTimeout = DefaultConnectTimeout\n    this.#log(`Open!`)\n    this.#setupEphemeral()\n    this.emit(\"connected\", wasReconnect)\n    this.#sendPendingRaw()\n  }\n\n  #onClose(e: WebSocket.CloseEvent) {\n    // Log close event details to console for debugging\n    const closeMsg = `[${this.address}] WebSocket closed - Code: ${e.code}${e.reason ? `, Reason: ${e.reason}` : \"\"} (wasUp=${this.#wasUp}, connecting=${this.#connectStarted}, closing=${this.#closing})`\n    if (e.code !== 1000 && e.code !== 1001) {\n      // Abnormal closure codes\n      console.warn(closeMsg)\n    } else {\n      this.#log(closeMsg)\n    }\n\n    // if not explicity closed or closed after, start re-connect timer\n    if (this.#wasUp && !this.#closing) {\n      this.#downCount++\n      this.#reconnectTimer(e)\n    } else {\n      this.#downCount = 0\n      if (this.ReconnectTimer) {\n        clearTimeout(this.ReconnectTimer)\n        this.ReconnectTimer = undefined\n      }\n    }\n\n    this.emit(\"disconnect\", e.code)\n    this.#reset()\n  }\n\n  #reconnectTimer(e: WebSocket.CloseEvent) {\n    if (this.ReconnectTimer) {\n      clearTimeout(this.ReconnectTimer)\n      this.ReconnectTimer = undefined\n    }\n    this.ConnectTimeout = this.ConnectTimeout * 2\n    this.#log(\n      `Closed (code=${e.code}), trying again in ${(this.ConnectTimeout / 1000).toFixed(0).toLocaleString()} sec`,\n    )\n    this.ReconnectTimer = setTimeout(() => {\n      this.ReconnectTimer = undefined\n      try {\n        this.connect()\n      } catch {}\n    }, this.ConnectTimeout)\n  }\n\n  #onMessage(e: WebSocket.MessageEvent) {\n    this.#activity = unixNowMs()\n    if ((e.data as string).length > 0) {\n      let msg: Array<string | NostrEvent | boolean>\n      try {\n        msg = JSON.parse(e.data as string) as Array<string | NostrEvent | boolean>\n      } catch {\n        this.#log(\"Dropping malformed relay message (JSON parse error): %s\", e.data)\n        return\n      }\n      const tag = msg[0] as string\n      switch (tag) {\n        case \"AUTH\": {\n          if (this.#expectAuth) {\n            this.#onAuthAsync(msg[1] as string)\n              .then(() => this.#sendPendingRaw())\n              .catch(this.#log)\n            // todo: stats events received\n          } else {\n            this.#log(\"Ignoring unexpected AUTH request\")\n          }\n          break\n        }\n        case \"EVENT\": {\n          const ev = {\n            ...(msg[2] as NostrEvent),\n            relays: [this.address],\n          } as TaggedNostrEvent\n\n          if (!EventExt.isWellFormed(ev)) {\n            this.#log(\"Rejecting malformed event %O\", ev)\n            return\n          }\n          this.emit(\"unverifiedEvent\", msg[1] as string, ev)\n          break\n        }\n        case \"EOSE\": {\n          this.emit(\"eose\", msg[1] as string)\n          break\n        }\n        case \"OK\": {\n          // feedback to broadcast call\n          this.#log(`OK: %O`, msg)\n          const id = msg[1] as string\n          const cb = this.EventsCallback.get(id)\n          if (cb) {\n            this.EventsCallback.delete(id)\n            cb(msg as Array<string | boolean>)\n          }\n          break\n        }\n        case \"NOTICE\": {\n          this.emit(\"notice\", msg[1] as string)\n          this.#log(`NOTICE: ${msg[1]}`)\n          break\n        }\n        case \"CLOSED\": {\n          this.emit(\"closed\", msg[1] as string, msg[2] as string)\n          this.#log(`CLOSED: ${msg.slice(1)}`)\n          break\n        }\n        default: {\n          this.emit(\"unknownMessage\", msg)\n          break\n        }\n      }\n    }\n  }\n\n  #onError(e: WebSocket.ErrorEvent) {\n    // WebSocket errors in browsers typically don't contain useful information\n    // The close event will have more details (code and reason)\n    if (e.error instanceof Error) {\n      console.error(`[${this.address}] WebSocket error:`, e.error.message)\n      this.#log(\"Error with details: %O\", e.error)\n    } else {\n      console.warn(\n        `[${this.address}] WebSocket error occurred (close event will contain more details). ReadyState: ${this.Socket?.readyState}`,\n      )\n      this.#log(\"Error event: %O\", e)\n    }\n    this.emit(\"change\")\n    this.emit(\"error\")\n  }\n\n  /**\n   * Send event on this connection\n   */\n  sendEvent(e: NostrEvent) {\n    if (!this.settings.write) {\n      return\n    }\n    this.#send([\"EVENT\", e])\n    // todo: stats events send\n    this.emit(\"change\")\n  }\n\n  /**\n   * Send event on this connection and wait for OK response\n   */\n  async publish(e: NostrEvent, timeout = 5000) {\n    return await new Promise<OkResponse>((resolve, reject) => {\n      if (!this.settings.write) {\n        reject(new Error(\"Not a write relay\"))\n        return\n      }\n\n      if (this.EventsCallback.has(e.id)) {\n        resolve({\n          ok: false,\n          id: e.id,\n          relay: this.address,\n          message: \"Duplicate request\",\n          event: e,\n        })\n        return\n      }\n      const t = setTimeout(() => {\n        this.EventsCallback.delete(e.id)\n        resolve({\n          ok: false,\n          id: e.id,\n          relay: this.address,\n          message: \"Timeout waiting for OK response\",\n          event: e,\n        })\n      }, timeout)\n\n      this.EventsCallback.set(e.id, msg => {\n        clearTimeout(t)\n        const [_, id, accepted, message] = msg\n        resolve({\n          ok: accepted as boolean,\n          id: id as string,\n          relay: this.address,\n          message: message as string | undefined,\n          event: e,\n        })\n      })\n\n      this.#send([\"EVENT\", e])\n      // todo: stats events send\n      this.emit(\"change\")\n    })\n  }\n\n  /**\n   * Using relay document to determine if this relay supports a feature\n   */\n  supportsNip(n: number) {\n    return this.info?.supported_nips?.some(a => a === n) ?? false\n  }\n\n  /**\n   * Send command to the relay\n   * @param cmd The REQ to send to the server\n   * @param cbSent Callback when sent to relay\n   */\n  request(cmd: ReqCommand, cbSent?: () => void): void {\n    const filters = cmd.slice(2) as Array<ReqFilter>\n    const requestKinds = new Set(filters.flatMap(a => a.kinds ?? []))\n    const ExpectAuth = [EventKind.DirectMessage, EventKind.GiftWrap, 7000 as EventKind]\n    if (ExpectAuth.some(a => requestKinds.has(a)) && !this.#expectAuth) {\n      this.#expectAuth = true\n      this.#log(\"Setting expectAuth flag %o\", requestKinds)\n    }\n\n    this.#sendRequestCommand(cmd)\n    cbSent?.()\n    this.emit(\"change\")\n  }\n\n  closeRequest(id: string) {\n    if (this.#activeRequests.has(id)) {\n      this.#activeRequests.delete(id)\n      this.#send([\"CLOSE\", id])\n      this.emit(\"eose\", id)\n      this.emit(\"change\")\n    }\n  }\n\n  get activeSubscriptions() {\n    return this.#activeRequests.size\n  }\n\n  get maxSubscriptions() {\n    return this.info?.limitation?.max_subscriptions ?? 20\n  }\n\n  #sendRequestCommand(cmd: ReqCommand) {\n    try {\n      this.#activeRequests.set(cmd[1], cmd)\n      this.#send(cmd)\n    } catch (e) {\n      console.error(e)\n    }\n  }\n\n  #reset() {\n    // reset connection Id on disconnect, for query-tracking\n    this.id = crypto.randomUUID()\n    this.#expectAuth = false\n    this.#log(\"Reset active=%O, raw=%O\", [...this.#activeRequests.keys()], [...this.PendingRaw])\n    for (const [id] of this.#activeRequests) {\n      this.emit(\"closed\", id, \"connection closed\")\n    }\n    for (const raw of this.PendingRaw) {\n      if (Array.isArray(raw) && raw[0] === \"REQ\") {\n        this.emit(\"closed\", raw[1], \"connection closed\")\n      }\n    }\n    this.#activeRequests.clear()\n    this.PendingRaw = []\n\n    this.emit(\"change\")\n  }\n\n  /**\n   * Send raw json object on wire\n   */\n  sendRaw(obj: object) {\n    this.#send(obj)\n  }\n\n  #send(obj: object) {\n    const authPending = !this.Authed && (this.AwaitingAuth.size > 0 || this.info?.limitation?.auth_required === true)\n    if (!this.isOpen || authPending) {\n      this.PendingRaw.push(obj)\n      return false\n    }\n\n    this.#sendPendingRaw()\n    this.#sendOnWire(obj)\n  }\n\n  #sendPendingRaw() {\n    while (this.PendingRaw.length > 0) {\n      const next = this.PendingRaw.shift()\n      if (next) {\n        this.#sendOnWire(next)\n      }\n    }\n  }\n\n  #sendOnWire(obj: unknown) {\n    if (this.Socket?.readyState !== WebSocket.OPEN) {\n      throw new Error(`Socket is not open, state is ${this.Socket?.readyState}`)\n    }\n    const json = JSON.stringify(obj)\n    this.#activity = unixNowMs()\n    this.Socket.send(json)\n    return true\n  }\n\n  async #onAuthAsync(challenge: string): Promise<void> {\n    const authCleanup = () => {\n      this.AwaitingAuth.delete(challenge)\n    }\n    this.AwaitingAuth.set(challenge, true)\n    const authEvent = await new Promise<NostrEvent>((resolve, reject) => {\n      const t = setTimeout(() => {\n        authCleanup()\n        reject(new Error(\"AUTH handler timed out — no auth event provided\"))\n      }, AuthTimeout)\n      this.emit(\"auth\", challenge, this.address, (ev: NostrEvent) => {\n        clearTimeout(t)\n        resolve(ev)\n      })\n    })\n    this.#log(\"Auth result: %o\", authEvent)\n    if (!authEvent) {\n      authCleanup()\n      throw new Error(\"No auth event\")\n    }\n\n    return await new Promise(resolve => {\n      const t = setTimeout(() => {\n        authCleanup()\n        resolve()\n      }, AuthTimeout)\n\n      this.EventsCallback.set(authEvent.id, msg => {\n        clearTimeout(t)\n        authCleanup()\n        if (msg.length > 3 && msg[2] === true) {\n          this.Authed = true\n          // Resend all active requests after successful auth\n          this.#log(\"Auth successful, resending %d active requests\", this.#activeRequests.size)\n          for (const [, cmd] of this.#activeRequests) {\n            this.#sendOnWire(cmd)\n          }\n        }\n        resolve()\n      })\n\n      this.#sendOnWire([\"AUTH\", authEvent])\n    })\n  }\n\n  #setupEphemeral() {\n    if (this.#ephemeralCheck) {\n      clearInterval(this.#ephemeralCheck)\n      this.#ephemeralCheck = undefined\n    }\n    if (this.ephemeral) {\n      this.#ephemeralCheck = setInterval(() => {\n        const lastActivity = unixNowMs() - this.#activity\n        if (lastActivity > 10_000 && !this.#closing) {\n          if (this.#activeRequests.size > 0) {\n            this.#log(\"Inactive connection has %d active requests! %O\", this.#activeRequests.size, this.#activeRequests)\n          } else {\n            this.close()\n          }\n        }\n      }, 5_000)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/const.ts",
    "content": "/**\n * Websocket re-connect timeout\n */\nexport const DefaultConnectTimeout = 2000\n\n/**\n * Hashtag regex\n */\n// eslint-disable-next-line no-useless-escape\nexport const HashtagRegex = /(#[^\\s!@#$%^&*()=+./,[{\\]};:'\"?><]+)/g\n\n/**\n * Legacy tag reference regex\n */\nexport const TagRefRegex = /(#\\[\\d+\\])/gm\n\n/**\n * How long profile cache should be considered valid for\n */\nexport const ProfileCacheExpire = 1_000 * 60 * 60 * 6\n\n/**\n * How long before relay lists should be refreshed\n */\nexport const RelayListCacheExpire = 1_000 * 60 * 60 * 12\n\n/**\n * Extract file extensions regex\n */\n// eslint-disable-next-line no-useless-escape\nexport const FileExtensionRegex = /\\.([\\w]{1,7})$/i\n\n/**\n * Simple lightning invoice regex\n */\nexport const InvoiceRegex = /(lnbc\\w+)/gi\n\n/*\n * Regex to match any base64 string\n */\nexport const CashuRegex = /(cashuA[A-Za-z0-9_-]{0,10000}={0,3})/gi\n\n/**\n * Regex to match any npub/nevent/naddr/nprofile/note\n */\nexport const MentionNostrEntityRegex = /@n(pub|profile|event|ote|addr|)1[acdefghjklmnpqrstuvwxyz023456789]+/g\n\n/**\n * Regex to match markdown code content (triple backticks)\n */\nexport const MarkdownCodeRegex = /(```.*?```)/gms\n\n/**\n * Regex to match inline code content (single backticks)\n */\nexport const InlineCodeRegex = /(`[^`\\n]+?`)/g\n\n/**\n * Public metadata relays\n */\nexport const MetadataRelays = [\"wss://purplepag.es/\", \"wss://relay.nostr.band/\", \"wss://relay.snort.social/\"]\n\n/**\n * Default public relays used when user has no configured relays\n */\nexport const DefaultRelays = [\n  \"wss://relay.damus.io\",\n  \"wss://nos.lol\",\n  \"wss://relay.nostr.band\",\n  \"wss://relay.snort.social\",\n  \"wss://nostr.wine\",\n]\n\n/**\n * Timeout for relay AUTH challenge response (ms)\n */\nexport const AuthTimeout = 10_000\n\n/**\n * Timeout for NIP-46 remote signer RPC response (ms)\n */\nexport const Nip46RpcTimeout = 30_000\n\n/**\n * Timeout for query EOSE in QueryManager.fetch() (ms)\n */\nexport const QueryFetchTimeout = 30_000\n\n/**\n * Timeout for NIP-55 clipboard-based signer response (ms)\n */\nexport const Nip55SignerTimeout = 120_000\n"
  },
  {
    "path": "packages/system/src/encryption/index.ts",
    "content": "export enum MessageEncryptorVersion {\n  Nip4 = 0,\n  Nip44 = 1,\n}\n\nexport interface MessageEncryptor {\n  encryptData(plaintext: string): Promise<string> | string\n  decryptData(ciphertext: string): Promise<string> | string\n}\n"
  },
  {
    "path": "packages/system/src/encryption/nip44.ts",
    "content": "import { chacha20 } from \"@noble/ciphers/chacha.js\"\nimport { equalBytes } from \"@noble/ciphers/utils.js\"\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\"\nimport { extract as hkdf_extract, expand as hkdf_expand } from \"@noble/hashes/hkdf.js\"\nimport { hmac } from \"@noble/hashes/hmac.js\"\nimport { sha256 } from \"@noble/hashes/sha2.js\"\nimport { concatBytes, hexToBytes, randomBytes, utf8ToBytes } from \"@noble/hashes/utils.js\"\nimport { base64 } from \"@scure/base\"\n\ndeclare const TextDecoder: any\n\nconst decoder = new TextDecoder()\nconst u = {\n  minPlaintextSize: 0x0001, // 1b msg => padded to 32b\n  maxPlaintextSize: 0xffff, // 65535 (64kb-1) => padded to 64kb\n\n  utf8Encode: utf8ToBytes,\n  utf8Decode(bytes: Uint8Array) {\n    return decoder.decode(bytes)\n  },\n\n  getConversationKey(privkeyA: string, pubkeyB: string): Uint8Array {\n    const sharedX = secp256k1.getSharedSecret(hexToBytes(privkeyA), hexToBytes(\"02\" + pubkeyB)).subarray(1, 33)\n    return hkdf_extract(sha256, sharedX, utf8ToBytes(\"nip44-v2\"))\n  },\n\n  getMessageKeys(conversationKey: Uint8Array, nonce: Uint8Array) {\n    const keys = hkdf_expand(sha256, conversationKey, nonce, 76)\n    return {\n      chacha_key: keys.subarray(0, 32),\n      chacha_nonce: keys.subarray(32, 44),\n      hmac_key: keys.subarray(44, 76),\n    }\n  },\n\n  calcPaddedLen(len: number): number {\n    if (!Number.isSafeInteger(len) || len < 1) throw new Error(\"expected positive integer\")\n    if (len <= 32) return 32\n    const nextPower = 1 << (Math.floor(Math.log2(len - 1)) + 1)\n    const chunk = nextPower <= 256 ? 32 : nextPower / 8\n    return chunk * (Math.floor((len - 1) / chunk) + 1)\n  },\n\n  writeU16BE(num: number) {\n    if (!Number.isSafeInteger(num) || num < u.minPlaintextSize || num > u.maxPlaintextSize)\n      throw new Error(\"invalid plaintext size: must be between 1 and 65535 bytes\")\n    const arr = new Uint8Array(2)\n    new DataView(arr.buffer).setUint16(0, num, false)\n    return arr\n  },\n\n  pad(plaintext: string): Uint8Array {\n    const unpadded = u.utf8Encode(plaintext)\n    const unpaddedLen = unpadded.length\n    const prefix = u.writeU16BE(unpaddedLen)\n    const suffix = new Uint8Array(u.calcPaddedLen(unpaddedLen) - unpaddedLen)\n    return concatBytes(prefix, unpadded, suffix)\n  },\n\n  unpad(padded: Uint8Array): string {\n    const unpaddedLen = new DataView(padded.buffer).getUint16(0)\n    const unpadded = padded.subarray(2, 2 + unpaddedLen)\n    if (\n      unpaddedLen < u.minPlaintextSize ||\n      unpaddedLen > u.maxPlaintextSize ||\n      unpadded.length !== unpaddedLen ||\n      padded.length !== 2 + u.calcPaddedLen(unpaddedLen)\n    )\n      throw new Error(\"invalid padding\")\n    return u.utf8Decode(unpadded)\n  },\n\n  hmacAad(key: Uint8Array, message: Uint8Array, aad: Uint8Array) {\n    if (aad.length !== 32) throw new Error(\"AAD associated data must be 32 bytes\")\n    const combined = concatBytes(aad, message)\n    return hmac(sha256, key, combined)\n  },\n\n  // metadata: always 65b (version: 1b, nonce: 32b, max: 32b)\n  // plaintext: 1b to 0xffff\n  // padded plaintext: 32b to 0xffff\n  // ciphertext: 32b+2 to 0xffff+2\n  // raw payload: 99 (65+32+2) to 65603 (65+0xffff+2)\n  // compressed payload (base64): 132b to 87472b\n  decodePayload(payload: string) {\n    if (typeof payload !== \"string\") throw new Error(\"payload must be a valid string\")\n    const plen = payload.length\n    if (plen < 132 || plen > 87472) throw new Error(\"invalid payload length: \" + plen)\n    if (payload[0] === \"#\") throw new Error(\"unknown encryption version\")\n    if (payload.startsWith(\"{\") && payload.endsWith(\"}\")) {\n      throw new Error(\"invalid base64: JSON string in content\")\n    }\n    let data: Uint8Array\n    try {\n      data = base64.decode(payload)\n    } catch (error) {\n      throw new Error(\"invalid base64: \" + (error as any).message)\n    }\n    const dlen = data.length\n    if (dlen < 99 || dlen > 65603) throw new Error(\"invalid data length: \" + dlen)\n    const vers = data[0]\n    return {\n      version: vers,\n      nonce: data.subarray(1, 33),\n      ciphertext: data.subarray(33, vers === 2 ? -32 : undefined),\n      mac: vers === 2 ? data.subarray(-32) : undefined,\n    }\n  },\n}\n\nfunction encrypt_v2(plaintext: string, conversationKey: Uint8Array, nonce = randomBytes(32)) {\n  const { chacha_key, chacha_nonce, hmac_key } = u.getMessageKeys(conversationKey, nonce)\n  const padded = u.pad(plaintext)\n  const ciphertext = chacha20(chacha_key, chacha_nonce, padded)\n  const mac = u.hmacAad(hmac_key, ciphertext, nonce)\n  return base64.encode(concatBytes(new Uint8Array([2]), nonce, ciphertext, mac))\n}\n\nfunction decrypt_v2(ciphertext: Uint8Array, nonce: Uint8Array, mac: Uint8Array, conversationKey: Uint8Array) {\n  const { chacha_key, chacha_nonce, hmac_key } = u.getMessageKeys(conversationKey, nonce)\n  const calculatedMac = u.hmacAad(hmac_key, ciphertext, nonce)\n  if (!equalBytes(calculatedMac, mac!)) throw new Error(\"invalid MAC\")\n  const padded = chacha20(chacha_key, chacha_nonce, ciphertext)\n  return u.unpad(padded)\n}\n\nfunction decrypt_v1(ciphertext: Uint8Array, nonce: Uint8Array, conversationKey: Uint8Array) {\n  const padded = chacha20(conversationKey, nonce, ciphertext)\n  return u.unpad(padded)\n}\nexport const nip44 = {\n  utils: u,\n  v1: {\n    getConversationKey: (privKey: string, pubKey: string) => {\n      const key = secp256k1.getSharedSecret(hexToBytes(privKey), hexToBytes(\"02\" + pubKey))\n      return sha256(key.slice(1, 33))\n    },\n    decrypt: decrypt_v1,\n  },\n  v2: {\n    getConversationKey: u.getConversationKey,\n    encrypt: encrypt_v2,\n    decrypt: decrypt_v2,\n  },\n}\n"
  },
  {
    "path": "packages/system/src/encryption/pin-encrypted.ts",
    "content": "import { xchacha20 } from \"@noble/ciphers/chacha.js\"\nimport { equalBytes } from \"@noble/ciphers/utils.js\"\nimport { hkdf } from \"@noble/hashes/hkdf.js\"\nimport { hmac } from \"@noble/hashes/hmac.js\"\nimport { scryptAsync } from \"@noble/hashes/scrypt.js\"\nimport { sha256 } from \"@noble/hashes/sha2.js\"\nimport { bytesToHex, hexToBytes, randomBytes, utf8ToBytes } from \"@noble/hashes/utils.js\"\nimport { base64 } from \"@scure/base\"\n\nexport class InvalidPinError extends Error {\n  constructor() {\n    super()\n  }\n}\n\nexport abstract class KeyStorage {\n  // Raw value\n  abstract get value(): string\n\n  /**\n   * Is the storage locked\n   */\n  abstract shouldUnlock(): boolean\n\n  abstract unlock(code: string): Promise<void>\n\n  /**\n   * Get a payload object which can be serialized to JSON\n   */\n  abstract toPayload(): Object\n\n  /**\n   * Create a key storage class from its payload\n   */\n  static fromPayload(o: object) {\n    if (\"raw\" in o && typeof o.raw === \"string\") {\n      return new NotEncrypted(o.raw)\n    } else {\n      return new PinEncrypted(o as unknown as PinEncryptedPayload)\n    }\n  }\n}\n\n/**\n * Pin protected data\n *\n * Encryption scheme (encrypt-then-MAC with key separation):\n *   masterKey  = scrypt(pin, salt)\n *   encKey     = HKDF(masterKey, salt, info=\"pin-enc\")   — 32 bytes\n *   macKey     = HKDF(masterKey, salt, info=\"pin-mac\")   — 32 bytes\n *   ciphertext = XChaCha20(encKey, nonce, plaintext)\n *   mac        = HMAC-SHA256(macKey, nonce || ciphertext) — verified before decryption\n */\nexport class PinEncrypted extends KeyStorage {\n  static readonly #opts = { N: 2 ** 20, r: 8, p: 1, dkLen: 32 }\n  #decrypted?: Uint8Array\n  #encrypted: PinEncryptedPayload\n\n  constructor(enc: PinEncryptedPayload) {\n    super()\n    this.#encrypted = enc\n  }\n\n  get value() {\n    if (!this.#decrypted) throw new Error(\"Content has not been decrypted yet\")\n    return bytesToHex(this.#decrypted)\n  }\n\n  override shouldUnlock(): boolean {\n    return !this.#decrypted\n  }\n\n  override async unlock(pin: string) {\n    // Only the v2 (encrypt-then-MAC with key separation) format is supported.\n    // Legacy v1 payloads (no `v` field) used MAC-then-encrypt with a shared key\n    // and cannot be decrypted securely — they must be re-encrypted by the user.\n    if (this.#encrypted.v !== 2) throw new InvalidPinError()\n\n    let salt: Uint8Array, ciphertext: Uint8Array, nonce: Uint8Array, actualMac: Uint8Array\n    try {\n      salt = base64.decode(this.#encrypted.salt)\n      ciphertext = base64.decode(this.#encrypted.ciphertext)\n      nonce = base64.decode(this.#encrypted.iv)\n      actualMac = base64.decode(this.#encrypted.mac)\n    } catch {\n      throw new InvalidPinError()\n    }\n\n    // Validate expected field lengths before any cryptographic operation\n    if (salt.length !== 24 || nonce.length !== 24 || actualMac.length !== 32) throw new InvalidPinError()\n\n    const masterKey = await scryptAsync(pin, salt, PinEncrypted.#opts)\n    const encKey = hkdf(sha256, masterKey, salt, utf8ToBytes(\"pin-enc\"), 32)\n    const macKey = hkdf(sha256, masterKey, salt, utf8ToBytes(\"pin-mac\"), 32)\n\n    // Verify MAC over (nonce || ciphertext) before decryption — encrypt-then-MAC\n    const macData = new Uint8Array(nonce.length + ciphertext.length)\n    macData.set(nonce, 0)\n    macData.set(ciphertext, nonce.length)\n    const expectedMac = hmac(sha256, macKey, macData)\n    if (!equalBytes(expectedMac, actualMac)) throw new InvalidPinError()\n\n    let plaintext: Uint8Array\n    try {\n      plaintext = xchacha20(encKey, nonce, ciphertext)\n    } catch {\n      throw new InvalidPinError()\n    }\n    if (plaintext.length !== 32) throw new InvalidPinError()\n    this.#decrypted = plaintext\n  }\n\n  toPayload() {\n    return this.#encrypted\n  }\n\n  static async create(content: string, pin: string) {\n    const plaintext = hexToBytes(content)\n    if (plaintext.length !== 32) {\n      throw new Error(\"PinEncrypted content must be exactly 32 bytes (64 hex characters)\")\n    }\n    const salt = randomBytes(24)\n    const nonce = randomBytes(24)\n    const masterKey = await scryptAsync(pin, salt, PinEncrypted.#opts)\n    const encKey = hkdf(sha256, masterKey, salt, utf8ToBytes(\"pin-enc\"), 32)\n    const macKey = hkdf(sha256, masterKey, salt, utf8ToBytes(\"pin-mac\"), 32)\n\n    // Encrypt first, then MAC over (nonce || ciphertext) — encrypt-then-MAC\n    const ciphertext = xchacha20(encKey, nonce, plaintext)\n    const macData = new Uint8Array(nonce.length + ciphertext.length)\n    macData.set(nonce, 0)\n    macData.set(ciphertext, nonce.length)\n    const mac = base64.encode(hmac(sha256, macKey, macData))\n\n    const ret = new PinEncrypted({\n      v: 2,\n      salt: base64.encode(salt),\n      ciphertext: base64.encode(ciphertext),\n      iv: base64.encode(nonce),\n      mac,\n    })\n    ret.#decrypted = plaintext\n    return ret\n  }\n}\n\nexport class NotEncrypted extends KeyStorage {\n  #key: string\n\n  constructor(key: string) {\n    super()\n    this.#key = key\n  }\n\n  get value() {\n    return this.#key\n  }\n\n  override shouldUnlock(): boolean {\n    return false\n  }\n\n  override unlock(code: string): Promise<void> {\n    throw new Error(\"Method not implemented.\")\n  }\n\n  override toPayload(): Object {\n    return {\n      raw: this.#key,\n    }\n  }\n}\n\nexport interface PinEncryptedPayload {\n  /** Format version. v2 = encrypt-then-MAC with HKDF key separation. Absence = legacy v1. */\n  v?: number\n  salt: string // for KDF\n  ciphertext: string\n  iv: string\n  mac: string\n}\n"
  },
  {
    "path": "packages/system/src/event-builder.ts",
    "content": "import type { EventKind, NostrEvent, EventSigner, PowMiner } from \".\"\nimport { HashtagRegex, MentionNostrEntityRegex } from \"./const\"\nimport { getPublicKey, jitter, NostrPrefix, unixNow } from \"@snort/shared\"\nimport { EventExt } from \"./event-ext\"\nimport { type NostrLink, tryParseNostrLink } from \"./nostr-link\"\n\nexport class EventBuilder {\n  /**\n   * Client tag to attach to all events\n   */\n  static ClientTag: Array<string> | undefined = [\"client\", \"snort_system\"]\n\n  #kind?: EventKind\n  #content?: string\n  #createdAt?: number\n  #pubkey?: string\n  #tags: Array<Array<string>> = []\n  #pow?: number\n  #powMiner?: PowMiner\n  #jitter?: number\n\n  get pubkey() {\n    return this.#pubkey\n  }\n\n  /**\n   * Populate builder with values from link\n   */\n  fromLink(link: NostrLink) {\n    if (link.kind) {\n      this.#kind = link.kind\n    }\n    if (link.author) {\n      this.#pubkey = link.author\n    }\n    if (link.type === NostrPrefix.Address && link.id) {\n      this.tag([\"d\", link.id])\n    }\n  }\n\n  jitter(n: number) {\n    this.#jitter = n\n    return this\n  }\n\n  kind(k: EventKind) {\n    this.#kind = k\n    return this\n  }\n\n  content(c: string) {\n    this.#content = c\n    return this\n  }\n\n  createdAt(n: number) {\n    this.#createdAt = n\n    return this\n  }\n\n  pubKey(k: string) {\n    this.#pubkey = k\n    return this\n  }\n\n  tag(t: Array<string>): EventBuilder {\n    const duplicate = this.#tags.some(a => a.length === t.length && a.every((b, i) => b !== a[i]))\n    if (duplicate) return this\n    this.#tags.push(t)\n    return this\n  }\n\n  pow(target: number, miner?: PowMiner) {\n    this.#pow = target\n    this.#powMiner = miner ?? {\n      minePow: (ev, target) => {\n        EventExt.minePow(ev, target)\n        return Promise.resolve(ev)\n      },\n    }\n    return this\n  }\n\n  /**\n   * Extract mentions\n   */\n  processContent() {\n    if (this.#content) {\n      this.#content = this.#content.replace(MentionNostrEntityRegex, m => this.#replaceMention(m))\n\n      const hashTags = [...this.#content.matchAll(HashtagRegex)]\n      hashTags.map(hashTag => {\n        this.#addHashtag(hashTag[0])\n      })\n    }\n    return this\n  }\n\n  build() {\n    this.#validate()\n    const ev = {\n      id: \"\",\n      pubkey: this.#pubkey ?? \"\",\n      content: this.#content ?? \"\",\n      kind: this.#kind,\n      created_at: (this.#createdAt ?? unixNow()) - (this.#jitter ? Math.floor(jitter(this.#jitter)) : 0),\n      tags: this.#tags.sort((a, b) => a[0].localeCompare(b[0])),\n    } as NostrEvent\n    if (EventBuilder.ClientTag && EventBuilder.ClientTag[0] === \"client\" && EventBuilder.ClientTag.length > 1) {\n      ev.tags.push(EventBuilder.ClientTag)\n    }\n    ev.id = EventExt.createId(ev)\n    return ev\n  }\n\n  /**\n   * Build and sign event\n   * @param pk Private key to sign event with\n   */\n  async buildAndSign(pk: string | EventSigner) {\n    if (typeof pk === \"string\") {\n      const ev = this.pubKey(getPublicKey(pk)).build()\n      return EventExt.sign(await this.#mine(ev), pk)\n    } else {\n      const ev = this.pubKey(await pk.getPubKey()).build()\n      return await pk.sign(await this.#mine(ev))\n    }\n  }\n\n  async #mine(ev: NostrEvent) {\n    if (this.#pow && this.#powMiner) {\n      const ret = await this.#powMiner.minePow(ev, this.#pow)\n      return ret\n    }\n    return ev\n  }\n\n  #validate() {\n    if (this.#kind === undefined) {\n      throw new Error(\"Kind must be set\")\n    }\n    if (this.#pubkey === undefined) {\n      throw new Error(\"Pubkey must be set\")\n    }\n  }\n\n  #replaceMention(match: string) {\n    const npub = match.slice(1)\n    const link = tryParseNostrLink(npub)\n    if (link) {\n      if (link.type === NostrPrefix.Profile || link.type === NostrPrefix.PublicKey) {\n        this.tag([\"p\", link.id])\n      }\n      return `nostr:${link.encode()}`\n    } else {\n      return match\n    }\n  }\n\n  #addHashtag(match: string) {\n    const tag = match.slice(1)\n    this.tag([\"t\", tag.toLowerCase()])\n  }\n}\n"
  },
  {
    "path": "packages/system/src/event-ext.ts",
    "content": "import { schnorr } from \"@noble/curves/secp256k1.js\"\nimport { bytesToHex, hexToBytes } from \"@noble/hashes/utils.js\"\nimport { getPublicKey, sha256, unixNow, unwrap } from \"@snort/shared\"\nimport { LRUCache } from \"typescript-lru-cache\"\nimport { EventKind, Nip10, Nip22, type NostrEvent, type NostrLink, type NotSignedNostrEvent, parseZap } from \".\"\nimport { minePow } from \"./pow-util\"\nimport { findTag } from \"./utils\"\n\n/**\n * Generic thread structure extracted from a note\n */\nexport interface Thread {\n  kind: \"nip10\" | \"nip22\"\n  root?: NostrLink\n  replyTo?: NostrLink\n  mentions: Array<NostrLink>\n  pubKeys: Array<NostrLink>\n}\n\nexport enum EventType {\n  Regular,\n  Replaceable,\n  Addressable,\n}\n\n/*\n * Internal cache of parsed threads\n */\nconst ThreadCache = new LRUCache<string, Thread | undefined>({\n  maxSize: 1000,\n})\n\n/**\n * Set of event IDs whose Schnorr signature has already been verified successfully.\n * ID-based (not object-based) so re-arrivals of the same event from different\n * relays are also skipped. Capped to avoid unbounded growth.\n */\nconst MAX_VERIFIED_CACHE = 50_000\nconst VerifiedEventIds = new Set<string>()\n\n/**\n * Helper class for parsing event data\n */\nexport abstract class EventExt {\n  /**\n   * Get the pub key of the creator of this event.\n   *\n   * NIP-26 delegation tags are intentionally ignored: accepting an unverified\n   * delegation tag would allow any event to claim authorship by any pubkey.\n   * Full NIP-26 support requires verifying the delegation token signature\n   * before trusting the delegator pubkey.\n   */\n  static getRootPubKey(e: NostrEvent): string {\n    if (e.kind === EventKind.ZapReceipt) {\n      const bigP = findTag(e, \"P\")\n      if (bigP) {\n        return bigP\n      }\n      const parsedZap = parseZap(e)\n      if (parsedZap?.sender) {\n        return parsedZap.sender\n      }\n    }\n    return e.pubkey\n  }\n\n  /**\n   * Sign this message with a private key\n   */\n  static sign(e: NostrEvent, key: string) {\n    e.pubkey = getPublicKey(key)\n    e.id = EventExt.createId(e)\n\n    const sig = schnorr.sign(hexToBytes(e.id), hexToBytes(key))\n    e.sig = bytesToHex(sig)\n    return e\n  }\n\n  /**\n   * Check the signature of this event.\n   * - Validates that `sig` and `pubkey` are correctly-formatted hex strings.\n   * - Validates that `id` matches the canonical hash of the event payload.\n   * - Verifies the Schnorr signature.\n   * Never throws; returns `false` for any malformed or untrusted input.\n   * @returns True only if the event is cryptographically authentic.\n   */\n  static verify(e: NostrEvent) {\n    // Schnorr sig = 64 bytes = 128 hex chars; pubkey = 32 bytes = 64 hex chars\n    if (!e.sig || e.sig.length !== 128 || !/^[0-9a-f]+$/i.test(e.sig)) return false\n    if (!e.pubkey || e.pubkey.length !== 64 || !/^[0-9a-f]+$/i.test(e.pubkey)) return false\n\n    // Always recompute the ID from the payload — if it doesn't match e.id, the\n    // event is malformed/tampered regardless of what's in the verified cache.\n    const id = EventExt.createId(e)\n    if (e.id !== id) return false\n\n    // Fast path: this exact payload hash has already passed Schnorr verification.\n    // Safe because we just confirmed e.id === sha256(canonical payload), so a\n    // forged event with a stolen ID would have failed the hash check above first.\n    if (VerifiedEventIds.has(id)) return true\n\n    try {\n      const ok = schnorr.verify(hexToBytes(e.sig), hexToBytes(id), hexToBytes(e.pubkey))\n      if (ok) EventExt.markVerified(e)\n      return ok\n    } catch {\n      return false\n    }\n  }\n\n  /**\n   * Returns true if this event ID has already been verified in the current session.\n   */\n  static isVerified(e: NostrEvent) {\n    return VerifiedEventIds.has(e.id)\n  }\n\n  /**\n   * Mark an event as verified. Call this after an external verifier (e.g. WASM)\n   * has confirmed the signature so that subsequent verify() calls are skipped\n   * for any object carrying the same event ID.\n   */\n  static markVerified(e: NostrEvent) {\n    if (VerifiedEventIds.size >= MAX_VERIFIED_CACHE) {\n      VerifiedEventIds.clear()\n    }\n    VerifiedEventIds.add(e.id)\n  }\n\n  static createId(e: NostrEvent | NotSignedNostrEvent) {\n    const payload = [0, e.pubkey, e.created_at, e.kind, e.tags, e.content]\n    return sha256(JSON.stringify(payload))\n  }\n\n  /**\n   * Mine POW for an event (NIP-13)\n   */\n  static minePow(e: NostrEvent, target: number) {\n    return minePow(e, target)\n  }\n\n  /**\n   * Create a new event for a specific pubkey\n   */\n  static forPubKey(pk: string, kind: EventKind) {\n    return {\n      pubkey: pk,\n      kind: kind,\n      created_at: unixNow(),\n      content: \"\",\n      tags: [],\n      id: \"\",\n      sig: \"\",\n    } as NostrEvent\n  }\n\n  static extractThread(ev: NostrEvent): Thread | undefined {\n    const cacheKey = EventExt.keyOf(ev)\n    const cached = ThreadCache.get(cacheKey)\n    if (cached) return cached\n\n    // parse thread as NIP-22 if there is E+K\n    if (ev.tags.some(a => a[0] === \"E\") && ev.tags.some(a => a[0] === \"K\")) {\n      const v = Nip22.parseThread(ev)\n      ThreadCache.set(cacheKey, v)\n      return v\n    } else {\n      const v = Nip10.parseThread(ev)\n      ThreadCache.set(cacheKey, v)\n      return v\n    }\n  }\n\n  /**\n   * Assign props if undefined\n   */\n  static fixupEvent(e: NostrEvent) {\n    e.tags ??= []\n    e.created_at ??= 0\n    e.content ??= \"\"\n    e.id ??= \"\"\n    e.kind ??= 0\n    e.pubkey ??= \"\"\n    e.sig ??= \"\"\n  }\n\n  static getType(kind: number) {\n    const legacyReplaceable = [0, 3, 41]\n    if (kind >= 30_000 && kind < 40_000) {\n      return EventType.Addressable\n    } else if (kind >= 10_000 && kind < 20_000) {\n      return EventType.Replaceable\n    } else if (legacyReplaceable.includes(kind)) {\n      return EventType.Replaceable\n    } else {\n      return EventType.Regular\n    }\n  }\n\n  static isReplaceable(kind: number) {\n    const t = EventExt.getType(kind)\n    return t === EventType.Replaceable || t === EventType.Addressable\n  }\n\n  static isAddressable(kind: number) {\n    const t = EventExt.getType(kind)\n    return t === EventType.Addressable\n  }\n\n  /**\n   * Check that an event is structurally well-formed WITHOUT verifying the\n   * Schnorr signature. Specifically: `sig` must be present, `tags` must be\n   * an array, and addressable events must have a `\"d\"` tag.\n   * Never throws; returns `false` for any malformed input.\n   * Use `isValid` when cryptographic authenticity is required.\n   */\n  static isWellFormed(ev: NostrEvent) {\n    if (ev.sig === undefined) return false\n    if (!Array.isArray(ev.tags)) return false\n    const type = EventExt.getType(ev.kind)\n    if (type === EventType.Addressable) {\n      if (!findTag(ev, \"d\")) return false\n    }\n    return true\n  }\n\n  /**\n   * Check that an event is structurally well-formed AND has a valid Schnorr\n   * signature. Use this wherever event authenticity matters (relay message\n   * handlers, NIP-46, etc.).\n   */\n  static isValid(ev: NostrEvent) {\n    return EventExt.isWellFormed(ev) && EventExt.verify(ev)\n  }\n\n  /**\n   * Create a string key for an event\n   *\n   * Addressable: {kind}:{pubkey}:{identifier}\n   *\n   * Replaceable: {kind}:{pubkey}\n   *\n   * {id}\n   */\n  static keyOf(e: NostrEvent) {\n    switch (EventExt.getType(e.kind)) {\n      case EventType.Addressable:\n        return `${e.kind}:${e.pubkey}:${unwrap(findTag(e, \"d\"))}`\n      case EventType.Replaceable:\n        return `${e.kind}:${e.pubkey}`\n      default:\n        return e.id\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/event-kind.ts",
    "content": "enum EventKind {\n  Unknown = -1,\n  SetMetadata = 0,\n  TextNote = 1,\n  RecommendServer = 2,\n  ContactList = 3, // NIP-02\n  DirectMessage = 4, // NIP-04\n  Deletion = 5, // NIP-09\n  Repost = 6, // NIP-18\n  Reaction = 7, // NIP-25\n  BadgeAward = 8, // NIP-58\n  SimpleChatMessage = 9, // NIP-29\n  SealedRumor = 13, // NIP-59\n  ChatRumor = 14, // NIP-24\n  Photo = 20, // NIP-68\n  Video = 21, // NIP-71\n  ShortVideo = 22, // NIP-71\n  PublicChatChannel = 40, // NIP-28\n  PublicChatMetadata = 41, // NIP-28\n  PublicChatMessage = 42, // NIP-28\n  PublicChatMuteMessage = 43, // NIP-28\n  PublicChatMuteUser = 44, // NIP-28\n  SnortSubscriptions = 1000, // NIP-XX\n  Comment = 1111, // NIP-22\n  Polls = 6969, // NIP-69\n  GiftWrap = 1059, // NIP-59\n  FileHeader = 1063, // NIP-94\n  Relays = 10002, // NIP-65\n  Ephemeral = 20_000,\n  Auth = 22242, // NIP-42\n\n  MuteList = 10_000, // NIP-51\n  PinList = 10_001, // NIP-51\n  BookmarksList = 10_003, // NIP-51\n  CommunitiesList = 10_004, // NIP-51\n  PublicChatsList = 10_005, // NIP-51\n  BlockedRelaysList = 10_006, // NIP-51\n  SearchRelaysList = 10_007, // NIP-51\n  InterestsList = 10_015, // NIP-51\n  EmojisList = 10_030, // NIP-51\n  BlossomServerList = 10_063,\n  StorageServerList = 10_096, // NIP-96 server list\n\n  FollowSet = 30_000, // NIP-51\n  RelaySet = 30_002, // NIP-51\n  BookmarkSet = 30_003, // NIP-51\n  CurationSet = 30_004, // NIP-51\n  InterestSet = 30_015, // NIP-15\n  EmojiSet = 30_030, // NIP-51\n  StarterPackSet = 39_089, // NIP-51\n\n  Badge = 30009, // NIP-58\n  ProfileBadges = 30008, // NIP-58\n\n  LongFormTextNote = 30023, // NIP-23\n  AppData = 30_078, // NIP-78\n  LiveEvent = 30311, // NIP-53\n  LiveEventChat = 1311, // NIP-53\n  UserStatus = 30315, // NIP-38\n  ZapstrTrack = 31337,\n  ApplicationHandler = 31_990,\n  SimpleChatMetadata = 39_000, // NIP-29\n  ZapRequest = 9734, // NIP 57\n  ZapReceipt = 9735, // NIP 57\n  HttpAuthentication = 27235, // NIP 98 - HTTP Authentication\n}\n\nexport default EventKind\n"
  },
  {
    "path": "packages/system/src/event-publisher.ts",
    "content": "import { unwrap } from \"@snort/shared\"\n\nimport {\n  EventKind,\n  type EventSigner,\n  type FullRelaySettings,\n  type NostrEvent,\n  NostrLink,\n  type NotSignedNostrEvent,\n  type PowMiner,\n  PrivateKeySigner,\n  type RelaySettings,\n  type SignerSupports,\n  settingsToRelayTag,\n  type TaggedNostrEvent,\n  type ToNostrEventTag,\n  type UserMetadata,\n} from \".\"\n\nimport { EventBuilder } from \"./event-builder\"\nimport { Nip7Signer } from \"./impl/nip7\"\nimport { Nip10 } from \"./impl/nip10\"\nimport { Nip22 } from \"./impl/nip22\"\nimport { Nip25 } from \"./impl/nip25\"\nimport { findTag } from \"./utils\"\n\ntype EventBuilderHook = (ev: EventBuilder) => EventBuilder\n\nexport class EventPublisher {\n  #pubKey: string\n  #signer: EventSigner\n  #pow?: number\n  #miner?: PowMiner\n\n  constructor(signer: EventSigner, pubKey: string) {\n    this.#signer = signer\n    this.#pubKey = pubKey\n  }\n\n  get signer() {\n    return this.#signer\n  }\n\n  /**\n   * Create a NIP-07 EventPublisher\n   */\n  static async nip7() {\n    if (\"nostr\" in window) {\n      const signer = new Nip7Signer()\n      const pubkey = await signer.getPubKey()\n      if (pubkey) {\n        return new EventPublisher(signer, pubkey)\n      }\n    }\n  }\n\n  /**\n   * Create an EventPublisher for a private key\n   */\n  static privateKey(privateKey: string | Uint8Array) {\n    const signer = new PrivateKeySigner(privateKey)\n    return new EventPublisher(signer, signer.getPubKey())\n  }\n\n  supports(t: SignerSupports) {\n    return this.#signer.supports.includes(t)\n  }\n\n  get pubKey() {\n    return this.#pubKey\n  }\n\n  /**\n   * Create a copy of this publisher with PoW\n   */\n  pow(target: number, miner?: PowMiner) {\n    const ret = new EventPublisher(this.#signer, this.#pubKey)\n    ret.#pow = target\n    ret.#miner = miner\n    return ret\n  }\n\n  #eb(k: EventKind) {\n    const eb = new EventBuilder()\n    return eb.pubKey(this.#pubKey).kind(k)\n  }\n\n  async #sign(eb: EventBuilder) {\n    return await (this.#pow ? eb.pow(this.#pow, this.#miner) : eb).buildAndSign(this.#signer)\n  }\n\n  async nip4Encrypt(content: string, otherKey: string) {\n    return await this.#signer.nip4Encrypt(content, otherKey)\n  }\n\n  async nip4Decrypt(content: string, otherKey: string) {\n    return await this.#signer.nip4Decrypt(content, otherKey)\n  }\n\n  async nip42Auth(challenge: string, relay: string) {\n    const eb = this.#eb(EventKind.Auth)\n    eb.tag([\"relay\", relay])\n    eb.tag([\"challenge\", challenge])\n    return await this.#sign(eb)\n  }\n\n  /**\n   * Build a mute list event using lists of pubkeys\n   * @param pub Public mute list\n   * @param priv Private mute list\n   */\n  async muted(pub: Array<string>, priv: Array<string>) {\n    const eb = this.#eb(EventKind.MuteList)\n    pub.forEach(p => {\n      eb.tag([\"p\", p])\n    })\n    if (priv.length > 0) {\n      const ps = priv.map(p => [\"p\", p])\n      const plaintext = JSON.stringify(ps)\n      eb.content(await this.#signer.nip44Encrypt(plaintext, this.#pubKey))\n    }\n    return await this.#sign(eb)\n  }\n\n  /**\n   * Build a pin list event using lists of event links\n   */\n  async pinned(notes: Array<ToNostrEventTag>) {\n    const eb = this.#eb(EventKind.PinList)\n    notes.forEach(n => {\n      eb.tag(unwrap(n.toEventTag()))\n    })\n    return await this.#sign(eb)\n  }\n\n  /**\n   * Build a categorized bookmarks event with a given label\n   * @param notes List of bookmarked links\n   */\n  async bookmarks(notes: Array<ToNostrEventTag>) {\n    const eb = this.#eb(EventKind.BookmarksList)\n    notes.forEach(n => {\n      eb.tag(unwrap(n.toEventTag()))\n    })\n    return await this.#sign(eb)\n  }\n\n  async metadata(obj: UserMetadata) {\n    const eb = this.#eb(EventKind.SetMetadata)\n    eb.content(JSON.stringify(obj))\n    return await this.#sign(eb)\n  }\n\n  /**\n   * Create a basic text note\n   */\n  async note(msg: string, fnExtra?: EventBuilderHook) {\n    const eb = this.#eb(EventKind.TextNote)\n    eb.content(msg)\n    eb.processContent()\n    fnExtra?.(eb)\n    return await this.#sign(eb)\n  }\n\n  /**\n   * Create a zap request event for a given target event/profile\n   * @param amount Millisats amout!\n   * @param author Author pubkey to tag in the zap\n   * @param note Note Id to tag in the zap\n   * @param msg Custom message to be included in the zap\n   */\n  async zap(\n    amount: number,\n    author: string,\n    relays: Array<string>,\n    note?: NostrLink,\n    msg?: string,\n    fnExtra?: EventBuilderHook,\n  ) {\n    const eb = this.#eb(EventKind.ZapRequest)\n    eb.content(msg?.trim() ?? \"\")\n    if (note) {\n      // HACK: remove relay tag, some zap services dont like relay tags\n      eb.tag(unwrap(note.toEventTag()).slice(0, 2))\n    }\n    eb.tag([\"p\", author])\n    eb.tag([\"relays\", ...relays.map(a => a.trim())])\n    eb.tag([\"amount\", amount.toString()])\n    eb.processContent()\n    fnExtra?.(eb)\n    return await this.#sign(eb)\n  }\n\n  /**\n   * Reply to a note\n   *\n   * Replies to kind 1 notes are kind 1, otherwise kind 1111\n   */\n  async reply(replyTo: TaggedNostrEvent, msg: string, fnExtra?: EventBuilderHook) {\n    const replyKind = replyTo.kind === EventKind.TextNote ? EventKind.TextNote : EventKind.Comment\n    const eb = this.#eb(replyKind)\n    eb.content(msg)\n\n    if (replyKind === EventKind.TextNote) {\n      Nip10.replyTo(replyTo, eb)\n    } else {\n      Nip22.replyTo(replyTo, eb)\n    }\n    eb.processContent()\n    fnExtra?.(eb)\n    return await this.#sign(eb)\n  }\n\n  async react(evRef: NostrEvent, content = \"+\") {\n    const eb = this.#eb(EventKind.Reaction)\n    eb.content(content)\n    eb.tag(Nip25.reactToEvent(evRef))\n    eb.tag([\"p\", evRef.pubkey])\n    eb.tag([\"k\", evRef.kind.toString()])\n    return await this.#sign(eb)\n  }\n\n  async relayList(relays: Array<FullRelaySettings> | Record<string, RelaySettings>) {\n    if (!Array.isArray(relays)) {\n      relays = Object.entries(relays).map(([k, v]) => ({\n        url: k,\n        settings: v,\n      }))\n    }\n    const eb = this.#eb(EventKind.Relays)\n    for (const rx of relays) {\n      const tag = settingsToRelayTag(rx)\n      if (tag) {\n        eb.tag(tag)\n      }\n    }\n    return await this.#sign(eb)\n  }\n\n  async contactList(tags: Array<[string, string]>, relays?: Record<string, RelaySettings>) {\n    const eb = this.#eb(EventKind.ContactList)\n    tags.forEach(a => eb.tag(a))\n    if (relays) {\n      eb.content(JSON.stringify(relays))\n    }\n    return await this.#sign(eb)\n  }\n\n  /**\n   * Delete an event (NIP-09)\n   */\n  async delete(id: string) {\n    const eb = this.#eb(EventKind.Deletion)\n    eb.tag([\"e\", id])\n    return await this.#sign(eb)\n  }\n\n  /**\n   * Repost a note (NIP-18)\n   */\n  async repost(note: NostrEvent) {\n    const eb = this.#eb(EventKind.Repost)\n    eb.tag(unwrap(NostrLink.fromEvent(note).toEventTag()))\n    eb.tag([\"p\", note.pubkey])\n    return await this.#sign(eb)\n  }\n\n  async decryptDm(note: NostrEvent) {\n    if (note.kind === EventKind.SealedRumor) {\n      const unseal = await this.unsealRumor(note)\n      return unseal.content\n    }\n    if (\n      note.kind === EventKind.DirectMessage &&\n      note.pubkey !== this.#pubKey &&\n      !note.tags.some(a => a[1] === this.#pubKey)\n    ) {\n      throw new Error(\"Can't decrypt, DM does not belong to this user\")\n    }\n    const otherPubKey = note.pubkey === this.#pubKey ? unwrap(note.tags.find(a => a[0] === \"p\")?.[1]) : note.pubkey\n    return await this.nip4Decrypt(note.content, otherPubKey)\n  }\n\n  async sendDm(content: string, to: string) {\n    const eb = this.#eb(EventKind.DirectMessage)\n    eb.content(await this.nip4Encrypt(content, to))\n    eb.tag([\"p\", to])\n    return await this.#sign(eb)\n  }\n\n  async generic(fnHook: EventBuilderHook) {\n    const eb = new EventBuilder()\n    eb.pubKey(this.#pubKey)\n    fnHook(eb)\n    return await this.#sign(eb)\n  }\n\n  async appData(data: object, id: string) {\n    const eb = this.#eb(EventKind.AppData)\n    eb.content(await this.#signer.nip44Encrypt(JSON.stringify(data), this.#pubKey))\n    eb.tag([\"d\", id])\n    return await this.#sign(eb)\n  }\n\n  /**\n   * NIP-59 Gift Wrap event with ephemeral key\n   */\n  async giftWrap(inner: NostrEvent, explicitP?: string, powTarget?: number, powMiner?: PowMiner) {\n    const signer = PrivateKeySigner.random()\n\n    const pTag = explicitP ?? findTag(inner, \"p\")\n    if (!pTag) throw new Error(\"Inner event must have a p tag\")\n\n    const eb = new EventBuilder()\n    eb.pubKey(signer.getPubKey())\n    eb.kind(EventKind.GiftWrap)\n    eb.tag([\"p\", pTag])\n    if (powTarget) {\n      eb.pow(powTarget, powMiner)\n    }\n    eb.content(await signer.nip44Encrypt(JSON.stringify(inner), pTag))\n    eb.jitter(60 * 60 * 24)\n\n    return await eb.buildAndSign(signer)\n  }\n\n  async unwrapGift(gift: NostrEvent) {\n    const body = await this.#signer.nip44Decrypt(gift.content, gift.pubkey)\n    try {\n      return JSON.parse(body) as NostrEvent\n    } catch {\n      throw new Error(`Failed to parse gift-wrapped event content: ${gift.id}`)\n    }\n  }\n\n  /**\n   * Create an unsigned gossip message\n   */\n  createUnsigned(kind: EventKind, content: string, fnHook: EventBuilderHook) {\n    const eb = new EventBuilder()\n    eb.pubKey(this.pubKey)\n    eb.kind(kind)\n    eb.content(content)\n    fnHook(eb)\n    return eb.build() as NotSignedNostrEvent\n  }\n\n  /**\n   * Create sealed rumor\n   */\n  async sealRumor(inner: NotSignedNostrEvent, toKey: string) {\n    const eb = this.#eb(EventKind.SealedRumor)\n    eb.content(await this.#signer.nip44Encrypt(JSON.stringify(inner), toKey))\n    return await this.#sign(eb)\n  }\n\n  /**\n   * Unseal rumor\n   */\n  async unsealRumor(inner: NostrEvent) {\n    if (inner.kind !== EventKind.SealedRumor) throw new Error(\"Not a sealed rumor event\")\n    const body = await this.#signer.nip44Decrypt(inner.content, inner.pubkey)\n    try {\n      return JSON.parse(body) as NostrEvent\n    } catch {\n      throw new Error(`Failed to parse sealed rumor content: ${inner.id}`)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/filter-cache-layer.ts",
    "content": "import type { BuiltRawReqFilter } from \"./request-builder\"\nimport type { NostrEvent } from \"./nostr\"\nimport type { Query } from \"./query\"\n\nexport interface EventCache {\n  bulkGet: (ids: Array<string>) => Promise<Array<NostrEvent>>\n}\n\nexport interface FilterCacheLayer {\n  processFilter(q: Query, req: BuiltRawReqFilter): Promise<BuiltRawReqFilter>\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip10.ts",
    "content": "import { dedupeBy, NostrPrefix } from \"@snort/shared\"\nimport { type NostrEvent, NostrLink, type Thread, type EventBuilder, LinkScope, type TaggedNostrEvent } from \"..\"\nimport { LRUCache } from \"typescript-lru-cache\"\n\nconst ThreadCache = new LRUCache<string, Thread | undefined>({ maxSize: 1000 })\n\n/**\n * Utility class which exports functions used in NIP-10\n */\nexport class Nip10 {\n  /**\n   * Reply to an event using NIP-10 tagging\n   */\n  static replyTo(ev: TaggedNostrEvent, eb: EventBuilder) {\n    const link = NostrLink.fromEvent(ev)\n    const thread = Nip10.parseThread(ev)\n    if (thread) {\n      // get the root tag or the reply tag of the note you're replying to\n      // some clients didnt add the root tag when replying directly to the root note\n      const rootOrReplyAsRoot = (thread.root || thread.replyTo)!\n      eb.tag(Nip10.linkToTag(rootOrReplyAsRoot, LinkScope.Root))\n      eb.tag(Nip10.linkToTag(link, LinkScope.Reply))\n\n      for (const pk of thread.pubKeys) {\n        // skip own pubkey and authors pubkey\n        // authors p tag will be added at the end\n        if (pk.id === eb.pubkey || pk.id === ev.pubkey) {\n          continue\n        }\n        eb.tag(Nip10.linkToTag(pk))\n      }\n    } else {\n      eb.tag(Nip10.linkToTag(link, LinkScope.Root))\n    }\n    // always tag the author of the event you're replying to\n    if (ev.pubkey !== eb.pubkey) {\n      const authorLink = NostrLink.publicKey(ev.pubkey, ev.relays)\n      eb.tag(Nip10.linkToTag(authorLink))\n    }\n  }\n\n  static parseThread(ev: NostrEvent) {\n    const cached = ThreadCache.get(ev.id)\n    if (cached) {\n      return cached\n    }\n    const links = NostrLink.fromTags(ev.tags)\n    const ret = Nip10.fromLinks(links)\n    ThreadCache.set(ev.id, ret)\n    return ret\n  }\n\n  /**\n   * Parse a thread from a parsed set of tag links\n   */\n  static fromLinks(links: Array<NostrLink>) {\n    const ret = {\n      kind: \"nip10\",\n      mentions: [],\n      pubKeys: [],\n    } as Thread\n\n    // NIP-10: Only e and a tags are used for thread structure (positional or marked)\n    const replyTags = links.filter(a => [NostrPrefix.Event, NostrPrefix.Note, NostrPrefix.Address].includes(a.type))\n    if (replyTags.length > 0) {\n      const marked = replyTags.some(a => a.scope)\n      if (!marked) {\n        ret.root = replyTags[0]\n        ret.root.scope = LinkScope.Root\n        if (replyTags.length > 1) {\n          ret.replyTo = replyTags[replyTags.length - 1]\n          ret.replyTo.scope = LinkScope.Reply\n        }\n        if (replyTags.length > 2) {\n          ret.mentions = replyTags.slice(1, -1)\n          ret.mentions.forEach(a => (a.scope = LinkScope.Mention))\n        }\n      } else {\n        const root = replyTags.find(a => a.scope === LinkScope.Root)\n        const reply = replyTags.find(a => a.scope === LinkScope.Reply)\n        ret.root = root\n        ret.replyTo = reply\n        ret.mentions = replyTags.filter(a => a.scope === LinkScope.Mention)\n      }\n\n      // if no root or reply, not a thread\n      if (ret.root === undefined && ret.replyTo === undefined) {\n        return undefined\n      }\n\n      // extract all pubkey mentions from tags\n      const pubKeyLinks = links.filter(a => [NostrPrefix.PublicKey, NostrPrefix.Profile].includes(a.type))\n      // remove duplicate pubkey mentions\n      ret.pubKeys = dedupeBy(pubKeyLinks, n => n.id)\n\n      return ret\n    } else {\n      return undefined\n    }\n  }\n\n  /**\n   * Convert a link to an event tag\n   */\n  static linkToTag(link: NostrLink, withScope?: LinkScope) {\n    const suffix: Array<string> = []\n    if (link.relays && link.relays.length > 0) {\n      suffix.push(link.relays[0])\n    }\n    const scope = withScope ?? link.scope\n    const markerString = Nip10.scopeToMarker(scope)\n    if (markerString) {\n      if (suffix[0] === undefined) {\n        suffix.push(\"\") // empty relay hint\n      }\n      suffix.push(markerString)\n    }\n\n    if (link.type === NostrPrefix.PublicKey || link.type === NostrPrefix.Profile) {\n      return [\"p\", link.id, ...suffix]\n    } else if (link.type === NostrPrefix.Note || link.type === NostrPrefix.Event) {\n      if (link.author) {\n        if (suffix[0] === undefined) {\n          suffix.push(\"\") // empty relay hint\n        }\n        if (suffix[1] === undefined) {\n          suffix.push(\"\") // empty marker\n        }\n        suffix.push(link.author)\n      }\n      return [\"e\", link.id, ...suffix]\n    } else if (link.type === NostrPrefix.Address) {\n      return [\"a\", `${link.kind}:${link.author}:${link.id}`, ...suffix]\n    }\n    throw new Error(\"Invalid link\")\n  }\n\n  /**\n   * Converts a link scope to a marker string\n   */\n  static scopeToMarker(scope?: LinkScope) {\n    switch (scope) {\n      case LinkScope.Root:\n        return \"root\" as const\n      case LinkScope.Reply:\n        return \"reply\" as const\n      case LinkScope.Mention:\n        return \"mention\" as const\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip11.ts",
    "content": "import { LRUCache } from \"typescript-lru-cache\"\n\nexport interface RelayInfoDocument {\n  name?: string\n  description?: string\n  pubkey?: string\n  contact?: string\n  supported_nips?: number[]\n  software?: string\n  version?: string\n  limitation?: {\n    payment_required?: boolean\n    max_subscriptions?: number\n    max_filters?: number\n    max_event_tags?: number\n    auth_required?: boolean\n    write_restricted?: boolean\n  }\n  relay_countries?: Array<string>\n  language_tags?: Array<string>\n  tags?: Array<string>\n  posting_policy?: string\n  negentropy?: number\n}\n\n/**\n * Internal cache of relay info documents\n */\nconst RelayInfoCache = new LRUCache<string, RelayInfoDocument>({ maxSize: 100 })\n\nexport class Nip11 {\n  static async loadRelayDocument(url: string) {\n    // Check cache first\n    const cached = RelayInfoCache.get(url)\n    if (cached) {\n      return cached\n    }\n\n    const u = new URL(url)\n    const rsp = await fetch(`${u.protocol === \"wss:\" ? \"https:\" : \"http:\"}//${u.host}`, {\n      headers: {\n        accept: \"application/nostr+json\",\n      },\n    })\n    if (rsp.ok) {\n      const data = await rsp.json()\n      for (const [k, v] of Object.entries(data)) {\n        if (v === \"unset\" || v === \"\" || v === \"~\") {\n          data[k] = undefined\n        }\n      }\n      const doc = data as RelayInfoDocument\n      // Store in cache\n      RelayInfoCache.set(url, doc)\n      return doc\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip18.ts",
    "content": "import { NostrPrefix } from \"@snort/shared\"\nimport { LinkScope, type NostrLink } from \"../nostr-link\"\n\n/**\n * [NIP-18](https://github.com/nostr-protocol/nips/blob/master/18.md) specific methods\n */\nexport class Nip18 {\n  static linkToTag(link: NostrLink) {\n    if (link.scope !== LinkScope.Quote) {\n      throw new Error(\"Link is not a quote\")\n    }\n\n    const ret = [\"q\", link.tagKey]\n    if (link.relays && link.relays.length > 0) {\n      ret.push(link.relays[0])\n    }\n\n    // Per NIP-18 spec: only add pubkey for regular events (not addresses)\n    // Addresses already encode the author in tagKey as kind:author:d-tag\n    const isRegularEvent = link.type === NostrPrefix.Event || link.type === NostrPrefix.Note\n    if (link.author && isRegularEvent) {\n      if (ret.length === 2) {\n        ret.push(\"\") // empty relay\n      }\n      ret.push(link.author)\n    }\n\n    return ret\n  }\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip22.ts",
    "content": "import { dedupe, dedupeBy, NostrPrefix } from \"@snort/shared\"\nimport { findTag } from \"../utils\"\nimport { type EventBuilder, LinkScope, type NostrEvent, NostrLink, type Thread } from \"../index\"\n\nexport class Nip22 {\n  /**\n   * Get the root scope tag (E/A/I) or\n   * create a root scope tag from the provided event\n   */\n  static rootScopeOf(other: NostrEvent) {\n    // check if other is already scoped to thread root\n    const otherLinks = NostrLink.fromTags(other.tags)\n    const otherRoot = otherLinks.find(a => a.scope === LinkScope.Root)\n    return otherRoot ?? NostrLink.fromEvent(other)\n  }\n\n  static replyTo(other: NostrEvent, eb: EventBuilder) {\n    const linkOther = NostrLink.fromEvent(other)\n    const rootScope = Nip22.linkToTag(Nip22.rootScopeOf(other))\n    const rootKind = [\"K\", findTag(other, \"K\") ?? other.kind.toString()]\n    const rootAuthor = [\"P\", findTag(other, \"P\") ?? other.pubkey]\n\n    const replyScope = Nip22.linkToTag(linkOther)\n    const replyKind = [\"k\", other.kind.toString()]\n    const replyAuthor = [\"p\", other.pubkey]\n\n    if (rootScope === undefined || replyScope === undefined) {\n      throw new Error(\"RootScope or ReplyScope are undefined!\")\n    }\n\n    eb.tag(rootScope)\n    eb.tag(rootKind)\n    eb.tag(rootAuthor)\n    eb.tag(replyScope)\n    eb.tag(replyKind)\n    eb.tag(replyAuthor)\n  }\n\n  /**\n   * Parse NIP-22 comment thread structure\n   * NIP-22 uses uppercase tags (E/A/I) for root and lowercase (e/a/i) for parent\n   */\n  static parseThread(ev: NostrEvent): Thread | undefined {\n    const links = NostrLink.fromTags(ev.tags)\n    return Nip22.fromLinks(links, ev)\n  }\n\n  /**\n   * Parse a NIP-22 thread from a parsed set of tag links\n   */\n  static fromLinks(links: Array<NostrLink>, ev: NostrEvent) {\n    const ret = {\n      kind: \"nip22\",\n      mentions: [],\n      pubKeys: [],\n    } as Thread\n\n    // NIP-22: Only e/a tags are used for thread structure\n    // Use LinkScope to identify root vs reply\n    const replyTags = links.filter(a => [NostrPrefix.Event, NostrPrefix.Note, NostrPrefix.Address].includes(a.type))\n\n    if (replyTags.length > 0) {\n      // Find root and reply based on LinkScope\n      ret.root = replyTags.find(a => a.scope === LinkScope.Root)\n      ret.replyTo = replyTags.find(a => a.scope === LinkScope.Reply)\n      ret.mentions = replyTags.filter(a => a.scope === LinkScope.Mention)\n\n      // Apply kind from 'K' tag to root if present\n      if (ret.root) {\n        const kTag = findTag(ev, \"K\")\n        if (kTag && ret.root.kind === undefined) {\n          const kind = parseInt(kTag)\n          if (!isNaN(kind)) {\n            ret.root.kind = kind\n          }\n        }\n      }\n\n      // Apply kind from 'k' tag to reply if present\n      if (ret.replyTo) {\n        const kTag = findTag(ev, \"k\")\n        if (kTag && ret.replyTo.kind === undefined) {\n          const kind = parseInt(kTag)\n          if (!isNaN(kind)) {\n            ret.replyTo.kind = kind\n          }\n        }\n      }\n\n      // remove duplicate pubkey mentions\n      ret.pubKeys = dedupeBy(\n        links.filter(a => [NostrPrefix.PublicKey, NostrPrefix.Profile].includes(a.type)),\n        n => n.id,\n      )\n\n      // if no root or reply, not a thread\n      if (ret.root === undefined && ret.replyTo === undefined) {\n        return undefined\n      }\n\n      return ret\n    } else {\n      return undefined\n    }\n  }\n\n  /**\n   * Create a NIP-22 tag from an object link\n   */\n  static linkToTag(link: NostrLink) {\n    // TODO: implement\n  }\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip25.ts",
    "content": "import { unwrap } from \"@snort/shared\"\nimport { EventExt, type TaggedNostrEvent, type NostrEvent } from \"..\"\nimport { findTag } from \"../utils\"\n\n/**\n * Implementing [NIP-25](https://github.com/nostr-protocol/nips/blob/master/25.md) reactions\n */\nexport class Nip25 {\n  /**\n   * Create an event reaction tag\n   */\n  static reactToEvent(ev: TaggedNostrEvent | NostrEvent) {\n    const relayHint = \"relays\" in ev ? (ev.relays?.[0] ?? \"\") : \"\"\n    if (EventExt.isAddressable(ev.kind)) {\n      return [\"a\", `${ev.kind}:${ev.pubkey}:${unwrap(findTag(ev, \"d\"))}`, relayHint, ev.pubkey]\n    } else {\n      return [\"e\", ev.id, relayHint, ev.pubkey]\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip4.ts",
    "content": "import { type MessageEncryptor, MessageEncryptorVersion } from \"..\"\nimport { secp256k1 } from \"@noble/curves/secp256k1.js\"\nimport { hexToBytes } from \"@noble/hashes/utils.js\"\nimport { base64 } from \"@scure/base\"\n\nexport class Nip4WebCryptoEncryptor implements MessageEncryptor {\n  #sharedSecret?: CryptoKey\n  constructor(\n    readonly privKey: string,\n    readonly pubKey: string,\n  ) {}\n\n  getSharedSecret(privateKey: string, publicKey: string) {\n    const sharedPoint = secp256k1.getSharedSecret(hexToBytes(privateKey), hexToBytes(\"02\" + publicKey))\n    const sharedX = sharedPoint.slice(1, 33)\n    return sharedX\n  }\n\n  async encryptData(content: string) {\n    if (!this.#sharedSecret) {\n      this.#sharedSecret = await this.#importKey(this.getSharedSecret(this.privKey, this.pubKey))\n    }\n    const iv = window.crypto.getRandomValues(new Uint8Array(16))\n    const data = new TextEncoder().encode(content)\n    const result = await window.crypto.subtle.encrypt(\n      {\n        name: \"AES-CBC\",\n        iv: iv,\n      },\n      this.#sharedSecret,\n      data,\n    )\n    return `${base64.encode(new Uint8Array(result))}?iv=${base64.encode(iv)}`\n  }\n\n  async decryptData(payload: string) {\n    if (!this.#sharedSecret) {\n      this.#sharedSecret = await this.#importKey(this.getSharedSecret(this.privKey, this.pubKey))\n    }\n    const [ciphertext, nonce] = payload.split(\"?iv=\")\n    const result = await window.crypto.subtle.decrypt(\n      {\n        name: \"AES-CBC\",\n        iv: base64.decode(nonce).buffer as ArrayBuffer,\n      },\n      this.#sharedSecret,\n      base64.decode(ciphertext).buffer as ArrayBuffer,\n    )\n    return new TextDecoder().decode(result)\n  }\n\n  async #importKey(sharedSecet: Uint8Array) {\n    return await window.crypto.subtle.importKey(\"raw\", sharedSecet.buffer as ArrayBuffer, { name: \"AES-CBC\" }, false, [\n      \"encrypt\",\n      \"decrypt\",\n    ])\n  }\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip44.ts",
    "content": "import { nip44 } from \"../encryption/nip44\"\nimport type { MessageEncryptor } from \"..\"\n\nexport class Nip44Encryptor implements MessageEncryptor {\n  constructor(\n    readonly privateKey: string,\n    readonly publicKey: string,\n  ) {}\n\n  encryptData(plaintext: string) {\n    const conversationKey = nip44.v2.getConversationKey(this.privateKey, this.publicKey)\n    return nip44.v2.encrypt(plaintext, conversationKey)\n  }\n\n  decryptData(payload: string): string {\n    const { version, ciphertext, nonce, mac } = nip44.utils.decodePayload(payload)\n    if (version === 1) {\n      const conversationKey = nip44.v1.getConversationKey(this.privateKey, this.publicKey)\n      return nip44.v1.decrypt(ciphertext, nonce, conversationKey)\n    }\n    if (version === 2) {\n      const conversationKey = nip44.v2.getConversationKey(this.privateKey, this.publicKey)\n      return nip44.v2.decrypt(ciphertext, nonce, mac!, conversationKey)\n    }\n    throw new Error(`Unsupported payload version: ${version}`)\n  }\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip46.ts",
    "content": "import { secp256k1 } from \"@noble/curves/secp256k1.js\"\nimport { bech32ToHex, unwrap } from \"@snort/shared\"\nimport debug from \"debug\"\nimport { EventEmitter } from \"eventemitter3\"\nimport { Connection } from \"../connection\"\nimport { Nip46RpcTimeout } from \"../const\"\nimport { EventBuilder } from \"../event-builder\"\nimport { EventExt } from \"../event-ext\"\nimport type EventKind from \"../event-kind\"\nimport type { NostrEvent } from \"../nostr\"\nimport { type EventSigner, PrivateKeySigner } from \"../signer\"\n\nconst NIP46_KIND = 24_133\n// FIXME add all kinds that Snort signs\nconst PERMS =\n  \"nip04_encrypt,nip04_decrypt,sign_event:0,sign_event:1,sign_event:3,sign_event:4,sign_event:6,sign_event:7,sign_event:30078\"\n\ninterface Nip46Request {\n  id: string\n  method: string\n  params: Array<string>\n}\n\ninterface Nip46Response {\n  id: string\n  result: string\n  error: string\n}\n\ninterface QueueObj {\n  resolve: (o: Nip46Response) => void\n  reject: (e: Error) => void\n  authed?: boolean\n}\n\ninterface Nip46Events {\n  oauth: (url: string) => void\n  ready: () => void\n}\n\nexport class Nip46Signer extends EventEmitter<Nip46Events> implements EventSigner {\n  #conn?: Connection\n  #relay: string\n  #localPubkey: string\n  #remotePubkey?: string\n  #token?: string\n  #insideSigner: EventSigner\n  #commandQueue: Map<string, QueueObj> = new Map()\n  #log = debug(\"NIP-46\")\n  #proto: string\n  #didInit: boolean = false\n\n  /**\n   * Start NIP-46 connection\n   * @param config bunker/nostrconnect://{npub/hex-pubkey}?relay={websocket-url}#{token-hex}\n   * @param insideSigner\n   */\n  constructor(config: string, insideSigner?: EventSigner) {\n    super()\n    const u = new URL(config)\n    this.#proto = u.protocol\n    this.#localPubkey = u.hostname || u.pathname.substring(2)\n\n    if (u.hash.length > 1) {\n      this.#token = u.hash.substring(1)\n    } else {\n      this.#token = u.searchParams.get(\"secret\") || undefined\n    }\n    if (this.#localPubkey.startsWith(\"npub\")) {\n      this.#localPubkey = bech32ToHex(this.#localPubkey)\n    }\n\n    this.#relay = unwrap(u.searchParams.get(\"relay\"))\n    this.#insideSigner = insideSigner ?? new PrivateKeySigner(secp256k1.keygen().secretKey)\n\n    if (this.isBunker) {\n      this.#remotePubkey = this.#localPubkey\n    }\n  }\n\n  get supports(): string[] {\n    return [\"nip44\"]\n  }\n\n  get relays() {\n    return [this.#relay]\n  }\n\n  get privateKey(): string | undefined {\n    if (this.#insideSigner instanceof PrivateKeySigner) {\n      return this.#insideSigner.privateKey\n    }\n    return undefined\n  }\n\n  get isBunker() {\n    return this.#proto === \"bunker:\"\n  }\n\n  /**\n   * Connect to the bunker relay\n   * @param autoConnect Start connect flow for pubkey\n   * @returns\n   */\n  async init(autoConnect = true) {\n    this.#localPubkey = await this.#insideSigner.getPubKey()\n    return await new Promise<void>((resolve, reject) => {\n      this.#conn = new Connection(this.#relay, { read: true, write: true })\n      this.#conn.on(\"unverifiedEvent\", (_sub, e) => {\n        // Verify the Schnorr signature before processing the NIP-46 message to\n        // prevent forged protocol messages from an attacker on a public relay.\n        if (!EventExt.isValid(e)) {\n          this.#log(\"Dropping NIP-46 event with invalid signature from %s\", e.pubkey)\n          return\n        }\n        this.#onReply(e).catch(err => this.#log(\"Error handling NIP-46 reply: %O\", err))\n      })\n      this.#conn.on(\"connected\", async () => {\n        this.#conn?.request([\n          \"REQ\",\n          \"reply\",\n          {\n            kinds: [NIP46_KIND],\n            \"#p\": [this.#localPubkey],\n            // strfry doesn't always delete ephemeral events\n            since: Math.floor(Date.now() / 1000 - 10),\n          },\n        ])\n\n        this.emit(\"ready\")\n\n        if (autoConnect) {\n          if (this.isBunker) {\n            const rsp = await this.#connect(unwrap(this.#remotePubkey))\n            if (rsp.result === \"ack\") {\n              resolve()\n            } else {\n              reject(rsp.error)\n            }\n          } else {\n            this.#commandQueue.set(\"connect\", {\n              reject,\n              resolve: () => {\n                resolve()\n              },\n            })\n          }\n        } else {\n          resolve()\n        }\n      })\n      this.#conn.connect()\n      this.#didInit = true\n    })\n  }\n\n  async close() {\n    if (this.#conn) {\n      await this.#disconnect()\n      this.#conn.closeRequest(\"reply\")\n      this.#conn.close()\n      this.#conn = undefined\n      this.#didInit = false\n    }\n  }\n\n  async describe() {\n    const rsp = await this.#rpc(\"describe\", [])\n    return JSON.parse(rsp.result) as Array<string>\n  }\n\n  async getPubKey() {\n    //const rsp = await this.#rpc(\"get_public_key\", []);\n    //return rsp.result as string;\n    if (!this.#remotePubkey) throw new Error(\"Remote pubkey not yet known; call init() first\")\n    return this.#remotePubkey\n  }\n\n  async nip4Encrypt(content: string, otherKey: string) {\n    const rsp = await this.#rpc(\"nip04_encrypt\", [otherKey, content])\n    return rsp.result as string\n  }\n\n  async nip4Decrypt(content: string, otherKey: string) {\n    const rsp = await this.#rpc(\"nip04_decrypt\", [otherKey, content])\n    return rsp.result as string\n  }\n\n  nip44Encrypt(_content: string, _key: string): Promise<string> {\n    throw new Error(\"Method not implemented.\")\n  }\n\n  nip44Decrypt(_content: string, _otherKey: string): Promise<string> {\n    throw new Error(\"Method not implemented.\")\n  }\n\n  async sign(ev: NostrEvent) {\n    const rsp = await this.#rpc(\"sign_event\", [JSON.stringify(ev)])\n    const signed = JSON.parse(rsp.result as string) as NostrEvent\n    if (signed.id !== ev.id) {\n      throw new Error(\n        \"Signer returned different event id! Please check your event format or contact the signer developer!\",\n      )\n    }\n    return {\n      ...ev,\n      sig: signed.sig,\n    }\n  }\n\n  /**\n   * NIP-46 oAuth bunker signup\n   * @param name Desired name\n   * @param domain Desired domain\n   * @param email Backup email address\n   * @returns\n   */\n  async createAccount(name: string, domain: string, email?: string) {\n    await this.init(false)\n    const rsp = await this.#rpc(\"create_account\", [name, domain, email ?? \"\", PERMS])\n    if (!rsp.error) {\n      this.#remotePubkey = rsp.result as string\n    }\n  }\n\n  async #disconnect() {\n    return await this.#rpc(\"disconnect\", [])\n  }\n\n  async #connect(pk: string) {\n    const connectParams = [pk, this.#token ?? \"\", PERMS]\n    return await this.#rpc(\"connect\", connectParams)\n  }\n\n  async #onReply(e: NostrEvent) {\n    if (e.kind !== NIP46_KIND) {\n      throw new Error(\"Unknown event kind\")\n    }\n\n    const decryptedContent = await this.#insideSigner.nip44Decrypt(e.content, e.pubkey)\n    let reply: Nip46Request | Nip46Response\n    try {\n      reply = JSON.parse(decryptedContent) as Nip46Request | Nip46Response\n    } catch {\n      this.#log(\"Dropping NIP-46 event with malformed JSON payload from %s\", e.pubkey)\n      return\n    }\n\n    let id = reply.id\n    // Log only the id/method — never the decrypted params/result which may contain secrets.\n    if (\"method\" in reply) {\n      this.#log(\"Recv request id=%s method=%s\", reply.id, reply.method)\n    } else {\n      this.#log(\"Recv response id=%s error=%s\", reply.id, reply.error || \"(none)\")\n    }\n    if (\"method\" in reply && reply.method === \"connect\") {\n      this.#remotePubkey = reply.params[0]\n      await this.#sendCommand(\n        {\n          id: reply.id,\n          result: \"ack\",\n          error: \"\",\n        },\n        unwrap(this.#remotePubkey),\n      )\n      id = \"connect\"\n    } else if (!this.#remotePubkey) {\n      // nostrconnect flow: signer sends a response to an implicit connect\n      this.#remotePubkey = e.pubkey\n      await this.#sendCommand(\n        {\n          id: reply.id,\n          result: \"ack\",\n          error: \"\",\n        },\n        e.pubkey,\n      )\n      id = \"connect\"\n    }\n    const pending = this.#commandQueue.get(id)\n    if (!pending) {\n      this.#log(\"No pending command for id=%s, ignoring\", id)\n      return\n    }\n\n    if (\"result\" in reply && reply.result === \"auth_url\") {\n      if (!pending.authed) this.emit(\"oauth\", reply.error)\n      pending.authed = true\n    } else {\n      const rx = reply as Nip46Response\n      if (rx.error) {\n        pending.reject(new Error(rx.error))\n      } else {\n        pending.resolve(rx)\n      }\n      this.#commandQueue.delete(reply.id)\n    }\n  }\n\n  async #rpc(method: string, params: Array<string>) {\n    if (!this.#didInit) {\n      await this.init()\n    }\n    if (!this.#conn) throw new Error(\"Connection error\")\n\n    const payload = {\n      id: crypto.randomUUID(),\n      method,\n      params,\n    } as Nip46Request\n\n    this.#sendCommand(payload, unwrap(this.#remotePubkey))\n    return await new Promise<Nip46Response>((resolve, reject) => {\n      const timeout = setTimeout(() => {\n        this.#commandQueue.delete(payload.id)\n        reject(new Error(`NIP-46 RPC timed out after ${Nip46RpcTimeout}ms (method=${method})`))\n      }, Nip46RpcTimeout)\n      this.#commandQueue.set(payload.id, {\n        resolve: async (o: Nip46Response) => {\n          clearTimeout(timeout)\n          resolve(o)\n        },\n        reject: (e: Error) => {\n          clearTimeout(timeout)\n          reject(e)\n        },\n      })\n    })\n  }\n\n  async #sendCommand(payload: Nip46Request | Nip46Response, target: string) {\n    if (!this.#conn) return\n\n    const eb = new EventBuilder()\n    eb.kind(NIP46_KIND as EventKind)\n      .content(await this.#insideSigner.nip44Encrypt(JSON.stringify(payload), target))\n      .tag([\"p\", target])\n\n    // Log only the id/method — never the params which may contain secrets.\n    if (\"method\" in payload) {\n      this.#log(\"Send request id=%s method=%s\", payload.id, payload.method)\n    } else {\n      this.#log(\"Send response id=%s\", payload.id)\n    }\n    const evCommand = await eb.buildAndSign(this.#insideSigner)\n    await this.#conn.publish(evCommand)\n  }\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip55.ts",
    "content": "import { bech32ToHex } from \"@snort/shared\"\nimport debug from \"debug\"\nimport { Nip55SignerTimeout } from \"../const\"\nimport type { NostrEvent, NotSignedNostrEvent } from \"../nostr\"\nimport type { EventSigner } from \"../signer\"\n\nexport class Nip55Signer implements EventSigner {\n  #log = debug(\"NIP-55\")\n  #queue: Array<{ id: string; resolve: (o: any) => void; reject: () => void }> = []\n\n  init(): Promise<void> {\n    // nothing here\n    return Promise.resolve()\n  }\n\n  async getPubKey() {\n    let pk = await this.#call(\"get_public_key\", \"signature\")\n    if (pk.startsWith(\"npub\")) {\n      pk = bech32ToHex(pk)\n    }\n    return pk\n  }\n\n  async nip4Encrypt(content: string, key: string) {\n    return await this.#call(\"nip04_encrypt\", \"signature\", content, new Map([[\"pubkey\", key]]))\n  }\n\n  async nip4Decrypt(content: string, otherKey: string) {\n    return await this.#call(\"nip04_decrypt\", \"signature\", content, new Map([[\"pubkey\", otherKey]]))\n  }\n\n  async nip44Encrypt(content: string, key: string) {\n    return await this.#call(\"nip44_encrypt\", \"signature\", content, new Map([[\"pubkey\", key]]))\n  }\n\n  async nip44Decrypt(content: string, otherKey: string) {\n    return await this.#call(\"nip44_decrypt\", \"signature\", content, new Map([[\"pubkey\", otherKey]]))\n  }\n\n  async sign(ev: NostrEvent | NotSignedNostrEvent) {\n    const evRet = await this.#call(\"sign_event\", \"event\", ev)\n    return JSON.parse(evRet)\n  }\n\n  get supports(): string[] {\n    return [\"nip04\", \"nip44\"]\n  }\n\n  #call(\n    method: string,\n    returnType: string,\n    obj?: NostrEvent | NotSignedNostrEvent | string,\n    otherParams?: Map<string, string>,\n  ) {\n    const id = crypto.randomUUID()\n    const objString = typeof obj === \"string\" ? obj : obj != undefined ? JSON.stringify(obj) : undefined\n\n    const params = new URLSearchParams()\n    params.append(\"compressionType\", \"none\")\n    params.append(\"returnType\", returnType)\n    params.append(\"type\", method)\n    if (otherParams) {\n      for (const [k, v] of otherParams) {\n        params.append(k, v)\n      }\n    }\n\n    return new Promise<string>((resolve, reject) => {\n      const t = setInterval(async () => {\n        if (document.hasFocus()) {\n          const text = await navigator.clipboard.readText()\n          if (text) {\n            this.#log(\"Response: %s\", text)\n            await navigator.clipboard.writeText(\"\")\n            clearInterval(t)\n            clearTimeout(timeout)\n            resolve(text)\n          }\n        }\n      }, 500)\n\n      const timeout = setTimeout(() => {\n        clearInterval(t)\n        reject(new Error(`NIP-55 signer timed out after ${Nip55SignerTimeout}ms — no clipboard response received`))\n      }, Nip55SignerTimeout)\n\n      const dst = `nostrsigner:${objString ?? \"\"}?${params.toString()}`\n      this.#log(\"Sending command %s, %s\", id, dst)\n      globalThis.location.href = dst\n    })\n  }\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip57.ts",
    "content": "import debug from \"debug\"\nimport { LRUCache } from \"typescript-lru-cache\"\nimport { decodeInvoice, type InvoiceDetails } from \"@snort/shared\"\nimport type { NostrEvent } from \"../nostr\"\nimport { findTag } from \"../utils\"\nimport { NostrLink } from \"../nostr-link\"\nimport { Nip10 } from \"./nip10\"\n\nconst Log = debug(\"zaps\")\n\n/**\n * Internal cache of parsed zap events\n */\nconst ParsedZapCache = new LRUCache<string, ParsedZap>({ maxSize: 1000 })\n\nfunction getInvoice(zap: NostrEvent): InvoiceDetails | undefined {\n  const bolt11 = findTag(zap, \"bolt11\")\n  if (!bolt11) {\n    throw new Error(\"Invalid zap, missing bolt11 tag\")\n  }\n  return decodeInvoice(bolt11)\n}\n\nexport function parseZap(zapReceipt: NostrEvent): ParsedZap {\n  const existing = ParsedZapCache.get(zapReceipt.id)\n  if (existing) {\n    return existing\n  }\n\n  let innerZapJson = findTag(zapReceipt, \"description\")\n  if (innerZapJson) {\n    try {\n      const invoice = getInvoice(zapReceipt)\n      if (innerZapJson.startsWith(\"%\")) {\n        innerZapJson = decodeURIComponent(innerZapJson)\n      }\n      const zapRequest: NostrEvent = JSON.parse(innerZapJson)\n      if (Array.isArray(zapRequest)) {\n        // old format, ignored\n        throw new Error(\"deprecated zap format\")\n      }\n      const zapRequestThread = Nip10.parseThread(zapRequest)\n      const requestContext = zapRequestThread?.root\n\n      const anonZap = zapRequest.tags.find(a => a[0] === \"anon\")\n      const pollOpt = zapRequest.tags.find(a => a[0] === \"poll_option\")?.[1]\n      const ret: ParsedZap = {\n        id: zapReceipt.id,\n        zapService: zapReceipt.pubkey,\n        amount: (invoice?.amount ?? 0) / 1000,\n        event: requestContext,\n        sender: zapRequest.pubkey,\n        receiver: findTag(zapRequest, \"p\"),\n        valid: true,\n        anonZap: anonZap !== undefined,\n        content: zapRequest.content,\n        errors: [],\n        pollOption: pollOpt ? Number(pollOpt) : undefined,\n        targetEvents: NostrLink.fromTags(zapRequest.tags),\n        created_at: zapRequest.created_at,\n      }\n      if (findTag(zapRequest, \"p\") !== findTag(zapReceipt, \"p\")) {\n        ret.valid = false\n        ret.errors.push(\"p tags dont match\")\n      }\n      if (findTag(zapRequest, \"amount\") === invoice?.amount) {\n        ret.valid = false\n        ret.errors.push(\"amount tag does not match invoice amount\")\n      }\n      if (!ret.valid) {\n        Log(\"Invalid zap %O\", ret)\n      }\n      return ret\n    } catch {\n      // ignored\n    }\n  }\n  const ret = {\n    id: zapReceipt.id,\n    zapService: zapReceipt.pubkey,\n    amount: 0,\n    valid: false,\n    anonZap: false,\n    errors: [\"invalid zap, parsing failed\"],\n    targetEvents: [],\n    created_at: zapReceipt.created_at,\n  } as ParsedZap\n  if (!ret.valid) {\n    Log(\"Invalid zap %O\", ret)\n  }\n  ParsedZapCache.set(ret.id, ret)\n  return ret\n}\n\nexport interface ParsedZap {\n  id: string\n  amount: number\n  zapService: string\n  valid: boolean\n  errors: Array<string>\n\n  anonZap: boolean\n  event?: NostrLink\n  receiver?: string\n  content?: string\n  sender?: string\n  pollOption?: number\n  created_at: number\n\n  /**\n   * A list of targets this zap is zapping\n   */\n  targetEvents: Array<NostrLink>\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip7.ts",
    "content": "import { type WorkQueueItem, processWorkQueue, barrierQueue, unwrap } from \"@snort/shared\"\nimport type { EventSigner, NostrEvent } from \"..\"\n\nconst Nip7Queue: Array<WorkQueueItem> = []\nprocessWorkQueue(Nip7Queue)\n\ndeclare global {\n  interface NostrEncryptor {\n    encrypt(recipientHexPubKey: string, value: string): Promise<string>\n    decrypt(senderHexPubKey: string, value: string): Promise<string>\n  }\n  interface Window {\n    nostr?: {\n      getPublicKey: () => Promise<string>\n      signEvent: (ev: NostrEvent) => Promise<NostrEvent>\n      nip04?: NostrEncryptor\n      nip44?: NostrEncryptor\n    }\n  }\n}\n\nexport class Nip7Signer implements EventSigner {\n  get supports(): string[] {\n    const supports = [\"nip04\"]\n    if (window.nostr && \"nip44\" in window.nostr) {\n      supports.push(\"nip44\")\n    }\n    return supports\n  }\n\n  init(): Promise<void> {\n    return Promise.resolve()\n  }\n\n  async getPubKey(): Promise<string> {\n    if (!window.nostr) {\n      throw new Error(\"Cannot use NIP-07 signer, not found!\")\n    }\n    return await barrierQueue(Nip7Queue, () => unwrap(window.nostr).getPublicKey())\n  }\n\n  async nip4Encrypt(content: string, key: string): Promise<string> {\n    if (!window.nostr) {\n      throw new Error(\"Cannot use NIP-07 signer, not found!\")\n    }\n    return await barrierQueue(Nip7Queue, () =>\n      unwrap(window.nostr?.nip04?.encrypt).call(window.nostr?.nip04, key, content),\n    )\n  }\n\n  async nip4Decrypt(content: string, otherKey: string): Promise<string> {\n    if (!window.nostr) {\n      throw new Error(\"Cannot use NIP-07 signer, not found!\")\n    }\n    return await barrierQueue(Nip7Queue, () =>\n      unwrap(window.nostr?.nip04?.decrypt).call(window.nostr?.nip04, otherKey, content),\n    )\n  }\n\n  async nip44Encrypt(content: string, key: string): Promise<string> {\n    if (!window.nostr) {\n      throw new Error(\"Cannot use NIP-07 signer, not found!\")\n    }\n    return await barrierQueue(Nip7Queue, async () => {\n      const nostr = globalThis.window.nostr\n      if (!nostr) throw new Error(\"Nostr signer not found\")\n      return await nostr.nip44!.encrypt(key, content)\n    })\n  }\n\n  async nip44Decrypt(content: string, otherKey: string): Promise<string> {\n    if (!window.nostr) {\n      throw new Error(\"Cannot use NIP-07 signer, not found!\")\n    }\n    return await barrierQueue(Nip7Queue, async () => {\n      const nostr = globalThis.window.nostr\n      if (!nostr) throw new Error(\"Nostr signer not found\")\n      return await nostr.nip44!.decrypt(otherKey, content)\n    })\n  }\n\n  async sign(ev: NostrEvent): Promise<NostrEvent> {\n    if (!window.nostr) {\n      throw new Error(\"Cannot use NIP-07 signer, not found!\")\n    }\n    return await barrierQueue(Nip7Queue, async () => {\n      const signed = await unwrap(window.nostr).signEvent(ev)\n      if (signed.id !== ev.id) {\n        throw new Error(\n          \"Signer returned different event id! Please check your event format or contact the signer developer!\",\n        )\n      }\n      return {\n        ...ev,\n        sig: signed.sig,\n      }\n    })\n  }\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip90.ts",
    "content": "import { isHex, sanitizeRelayUrl } from \"@snort/shared\"\nimport type { EventSigner } from \"../signer\"\nimport { EventBuilder } from \"../event-builder\"\nimport type { NostrEvent, TaggedNostrEvent } from \"../nostr\"\nimport type { SystemInterface } from \"../system\"\nimport { RequestBuilder } from \"../request-builder\"\nimport { NostrLink } from \"../nostr-link\"\nimport { findTag } from \"../utils\"\nimport debug from \"debug\"\nimport EventEmitter from \"eventemitter3\"\n\nexport enum DVMJobState {\n  /**\n   * Job is new and never sent to any relays\n   */\n  New = \"new\",\n\n  /**\n   * Job was sent to relays\n   */\n  Init = \"init\",\n\n  /**\n   * DVM server requested payment\n   */\n  PaymentRequired = \"payment-required\",\n\n  /**\n   * DVM server is processing the request\n   */\n  Processing = \"processing\",\n\n  /**\n   * DVM server was unable to process the request\n   */\n  Error = \"error\",\n\n  /**\n   * DVM job was successful\n   */\n  Success = \"success\",\n\n  /**\n   * The job was partially completed\n   */\n  Partial = \"partial\",\n}\n\n/**\n * Events emitted by the DVM job\n */\nexport interface DVMJobEvents {\n  /**\n   * Job state changed\n   */\n  state(newState: DVMJobState): void\n\n  /**\n   * DVM server requested payment\n   */\n  paymentRequested(): void\n\n  /**\n   * DVM server returned an error\n   */\n  error(message?: string): void\n\n  /**\n   * Job was successful\n   */\n  result(ev: TaggedNostrEvent): void\n}\n\n/**\n * Job input params\n */\nexport interface DVMJobInput {\n  /**\n   * The argument for the input\n   */\n  data: string\n\n  /**\n   * The way this argument should be interpreted\n   */\n  inputType: \"url\" | \"event\" | \"job\" | \"text\"\n\n  /**\n   * If event or job input-type, the relay where the event/job was published, otherwise optional or empty string\n   */\n  relay?: string\n\n  /**\n   * An optional field indicating how this input should be used within the context of the job\n   */\n  marker?: string\n}\n\n/**\n * Generic DVM job request class\n */\nexport class DVMJobRequest extends EventEmitter<DVMJobEvents> {\n  private log = debug(\"NIP-90\")\n\n  /**\n   * Internal instance ID\n   */\n  #id = crypto.randomUUID()\n\n  /**\n   * Internal job state\n   */\n  #state = DVMJobState.New\n\n  /**\n   * Internal job event sent to relays\n   */\n  #jobEvent?: NostrEvent\n\n  /**\n   * Job request kind number\n   */\n  readonly kind: number\n\n  /**\n   * The response kind used to reply to this job\n   */\n  readonly responseKind: number\n\n  /**\n   *  Input data for the job (zero or more inputs)\n   */\n  private input?: Array<DVMJobInput>\n\n  /**\n   * Param tags K/V\n   */\n  private params?: Map<string, string>\n\n  /**\n   * Expected output format. Different job request kind defines this more precisely\n   */\n  private output?: string\n\n  /**\n   * Customer MAY specify a maximum amount (in millisats) they are willing to pay\n   */\n  private bid?: number\n\n  /**\n   * List of relays where Service Providers SHOULD publish responses to\n   */\n  private relays?: Set<string>\n\n  /**\n   * Service Providers the customer is interested in. Other SPs MIGHT still choose to process the job\n   */\n  private serviceProvider?: string\n\n  /**\n   * If encryption is enabled\n   */\n  private encrypted: boolean\n\n  constructor(kind: number, response?: number) {\n    super()\n    this.kind = kind\n    this.responseKind = response ?? 6000 + (kind - 5000)\n    this.encrypted = false\n  }\n\n  /**\n   * Get the instance ID\n   */\n  get id() {\n    return this.#id\n  }\n\n  get state() {\n    return this.#state\n  }\n\n  private set state(v: DVMJobState) {\n    this.#state = v\n    this.emit(\"state\", v)\n  }\n\n  /**\n   * Add an input for the job request\n   */\n  addInput(input: DVMJobInput) {\n    this.input ??= []\n    this.input.push(input)\n    return this\n  }\n\n  /**\n   * Set a param for the request\n   * @param k The param name\n   * @param v The param value\n   */\n  setParam(k: string, v: string) {\n    this.params ??= new Map()\n    this.params.set(k, v)\n    return this\n  }\n\n  /**\n   * Remove a param from the job request\n   */\n  removeParam(k: string) {\n    this.params?.delete(k)\n    return this\n  }\n\n  /**\n   * Set to use encryption for the inputs / params\n   */\n  setEncrypted(encrypted: boolean) {\n    this.encrypted = encrypted\n    return this\n  }\n\n  /**\n   * Set the service provider pubkey\n   */\n  setServiceProvider(p: string) {\n    if (p.length !== 64 || !isHex(p)) {\n      throw new Error(\"Provider must be a hex pubkey\")\n    }\n    this.serviceProvider = p\n    return this\n  }\n\n  /**\n   * Set the desired output MIME\n   */\n  setOutput(mime: string) {\n    this.output = mime\n    return this\n  }\n\n  /**\n   * Set the bid amount in milli-sats\n   */\n  setBid(amount: number) {\n    this.bid = amount\n    return this\n  }\n\n  /**\n   * Add a relay where the job feedback / results should be sent\n   */\n  addRelay(relay: string) {\n    this.relays ??= new Set()\n    const cleaned = sanitizeRelayUrl(relay)\n    if (!cleaned) {\n      throw new Error(\"Invalid relay URL\")\n    }\n    this.relays.add(cleaned)\n    return this\n  }\n\n  /**\n   * Remove a relay\n   */\n  removeRelay(relay: string) {\n    const cleaned = sanitizeRelayUrl(relay)\n    if (cleaned) {\n      this.relays?.delete(cleaned)\n    }\n    return this\n  }\n\n  /**\n   * Build the final job request Nostr event\n   */\n  async buildEvent(signer: EventSigner): Promise<NostrEvent> {\n    const inputTags = []\n    for (const input of this.input ?? []) {\n      const iTag = [\"i\", input.data, input.inputType]\n      if (input.relay) {\n        iTag.push(input.relay)\n      }\n      if (input.marker) {\n        iTag.push(input.marker)\n      }\n      inputTags.push(iTag)\n    }\n    for (const [k, v] of this.params?.entries() ?? []) {\n      inputTags.push([\"param\", k, v])\n    }\n    const otherTags = []\n    if (this.output) {\n      otherTags.push([\"output\", this.output])\n    }\n    if (this.bid) {\n      otherTags.push([\"bid\", this.bid.toString()])\n    }\n    if (this.relays && this.relays.size > 0) {\n      otherTags.push([\"relays\", ...this.relays])\n    }\n    if (this.serviceProvider) {\n      otherTags.push([\"p\", this.serviceProvider])\n    }\n    if (this.encrypted) {\n      if (!this.serviceProvider) {\n        throw new Error(\"Cannot encrypt job without service provider pubkey\")\n      }\n      otherTags.push([\"encrypted\", \"1\"])\n    }\n\n    const pubkey = await signer.getPubKey()\n    const eb = new EventBuilder().pubKey(pubkey).kind(this.kind)\n    if (this.encrypted) {\n      for (const t of otherTags) {\n        eb.tag(t)\n      }\n      const tagsEncrypted = JSON.stringify(inputTags)\n      eb.content(await signer.nip44Encrypt(tagsEncrypted, this.serviceProvider!))\n    } else {\n      for (const t of [...inputTags, ...otherTags]) {\n        eb.tag(t)\n      }\n    }\n    return await eb.buildAndSign(signer)\n  }\n\n  #handleReplyEvents(evs: Array<TaggedNostrEvent>) {\n    for (const e of evs) {\n      this.log(\"Processing response: %O\", e)\n      if (e.kind === 7000) {\n        const status = findTag(e, \"status\")\n        switch (status?.toLocaleLowerCase()) {\n          case \"error\": {\n            this.state = DVMJobState.Error\n            this.emit(\"error\", \"Request failed\")\n            break\n          }\n          case \"processing\": {\n            this.state = DVMJobState.Processing\n            break\n          }\n          case \"partial\": {\n            this.state = DVMJobState.Partial\n            break\n          }\n          case \"success\": {\n            this.state = DVMJobState.Success\n            break\n          }\n          default: {\n            this.log(\"Unknown feedback status: %s\", status)\n          }\n        }\n        return\n      } else if (e.kind === this.responseKind) {\n        if (this.serviceProvider && this.serviceProvider !== e.pubkey) {\n          return // another DVM replied to our request, ignore\n        }\n        const jobLink = NostrLink.fromEvent(this.#jobEvent!)\n        if (jobLink.isReplyToThis(e)) {\n          this.state = DVMJobState.Success\n          this.emit(\"result\", e)\n        }\n      }\n    }\n  }\n\n  /**\n   * Start job request flow\n   * @param signer Signer to sign job request events\n   * @param system System to send / receive events\n   * @param relays List of specific relays to send requests on\n   */\n  async request(signer: EventSigner, system: SystemInterface, relays?: Array<string>) {\n    if (this.state !== DVMJobState.New) {\n      throw new Error(\"Invalid job state, cannot send request\")\n    }\n    this.#jobEvent = await this.buildEvent(signer)\n    this.state = DVMJobState.Init\n\n    // sub to replies first\n    const rbReply = new RequestBuilder(`dvm-replies:${this.#jobEvent.id}`)\n    rbReply.withOptions({ leaveOpen: true, skipCache: true, groupingDelay: 0 })\n    const f = rbReply.withFilter().kinds([this.responseKind, 7000]).tag(\"e\", [this.#jobEvent.id])\n\n    // list for replies on the reply relays if specified\n    if (this.relays && this.relays.size > 0) {\n      f.relay([...this.relays])\n    }\n\n    const q = system.Query(rbReply)\n    q.uncancel() // might already exist so uncancel\n    q.on(\"event\", evs => this.#handleReplyEvents(evs))\n    q.start()\n\n    // send request\n    if (relays) {\n      for (const r of relays) {\n        await system.WriteOnceToRelay(r, this.#jobEvent)\n      }\n    } else {\n      await system.BroadcastEvent(this.#jobEvent)\n    }\n\n    // abort self when resut\n    this.on(\"result\", () => {\n      q.cancel()\n    })\n    return q\n  }\n\n  abort(system: SystemInterface) {\n    if (this.#jobEvent) {\n      const q = system.GetQuery(`dvm-replies:${this.#jobEvent.id}`)\n      q?.cancel()\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip92.ts",
    "content": "import { type Nip94Tags, readNip94Tags } from \"./nip94\"\n\n/**\n * https://github.com/nostr-protocol/nips/blob/master/92.md impl\n */\nexport class Nip92 {\n  /**\n   * Read NIP-94 tags from `imeta` tag\n   */\n  static parse(tag: Array<string>) {\n    return readNip94TagsFromIMeta(tag)\n  }\n\n  /**\n   * Read NIP-94 tags from all `imeta` tags\n   */\n  static parseAll(tags: Array<Array<string>>) {\n    const iMetaTags = tags.filter(a => a[0] === \"imeta\")\n    return iMetaTags.map(a => Nip92.parse(a))\n  }\n}\n\n/**\n * Read NIP-94 tags from `imeta` tag\n */\nexport function readNip94TagsFromIMeta(tag: Array<string>) {\n  if (tag.length < 2) {\n    throw new Error(\"Invalid tag, must have more than 1 string\")\n  }\n  const asTags = tag.slice(1).map(a => a.split(\" \", 2))\n  return readNip94Tags(asTags)\n}\n\nexport function nip94TagsToIMeta(meta: Nip94Tags) {\n  if (!meta.url) {\n    throw new Error(\"URL is required!\")\n  }\n  const ret: Array<string> = [\"imeta\"]\n  const ifPush = (key: string, value?: string | number) => {\n    if (value) {\n      ret.push(`${key} ${value}`)\n    }\n  }\n  ifPush(\"url\", meta.url)\n  ifPush(\"m\", meta.mimeType)\n  ifPush(\"x\", meta.hash)\n  ifPush(\"ox\", meta.originalHash)\n  ifPush(\"size\", meta.size)\n  ifPush(\"dim\", meta.dimensions?.join(\"x\"))\n  ifPush(\"magnet\", meta.magnet)\n  ifPush(\"blurhash\", meta.blurHash)\n  ifPush(\"thumb\", meta.thumb)\n  ifPush(\"summary\", meta.summary)\n  ifPush(\"alt\", meta.alt)\n  ifPush(\"duration\", meta.duration)\n  ifPush(\"bitrate\", meta.bitrate)\n  if (meta.image) {\n    meta.image.forEach(a => ifPush(\"image\", a))\n  }\n  if (meta.fallback) {\n    meta.fallback.forEach(a => ifPush(\"fallback\", a))\n  }\n\n  return ret\n}\n"
  },
  {
    "path": "packages/system/src/impl/nip94.ts",
    "content": "import { FileExtensionRegex } from \"../const\"\n\n/**\n * https://github.com/nostr-protocol/nips/blob/master/94.md impl\n */\nexport class Nip94 {\n  static parse(tags: Array<Array<string>>) {\n    return readNip94Tags(tags)\n  }\n}\n\nexport interface Nip94Tags {\n  url?: string\n  mimeType?: string\n  hash?: string\n  originalHash?: string\n  size?: number\n  dimensions?: [number, number]\n  magnet?: string\n  blurHash?: string\n  thumb?: string\n  image?: Array<string>\n  summary?: string\n  alt?: string\n  fallback?: Array<string>\n  duration?: number\n  bitrate?: number\n}\n\n/**\n * Read NIP-94 tags from event tags\n */\nexport function readNip94Tags(tags: Array<Array<string>>) {\n  const res: Nip94Tags = {}\n  for (const tx of tags) {\n    const [k, v] = tx as [string, string | undefined]\n    if (v === undefined) continue\n    switch (k) {\n      case \"url\": {\n        // if URL already set, treat next url as fallback\n        if (res.url) {\n          res.fallback ??= []\n          res.fallback.push(v)\n        } else {\n          res.url = v\n        }\n        break\n      }\n      case \"m\": {\n        res.mimeType = v\n        break\n      }\n      case \"x\": {\n        res.hash = v\n        break\n      }\n      case \"ox\": {\n        res.originalHash = v\n        break\n      }\n      case \"size\": {\n        res.size = Number(v)\n        break\n      }\n      case \"dim\": {\n        res.dimensions = v.split(\"x\").map(Number) as [number, number]\n        break\n      }\n      case \"magnet\": {\n        res.magnet = v\n        break\n      }\n      case \"blurhash\": {\n        res.blurHash = v\n        break\n      }\n      case \"thumb\": {\n        res.thumb = v\n        break\n      }\n      case \"image\": {\n        res.image ??= []\n        res.image.push(v)\n        break\n      }\n      case \"summary\": {\n        res.summary = v\n        break\n      }\n      case \"alt\": {\n        res.alt = v\n        break\n      }\n      case \"fallback\": {\n        res.fallback ??= []\n        res.fallback.push(v)\n        break\n      }\n      case \"duration\": {\n        res.duration = Number(v)\n        break\n      }\n      case \"bitrate\": {\n        res.bitrate = Number(v)\n        break\n      }\n    }\n  }\n  return res\n}\n\nexport function addExtensionToNip94Url(meta: Nip94Tags) {\n  if (!meta.url?.match(FileExtensionRegex) && meta.mimeType) {\n    switch (meta.mimeType) {\n      case \"image/webp\": {\n        return `${meta.url}.webp`\n      }\n      case \"image/jpeg\":\n      case \"image/jpg\": {\n        return `${meta.url}.jpg`\n      }\n      case \"video/mp4\": {\n        return `${meta.url}.mp4`\n      }\n    }\n  }\n  return meta.url\n}\n"
  },
  {
    "path": "packages/system/src/index.ts",
    "content": "export * from \"./cache/index\"\nexport * from \"./cache/user-follows-lists\"\nexport * from \"./cache/user-metadata\"\nexport * from \"./cache/user-relays\"\nexport * from \"./cache-relay\"\nexport * from \"./connection\"\nexport * from \"./connection-cache-relay\"\nexport * from \"./const\"\nexport * from \"./encryption\"\nexport * from \"./encryption/pin-encrypted\"\nexport * from \"./event-builder\"\nexport * from \"./event-ext\"\nexport { default as EventKind } from \"./event-kind\"\nexport * from \"./event-publisher\"\nexport * from \"./impl/nip4\"\nexport * from \"./impl/nip7\"\nexport * from \"./impl/nip10\"\nexport * from \"./impl/nip11\"\nexport * from \"./impl/nip18\"\nexport * from \"./impl/nip22\"\nexport * from \"./impl/nip25\"\nexport * from \"./impl/nip44\"\nexport * from \"./impl/nip46\"\nexport * from \"./impl/nip55\"\nexport * from \"./impl/nip57\"\nexport * from \"./impl/nip57\"\nexport * from \"./impl/nip90\"\nexport * from \"./impl/nip92\"\nexport * from \"./impl/nip94\"\nexport * from \"./nips\"\nexport * from \"./nostr\"\nexport * from \"./nostr-link\"\nexport { NostrSystem } from \"./nostr-system\"\nexport * from \"./note-collection\"\nexport * from \"./outbox\"\nexport * from \"./pow\"\nexport * from \"./pow-util\"\nexport * from \"./profile-cache\"\nexport * from \"./query\"\nexport * from \"./query-optimizer\"\nexport * from \"./relays\"\nexport * from \"./request-builder\"\nexport * from \"./signer\"\nexport * from \"./sync\"\nexport * from \"./system\"\nexport * from \"./text\"\nexport * from \"./trace-timeline\"\nexport * from \"./user-state\"\nexport * from \"./utils\"\n"
  },
  {
    "path": "packages/system/src/negentropy/accumulator.ts",
    "content": "import { sha256 } from \"@noble/hashes/sha2.js\"\nimport { encodeVarInt, FINGERPRINT_SIZE } from \"./utils\"\n\nexport class Accumulator {\n  #buf!: Uint8Array\n\n  constructor() {\n    this.setToZero()\n  }\n\n  setToZero() {\n    this.#buf = new Uint8Array(32)\n  }\n\n  add(otherBuf: Uint8Array) {\n    let currCarry = 0,\n      nextCarry = 0\n    const p = new DataView(this.#buf.buffer)\n    const po = new DataView(otherBuf.buffer)\n\n    for (let i = 0; i < 8; i++) {\n      const offset = i * 4\n      const orig = p.getUint32(offset, true)\n      const otherV = po.getUint32(offset, true)\n\n      let next = orig\n\n      next += currCarry\n      next += otherV\n      if (next > 4294967295) nextCarry = 1\n\n      p.setUint32(offset, next & 4294967295, true)\n      currCarry = nextCarry\n      nextCarry = 0\n    }\n  }\n\n  negate() {\n    const p = new DataView(this.#buf.buffer)\n\n    for (let i = 0; i < 8; i++) {\n      const offset = i * 4\n      p.setUint32(offset, ~p.getUint32(offset, true))\n    }\n\n    const one = new Uint8Array(32)\n    one[0] = 1\n    this.add(one)\n  }\n\n  getFingerprint(n: number) {\n    const varInt = encodeVarInt(n)\n    const copy = new Uint8Array(this.#buf.length + varInt.length)\n    copy.set(this.#buf)\n    copy.set(varInt, this.#buf.length)\n\n    const hash = sha256(copy)\n    return hash.subarray(0, FINGERPRINT_SIZE)\n  }\n}\n"
  },
  {
    "path": "packages/system/src/negentropy/negentropy-flow.ts",
    "content": "import { bytesToHex, hexToBytes } from \"@noble/hashes/utils.js\"\nimport type { ConnectionType } from \"../connection-pool\"\nimport type { ReqFilter, TaggedNostrEvent } from \"../nostr\"\nimport { Negentropy } from \"./negentropy\"\nimport { NegentropyStorageVector } from \"./vector-storage\"\nimport debug from \"debug\"\nimport { EventEmitter } from \"eventemitter3\"\n\nexport interface NegentropyFlowEvents {\n  /**\n   * When sync is finished emit a set of filters which can resolve sync\n   */\n  finish: (req: Array<ReqFilter>) => void\n\n  /**\n   * If an error is detected and Negentropy flow is not supported\n   */\n  error: () => void\n}\n\n/**\n * Negentropy sync flow on connection\n */\nexport class NegentropyFlow extends EventEmitter<NegentropyFlowEvents> {\n  readonly idSize: number = 16\n  #log = debug(\"NegentropyFlow\")\n  #id: string\n  #connection: ConnectionType\n  #filters: Array<ReqFilter>\n  #negentropy: Negentropy\n  #need: Array<string> = []\n\n  constructor(id: string, conn: ConnectionType, set: Array<TaggedNostrEvent>, filters: Array<ReqFilter>) {\n    super()\n    this.#id = id\n    this.#connection = conn\n    this.#filters = filters\n\n    this.#connection.on(\"unknownMessage\", msg => this.#handleMessage(msg))\n    this.#connection.on(\"notice\", n => this.#handleMessage([\"NOTICE\", n]))\n\n    const storage = new NegentropyStorageVector()\n    set.forEach(a => storage.insert(a.created_at, a.id))\n    storage.seal()\n    this.#negentropy = new Negentropy(storage, 50_000)\n  }\n\n  /**\n   * Start sync\n   */\n  start() {\n    const init = this.#negentropy.initiate()\n    this.#connection.sendRaw([\"NEG-OPEN\", this.#id, this.#filters, bytesToHex(init)])\n  }\n\n  #handleMessage(msg: Array<any>) {\n    try {\n      switch (msg[0] as string) {\n        case \"NOTICE\": {\n          const [_, errorMsg] = msg as [string, string]\n          if (errorMsg.includes(\"negentropy disabled\") || errorMsg.includes(\"negentropy error\")) {\n            this.#log(\"SYNC ERROR: %s\", errorMsg)\n            this.#cleanup(true)\n          }\n          break\n        }\n        case \"NEG-ERROR\": {\n          const [_, id, errorMsg] = msg as [string, string, string]\n          if (id !== this.#id) break\n          this.#log(\"SYNC ERROR %s\", errorMsg)\n          this.#cleanup(true)\n          break\n        }\n        case \"NEG-MSG\": {\n          const [, id, payload] = msg as [string, string, string]\n          if (id !== this.#id) break\n          const query = hexToBytes(payload)\n          const [nextMsg, , need] = this.#negentropy.reconcile(query)\n          if (need.length > 0) {\n            this.#need.push(...need.map(bytesToHex))\n          }\n          if (nextMsg) {\n            this.#connection.sendRaw([\"NEG-MSG\", this.#id, bytesToHex(nextMsg)])\n          } else {\n            this.#connection.sendRaw([\"NEG-CLOSE\", this.#id])\n            this.#cleanup()\n          }\n          break\n        }\n      }\n    } catch (e) {\n      console.error(e)\n    }\n  }\n\n  #cleanup(error = false) {\n    this.#connection.off(\"unknownMessage\", msg => this.#handleMessage(msg))\n    this.#connection.off(\"notice\", n => this.#handleMessage([\"NOTICE\", n]))\n    this.emit(\"finish\", this.#need.length > 0 ? [{ ids: this.#need }] : [])\n    if (error) {\n      this.emit(\"error\")\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/negentropy/negentropy.ts",
    "content": "import { bytesToHex } from \"@noble/hashes/utils.js\"\nimport { WrappedBuffer } from \"./wrapped-buffer\"\nimport type { NegentropyStorageVector, VectorStorageItem } from \"./vector-storage\"\nimport {\n  PROTOCOL_VERSION,\n  getByte,\n  encodeVarInt,\n  Mode,\n  decodeVarInt,\n  getBytes,\n  FINGERPRINT_SIZE,\n  compareUint8Array,\n} from \"./utils\"\n\nexport class Negentropy {\n  readonly #storage: NegentropyStorageVector\n  readonly #frameSizeLimit: number\n  #lastTimestampIn: number\n  #lastTimestampOut: number\n  #isInitiator: boolean = false\n\n  constructor(storage: NegentropyStorageVector, frameSizeLimit = 0) {\n    if (frameSizeLimit !== 0 && frameSizeLimit < 4096) throw Error(\"frameSizeLimit too small\")\n\n    this.#storage = storage\n    this.#frameSizeLimit = frameSizeLimit\n\n    this.#lastTimestampIn = 0\n    this.#lastTimestampOut = 0\n  }\n\n  #bound(timestamp: number, id?: Uint8Array) {\n    return { timestamp, id: id ? id : new Uint8Array(0) }\n  }\n\n  initiate() {\n    if (this.#isInitiator) throw Error(\"already initiated\")\n    this.#isInitiator = true\n\n    const output = new WrappedBuffer()\n    output.set([PROTOCOL_VERSION])\n\n    this.splitRange(0, this.#storage.size(), this.#bound(Number.MAX_VALUE), output)\n\n    return this.#renderOutput(output)\n  }\n\n  setInitiator() {\n    this.#isInitiator = true\n  }\n\n  reconcile(query: WrappedBuffer | Uint8Array): [Uint8Array | undefined, Array<Uint8Array>, Array<Uint8Array>] {\n    const haveIds: Array<Uint8Array> = [],\n      needIds: Array<Uint8Array> = []\n    query = query instanceof WrappedBuffer ? query : new WrappedBuffer(query)\n\n    this.#lastTimestampIn = this.#lastTimestampOut = 0 // reset for each message\n\n    const fullOutput = new WrappedBuffer()\n    fullOutput.set([PROTOCOL_VERSION])\n\n    const protocolVersion = getByte(query)\n    if (protocolVersion < 96 || protocolVersion > 111) throw Error(\"invalid negentropy protocol version byte\")\n    if (protocolVersion !== PROTOCOL_VERSION) {\n      if (this.#isInitiator) throw Error(\"unsupported negentropy protocol version requested: \" + (protocolVersion - 96))\n      else return [this.#renderOutput(fullOutput), haveIds, needIds]\n    }\n\n    const storageSize = this.#storage.size()\n    let prevBound = this.#bound(0)\n    let prevIndex = 0\n    let skip = false\n\n    while (query.length !== 0) {\n      const o = new WrappedBuffer()\n\n      const doSkip = () => {\n        if (skip) {\n          skip = false\n          o.append(this.encodeBound(prevBound))\n          o.append(encodeVarInt(Mode.Skip))\n        }\n      }\n\n      const currBound = this.decodeBound(query)\n      const mode = query.length === 0 ? 0 : decodeVarInt(query)\n\n      const lower = prevIndex\n      let upper = this.#storage.findLowerBound(prevIndex, storageSize, currBound)\n\n      if (mode === Mode.Skip) {\n        skip = true\n      } else if (mode === Mode.Fingerprint) {\n        const theirFingerprint = getBytes(query, FINGERPRINT_SIZE)\n        const ourFingerprint = this.#storage.fingerprint(lower, upper)\n\n        if (compareUint8Array(theirFingerprint, ourFingerprint) !== 0) {\n          doSkip()\n          this.splitRange(lower, upper, currBound, o)\n        } else {\n          skip = true\n        }\n      } else if (mode === Mode.IdList) {\n        const numIds = decodeVarInt(query)\n\n        const theirElems = {} as Record<string, Uint8Array> // stringified Uint8Array -> original Uint8Array (or hex)\n        for (let i = 0; i < numIds; i++) {\n          const e = getBytes(query, this.#storage.idSize)\n          theirElems[bytesToHex(e)] = e\n        }\n\n        this.#storage.iterate(lower, upper, item => {\n          const k = bytesToHex(item.id)\n          if (!theirElems[k]) {\n            // ID exists on our side, but not their side\n            if (this.#isInitiator) haveIds.push(item.id)\n          } else {\n            // ID exists on both sides\n            delete theirElems[k]\n          }\n\n          return true\n        })\n\n        if (this.#isInitiator) {\n          skip = true\n\n          for (const v of Object.values(theirElems)) {\n            // ID exists on their side, but not our side\n            needIds.push(v)\n          }\n        } else {\n          doSkip()\n\n          const responseIds = new WrappedBuffer()\n          let numResponseIds = 0\n          let endBound = currBound\n\n          this.#storage.iterate(lower, upper, (item, index) => {\n            if (this.exceededFrameSizeLimit(fullOutput.length + responseIds.length)) {\n              endBound = item\n              upper = index // shrink upper so that remaining range gets correct fingerprint\n              return false\n            }\n\n            responseIds.append(item.id)\n            numResponseIds++\n            return true\n          })\n\n          o.append(this.encodeBound(endBound))\n          o.append(encodeVarInt(Mode.IdList))\n          o.append(encodeVarInt(numResponseIds))\n          o.append(responseIds.unwrap())\n\n          fullOutput.append(o.unwrap())\n          o.clear()\n        }\n      } else {\n        throw Error(\"unexpected mode\")\n      }\n\n      if (this.exceededFrameSizeLimit(fullOutput.length + o.length)) {\n        // frameSizeLimit exceeded: Stop range processing and return a fingerprint for the remaining range\n        const remainingFingerprint = this.#storage.fingerprint(upper, storageSize)\n\n        fullOutput.append(this.encodeBound(this.#bound(Number.MAX_VALUE)))\n        fullOutput.append(encodeVarInt(Mode.Fingerprint))\n        fullOutput.append(remainingFingerprint)\n        break\n      } else {\n        fullOutput.append(o.unwrap())\n      }\n\n      prevIndex = upper\n      prevBound = currBound\n    }\n\n    return [fullOutput.length === 1 && this.#isInitiator ? undefined : this.#renderOutput(fullOutput), haveIds, needIds]\n  }\n\n  async splitRange(lower: number, upper: number, upperBound: VectorStorageItem, o: WrappedBuffer) {\n    const numElems = upper - lower\n    const buckets = 16\n\n    if (numElems < buckets * 2) {\n      o.append(this.encodeBound(upperBound))\n      o.append(encodeVarInt(Mode.IdList))\n\n      o.append(encodeVarInt(numElems))\n      this.#storage.iterate(lower, upper, item => {\n        o.append(item.id)\n        return true\n      })\n    } else {\n      const itemsPerBucket = Math.floor(numElems / buckets)\n      const bucketsWithExtra = numElems % buckets\n      let curr = lower\n\n      for (let i = 0; i < buckets; i++) {\n        const bucketSize = itemsPerBucket + (i < bucketsWithExtra ? 1 : 0)\n        const ourFingerprint = this.#storage.fingerprint(curr, curr + bucketSize)\n        curr += bucketSize\n\n        let nextBound\n\n        if (curr === upper) {\n          nextBound = upperBound\n        } else {\n          let prevItem: VectorStorageItem, currItem: VectorStorageItem\n\n          this.#storage.iterate(curr - 1, curr + 1, (item, index) => {\n            if (index === curr - 1) prevItem = item\n            else currItem = item\n            return true\n          })\n\n          nextBound = this.getMinimalBound(prevItem!, currItem!)\n        }\n\n        o.append(this.encodeBound(nextBound))\n        o.append(encodeVarInt(Mode.Fingerprint))\n        o.append(ourFingerprint)\n      }\n    }\n  }\n\n  #renderOutput(o: WrappedBuffer) {\n    return o.unwrap()\n  }\n\n  exceededFrameSizeLimit(n: number) {\n    return this.#frameSizeLimit && n > this.#frameSizeLimit - 200\n  }\n\n  // Decoding\n  decodeTimestampIn(encoded: Uint8Array | WrappedBuffer) {\n    let timestamp = decodeVarInt(encoded)\n    timestamp = timestamp === 0 ? Number.MAX_VALUE : timestamp - 1\n    if (this.#lastTimestampIn === Number.MAX_VALUE || timestamp === Number.MAX_VALUE) {\n      this.#lastTimestampIn = Number.MAX_VALUE\n      return Number.MAX_VALUE\n    }\n    timestamp += this.#lastTimestampIn\n    this.#lastTimestampIn = timestamp\n    return timestamp\n  }\n\n  decodeBound(encoded: Uint8Array | WrappedBuffer) {\n    const timestamp = this.decodeTimestampIn(encoded)\n    const len = decodeVarInt(encoded)\n    if (len > this.#storage.idSize) throw Error(\"bound key too long\")\n    const id = new Uint8Array(this.#storage.idSize)\n    const encodedId = getBytes(encoded, Math.min(len, encoded.length))\n    id.set(encodedId)\n    return { timestamp, id: id as Uint8Array<ArrayBufferLike> }\n  }\n\n  // Encoding\n  encodeTimestampOut(timestamp: number) {\n    if (timestamp === Number.MAX_VALUE) {\n      this.#lastTimestampOut = Number.MAX_VALUE\n      return encodeVarInt(0)\n    }\n\n    const temp = timestamp\n    timestamp -= this.#lastTimestampOut\n    this.#lastTimestampOut = temp\n    return encodeVarInt(timestamp + 1)\n  }\n\n  encodeBound(key: VectorStorageItem) {\n    const tsBytes = this.encodeTimestampOut(key.timestamp)\n    const idLenBytes = encodeVarInt(key.id.length)\n    const output = new Uint8Array(tsBytes.length + idLenBytes.length + key.id.length)\n    output.set(tsBytes)\n    output.set(idLenBytes, tsBytes.length)\n    output.set(key.id, tsBytes.length + idLenBytes.length)\n    return output\n  }\n\n  getMinimalBound(prev: VectorStorageItem, curr: VectorStorageItem) {\n    if (curr.timestamp !== prev.timestamp) {\n      return this.#bound(curr.timestamp)\n    } else {\n      let sharedPrefixBytes = 0\n      const currKey = curr.id\n      const prevKey = prev.id\n\n      for (let i = 0; i < this.#storage.idSize; i++) {\n        if (currKey[i] !== prevKey[i]) break\n        sharedPrefixBytes++\n      }\n\n      return this.#bound(curr.timestamp, curr.id.subarray(0, sharedPrefixBytes + 1))\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/negentropy/utils.ts",
    "content": "import type { VectorStorageItem } from \"./vector-storage\"\nimport { WrappedBuffer } from \"./wrapped-buffer\"\n\nexport const PROTOCOL_VERSION = 0x61 // Version 1\nexport const FINGERPRINT_SIZE = 16\n\nexport enum Mode {\n  Skip = 0,\n  Fingerprint = 1,\n  IdList = 2,\n}\n\n/**\n * Decode variable int, also consumes the bytes from buf\n */\nexport function decodeVarInt(buf: Uint8Array | WrappedBuffer) {\n  let res = 0\n\n  while (1) {\n    if (buf.length === 0) throw Error(\"parse ends prematurely\")\n    let byte = 0\n    if (buf instanceof WrappedBuffer) {\n      byte = buf.shift()\n    } else {\n      byte = buf[0]\n      buf = buf.subarray(1)\n    }\n    res = (res << 7) | (byte & 127)\n    if ((byte & 128) === 0) break\n  }\n\n  return res\n}\n\nexport function encodeVarInt(n: number) {\n  if (n === 0) return new Uint8Array([0])\n\n  const o = []\n  while (n !== 0) {\n    o.push(n & 127)\n    n >>>= 7\n  }\n  o.reverse()\n\n  for (let i = 0; i < o.length - 1; i++) o[i] |= 128\n\n  return new Uint8Array(o)\n}\n\nexport function getByte(buf: WrappedBuffer) {\n  return getBytes(buf, 1)[0]\n}\n\nexport function getBytes(buf: WrappedBuffer | Uint8Array, n: number) {\n  if (buf.length < n) throw Error(\"parse ends prematurely\")\n  if (buf instanceof WrappedBuffer) {\n    return buf.shiftN(n)\n  } else {\n    const ret = buf.subarray(0, n)\n    buf = buf.subarray(n)\n    return ret\n  }\n}\n\nexport function compareUint8Array(a: Uint8Array, b: Uint8Array) {\n  for (let i = 0; i < a.byteLength; i++) {\n    if (a[i] < b[i]) return -1\n    if (a[i] > b[i]) return 1\n  }\n\n  if (a.byteLength > b.byteLength) return 1\n  if (a.byteLength < b.byteLength) return -1\n\n  return 0\n}\n\nexport function itemCompare(a: VectorStorageItem, b: VectorStorageItem) {\n  if (a.timestamp === b.timestamp) {\n    return compareUint8Array(a.id, b.id)\n  }\n\n  return a.timestamp - b.timestamp\n}\n"
  },
  {
    "path": "packages/system/src/negentropy/vector-storage.ts",
    "content": "import { hexToBytes } from \"@noble/hashes/utils.js\"\nimport { Accumulator } from \"./accumulator\"\nimport { itemCompare } from \"./utils\"\n\nexport interface VectorStorageItem {\n  timestamp: number\n  id: Uint8Array\n}\n\nconst IdSize = 32\n\nexport class NegentropyStorageVector {\n  #items: Array<VectorStorageItem> = []\n  #sealed = false\n\n  constructor(other?: Array<VectorStorageItem>) {\n    if (other) {\n      this.#items = other\n      this.#sealed = true\n    }\n  }\n\n  get idSize() {\n    return IdSize\n  }\n\n  insert(timestamp: number, id: string) {\n    if (this.#sealed) throw Error(\"already sealed\")\n    const idData = hexToBytes(id)\n    if (idData.byteLength !== IdSize) throw Error(\"bad id size for added item\")\n    this.#items.push({ timestamp, id: idData })\n  }\n\n  seal() {\n    if (this.#sealed) throw Error(\"already sealed\")\n    this.#sealed = true\n\n    this.#items.sort(itemCompare)\n\n    for (let i = 1; i < this.#items.length; i++) {\n      if (itemCompare(this.#items[i - 1], this.#items[i]) === 0) {\n        throw Error(\"duplicate item inserted\")\n      }\n    }\n  }\n\n  unseal() {\n    this.#sealed = false\n  }\n\n  size() {\n    this.#checkSealed()\n    return this.#items.length\n  }\n\n  getItem(i: number) {\n    this.#checkSealed()\n    if (i >= this.#items.length) throw Error(\"out of range\")\n    return this.#items[i]\n  }\n\n  iterate(begin: number, end: number, cb: (item: VectorStorageItem, index: number) => boolean) {\n    this.#checkSealed()\n    this.#checkBounds(begin, end)\n\n    for (let i = begin; i < end; ++i) {\n      if (!cb(this.#items[i], i)) break\n    }\n  }\n\n  findLowerBound(begin: number, end: number, bound: VectorStorageItem) {\n    this.#checkSealed()\n    this.#checkBounds(begin, end)\n\n    return this.#binarySearch(this.#items, begin, end, a => itemCompare(a, bound) < 0)\n  }\n\n  fingerprint(begin: number, end: number) {\n    const out = new Accumulator()\n\n    this.iterate(begin, end, item => {\n      out.add(item.id)\n      return true\n    })\n\n    return out.getFingerprint(end - begin)\n  }\n\n  #checkSealed() {\n    if (!this.#sealed) throw Error(\"not sealed\")\n  }\n\n  #checkBounds(begin: number, end: number) {\n    if (begin > end || end > this.#items.length) throw Error(\"bad range\")\n  }\n\n  #binarySearch(arr: Array<VectorStorageItem>, first: number, last: number, cmp: (item: VectorStorageItem) => boolean) {\n    let count = last - first\n\n    while (count > 0) {\n      let it = first\n      const step = Math.floor(count / 2)\n      it += step\n\n      if (cmp(arr[it])) {\n        first = ++it\n        count -= step + 1\n      } else {\n        count = step\n      }\n    }\n\n    return first\n  }\n}\n"
  },
  {
    "path": "packages/system/src/negentropy/wrapped-buffer.ts",
    "content": "export class WrappedBuffer {\n  #raw: Uint8Array\n  #length: number\n\n  constructor(buffer?: Uint8Array) {\n    this.#raw = buffer ? new Uint8Array(buffer) : new Uint8Array(512)\n    this.#length = buffer ? buffer.length : 0\n  }\n\n  unwrap() {\n    return this.#raw.subarray(0, this.#length)\n  }\n\n  get capacity() {\n    return this.#raw.byteLength\n  }\n\n  get length() {\n    return this.#length\n  }\n\n  set(val: ArrayLike<number>, offset?: number) {\n    this.#raw.set(val, offset)\n    this.#length = (offset ?? 0) + val.length\n  }\n\n  append(val: ArrayLike<number>) {\n    const targetSize = val.length + this.#length\n    this.resize(targetSize)\n\n    this.#raw.set(val, this.#length)\n    this.#length += val.length\n  }\n\n  clear() {\n    this.#length = 0\n    this.#raw.fill(0)\n  }\n\n  resize(newSize: number) {\n    if (this.capacity < newSize) {\n      const newCapacity = Math.max(this.capacity * 2, newSize)\n      const newArr = new Uint8Array(newCapacity)\n      newArr.set(this.#raw)\n      this.#raw = newArr\n    }\n  }\n\n  shift() {\n    const first = this.#raw[0]\n    this.#raw = this.#raw.subarray(1)\n    this.#length--\n    return first\n  }\n\n  shiftN(n = 1) {\n    const firstSubarray = this.#raw.subarray(0, n)\n    this.#raw = this.#raw.subarray(n)\n    this.#length -= n\n    return firstSubarray\n  }\n}\n"
  },
  {
    "path": "packages/system/src/nips.ts",
    "content": "export enum Nips {\n  Search = 50,\n  GetMatchingEventIds = 114,\n}\n"
  },
  {
    "path": "packages/system/src/nostr-link.ts",
    "content": "import {\n  bech32ToHex,\n  hexToBech32,\n  isHex,\n  removeUndefined,\n  unwrap,\n  Bech32Regex,\n  sanitizeRelayUrl,\n  appendDedupe,\n  NostrPrefix,\n  encodeTLV,\n  decodeTLV,\n  TLVEntryType,\n  isPrefixTlvIdHex,\n} from \"@snort/shared\"\nimport { EventExt, EventKind, Nip10, type NostrEvent, type TaggedNostrEvent } from \".\"\nimport { findTag } from \"./utils\"\nimport { hexToBytes } from \"@noble/hashes/utils.js\"\nimport { utf8ToBytes } from \"@noble/ciphers/utils.js\"\n\n/**\n * An object which can be stored in a nostr event as a tag\n */\nexport interface ToNostrEventTag {\n  toEventTag(): Array<string> | undefined\n  equals(other: ToNostrEventTag): boolean\n}\n\n/**\n * A hashtag [\"t\", ... ] tag\n */\nexport class NostrHashtagLink implements ToNostrEventTag {\n  constructor(readonly tag: string) {}\n\n  equals(other: ToNostrEventTag): boolean {\n    const otherTag = other.toEventTag()\n    return otherTag?.at(0) === \"t\" && otherTag?.at(1) === this.tag\n  }\n\n  toEventTag() {\n    return [\"t\", this.tag]\n  }\n}\n\n/**\n * A generic tag which could not be specifically parsed\n */\nexport class UnknownTag implements ToNostrEventTag {\n  constructor(readonly value: Array<string>) {}\n\n  equals(other: ToNostrEventTag): boolean {\n    const otherTag = other.toEventTag()\n    return otherTag?.at(0) === this.value.at(0) && otherTag?.at(1) === this.value.at(1)\n  }\n\n  toEventTag(): string[] | undefined {\n    return this.value\n  }\n}\n\n/**\n * Link scope for reply tags\n */\nexport enum LinkScope {\n  /**\n   * Link points to the root note of the thread\n   */\n  Root = \"root\",\n  /**\n   * Link points to the note being replied to\n   */\n  Reply = \"reply\",\n  /**\n   * Link mentions another object without directly replying\n   */\n  Mention = \"mention\",\n  /**\n   * Link mentions another object (`q` tag)\n   */\n  Quote = \"quote\",\n}\n\n/**\n * A link to another object on Nostr\n */\nexport class NostrLink implements ToNostrEventTag {\n  /**\n   * A nostr kind number (only a hint)\n   */\n  kind?: EventKind\n  /**\n   * Link scope for tagging\n   */\n  scope?: LinkScope\n\n  constructor(\n    readonly type: NostrPrefix,\n    readonly id: string,\n    kind?: number,\n    readonly author?: string,\n    readonly relays?: Array<string>,\n    scope?: LinkScope | string,\n  ) {\n    if (isPrefixTlvIdHex(type) && !isHex(id)) {\n      throw new Error(`ID must be hex: ${JSON.stringify(id)}`)\n    }\n    if (author && !isHex(author)) {\n      throw new Error(`Author must be hex: ${author}`)\n    }\n    this.kind = kind\n\n    // convert legacy marker string to scope\n    if (scope) {\n      if (typeof scope === \"string\") {\n        switch (scope.toLowerCase()) {\n          case \"root\": {\n            this.scope = LinkScope.Root\n            break\n          }\n          case \"reply\": {\n            this.scope = LinkScope.Reply\n            break\n          }\n          case \"mention\": {\n            this.scope = LinkScope.Mention\n            break\n          }\n          default: {\n            throw new Error(`Invalid marker: ${scope}`)\n          }\n        }\n      } else {\n        this.scope = scope\n      }\n    }\n  }\n\n  /**\n   * Encode the link into a [NIP-19](https://github.com/nostr-protocol/nips/blob/master/19.md) entity\n   */\n  encode(type?: NostrPrefix): string {\n    try {\n      // cant encode 'naddr' to 'note'/'nevent' because 'id' is not hex\n      const newType = this.type === NostrPrefix.Address ? this.type : (type ?? this.type)\n      if (newType === NostrPrefix.Note || newType === NostrPrefix.PrivateKey || newType === NostrPrefix.PublicKey) {\n        return hexToBech32(newType, this.id)\n      } else if (!isPrefixTlvIdHex(newType)) {\n        return encodeTLV(newType, utf8ToBytes(this.id), this.relays, this.kind, this.author)\n      } else {\n        return encodeTLV(newType, hexToBytes(this.id), this.relays, this.kind, this.author)\n      }\n    } catch (e) {\n      console.error(\"Invalid data\", this, e)\n      throw e\n    }\n  }\n\n  /**\n   * Gets a string identifier for this link\n   *\n   * Works similarly to EventExt.keyOf\n   */\n  get tagKey() {\n    if (this.type === NostrPrefix.Address) {\n      return `${this.kind}:${this.author}:${this.id}`\n    }\n    return this.id\n  }\n\n  /**\n   * Create an event tag for this link (Uses Nip10)\n   */\n  toEventTag() {\n    return Nip10.linkToTag(this)\n  }\n\n  matchesEvent(ev: NostrEvent) {\n    if (this.type === NostrPrefix.Address) {\n      const dTag = findTag(ev, \"d\")\n      if (dTag && dTag === this.id && unwrap(this.author) === ev.pubkey && unwrap(this.kind) === ev.kind) {\n        return true\n      }\n    } else if (this.type === NostrPrefix.Event || this.type === NostrPrefix.Note) {\n      const ifSetCheck = <T>(a: T | undefined, b: T) => {\n        return !a || a === b\n      }\n      return (\n        (EventExt.isReplaceable(ev.kind) || ifSetCheck(this.id, ev.id)) &&\n        ifSetCheck(this.author, ev.pubkey) &&\n        ifSetCheck(this.kind, ev.kind)\n      )\n    }\n\n    return false\n  }\n\n  /**\n   * Is the supplied event a reply to this link\n   */\n  isReplyToThis(ev: NostrEvent) {\n    if (this.matchesEvent(ev)) return false // cant match self\n\n    const thread = EventExt.extractThread(ev)\n    if (!thread) return false // non-thread events are not replies\n\n    return (thread.root?.equals(this) || thread.replyTo?.equals(this)) ?? false\n  }\n\n  /**\n   * Does the supplied event contain a tag matching this link\n   */\n  referencesThis(ev: NostrEvent) {\n    for (const t of ev.tags) {\n      if (t[0] === \"e\" && t[1] === this.id && (this.type === NostrPrefix.Event || this.type === NostrPrefix.Note)) {\n        return true\n      }\n      if (t[0] === \"a\" && this.type === NostrPrefix.Address) {\n        const [kind, author, dTag] = t[1].split(\":\")\n        if (Number(kind) === this.kind && author === this.author && dTag === this.id) {\n          return true\n        }\n      }\n      if (\n        t[0] === \"p\" &&\n        (this.type === NostrPrefix.Profile || this.type === NostrPrefix.PublicKey) &&\n        this.id === t[1]\n      ) {\n        return true\n      }\n    }\n    return false\n  }\n\n  equals(other: NostrLink) {\n    return other.tagKey === this.tagKey\n  }\n\n  static fromTag(tag: Array<string>, author?: string, kind?: number) {\n    const relays = tag.length > 2 ? [tag[2]] : undefined\n    switch (tag[0]) {\n      case \"E\": {\n        return new NostrLink(NostrPrefix.Event, tag[1], kind, author ?? tag[3], relays, LinkScope.Root)\n      }\n      case \"e\": {\n        const markerIsPubkey = isHex(tag[3])\n        return new NostrLink(\n          NostrPrefix.Event,\n          tag[1],\n          kind,\n          author ?? (markerIsPubkey ? tag[3] : tag[4]),\n          relays,\n          markerIsPubkey ? undefined : tag[3],\n        )\n      }\n      case \"P\":\n      case \"p\": {\n        // [\"p\", <id>, <relay>]\n        const scope = tag[0] === \"P\" ? LinkScope.Root : undefined\n        return new NostrLink(NostrPrefix.Profile, tag[1], kind, author, relays, scope)\n      }\n      case \"A\":\n      case \"a\": {\n        const [kind, author, dTag] = tag[1].split(\":\")\n        if (!isHex(author)) {\n          throw new Error(`Invalid author in a tag: ${tag[1]}`)\n        }\n        const scope = tag[3] ?? (tag[0] === \"A\" ? LinkScope.Root : undefined)\n        return new NostrLink(NostrPrefix.Address, dTag, Number(kind), author, relays, scope)\n      }\n    }\n    throw new Error(\"Unknown tag!\")\n  }\n\n  static tryFromTag(tag: Array<string>, author?: string, kind?: number) {\n    try {\n      return NostrLink.fromTag(tag, author, kind)\n    } catch (e) {\n      // ignored\n    }\n  }\n\n  static fromTags(tags: ReadonlyArray<Array<string>>) {\n    return removeUndefined(\n      tags.map(a => {\n        try {\n          return NostrLink.fromTag(a)\n        } catch {\n          // ignored, cant be mapped\n        }\n      }),\n    )\n  }\n\n  /**\n   * Parse all tags even if they are unknown\n   */\n  static fromAllTags(tags: ReadonlyArray<Array<string>>): Array<ToNostrEventTag> {\n    return removeUndefined(\n      tags.map(a => {\n        try {\n          return NostrLink.fromTag(a)\n        } catch {\n          return new UnknownTag(a)\n        }\n      }),\n    )\n  }\n\n  /**\n   * Return all tags which are replies\n   */\n  static replyTags(tags: ReadonlyArray<Array<string>>): Array<NostrLink> {\n    return tags.filter(t => [\"e\", \"a\"].includes(t[0])).map(t => NostrLink.fromTag(t)!)\n  }\n\n  /**\n   * Create an event link from an existing nostr event\n   */\n  static fromEvent(ev: TaggedNostrEvent | NostrEvent) {\n    let relays = \"relays\" in ev ? ev.relays : undefined\n    // extract the relay tags from the event to use in linking to this event\n    const eventRelays = removeUndefined(\n      ev.tags\n        .filter(a => a[0] === \"relays\" || a[0] === \"relay\" || (a[0] === \"r\" && ev.kind == EventKind.Relays))\n        .flatMap(a => a.slice(1).map(b => sanitizeRelayUrl(b))),\n    )\n    relays = appendDedupe(relays, eventRelays)\n\n    if (ev.kind >= 30_000 && ev.kind < 40_000) {\n      const dTag = unwrap(findTag(ev, \"d\"))\n      return new NostrLink(NostrPrefix.Address, dTag, ev.kind, ev.pubkey, relays)\n    }\n    // TODO: why no kind 10k ???\n    return new NostrLink(NostrPrefix.Event, ev.id, ev.kind, ev.pubkey, relays)\n  }\n\n  static profile(pk: string, relays?: Array<string>) {\n    return new NostrLink(NostrPrefix.Profile, pk, undefined, undefined, relays)\n  }\n\n  static publicKey(pk: string, relays?: Array<string>) {\n    return new NostrLink(NostrPrefix.PublicKey, pk, undefined, undefined, relays)\n  }\n}\n\nexport function tryParseNostrLink(link: string, prefixHint?: NostrPrefix): NostrLink | undefined {\n  try {\n    return parseNostrLink(link, prefixHint)\n  } catch {\n    return undefined\n  }\n}\n\nexport function isNostrLink(link: string) {\n  const entity = link.startsWith(\"web+nostr:\") || link.startsWith(\"nostr:\") ? link.split(\":\")[1] : link\n  const ent = entity.match(Bech32Regex)?.[0]\n  return ent !== undefined\n}\n\nexport function trimNostrLink(link: string) {\n  let entity = link.startsWith(\"web+nostr:\") || link.startsWith(\"nostr:\") ? link.split(\":\")[1] : link\n\n  // trim any non-bech32 chars\n  entity = entity.match(Bech32Regex)?.[0] ?? entity\n  return entity\n}\n\nexport function parseNostrLink(link: string, prefixHint?: NostrPrefix): NostrLink {\n  const entity = trimNostrLink(link)\n\n  const isPrefix = (prefix: NostrPrefix) => {\n    return entity.startsWith(prefix)\n  }\n\n  if (isPrefix(NostrPrefix.PublicKey)) {\n    const id = bech32ToHex(entity)\n    if (id.length !== 64) throw new Error(\"Invalid nostr link, must contain 32 byte id\")\n    return new NostrLink(NostrPrefix.PublicKey, id)\n  } else if (isPrefix(NostrPrefix.Note)) {\n    const id = bech32ToHex(entity)\n    if (id.length !== 64) throw new Error(\"Invalid nostr link, must contain 32 byte id\")\n    return new NostrLink(NostrPrefix.Note, id)\n  } else if (isPrefix(NostrPrefix.Profile) || isPrefix(NostrPrefix.Event) || isPrefix(NostrPrefix.Address)) {\n    const decoded = decodeTLV(entity)\n\n    const id = decoded.find(a => a.type === TLVEntryType.Special)?.value as string\n    const relays = decoded.filter(a => a.type === TLVEntryType.Relay).map(a => a.value as string)\n    const author = decoded.find(a => a.type === TLVEntryType.Author)?.value as string\n    const kind = decoded.find(a => a.type === TLVEntryType.Kind)?.value as number\n\n    if (isPrefix(NostrPrefix.Profile)) {\n      if (id.length !== 64) throw new Error(\"Invalid nostr link, must contain 32 byte id\")\n      return new NostrLink(NostrPrefix.Profile, id, kind, author, relays)\n    } else if (isPrefix(NostrPrefix.Event)) {\n      if (id.length !== 64) throw new Error(\"Invalid nostr link, must contain 32 byte id\")\n      return new NostrLink(NostrPrefix.Event, id, kind, author, relays)\n    } else if (isPrefix(NostrPrefix.Address)) {\n      return new NostrLink(NostrPrefix.Address, id, kind, author, relays)\n    }\n  } else if (prefixHint) {\n    return new NostrLink(prefixHint, link)\n  }\n  throw new Error(\"Invalid nostr link\")\n}\n"
  },
  {
    "path": "packages/system/src/nostr-system.ts",
    "content": "import debug from \"debug\"\n\nimport { unixNowMs } from \"@snort/shared\"\nimport type { NostrEvent, TaggedNostrEvent, OkResponse } from \"./nostr\"\nimport type { RelaySettings } from \"./connection\"\nimport type { RequestBuilder } from \"./request-builder\"\nimport { TraceTimeline } from \"./trace-timeline\"\nimport {\n  ProfileLoaderService,\n  type SystemInterface,\n  type SystemSnapshot,\n  type QueryLike,\n  OutboxModel,\n  EventKind,\n  type SystemConfig,\n} from \".\"\nimport { RelayMetadataLoader } from \"./outbox\"\nimport { type ConnectionPool, DefaultConnectionPool } from \"./connection-pool\"\nimport { QueryManager } from \"./query-manager\"\nimport type { RequestRouter } from \"./request-router\"\nimport { SystemBase } from \"./system-base\"\nimport { SocialGraph } from \"nostr-social-graph\"\nimport { base64 } from \"@scure/base\"\n\n/**\n * Manages nostr content retrieval system\n */\nexport class NostrSystem extends SystemBase implements SystemInterface {\n  #log = debug(\"System\")\n  #queryManager: QueryManager\n\n  readonly profileLoader: ProfileLoaderService\n  readonly pool: ConnectionPool\n  readonly relayLoader: RelayMetadataLoader\n  readonly requestRouter: RequestRouter | undefined\n  readonly traceTimeline: TraceTimeline\n\n  constructor(props: Partial<SystemConfig>) {\n    super(props)\n\n    this.profileLoader = new ProfileLoaderService(this, this.config.profiles)\n    this.relayLoader = new RelayMetadataLoader(this, this.config.relays)\n    this.traceTimeline = new TraceTimeline()\n    this.pool = new DefaultConnectionPool(this)\n\n    // if automatic outbox model, setup request router as OutboxModel\n    if (this.config.automaticOutboxModel) {\n      this.requestRouter = OutboxModel.fromSystem(this)\n    }\n\n    // Cache everything\n    if (this.config.cachingRelay) {\n      this.pool.on(\"event\", async (_relay, _sub, ev) => {\n        await this.config.cachingRelay?.event(ev)\n      })\n    }\n\n    // Hook on-event when building follow graph\n    if (this.config.buildFollowGraph) {\n      let evBuf: Array<TaggedNostrEvent> = []\n      let t: ReturnType<typeof setTimeout> | undefined\n      this.pool.on(\"event\", (_relay, _sub, ev) => {\n        if (ev.kind === EventKind.ContactList) {\n          // fire&forget update\n          this.userFollowsCache.update({\n            loaded: unixNowMs(),\n            created: ev.created_at,\n            pubkey: ev.pubkey,\n            follows: ev.tags,\n          })\n\n          // buffer social graph updates into 500ms window\n          evBuf.push(ev)\n          if (!t) {\n            t = setTimeout(() => {\n              this.config.socialGraphInstance.handleEvent(evBuf)\n              evBuf = []\n            }, 500)\n          }\n        }\n      })\n    }\n\n    this.#queryManager = new QueryManager(this)\n\n    // hook connection pool\n    this.pool.on(\"connected\", (id, _wasReconnect) => {\n      // TODO: metrics\n    })\n    this.pool.on(\"connectFailed\", address => {\n      // TODO: metrics\n    })\n    this.pool.on(\"event\", (_, _sub, ev) => {\n      // TODO: metrics\n    })\n    this.pool.on(\"disconnect\", (id, code) => {\n      // TODO: metrics\n    })\n    this.pool.on(\"auth\", (_, c, r, cb) => this.emit(\"auth\", c, r, cb))\n    this.pool.on(\"notice\", (addr, msg) => {\n      this.#log(\"NOTICE: %s %s\", addr, msg)\n    })\n    this.#queryManager.on(\"change\", () => this.emit(\"change\", this.takeSnapshot()))\n    this.#queryManager.on(\"trace\", (event, queryName) => {\n      this.traceTimeline.addTrace(event, queryName)\n    })\n  }\n\n  async Init(follows?: Array<string>) {\n    const t = [\n      this.config.relays.preload(follows),\n      this.profileCache.preload(follows),\n      this.userFollowsCache.preload(follows),\n    ]\n    await Promise.all(t)\n    await this.PreloadSocialGraph(follows)\n  }\n\n  async PreloadSocialGraph(follows?: Array<string>, root?: string) {\n    // Insert data to socialGraph from cache\n    if (this.config.buildFollowGraph) {\n      const graphRoot = root ?? \"00\".repeat(32)\n      // load saved social graph\n      if (\"localStorage\" in globalThis) {\n        const saved = localStorage.getItem(\"social-graph\")\n        if (saved) {\n          try {\n            const data = base64.decode(saved)\n            this.config.socialGraphInstance = await SocialGraph.fromBinary(graphRoot, data)\n            this.#log(\"Loaded social graph snapshot from LocalStorage %d bytes\", data.length)\n          } catch (e) {\n            this.#log(\"Failed to load serialzied social-graph: %O\", e)\n            localStorage.removeItem(\"social-graph\")\n          }\n        }\n      }\n      await this.config.socialGraphInstance.setRoot(graphRoot)\n      const snapshot = this.userFollowsCache.snapshot().filter(a => !follows || follows.includes(a.pubkey))\n      this.config.socialGraphInstance.handleEvent(\n        snapshot.map(a => ({\n          id: \"\",\n          sig: \"\",\n          content: \"\",\n          kind: 3,\n          pubkey: a.pubkey,\n          created_at: a.created,\n          tags: a.follows,\n        })),\n      )\n    }\n  }\n\n  async ConnectToRelay(address: string, options: RelaySettings) {\n    await this.pool.connect(address, options, false)\n  }\n\n  ConnectEphemeralRelay(address: string) {\n    return this.pool.connect(address, { read: true, write: true }, true)\n  }\n\n  DisconnectRelay(address: string) {\n    this.pool.disconnect(address)\n  }\n\n  GetQuery(id: string): QueryLike | undefined {\n    return this.#queryManager.get(id)\n  }\n\n  Fetch(req: RequestBuilder, cb?: (evs: Array<TaggedNostrEvent>) => void) {\n    return this.#queryManager.fetch(req, cb)\n  }\n\n  Query(req: RequestBuilder): QueryLike {\n    return this.#queryManager.query(req)\n  }\n\n  HandleEvent(subId: string, ev: TaggedNostrEvent) {\n    this.#queryManager.handleEvent(subId, ev)\n    this.config.cachingRelay?.event(ev)\n  }\n\n  async BroadcastEvent(ev: NostrEvent, cb?: (rsp: OkResponse) => void): Promise<OkResponse[]> {\n    this.HandleEvent(\"*\", { ...ev, relays: [] })\n    return await this.pool.broadcast(ev, cb)\n  }\n\n  async WriteOnceToRelay(address: string, ev: NostrEvent): Promise<OkResponse> {\n    this.HandleEvent(\"*\", { ...ev, relays: [address] })\n    return await this.pool.broadcastTo(address, ev)\n  }\n\n  takeSnapshot(): SystemSnapshot {\n    return {\n      queries: [...this.#queryManager].map(([, a]) => {\n        return {\n          id: a.id,\n          filters: a.filters,\n          subFilters: [],\n        }\n      }),\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/nostr.ts",
    "content": "import type { RelaySettings } from \"./connection\"\n\nexport interface NostrEvent {\n  id: string\n  pubkey: string\n  created_at: number\n  kind: number\n  tags: Array<Array<string>>\n  content: string\n  sig: string\n}\n\nexport interface TaggedNostrEvent extends NostrEvent {\n  /**\n   * A list of relays this event was seen on\n   */\n  relays?: Array<string>\n\n  /**\n   * Additional context\n   */\n  context?: object\n}\n\nexport type ReqCommand = [cmd: \"REQ\", id: string, ...filters: Array<ReqFilter>]\n\n/**\n * Raw REQ filter object\n */\nexport interface ReqFilter {\n  ids?: string[]\n  authors?: string[]\n  kinds?: number[]\n  \"#e\"?: string[]\n  \"#p\"?: string[]\n  \"#t\"?: string[]\n  \"#d\"?: string[]\n  \"#r\"?: string[]\n  \"#a\"?: string[]\n  \"#g\"?: string[]\n  search?: string\n  since?: number\n  until?: number\n  limit?: number\n  relays?: string[]\n  [key: string]: Array<string> | Array<number> | string | number | undefined | boolean\n}\n\n/**\n * Medatadata event content\n */\nexport type UserMetadata = {\n  name?: string\n  display_name?: string\n  about?: string\n  picture?: string\n  website?: string\n  banner?: string\n  nip05?: string\n  lud06?: string\n  lud16?: string\n}\n\nexport interface FullRelaySettings {\n  url: string\n  settings: RelaySettings\n}\n\nexport type NotSignedNostrEvent = Omit<NostrEvent, \"sig\">\n\nexport interface OkResponse {\n  ok: boolean\n  id: string\n  relay: string\n  message?: string\n  event: NostrEvent\n}\n"
  },
  {
    "path": "packages/system/src/note-collection.ts",
    "content": "import { appendDedupe, SortedMap } from \"@snort/shared\"\nimport { EventEmitter } from \"eventemitter3\"\nimport { EventExt, EventType, type TaggedNostrEvent } from \".\"\nimport { findTag } from \"./utils\"\n\nexport const EmptySnapshot: NoteStoreSnapshotData = []\nexport type NoteStoreSnapshotData = Array<TaggedNostrEvent>\nexport type NoteStoreHook = () => void\nexport type NoteStoreHookRelease = () => void\nexport type OnEventCallback = (e: Readonly<Array<TaggedNostrEvent>>) => void\nexport type OnEventCallbackRelease = () => void\nexport type OnEoseCallback = (c: string) => void\nexport type OnEoseCallbackRelease = () => void\n\nexport interface NosteStoreEvents {\n  event: (evs: Array<TaggedNostrEvent>) => void\n}\n\n/**\n * Generic note store interface\n */\nexport abstract class NoteStore extends EventEmitter<NosteStoreEvents> {\n  abstract add(ev: Readonly<TaggedNostrEvent> | Readonly<Array<TaggedNostrEvent>>): void\n  abstract clear(): void\n\n  abstract get snapshot(): NoteStoreSnapshotData\n}\n\nexport abstract class HookedNoteStore extends NoteStore {\n  #storeSnapshot: NoteStoreSnapshotData | undefined\n  #nextEmit?: ReturnType<typeof setTimeout>\n  #bufEmit: Array<TaggedNostrEvent> = []\n\n  /**\n   * Interval to emit changes in milli-seconds\n   */\n  protected emitInterval = 300\n\n  /**\n   * Snapshot is computed lazily: only materialised when first read after a change.\n   * This avoids the O(n²) GC pressure of copying all events on every addition.\n   */\n  get snapshot() {\n    if (this.#storeSnapshot === undefined) {\n      this.#storeSnapshot = this.takeSnapshot() ?? []\n    }\n    return this.#storeSnapshot\n  }\n\n  abstract override add(ev: Readonly<TaggedNostrEvent> | Readonly<Array<TaggedNostrEvent>>): void\n  abstract override clear(): void\n  protected abstract takeSnapshot(): NoteStoreSnapshotData | undefined\n\n  protected onChange(changes: Array<TaggedNostrEvent>): void {\n    // Invalidate the cached snapshot; it will be recomputed on next read.\n    this.#storeSnapshot = undefined\n    this.#bufEmit.push(...changes)\n    if (!this.#nextEmit) {\n      this.#nextEmit = setTimeout(() => {\n        this.flushEmit()\n      }, this.emitInterval)\n    }\n  }\n\n  flushEmit() {\n    // Always clear the timer handle so onChange() can schedule a new one\n    this.#nextEmit = undefined\n    if (this.#bufEmit.length > 0) {\n      const cloned = [...this.#bufEmit]\n      this.#bufEmit = []\n      this.emit(\"event\", cloned)\n    }\n  }\n\n  /**\n   * Cancel any pending buffered emit and immediately notify listeners with an\n   * empty array, signalling that the store has been cleared.\n   */\n  protected onClear() {\n    this.#bufEmit = []\n    if (this.#nextEmit) {\n      clearTimeout(this.#nextEmit)\n      this.#nextEmit = undefined\n    }\n    this.#storeSnapshot = undefined\n    this.emit(\"event\", [])\n  }\n}\n\n/**\n * A note store that holds a single replaceable event for a given user defined key generator function\n */\nexport class KeyedReplaceableNoteStore extends HookedNoteStore {\n  #keyFn: (ev: TaggedNostrEvent) => string\n  #events: SortedMap<string, TaggedNostrEvent> = new SortedMap([], (a, b) => b[1].created_at - a[1].created_at)\n\n  constructor(fn: (ev: TaggedNostrEvent) => string) {\n    super()\n    this.#keyFn = fn\n  }\n\n  add(ev: TaggedNostrEvent | Array<TaggedNostrEvent>) {\n    ev = Array.isArray(ev) ? ev : [ev]\n    const changes: Array<TaggedNostrEvent> = []\n    ev.forEach(a => {\n      const keyOnEvent = this.#keyFn(a)\n      const existing = this.#events.get(keyOnEvent)\n      if (a.created_at > (existing?.created_at ?? 0)) {\n        if (existing) {\n          a.relays = appendDedupe(existing.relays, a.relays)\n        }\n        this.#events.set(keyOnEvent, a)\n        changes.push(a)\n      }\n    })\n    if (changes.length > 0) {\n      this.onChange(changes)\n    }\n    return changes.length\n  }\n\n  clear() {\n    this.#events.clear()\n    this.onClear()\n  }\n\n  takeSnapshot() {\n    return [...this.#events.values()]\n  }\n}\n\n/**\n * General use note store based on kind ranges\n */\nexport class NoteCollection extends KeyedReplaceableNoteStore {\n  constructor() {\n    super(e => {\n      switch (EventExt.getType(e.kind)) {\n        case EventType.Addressable:\n          return `${e.kind}:${e.pubkey}:${findTag(e, \"d\")}`\n        case EventType.Replaceable:\n          return `${e.kind}:${e.pubkey}`\n        default:\n          return e.id\n      }\n    })\n  }\n}\n"
  },
  {
    "path": "packages/system/src/outbox/index.ts",
    "content": "import type { SystemInterface, UsersRelays } from \"..\"\n\nexport const DefaultPickNRelays = 2\n\nexport interface AuthorsRelaysCache {\n  getFromCache(pubkey?: string): UsersRelays | undefined\n  update(obj: UsersRelays): Promise<\"new\" | \"updated\" | \"refresh\" | \"no_change\">\n  buffer(keys: Array<string>): Promise<Array<string>>\n  bulkSet(objs: Array<UsersRelays>): Promise<void>\n}\n\nexport interface PickedRelays {\n  key: string\n  relays: Array<string>\n}\n\nexport type EventFetcher = {\n  Fetch: SystemInterface[\"Fetch\"]\n}\n\nexport * from \"./outbox-model\"\nexport * from \"./relay-loader\"\n"
  },
  {
    "path": "packages/system/src/outbox/outbox-model.ts",
    "content": "import { appendDedupe, dedupe, removeUndefined, unixNowMs, unwrap } from \"@snort/shared\"\nimport debug from \"debug\"\nimport {\n  EventKind,\n  type NostrEvent,\n  parseRelaysFromKind,\n  type ReqFilter,\n  RequestBuilder,\n  type SystemInterface,\n} from \"..\"\nimport { RelayListCacheExpire } from \"../const\"\nimport type { FlatReqFilter } from \"../query-optimizer\"\nimport { BaseRequestRouter } from \"../request-router\"\nimport { type AuthorsRelaysCache, DefaultPickNRelays, type EventFetcher, type PickedRelays } from \".\"\n\n/**\n * Simple outbox model using most popular relays\n */\nexport class OutboxModel extends BaseRequestRouter {\n  #log = debug(\"OutboxModel\")\n  #relays: AuthorsRelaysCache\n  #fetcher: EventFetcher\n\n  constructor(relays: AuthorsRelaysCache, fetcher: EventFetcher) {\n    super()\n    this.#relays = relays\n    this.#fetcher = fetcher\n  }\n\n  static fromSystem(system: SystemInterface) {\n    return new OutboxModel(system.config.relays, system)\n  }\n\n  /**\n   * Pick top relays for each user\n   * @param authors The authors whos relays will be picked\n   * @param pickN Number of relays to pick per pubkey\n   * @param type Read/Write relays\n   * @returns\n   */\n  pickTopRelays(authors: Array<string>, pickN: number, type: \"write\" | \"read\"): Array<PickedRelays> {\n    // map of pubkey -> [write relays]\n    const allRelays = authors.map(a => {\n      return {\n        key: a,\n        relays: this.#relays\n          .getFromCache(a)\n          ?.relays?.filter(a => (type === \"write\" ? a.settings.write : a.settings.read))\n          .sort(() => (Math.random() < 0.5 ? 1 : -1)),\n      }\n    })\n\n    const missing = allRelays.filter(a => a.relays === undefined || a.relays.length === 0)\n    const hasRelays = allRelays.filter(a => a.relays !== undefined && a.relays.length > 0)\n\n    // map of relay -> [pubkeys]\n    const relayUserMap = hasRelays.reduce((acc, v) => {\n      for (const r of unwrap(v.relays)) {\n        if (!acc.has(r.url)) {\n          acc.set(r.url, new Set([v.key]))\n        } else {\n          unwrap(acc.get(r.url)).add(v.key)\n        }\n      }\n      return acc\n    }, new Map<string, Set<string>>())\n\n    // selection algo will just pick relays with the most users\n    const topRelays = [...relayUserMap.entries()].sort(([, v], [, v1]) => v1.size - v.size)\n\n    if (missing.length > 0) {\n      this.#log(\"No relay metadata found, outbox model will not work for %O\", missing)\n    }\n    // <relay, key[]> - count keys per relay\n    // <key, relay[]> - pick n top relays\n    // <relay, key[]> - map keys per relay (for subscription filter)\n    return hasRelays\n      .map(k => {\n        // pick top N relays for this key\n        const relaysForKey = topRelays\n          .filter(([, v]) => v.has(k.key))\n          .slice(0, pickN)\n          .map(([k]) => k)\n        return { key: k.key, relays: relaysForKey }\n      })\n      .concat(\n        missing.map(a => {\n          return {\n            key: a.key,\n            relays: [],\n          }\n        }),\n      )\n  }\n\n  /**\n   * Split a request filter by authors\n   * @param filter Filter to split\n   * @param pickN Number of relays to pick per author\n   * @returns\n   */\n  forRequest(filter: ReqFilter, pickN?: number): Array<ReqFilter> {\n    // when sending a request prioritize the #p filter over authors\n    const pattern = filter[\"#p\"] !== undefined ? \"inbox\" : \"outbox\"\n    const key = filter[\"#p\"] !== undefined ? \"#p\" : \"authors\"\n    const authors = filter[key]\n    if ((authors?.length ?? 0) === 0) {\n      return [filter]\n    }\n\n    const topWriteRelays = this.pickTopRelays(\n      unwrap(authors),\n      pickN ?? DefaultPickNRelays,\n      pattern === \"inbox\" ? \"read\" : \"write\",\n    )\n    const pickedRelays = dedupe(topWriteRelays.flatMap(a => a.relays))\n\n    const picked = pickedRelays.map(a => {\n      const keysOnPickedRelay = dedupe(topWriteRelays.filter(b => b.relays.includes(a)).map(b => b.key))\n      return {\n        ...filter,\n        [key]: keysOnPickedRelay,\n        relays: appendDedupe(filter.relays, [a]),\n      } as ReqFilter\n    })\n    const noRelays = dedupe(topWriteRelays.filter(a => a.relays.length === 0).map(a => a.key))\n    if (noRelays.length > 0) {\n      picked.push({\n        ...filter,\n        [key]: noRelays,\n      } as ReqFilter)\n    }\n    this.#log(\"Picked: pattern=%s, input=%O, output=%O\", pattern, filter, picked)\n    return picked\n  }\n\n  /**\n   * Split a flat request filter by authors\n   * @param filter Filter to split\n   * @param pickN Number of relays to pick per author\n   * @returns\n   */\n  forFlatRequest(input: Array<FlatReqFilter>, pickN?: number): Array<FlatReqFilter> {\n    const authors = removeUndefined(input.flatMap(a => a.authors))\n    if (authors.length === 0) {\n      return input\n    }\n    const topRelays = this.pickTopRelays(authors, pickN ?? DefaultPickNRelays, \"write\")\n    const pickedRelays = dedupe(topRelays.flatMap(a => a.relays))\n\n    const picked = pickedRelays.flatMap(a => {\n      const authorsOnRelay = new Set(topRelays.filter(v => v.relays.includes(a)).map(v => v.key))\n      return input\n        .filter(v => v.authors && authorsOnRelay.has(v.authors))\n        .flatMap(b => {\n          // if flat filter isnt already relay tagged, create a copy with the relay set;\n          // otherwise add a duplicate with the authors picked relay alongside the original\n          if (!b.relay) {\n            return [{ ...b, relay: a }]\n          } else {\n            return [b, { ...b, relay: a }]\n          }\n        })\n    })\n    const noRelays = new Set(topRelays.filter(v => v.relays.length === 0).map(v => v.key))\n    if (noRelays.size > 0) {\n      picked.push(...input.filter(v => !v.authors || noRelays.has(v.authors)))\n    }\n\n    this.#log(\"Picked: pattern=%s, input=%O, output=%O\", \"outbox\", input, picked)\n    return picked\n  }\n\n  /**\n   * Pick relay inboxs for replies\n   * @param ev The reply event to send\n   * @param system Nostr system interface\n   * @param pickN Number of relays to pick per recipient\n   * @returns\n   */\n  async forReply(ev: NostrEvent, pickN?: number) {\n    const recipients = dedupe([ev.pubkey, ...ev.tags.filter(a => a[0] === \"p\").map(a => a[1])])\n    await this.updateRelayLists(recipients)\n    const relays = this.pickTopRelays(recipients, pickN ?? DefaultPickNRelays, \"read\")\n    const ret = removeUndefined(dedupe(relays.flatMap(a => a.relays)))\n\n    this.#log(\"Picked: pattern=%s, input=%O, output=%O\", \"inbox\", ev, ret)\n    return ret\n  }\n\n  async forReplyTo(pk: string, pickN?: number | undefined): Promise<string[]> {\n    const recipients = [pk]\n    await this.updateRelayLists(recipients)\n    const relays = this.pickTopRelays(recipients, pickN ?? DefaultPickNRelays, \"read\")\n    const ret = removeUndefined(dedupe(relays.flatMap(a => a.relays)))\n\n    this.#log(\"Picked: pattern=%s, input=%s, output=%O\", \"inbox\", pk, ret)\n    return ret\n  }\n\n  /**\n   * Update relay cache with latest relay lists\n   * @param authors The authors to update relay lists for\n   */\n  async updateRelayLists(authors: Array<string>) {\n    await this.#relays.buffer(authors)\n    const expire = unixNowMs() - RelayListCacheExpire\n    const expired = authors.filter(a => (this.#relays.getFromCache(a)?.loaded ?? 0) < expire)\n    if (expired.length > 0) {\n      this.#log(\"Updating relays for authors: %O\", expired)\n      const rb = new RequestBuilder(\"system-update-relays-for-outbox\")\n      rb.withFilter().authors(expired).kinds([EventKind.Relays, EventKind.ContactList])\n      const relayLists = await this.#fetcher.Fetch(rb)\n      await this.#relays.bulkSet(\n        removeUndefined(\n          relayLists.map(a => {\n            const relays = parseRelaysFromKind(a)\n            if (!relays) return undefined\n            return {\n              relays: relays,\n              pubkey: a.pubkey,\n              created: a.created_at,\n              loaded: unixNowMs(),\n            }\n          }),\n        ),\n      )\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/outbox/relay-loader.ts",
    "content": "import { EventKind, RequestBuilder, type TaggedNostrEvent, type UsersRelays, parseRelaysFromKind } from \"..\"\nimport { unixNowMs } from \"@snort/shared\"\nimport { RelayListCacheExpire } from \"../const\"\nimport { BackgroundLoader } from \"../background-loader\"\n\nexport class RelayMetadataLoader extends BackgroundLoader<UsersRelays> {\n  override name(): string {\n    return \"RelayMetadataLoader\"\n  }\n\n  override onEvent(e: Readonly<TaggedNostrEvent>): UsersRelays | undefined {\n    try {\n      const relays = parseRelaysFromKind(e)\n      if (!relays) return\n      return {\n        relays: relays,\n        pubkey: e.pubkey,\n        created: e.created_at,\n        loaded: unixNowMs(),\n      }\n    } catch (e) {\n      // ignored\n    }\n  }\n\n  override getExpireCutoff(): number {\n    return unixNowMs() - RelayListCacheExpire\n  }\n\n  protected override buildSub(missing: string[]): RequestBuilder {\n    const rb = new RequestBuilder(\"relay-loader\")\n    rb.withOptions({\n      timeout: 10000,\n      outboxPickN: 4,\n    })\n    rb.withFilter().authors(missing).kinds([EventKind.Relays, EventKind.ContactList])\n    return rb\n  }\n}\n"
  },
  {
    "path": "packages/system/src/pow-util.ts",
    "content": "import { sha256 } from \"@noble/hashes/sha2.js\"\nimport { bytesToHex, utf8ToBytes } from \"@noble/hashes/utils.js\"\n\nexport interface NostrPowEvent {\n  id: string\n  pubkey: string\n  created_at: number\n  kind: number\n  tags: Array<Array<string>>\n  content: string\n  sig: string\n}\n\nexport function minePow(e: NostrPowEvent, target: number) {\n  let ctr = 0\n\n  let nonceTagIdx = e.tags.findIndex(a => a[0] === \"nonce\")\n  if (nonceTagIdx === -1) {\n    nonceTagIdx = e.tags.length\n    e.tags.push([\"nonce\", ctr.toString(), target.toString()])\n  }\n  do {\n    e.tags[nonceTagIdx][1] = (++ctr).toString()\n    e.id = createId(e)\n  } while (countLeadingZeros(e.id) < target)\n\n  return e\n}\n\nfunction createId(e: NostrPowEvent) {\n  const payload = [0, e.pubkey, e.created_at, e.kind, e.tags, e.content]\n  return bytesToHex(sha256(utf8ToBytes(JSON.stringify(payload))))\n}\n\nexport function countLeadingZeros(hex: string) {\n  let count = 0\n\n  for (let i = 0; i < hex.length; i++) {\n    const nibble = parseInt(hex[i], 16)\n    if (nibble === 0) {\n      count += 4\n    } else {\n      count += Math.clz32(nibble) - 28\n      break\n    }\n  }\n\n  return count\n}\n"
  },
  {
    "path": "packages/system/src/pow-worker.ts",
    "content": "/// <reference lib=\"webworker\" />\n\nimport { minePow, type NostrPowEvent } from \"./pow-util\"\n\nexport interface PowWorkerMessage {\n  id: string\n  cmd: \"req\" | \"rsp\"\n  event: NostrPowEvent\n  target: number\n}\n\nglobalThis.onmessage = ev => {\n  const data = ev.data as PowWorkerMessage\n  if (data.cmd === \"req\") {\n    queueMicrotask(() => {\n      minePow(data.event, data.target)\n      data.cmd = \"rsp\"\n      globalThis.postMessage(data)\n    })\n  }\n}\n"
  },
  {
    "path": "packages/system/src/pow.ts",
    "content": "import type { NostrEvent } from \"./nostr\"\nimport type { PowWorkerMessage } from \"./pow-worker\"\n\nexport interface PowMiner {\n  minePow(ev: NostrEvent, target: number): Promise<NostrEvent>\n}\n\ninterface PowQueue {\n  resolve: (ev: NostrEvent) => void\n  reject: () => void\n  timeout: ReturnType<typeof setTimeout>\n}\n\nexport class PowWorker implements PowMiner {\n  #worker: Worker\n  #queue: Map<string, PowQueue> = new Map()\n\n  constructor(workerPath: string) {\n    this.#worker = new Worker(workerPath, {\n      type: \"module\",\n      name: \"POW\",\n    })\n    this.#worker.onerror = ev => {\n      console.error(ev)\n    }\n    this.#worker.onmessage = ev => {\n      const data = ev.data as PowWorkerMessage\n      const job = this.#queue.get(data.id)\n      if (job) {\n        clearTimeout(job.timeout)\n        this.#queue.delete(data.id)\n        job.resolve(data.event)\n      }\n    }\n  }\n\n  minePow(ev: NostrEvent, target: number) {\n    return new Promise<NostrEvent>((resolve, reject) => {\n      const req = {\n        id: crypto.randomUUID(),\n        cmd: \"req\",\n        event: ev,\n        target,\n      } as PowWorkerMessage\n      this.#queue.set(req.id, {\n        resolve: ex => resolve(ex),\n        reject,\n        timeout: setTimeout(() => {\n          this.#queue.delete(req.id)\n          reject()\n        }, 600_000),\n      })\n      this.#worker.postMessage(req)\n    })\n  }\n}\n"
  },
  {
    "path": "packages/system/src/profile-cache.ts",
    "content": "import { unixNowMs } from \"@snort/shared\"\nimport { EventKind, RequestBuilder, type TaggedNostrEvent } from \".\"\nimport { BackgroundLoader } from \"./background-loader\"\nimport { type CachedMetadata, mapEventToProfile } from \"./cache\"\nimport { ProfileCacheExpire } from \"./const\"\n\nexport type { ProfilePriority } from \"./background-loader\"\n\nexport class ProfileLoaderService extends BackgroundLoader<CachedMetadata> {\n  override name(): string {\n    return \"ProfileLoaderService\"\n  }\n\n  override onEvent(e: Readonly<TaggedNostrEvent>): CachedMetadata | undefined {\n    return mapEventToProfile(e)\n  }\n\n  override getExpireCutoff(): number {\n    return unixNowMs() - ProfileCacheExpire\n  }\n\n  override buildSub(missing: string[]): RequestBuilder {\n    const sub = new RequestBuilder(`profiles`)\n    sub.withFilter().kinds([EventKind.SetMetadata]).authors(missing)\n    return sub\n  }\n}\n"
  },
  {
    "path": "packages/system/src/query-manager.ts",
    "content": "import { unixNowMs } from \"@snort/shared\"\nimport debug from \"debug\"\nimport { EventEmitter } from \"eventemitter3\"\nimport {\n  type BuiltRawReqFilter,\n  DefaultRelays,\n  Nips,\n  type ReqFilter,\n  type RequestBuilder,\n  type SystemInterface,\n  type TaggedNostrEvent,\n} from \".\"\nimport type { ConnectionType } from \"./connection-pool\"\nimport { QueryFetchTimeout } from \"./const\"\nimport { EventExt } from \"./event-ext\"\nimport { NegentropyFlow } from \"./negentropy/negentropy-flow\"\nimport { NoteCollection } from \"./note-collection\"\nimport { Query, QueryTrace, type QueryTraceEvent } from \"./query\"\nimport { eventMatchesFilter, isRequestSatisfied } from \"./request-matcher\"\nimport { trimFilters } from \"./request-trim\"\nimport { RangeSync } from \"./sync/range-sync\"\n\ninterface QueryManagerEvents {\n  change: () => void\n  trace: (event: QueryTraceEvent, queryName?: string) => void\n  request: (subId: string, req: BuiltRawReqFilter) => void\n}\n\ninterface PendingTrace {\n  query: Query\n  trace: QueryTrace\n  connection: ConnectionType\n  filters: BuiltRawReqFilter\n}\n\n/**\n * Query manager handles sending requests to the nostr network\n */\nexport class QueryManager extends EventEmitter<QueryManagerEvents> {\n  #log = debug(\"QueryManager\")\n\n  /**\n   * All active queries\n   */\n  #queries: Map<string, Query> = new Map()\n\n  /**\n   * Pending traces waiting for connection availability\n   */\n  #pendingTraces: Array<PendingTrace> = []\n\n  /**\n   * System interface handle\n   */\n  #system: SystemInterface\n\n  /**\n   * Map tracking which connections have had retry listeners attached to prevent duplicates\n   */\n  #connectionListeners: Set<string> = new Set()\n\n  /**\n   * Handle for the cleanup interval so it can be cleared on destroy()\n   */\n  #cleanupInterval?: ReturnType<typeof setInterval>\n\n  constructor(system: SystemInterface) {\n    super()\n    this.#system = system\n\n    // Set up global connection listeners for cleanup\n    this.#setupConnectionListeners()\n\n    this.#cleanupInterval = setInterval(() => this.#cleanup(), 1_000)\n  }\n\n  /**\n   * Stop all timers and remove all listeners.\n   * Call this when the QueryManager is no longer needed to prevent leaks.\n   */\n  destroy() {\n    if (this.#cleanupInterval) {\n      clearInterval(this.#cleanupInterval)\n      this.#cleanupInterval = undefined\n    }\n    for (const [, q] of this.#queries) {\n      q.cancel()\n    }\n    this.#queries.clear()\n    this.removeAllListeners()\n  }\n\n  #setupConnectionListeners() {\n    // Listen for new connections to retry pending traces\n    this.#system.pool.on(\"connected\", address => {\n      const conn = this.#system.pool.getConnection(address)\n      if (conn) {\n        this.#connectionListeners.delete(conn.id)\n        // Retry immediately — the connection is now open\n        this.#retryPendingTraces(conn)\n      }\n    })\n\n    // Clean up traces when connection disconnects\n    this.#system.pool.on(\"disconnect\", address => {\n      const conn = this.#system.pool.getConnection(address)\n      if (conn) {\n        this.#connectionListeners.delete(conn.id)\n        this.#pendingTraces = this.#pendingTraces.filter(p => p.connection.id !== conn.id)\n\n        // Mark all traces for this connection as dropped\n        for (const [_, query] of this.#queries) {\n          for (const trace of query.traces) {\n            if (trace.connId === conn.id && !trace.finished) {\n              trace.drop()\n            }\n          }\n        }\n      }\n    })\n  }\n\n  get(id: string) {\n    return this.#queries.get(id)\n  }\n\n  /**\n   * Compute query to send to relays\n   */\n  query(req: RequestBuilder): Query {\n    const existing = this.#queries.get(req.id)\n    if (existing) {\n      if (existing.addRequest(req)) {\n        existing.start() // start emit again\n        this.emit(\"change\")\n      }\n      return existing\n    } else {\n      const q = new Query(req)\n      q.on(\"trace\", e => {\n        this.emit(\"trace\", e, req.id)\n      })\n      q.on(\"request\", (_id, fx) => {\n        this.#send(q, fx)\n      })\n      q.on(\"end\", () => {\n        q.off(\"trace\")\n        q.off(\"request\")\n      })\n\n      this.#queries.set(req.id, q)\n      if (req.numFilters > 0) {\n        this.emit(\"change\")\n      }\n      return q\n    }\n  }\n\n  /**\n   * Manually insert events into query result set\n   */\n  handleEvent(sub: string, ev: TaggedNostrEvent) {\n    this.#queries.forEach(q => q.addEvent(sub, ev))\n  }\n\n  /**\n   * Async fetch results\n   */\n  async fetch(req: RequestBuilder, cb?: (evs: Array<TaggedNostrEvent>) => void) {\n    req.withOptions({ groupingDelay: 0 }) //disable grouping timer\n    const filters = req.buildRaw()\n    const q = this.query(req)\n    if (cb) {\n      q.on(\"event\", cb)\n    }\n\n    const pDone = new Promise<void>((resolve, reject) => {\n      const t = setTimeout(() => {\n        reject(\n          new Error(\n            `QueryManager.fetch() timed out after ${QueryFetchTimeout}ms — EOSE never received for \"${req.id}\"`,\n          ),\n        )\n      }, QueryFetchTimeout)\n      q.once(\"eose\", () => {\n        clearTimeout(t)\n        resolve()\n      })\n    })\n\n    q.start()\n    await pDone\n    const results = q.feed.takeSnapshot()\n    if (cb) {\n      q.flush()\n      q.off(\"event\", cb)\n    }\n    return results.filter(a => filters.some(b => eventMatchesFilter(a, b)))\n  }\n\n  *[Symbol.iterator]() {\n    for (const kv of this.#queries) {\n      yield kv\n    }\n  }\n\n  async #send(q: Query, filters: Array<ReqFilter>) {\n    // check for empty filters\n    filters = trimFilters(filters)\n\n    if (filters.length === 0) {\n      this.#log(\"Dropping %s %o\", q.id)\n      return\n    }\n\n    // automated outbox model, load relays for queried authors\n    for (const f of filters) {\n      if (f.authors) {\n        this.#system.relayLoader.TrackKeys(f.authors)\n      }\n    }\n\n    let syncFrom: Array<TaggedNostrEvent> | undefined\n    // fetch results from cache first, flag qSend for sync\n    if (this.#system.cacheRelay && !q.skipCache) {\n      const data = await this.#system.cacheRelay.query([\"REQ\", q.id, ...filters])\n      syncFrom = data\n      if (data.length > 0) {\n        this.#log(\"Adding from cache %s %O\", q.id, data)\n        q.feed.add(data)\n      }\n    }\n\n    // remove satisfied filters\n    if ((syncFrom?.length ?? 0) > 0) {\n      // only remove the \"ids\" filters\n      const newFilters = filters.filter(a => !isRequestSatisfied(a, syncFrom!))\n      if (newFilters.length !== filters.length) {\n        this.#log(\"Removing satisfied filters %o %o\", newFilters, filters)\n        filters = newFilters\n      }\n    }\n\n    // nothing left to send\n    if (filters.length === 0) {\n      this.#log(\"Dropping %s, all filters are satisfied\", q.id)\n      // Emit EOSE to unblock any pending fetch() calls\n      q.emit(\"eose\")\n      return\n    }\n\n    if (this.#system.requestRouter) {\n      filters = this.#system.requestRouter.forAllRequest(filters)\n    }\n\n    const compressed = this.#system.optimizer.compress(filters).reduce(\n      (acc, v) => {\n        for (const r of v.relays ?? [\"\"]) {\n          acc[r] ??= []\n          acc[r].push(v)\n        }\n        return acc\n      },\n      {} as Record<string, Array<ReqFilter>>,\n    )\n    const qSend = Object.entries(compressed).map(([k, v]) => {\n      return {\n        relay: k,\n        filters: v,\n        syncFrom: this.#system.config.disableSyncModule || !q.useSyncModule ? undefined : syncFrom,\n      } as BuiltRawReqFilter\n    })\n    await Promise.all(qSend.map(a => this.#sendToRelays(q, a)))\n  }\n\n  /**\n   * Check if query can be sent to this connection\n   */\n  #canSendQuery(c: ConnectionType, q: BuiltRawReqFilter, query: Query) {\n    // query is not for this relay\n    if (q.relay && q.relay !== c.address) {\n      return false\n    }\n    // connection is down, dont send\n    if (c.isDown) {\n      return false\n    }\n    // cannot send unless relay is tagged on ephemeral relay connection\n    if (!q.relay && c.ephemeral) {\n      this.#log(\"Cant send non-specific REQ to ephemeral connection %O %O %O\", q, q.relay, c)\n      return false\n    }\n    // search not supported, cant send\n    if (q.filters.some(a => a.search) && !c.info?.supported_nips?.includes(Nips.Search)) {\n      this.#log(\"Cant send REQ to non-search relay\", c.address)\n      return false\n    }\n    // query already closed, cant send\n    if (query.canRemove()) {\n      this.#log(\"Cant send REQ when query is closed\", query.id, q)\n      return false\n    }\n    return true\n  }\n\n  /**\n   * Create a new trace for a query and connection\n   */\n  createTrace(query: Query, connection: ConnectionType, filters: BuiltRawReqFilter): QueryTrace {\n    const trace = new QueryTrace(connection.address, filters.filters, connection.id, query.leaveOpen)\n\n    // Set up event listeners for this trace\n    const eventHandler = (_relay: string, sub: string, ev: TaggedNostrEvent) => {\n      if (trace.id === sub) {\n        query.addEvent(sub, ev)\n      }\n    }\n\n    const eoseHandler = (sub: string) => {\n      if (trace.id === sub) {\n        trace.eose()\n        if (!trace.leaveOpen) {\n          connection.closeRequest(trace.id)\n          trace.close()\n        }\n      }\n    }\n\n    const closedHandler = (sub: string) => {\n      if (trace.id === sub) {\n        trace.remoteClosed()\n      }\n    }\n\n    this.#system.pool.on(\"event\", eventHandler)\n    connection.on(\"eose\", eoseHandler)\n    connection.on(\"closed\", closedHandler)\n    query.on(\"end\", () => {\n      this.#system.pool.off(\"event\", eventHandler)\n      connection.off(\"eose\", eoseHandler)\n      connection.off(\"closed\", closedHandler)\n    })\n\n    return trace\n  }\n\n  /**\n   * Attempt to send a trace to a connection\n   * @returns true if sent, false if queued\n   */\n  sendTrace(query: Query, trace: QueryTrace, connection: ConnectionType, filters: BuiltRawReqFilter): boolean {\n    trace.queued()\n\n    // Queue if the connection is not yet open — will be retried on 'connected'\n    if (!connection.isOpen) {\n      this.#pendingTraces.push({ query, trace, connection, filters })\n      this.#log(\"Query queued for %s (not yet open): %O\", connection.address, filters)\n      return false\n    }\n\n    // Check if connection can handle more subscriptions\n    if (connection.activeSubscriptions >= connection.maxSubscriptions) {\n      this.#pendingTraces.push({ query, trace, connection, filters })\n      this.#log(\"Query queued for %s (at max subscriptions): %O\", connection.address, filters)\n      return false\n    }\n\n    // Normalize filters\n    const normalizedFilters = filters.filters.map(a => {\n      const copy = { ...a }\n      delete copy[\"relays\"]\n      return copy\n    })\n\n    if (filters.syncFrom !== undefined && !this.#system.config.disableSyncModule) {\n      // Handle SYNC command - use sync logic\n      this.#handleSync(trace, connection, filters.syncFrom, normalizedFilters)\n    } else {\n      connection.request([\"REQ\", trace.id, ...normalizedFilters], () => trace.sent())\n    }\n\n    this.#log(\n      \"Sent query %s to %s %s (streaming=%s) %O\",\n      trace.id,\n      connection.address,\n      query.id,\n      query.leaveOpen,\n      filters,\n    )\n    return true\n  }\n\n  /**\n   * Handle SYNC command using negentropy or fallback\n   */\n  #handleSync(\n    trace: QueryTrace,\n    connection: ConnectionType,\n    eventSet: Array<TaggedNostrEvent>,\n    filters: Array<ReqFilter>,\n  ) {\n    if ((connection.info?.negentropy ?? NaN) >= 1) {\n      // Use negentropy sync\n      const neg = new NegentropyFlow(trace.id, connection, eventSet, filters)\n      neg.once(\"finish\", newFilters => {\n        if (newFilters.length > 0) {\n          // Send request for missing event ids\n          connection.request([\"REQ\", trace.id, ...newFilters])\n        } else {\n          // no results to query, emulate closed\n          connection.emit(\"closed\", trace.id, \"Nothing to sync\")\n        }\n      })\n      neg.once(\"error\", () => {\n        this.#fallbackSync(trace, connection, eventSet, filters)\n      })\n      neg.start()\n      trace.sentSync()\n    } else {\n      // No negentropy support, use fallback\n      this.#fallbackSync(trace, connection, eventSet, filters)\n    }\n  }\n\n  /**\n   * Fallback sync methods when negentropy is not available\n   */\n  #fallbackSync(\n    trace: QueryTrace,\n    connection: ConnectionType,\n    eventSet: Array<TaggedNostrEvent>,\n    filters: Array<ReqFilter>,\n  ) {\n    // Signal sync fallback to trace\n    trace.syncFallback()\n\n    // if the event is replaceable there is no need to use any special sync query,\n    // just send the filters directly\n    const isReplaceableSync = filters.every(a => a.kinds?.every(b => EventExt.isReplaceable(b) ?? false))\n    if (filters.some(a => a.since || a.until || a.ids || a.limit) || isReplaceableSync) {\n      connection.request([\"REQ\", trace.id, ...filters], () => trace.sent())\n    } else if (this.#system.config.fallbackSync === \"since\") {\n      this.#syncSince(trace, connection, eventSet, filters)\n    } else if (this.#system.config.fallbackSync === \"range-sync\") {\n      this.#syncRangeSync(trace, connection, eventSet, filters)\n    } else {\n      throw new Error(\"No fallback sync method\")\n    }\n  }\n\n  /**\n   * Using the latest data, fetch only newer items\n   */\n  #syncSince(\n    trace: QueryTrace,\n    connection: ConnectionType,\n    eventSet: Array<TaggedNostrEvent>,\n    filters: Array<ReqFilter>,\n  ) {\n    const latest = eventSet.reduce((acc, v) => (acc = v.created_at > acc ? v.created_at : acc), 0)\n    const newFilters = filters.map(a => {\n      if (a.since || latest === 0) return a\n      return {\n        ...a,\n        since: latest + 1,\n      }\n    })\n    connection.request([\"REQ\", trace.id, ...newFilters], () => trace.sent())\n  }\n\n  /**\n   * Using the RangeSync class, sync data using fixed window size\n   */\n  #syncRangeSync(\n    trace: QueryTrace,\n    connection: ConnectionType,\n    eventSet: Array<TaggedNostrEvent>,\n    filters: Array<ReqFilter>,\n  ) {\n    const rs = RangeSync.forFetcher(async (rb, cb) => {\n      return await new Promise((resolve, reject) => {\n        const results = new NoteCollection()\n        const f = rb.buildRaw()\n        connection.on(\"unverifiedEvent\", (c, e) => {\n          if (rb.id === c) {\n            cb?.([e])\n            results.add(e)\n          }\n        })\n        connection.on(\"eose\", s => {\n          if (s === rb.id) {\n            resolve(results.takeSnapshot())\n          }\n        })\n        connection.request([\"REQ\", rb.id, ...f], undefined)\n      })\n    })\n    const latest = eventSet.reduce((acc, v) => (acc = v.created_at > acc ? v.created_at : acc), 0)\n    rs.setStartPoint(latest + 1)\n    rs.on(\"event\", ev => {\n      ev.forEach(e => connection.emit(\"unverifiedEvent\", trace.id, e))\n    })\n    for (const f of filters) {\n      rs.sync(f)\n    }\n  }\n\n  /**\n   * Retry pending traces for a connection\n   */\n  #retryPendingTraces(connection: ConnectionType) {\n    const pending = this.#pendingTraces.filter(p => p.connection.id === connection.id)\n    for (const p of pending) {\n      const sent = this.sendTrace(p.query, p.trace, p.connection, p.filters)\n      if (sent) {\n        // Remove from queue\n        this.#pendingTraces = this.#pendingTraces.filter(pt => pt !== p)\n      } else {\n        // Still can't send, stop trying\n        break\n      }\n    }\n  }\n\n  async #sendToRelays(q: Query, qSend: BuiltRawReqFilter) {\n    if (qSend.relay) {\n      const nc = await this.#system.pool.connect(qSend.relay, { read: true, write: true }, true)\n      if (nc) {\n        if (this.#canSendQuery(nc, qSend, q)) {\n          const trace = this.createTrace(q, nc, qSend)\n          q.addTrace(trace)\n          this.sendTrace(q, trace, nc, qSend)\n          return [trace]\n        } else {\n          this.#log(\"Cannot send query to %s: validation failed\", qSend.relay)\n        }\n      } else {\n        console.warn(\"Failed to connect to new relay for:\", qSend.relay, q)\n      }\n    } else {\n      const ret = []\n      for (const [a, s] of this.#system.pool) {\n        if (!s.ephemeral) {\n          if (this.#canSendQuery(s, qSend, q)) {\n            const trace = this.createTrace(q, s, qSend)\n            q.addTrace(trace)\n            this.sendTrace(q, trace, s, qSend)\n            ret.push(trace)\n          } else {\n            this.#log(\"Cannot send query to %s: validation failed\", a)\n          }\n        }\n      }\n      // If no relays in pool, connect to default relays\n      if (ret.length === 0) {\n        this.#log(\"No relays connected, using defaults\")\n        for (const relayUrl of DefaultRelays) {\n          const nc = await this.#system.pool.connect(relayUrl, { read: true, write: false }, true)\n          if (nc) {\n            if (this.#canSendQuery(nc, qSend, q)) {\n              const trace = this.createTrace(q, nc, qSend)\n              q.addTrace(trace)\n              this.sendTrace(q, trace, nc, qSend)\n              ret.push(trace)\n            }\n          }\n        }\n      }\n      return ret\n    }\n\n    this.emit(\"request\", q.id, qSend)\n  }\n\n  #cleanup() {\n    let changed = false\n    for (const [k, v] of this.#queries) {\n      if (v.canRemove()) {\n        v.closeQuery()\n        this.#queries.delete(k)\n        this.#log(\"Deleted query %s\", k)\n        changed = true\n      } else {\n        const now = unixNowMs()\n        for (const trace of v.traces) {\n          if (!trace.leaveOpen && !trace.finished && trace.createdAt + v.timeout < now) {\n            trace.timeout()\n          }\n        }\n      }\n    }\n    if (changed) {\n      this.emit(\"change\")\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/query-optimizer/index.ts",
    "content": "import { schnorr } from \"@noble/curves/secp256k1.js\"\nimport { hexToBytes } from \"@noble/hashes/utils.js\"\nimport { EventExt } from \"../event-ext\"\nimport type { NostrEvent, ReqFilter } from \"../nostr\"\nimport { expandFilter } from \"./request-expander\"\nimport { flatMerge, mergeSimilar } from \"./request-merger\"\nimport { diffFilters } from \"./request-splitter\"\n\nexport interface FlatReqFilter {\n  keys: number\n  ids?: string\n  authors?: string\n  kinds?: number\n  \"#e\"?: string\n  \"#p\"?: string\n  \"#t\"?: string\n  \"#d\"?: string\n  \"#r\"?: string\n  search?: string\n  since?: number\n  until?: number\n  limit?: number\n  relay?: string\n  resultSetId: string\n}\n\nexport interface Optimizer {\n  expandFilter(f: ReqFilter): Array<FlatReqFilter>\n  getDiff(prev: Array<ReqFilter>, next: Array<ReqFilter>): Array<FlatReqFilter>\n  flatMerge(all: Array<FlatReqFilter>): Array<ReqFilter>\n  compress(all: Array<ReqFilter>): Array<ReqFilter>\n  schnorrVerify(ev: NostrEvent): boolean\n  batchVerify(evs: Array<NostrEvent>): Array<boolean>\n}\n\nexport const DefaultOptimizer = {\n  expandFilter: (f: ReqFilter) => {\n    return expandFilter(f)\n  },\n  getDiff: (prev: Array<ReqFilter>, next: Array<ReqFilter>) => {\n    const diff = diffFilters(\n      prev.flatMap(a => expandFilter(a)),\n      next.flatMap(a => expandFilter(a)),\n    )\n    return diff.added\n  },\n  flatMerge: (all: Array<FlatReqFilter>) => {\n    return flatMerge(all)\n  },\n  compress: (all: Array<ReqFilter>) => {\n    return mergeSimilar(all)\n  },\n  schnorrVerify: ev => {\n    // Fast path: already verified (e.g. came through EventExt.verify earlier)\n    if (EventExt.isVerified(ev)) return true\n    const id = EventExt.createId(ev)\n    const ok = schnorr.verify(hexToBytes(ev.sig), hexToBytes(id), hexToBytes(ev.pubkey))\n    if (ok) EventExt.markVerified(ev)\n    return ok\n  },\n  batchVerify: evs => {\n    return evs.map(ev => {\n      if (EventExt.isVerified(ev)) return true\n      const id = EventExt.createId(ev)\n      const ok = schnorr.verify(hexToBytes(ev.sig), hexToBytes(id), hexToBytes(ev.pubkey))\n      if (ok) EventExt.markVerified(ev)\n      return ok\n    })\n  },\n} as Optimizer\n"
  },
  {
    "path": "packages/system/src/query-optimizer/request-expander.ts",
    "content": "import { sha256 } from \"@snort/shared\"\nimport type { FlatReqFilter } from \".\"\nimport type { ReqFilter } from \"../nostr\"\n\n/**\n * Expand a filter into its most fine grained form\n */\nexport function expandFilter(f: ReqFilter): Array<FlatReqFilter> {\n  const ret: Array<FlatReqFilter> = []\n  const src = Object.entries(f)\n\n  const id = resultSetId(f)\n\n  // Filter entries that are arrays and keep the rest as is\n  const arrays: [string, Array<string> | Array<number>][] = src.filter(([, value]) => Array.isArray(value)) as [\n    string,\n    Array<string> | Array<number>,\n  ][]\n  const constants = Object.fromEntries(src.filter(([, value]) => !Array.isArray(value))) as {\n    [key: string]: string | number | undefined\n  }\n\n  // Recursive function to compute cartesian product\n  function cartesianProduct(arr: [string, Array<string> | Array<number>][], temp: [string, any][] = []) {\n    if (arr.length === 0) {\n      ret.push(createFilterObject(temp, constants, id))\n      return\n    }\n    for (let i = 0; i < arr[0][1].length; i++) {\n      cartesianProduct(arr.slice(1), temp.concat([[arr[0][0], arr[0][1][i]]]))\n    }\n  }\n\n  // Create filter object from the combination\n  function createFilterObject(\n    combination: [string, any][],\n    constants: { [key: string]: string | number | undefined },\n    resultId: string,\n  ) {\n    const filterObject = { ...Object.fromEntries(combination), ...constants } as FlatReqFilter\n    filterObject.resultSetId = resultId\n    return filterObject\n  }\n\n  cartesianProduct(arrays)\n  return ret\n}\n\nfunction resultSetId(f: ReqFilter) {\n  if (f.limit !== undefined || f.since !== undefined || f.until !== undefined) {\n    const arrays = Object.entries(f)\n      .filter(([, a]) => Array.isArray(a))\n      .map(a => a as [string, Array<string | number>])\n      .sort()\n    const input = arrays.map(([, a]) => a.join(\",\")).join(\",\")\n    return sha256(input)\n  }\n  return \"\"\n}\n"
  },
  {
    "path": "packages/system/src/query-optimizer/request-merger.ts",
    "content": "import { distance } from \"@snort/shared\"\nimport type { ReqFilter } from \"..\"\nimport type { FlatReqFilter } from \".\"\n\nexport function canMergeFilters(a: FlatReqFilter | ReqFilter, b: FlatReqFilter | ReqFilter): boolean {\n  if (a.resultSetId !== b.resultSetId) {\n    return false\n  }\n  return distance(a, b) <= 1\n}\n\nexport function mergeSimilar(filters: Array<ReqFilter>): Array<ReqFilter> {\n  const ret = []\n\n  const fCopy = [...filters]\n  while (fCopy.length > 0) {\n    // safe: guarded by length check above\n    // biome-ignore lint/style/noNonNullAssertion: shift() is defined because length > 0\n    const current = fCopy.shift()!\n    const mergeSet = [current]\n    for (let i = 0; i < fCopy.length; i++) {\n      const f = fCopy[i]\n      if (!mergeSet.some(v => !canMergeFilters(v, f))) {\n        mergeSet.push(fCopy.splice(i, 1)[0])\n        i--\n      }\n    }\n    ret.push(simpleMerge(mergeSet))\n  }\n  return ret\n}\n\n/**\n * Simply flatten all filters into one\n * @param filters\n * @returns\n */\nexport function simpleMerge(filters: Array<ReqFilter>) {\n  const result: Record<string, Array<string | number> | number | string | undefined> = {}\n\n  filters.forEach(filter => {\n    Object.entries(filter).forEach(([key, value]) => {\n      if (Array.isArray(value)) {\n        const existing = result[key]\n        if (existing === undefined) {\n          result[key] = [...value]\n        } else {\n          const arr = existing as Array<string | number>\n          const toAdd = (value as Array<string | number>).filter(a => !arr.includes(a))\n          arr.push(...toAdd)\n        }\n      } else {\n        result[key] = value as number | string | undefined\n      }\n    })\n  })\n\n  return result as ReqFilter\n}\n\n/**\n * Check if a filter includes another filter, as in the bigger filter will include the same results as the samller filter\n * @param bigger\n * @param smaller\n * @returns\n */\nexport function filterIncludes(bigger: ReqFilter, smaller: ReqFilter) {\n  const outside = bigger as Record<string, Array<string | number> | number>\n  for (const [k, v] of Object.entries(smaller)) {\n    if (outside[k] === undefined) {\n      return false\n    }\n    if (Array.isArray(v) && v.some(a => !(outside[k] as Array<string | number>).includes(a))) {\n      return false\n    }\n    if (typeof v === \"number\") {\n      if (k === \"since\" && (outside[k] as number) > v) {\n        return false\n      }\n      if (k === \"until\" && (outside[k] as number) < v) {\n        return false\n      }\n      // limit cannot be checked and is ignored\n    }\n  }\n  return true\n}\n\n/**\n * Merge expanded flat filters into combined concise filters\n * @param all\n * @returns\n */\nexport function flatMerge(all: Array<FlatReqFilter>): Array<ReqFilter> {\n  let ret: Array<ReqFilter> = []\n\n  // to compute filters which can be merged we need to calucate the distance change between each filter\n  // then we can merge filters which are exactly 1 change diff from each other\n  function mergeFiltersInSet(filters: Array<FlatReqFilter>) {\n    return filters.reduce(\n      (acc, a) => {\n        Object.entries(a).forEach(([k, v]) => {\n          if (v === undefined) return\n          if (k === \"since\" || k === \"until\" || k === \"limit\" || k === \"search\" || k === \"resultSetId\") {\n            acc[k] = v as number | string\n          } else {\n            acc[k] ??= []\n            const arr = acc[k] as Array<string | number>\n            const scalar = v as string | number\n            if (!arr.includes(scalar)) {\n              arr.push(scalar)\n            }\n          }\n        })\n        return acc\n      },\n      {} as Record<string, Array<string | number> | number | string>,\n    ) as ReqFilter\n  }\n\n  // reducer, kinda verbose\n  while (all.length > 0) {\n    // biome-ignore lint/style/noNonNullAssertion: shift() is defined because length > 0\n    const currentFilter = all.shift()!\n    const mergeSet = [currentFilter]\n\n    for (let i = 0; i < all.length; i++) {\n      const f = all[i]\n\n      if (mergeSet.every(a => canMergeFilters(a, f))) {\n        mergeSet.push(all.splice(i, 1)[0])\n        i--\n      }\n    }\n    ret.push(mergeFiltersInSet(mergeSet))\n  }\n\n  while (true) {\n    const n = mergeSimilar([...ret])\n    if (n.length === ret.length) {\n      break\n    }\n    ret = n\n  }\n  ret.forEach(a => {\n    delete a.resultSetId\n  })\n  return ret\n}\n"
  },
  {
    "path": "packages/system/src/query-optimizer/request-splitter.ts",
    "content": "import { flatFilterEq } from \"../utils\"\nimport type { FlatReqFilter } from \".\"\n\nexport function diffFilters(prev: Array<FlatReqFilter>, next: Array<FlatReqFilter>, calcRemoved?: boolean) {\n  const added = []\n  const removed = []\n\n  for (const n of next) {\n    const px = prev.findIndex(a => flatFilterEq(a, n))\n    if (px !== -1) {\n      prev.splice(px, 1)\n    } else {\n      added.push(n)\n    }\n  }\n  if (calcRemoved) {\n    for (const p of prev) {\n      const px = next.findIndex(a => flatFilterEq(a, p))\n      if (px !== -1) {\n        next.splice(px, 1)\n      } else {\n        removed.push(p)\n      }\n    }\n  }\n  const changed = added.length > 0 || removed.length > 0\n  return {\n    added: changed ? added : [],\n    removed: changed ? removed : [],\n    changed,\n  }\n}\n"
  },
  {
    "path": "packages/system/src/query.ts",
    "content": "import debug from \"debug\"\nimport { EventEmitter } from \"eventemitter3\"\nimport { unixNowMs } from \"@snort/shared\"\n\nimport type { ReqFilter, TaggedNostrEvent } from \".\"\nimport { NoteCollection } from \"./note-collection\"\nimport type { RequestBuilder } from \"./request-builder\"\nimport { eventMatchesFilter } from \"./request-matcher\"\n\nexport enum QueryTraceState {\n  NEW = \"NEW\", // New state, not used trace\n  QUEUED = \"QUEUED\", // When first created\n  WAITING = \"WAITING\", // Waiting for relay response (sent REQ to relay, will close on EOSE)\n  WAITING_STREAM = \"WAITING_STREAM\", // Streaming (sent REQ to relay, will stay open after EOSE)\n  SYNC_WAITING = \"SYNC_WAITING\", // Waiting for SYNC response (sent NEG-OPEN)\n  SYNC_FALLBACK = \"SYNC_FALLBACK\", // SYNC not supported, falling back to REQ\n  EOSE = \"EOSE\", // Server told us there are no more results\n  LOCAL_CLOSE = \"LOCAL_CLOSE\", // We sent close to server\n  REMOTE_CLOSE = \"REMOTE_CLOSE\", // Server closed the request\n  DROP = \"DROP\", // Dropped due to disconnect\n  TIMEOUT = \"TIMEOUT\", // Closed because taking too long\n}\n\nexport interface QueryTraceEvent {\n  id: string\n  relay: string\n  connId: string\n  state: QueryTraceState\n  timestamp: number\n  filters: Array<ReqFilter>\n}\n\ninterface QueryTraceEvents {\n  stateChange: (event: QueryTraceEvent) => void\n}\n\n/**\n * Tracing for relay query status - pure state machine\n */\nexport class QueryTrace extends EventEmitter<QueryTraceEvents> {\n  readonly id: string\n  readonly createdAt: number\n  #currentState: QueryTraceState = QueryTraceState.NEW\n  filters: Array<ReqFilter>\n\n  constructor(\n    readonly relay: string,\n    filters: Array<ReqFilter>,\n    readonly connId: string,\n    readonly leaveOpen: boolean,\n  ) {\n    super()\n    this.id = crypto.randomUUID()\n    this.createdAt = unixNowMs()\n    this.filters = filters\n  }\n\n  #setState(state: QueryTraceState) {\n    // Only emit state change if the state actually changed\n    if (this.#currentState === state) {\n      return\n    }\n    this.#currentState = state\n    this.emit(\"stateChange\", {\n      id: this.id,\n      relay: this.relay,\n      connId: this.connId,\n      state: state,\n      timestamp: unixNowMs(),\n      filters: this.filters,\n    })\n  }\n\n  get currentState() {\n    return this.#currentState\n  }\n\n  queued() {\n    this.#setState(QueryTraceState.QUEUED)\n  }\n\n  sent() {\n    this.#setState(this.leaveOpen ? QueryTraceState.WAITING_STREAM : QueryTraceState.WAITING)\n  }\n\n  sentSync() {\n    this.#setState(QueryTraceState.SYNC_WAITING)\n  }\n\n  syncFallback() {\n    this.#setState(QueryTraceState.SYNC_FALLBACK)\n  }\n\n  eose() {\n    this.#setState(QueryTraceState.EOSE)\n  }\n\n  remoteClosed() {\n    this.#setState(QueryTraceState.REMOTE_CLOSE)\n  }\n\n  close() {\n    this.#setState(QueryTraceState.LOCAL_CLOSE)\n  }\n\n  drop() {\n    this.#setState(QueryTraceState.DROP)\n  }\n\n  timeout() {\n    this.#setState(QueryTraceState.TIMEOUT)\n  }\n\n  /**\n   * If tracing is finished\n   */\n  get finished() {\n    return [\n      QueryTraceState.EOSE,\n      QueryTraceState.TIMEOUT,\n      QueryTraceState.DROP,\n      QueryTraceState.REMOTE_CLOSE,\n      QueryTraceState.LOCAL_CLOSE,\n    ].includes(this.#currentState)\n  }\n}\n\nexport interface QueryEvents {\n  trace: (event: QueryTraceEvent) => void\n  request: (subId: string, req: Array<ReqFilter>) => void\n  event: (evs: Array<TaggedNostrEvent>) => void\n  /**\n   * Emitted when the query will be removed\n   */\n  end: () => void\n  /**\n   * Emitted when the query has either been EOSE / CLOSED / TIMEOUT\n   */\n  eose: () => void\n}\n\n/**\n * Active query - collects events and tracks traces\n */\nexport class Query extends EventEmitter<QueryEvents> {\n  id: string\n\n  /**\n   * RequestBuilder instance\n   */\n  requests: Array<ReqFilter> = []\n\n  /**\n   * Which relays this query has already been executed on (read-only tracking)\n   */\n  #tracing: Map<string, QueryTrace> = new Map()\n\n  /**\n   * Leave the query open until its removed\n   */\n  #leaveOpen = false\n\n  /**\n   * Skip cache layer\n   */\n  skipCache = false\n\n  /**\n   * Use sync module for this query\n   */\n  useSyncModule = false\n\n  /**\n   * Time when this query can be removed\n   */\n  #cancelAt?: number\n\n  /**\n   * Feed object which collects events\n   */\n  #feed: NoteCollection\n\n  /**\n   * Maximum waiting time for this query\n   */\n  readonly timeout: number\n\n  /**\n   * Milliseconds to wait before sending query (debounce)\n   */\n  #groupingDelay?: number\n\n  /**\n   * Timer which waits for no-change before emitting filters\n   */\n  #groupTimeout?: ReturnType<typeof setTimeout>\n\n  /**\n   * If the query should only every replace a previous trace on the same connection\n   */\n  #replaceable: boolean = false\n\n  /**\n   * List of UUID request builder instance ids appended to this query\n   */\n  #builderInstances: Set<string>\n\n  /** Total number of duplicates produced by this query */\n  #duplicates: number\n\n  #log = debug(\"Query\")\n\n  constructor(req: RequestBuilder) {\n    super()\n    this.id = req.id\n    this.#feed = new NoteCollection()\n    this.#feed.on(\"event\", evs => this.emit(\"event\", evs))\n    this.#builderInstances = new Set([])\n    this.#leaveOpen = req.options?.leaveOpen ?? false\n    this.skipCache = req.options?.skipCache ?? false\n    this.useSyncModule = req.options?.useSyncModule ?? false\n    this.timeout = req.options?.timeout ?? 5_000\n    this.#groupingDelay = req.options?.groupingDelay ?? 100\n    this.#replaceable = req.options?.replaceable ?? false\n    this.#duplicates = 0\n\n    this.addRequest(req)\n  }\n\n  /**\n   * Adds another request to this one\n   */\n  addRequest(req: RequestBuilder) {\n    if (this.#builderInstances.has(req.instance)) {\n      return\n    }\n    if (req.options?.extraEvents) {\n      this.#feed.add(req.options.extraEvents)\n    }\n    if (req.numFilters > 0) {\n      this.#log(\"Add query %O to %s\", req, this.id)\n      this.requests.push(...req.buildRaw())\n      this.#builderInstances.add(req.instance)\n      return true\n    }\n    return false\n  }\n\n  isOpen() {\n    return this.#cancelAt === undefined && this.#leaveOpen\n  }\n\n  canRemove() {\n    return this.#cancelAt !== undefined && this.#cancelAt < unixNowMs()\n  }\n\n  /**\n   * Recompute the complete set of compressed filters from all query traces\n   */\n  get filters() {\n    return [...this.#tracing.values()].flatMap(a => a.filters)\n  }\n\n  get feed() {\n    return this.#feed\n  }\n\n  get snapshot() {\n    return this.#feed.snapshot\n  }\n\n  get traces() {\n    return [...this.#tracing.values()]\n  }\n\n  get leaveOpen() {\n    return this.#leaveOpen\n  }\n\n  /**\n   * Flush any buffered data\n   */\n  flush() {\n    this.feed.flushEmit()\n    this.#emitFilters()\n  }\n\n  /**\n   * Add a trace to this query\n   */\n  addTrace(trace: QueryTrace) {\n    this.#tracing.set(trace.id, trace)\n    trace.on(\"stateChange\", event => {\n      this.emit(\"trace\", event)\n\n      // Check if done when reaching terminal state\n      if (\n        [\n          QueryTraceState.EOSE,\n          QueryTraceState.TIMEOUT,\n          QueryTraceState.DROP,\n          QueryTraceState.REMOTE_CLOSE,\n          QueryTraceState.LOCAL_CLOSE,\n        ].includes(event.state)\n      ) {\n        this.#log(\"Trace state changed to %s, progress=%d\", event.state, this.progress)\n        if (this.progress === 1) {\n          this.emit(\"eose\")\n        }\n      }\n    })\n  }\n\n  /**\n   * Remove a trace from this query\n   */\n  removeTrace(traceId: string) {\n    this.#tracing.delete(traceId)\n  }\n\n  /**\n   * Add event to feed if it matches any trace filter\n   */\n  addEvent(sub: string, e: TaggedNostrEvent) {\n    const trace = this.#tracing.get(sub)\n    if (trace || sub === \"*\") {\n      const filters = trace ? trace.filters : this.filters\n      if (filters.some(v => eventMatchesFilter(e, v))) {\n        const added = this.feed.add(e)\n        if (added === 0) {\n          this.#duplicates++\n          const ratio = this.#duplicates / this.feed.snapshot.length\n          if (ratio > 2) {\n            this.#log(\"High number of duplicates for: \", this.id, ratio, this.feed.snapshot.length)\n          }\n        }\n      } else {\n        this.#log(\"Event did not match filter, rejecting %O\", e)\n      }\n    }\n  }\n\n  /**\n   * This function should be called when this Query object and FeedStore is no longer needed\n   */\n  cancel() {\n    this.#cancelAt = unixNowMs() + 1_000\n  }\n\n  uncancel() {\n    this.#cancelAt = undefined\n  }\n\n  cleanup() {\n    if (this.#groupTimeout) {\n      clearTimeout(this.#groupTimeout)\n      this.#groupTimeout = undefined\n    }\n    this.emit(\"end\")\n  }\n\n  closeQuery() {\n    for (const qt of this.#tracing.values()) {\n      if (!qt.finished) {\n        qt.close()\n      }\n    }\n    this.cleanup()\n  }\n\n  /**\n   * Get the progress to EOSE, can be used to determine when we should load more content\n   */\n  get progress() {\n    const traces = [...this.#tracing.values()]\n    const thisProgress = traces.reduce((acc, v) => (acc += v.finished ? 1 : 0), 0) / traces.length\n    if (isNaN(thisProgress)) {\n      return 0\n    }\n    return thisProgress\n  }\n\n  /**\n   * Start filter emit\n   */\n  start() {\n    if (this.#groupingDelay) {\n      if (this.#groupTimeout !== undefined) return\n      this.#groupTimeout = setTimeout(() => {\n        this.#emitFilters()\n        this.#groupTimeout = undefined\n      }, this.#groupingDelay)\n    } else {\n      this.#emitFilters()\n    }\n  }\n\n  async #emitFilters() {\n    if (this.requests.length === 0) return\n    this.#log(\"Starting emit of %s\", this.id)\n    const rawFilters = [...this.requests]\n    this.requests = []\n    if (this.#replaceable) {\n      rawFilters.push(...this.filters)\n    }\n    if (rawFilters.length > 0) {\n      this.emit(\"request\", this.id, rawFilters)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/relays.ts",
    "content": "import { removeUndefined, sanitizeRelayUrl } from \"@snort/shared\"\nimport EventKind from \"./event-kind\"\nimport type { FullRelaySettings, NostrEvent } from \"./nostr\"\n\nexport function parseRelayTag(tag: Array<string>) {\n  if (tag[0] !== \"r\") return\n  const url = sanitizeRelayUrl(tag[1])\n  if (url) {\n    return {\n      url,\n      settings: {\n        read: tag[2] === \"read\" || tag[2] === undefined,\n        write: tag[2] === \"write\" || tag[2] === undefined,\n      },\n    } as FullRelaySettings\n  }\n}\n\nexport function parseRelayTags(tag: Array<Array<string>>) {\n  return removeUndefined(tag.map(parseRelayTag))\n}\n\nexport function parseRelaysFromKind(ev: NostrEvent) {\n  if (ev.kind === EventKind.ContactList) {\n    let relaysInContent: Record<string, { read: boolean; write: boolean }> | undefined\n    try {\n      relaysInContent =\n        ev.content.length > 0\n          ? (JSON.parse(ev.content) as Record<string, { read: boolean; write: boolean }>)\n          : undefined\n    } catch {\n      // Malformed kind-3 content — treat as if no relay list in content\n      relaysInContent = undefined\n    }\n    if (relaysInContent) {\n      return removeUndefined(\n        Object.entries(relaysInContent).map(([k, v]) => {\n          const url = sanitizeRelayUrl(k)\n          if (url) {\n            return {\n              url,\n              settings: {\n                read: v.read,\n                write: v.write,\n              },\n            } as FullRelaySettings\n          }\n        }),\n      )\n    }\n  } else if (ev.kind === EventKind.Relays) {\n    return parseRelayTags(ev.tags)\n  }\n}\n\n/**\n * Convert relay settings into NIP-65 relay tag\n */\nexport function settingsToRelayTag(rx: FullRelaySettings) {\n  const rTag = [\"r\", rx.url]\n  if (rx.settings.read && !rx.settings.write) {\n    rTag.push(\"read\")\n  }\n  if (rx.settings.write && !rx.settings.read) {\n    rTag.push(\"write\")\n  }\n  if (rx.settings.read || rx.settings.write) {\n    return rTag\n  }\n}\n"
  },
  {
    "path": "packages/system/src/request-builder.ts",
    "content": "import { appendDedupe, dedupe, NostrPrefix, removeUndefined, sanitizeRelayUrl, unwrap } from \"@snort/shared\"\n\nimport type EventKind from \"./event-kind\"\nimport { EventExt, NostrLink, type ToNostrEventTag } from \".\"\nimport type { ReqFilter, TaggedNostrEvent } from \"./nostr\"\nimport type { RequestRouter } from \"./request-router\"\nimport type { NostrEvent } from \"nostr-social-graph\"\n\n/**\n * A built REQ filter ready for sending to System\n */\nexport interface BuiltRawReqFilter {\n  filters: Array<ReqFilter>\n  relay: string\n  // Use set sync from an existing set of events\n  syncFrom?: Array<TaggedNostrEvent>\n}\n\nexport interface RequestBuilderOptions {\n  /**\n   * Dont send CLOSE directly after EOSE and allow events to stream in\n   */\n  leaveOpen?: boolean\n\n  /**\n   * Pick N relays per pubkey when using outbox strategy\n   */\n  outboxPickN?: number\n\n  /**\n   * Max wait time for this request\n   */\n  timeout?: number\n\n  /**\n   * How many milli-seconds to wait to allow grouping\n   */\n  groupingDelay?: number\n\n  /**\n   * Replace the query every time a change in the query is detected\n   *\n   * eg. Live stream chat reactions\n   */\n  replaceable?: boolean\n\n  /***\n   * If this query should skip the cache system\n   */\n  skipCache?: boolean\n\n  /**\n   * Enable sync module (negentropy/range-sync)\n   * When true, will use sync protocol if cache data is available\n   * When false, will send plain REQ without sync\n   * Default: false\n   */\n  useSyncModule?: boolean\n\n  /**\n   * Extra events to include in the store, added automatically\n   */\n  extraEvents?: Array<NostrEvent>\n}\n\n/**\n * Nostr REQ builder\n */\nexport class RequestBuilder {\n  id: string\n  instance: string\n  #builders: Array<RequestFilterBuilder>\n  #options?: RequestBuilderOptions\n\n  constructor(id: string) {\n    this.instance = crypto.randomUUID()\n    this.id = id\n    this.#builders = []\n  }\n\n  get numFilters() {\n    return this.#builders.length\n  }\n\n  get filterBuilders() {\n    return this.#builders\n  }\n\n  get options() {\n    return this.#options\n  }\n\n  clear() {\n    this.#builders = []\n    this.#options = undefined\n  }\n\n  /**\n   * Add another request builders filters to this one\n   */\n  add(other: RequestBuilder) {\n    this.#builders.push(...other.#builders)\n  }\n\n  withFilter() {\n    const ret = new RequestFilterBuilder()\n    this.#builders.push(ret)\n    return ret\n  }\n\n  withBareFilter(f: ReqFilter) {\n    const ret = new RequestFilterBuilder(f)\n    this.#builders.push(ret)\n    return ret\n  }\n\n  withOptions(opt: RequestBuilderOptions) {\n    this.#options = {\n      ...this.#options,\n      ...opt,\n    }\n    return this\n  }\n\n  /**\n   * Set relays for all filters in this builder\n   */\n  withRelays(relays: Array<string>) {\n    for (const builder of this.#builders) {\n      builder.relay(relays)\n    }\n    return this\n  }\n\n  buildRaw(): Array<ReqFilter> {\n    return this.#builders.map(f => f.filter)\n  }\n}\n\n/**\n * Builder class for a single request filter\n */\nexport class RequestFilterBuilder {\n  #filter: ReqFilter\n\n  constructor(f?: ReqFilter) {\n    this.#filter = f ?? {}\n  }\n\n  get filter() {\n    return {\n      ...this.#filter,\n    }\n  }\n\n  /**\n   * Use a specific relay for this request filter\n   */\n  relay(u: string | Array<string>) {\n    const relays = Array.isArray(u) ? u : [u]\n    this.#filter.relays = appendDedupe(this.#filter.relays, removeUndefined(relays.map(a => sanitizeRelayUrl(a))))\n    // make sure we dont have an empty array\n    if (this.#filter.relays?.length === 0) {\n      this.#filter.relays = undefined\n    }\n    return this\n  }\n\n  ids(ids: Array<string>) {\n    this.#filter.ids = appendDedupe(this.#filter.ids, ids)\n    return this\n  }\n\n  authors(authors?: Array<string>) {\n    if (!authors) return this\n    this.#filter.authors = appendDedupe(\n      this.#filter.authors,\n      authors.filter(a => a.length === 64),\n    )\n    return this\n  }\n\n  kinds(kinds?: Array<EventKind>) {\n    if (!kinds) return this\n    this.#filter.kinds = appendDedupe(this.#filter.kinds, kinds)\n    return this\n  }\n\n  since(since?: number) {\n    if (!since) return this\n    this.#filter.since = since\n    return this\n  }\n\n  until(until?: number) {\n    if (!until) return this\n    this.#filter.until = until\n    return this\n  }\n\n  limit(limit?: number) {\n    if (!limit) return this\n    this.#filter.limit = limit\n    return this\n  }\n\n  tag(key: \"e\" | \"p\" | \"d\" | \"t\" | \"r\" | \"a\" | \"g\" | string, value?: Array<string>) {\n    if (!value) return this\n    this.#filter[`#${key}`] = appendDedupe(this.#filter[`#${key}`] as Array<string>, value)\n    return this\n  }\n\n  /**\n   * Query by a nostr tag\n   */\n  tags(tags: Array<ToNostrEventTag>) {\n    for (const tag of tags) {\n      const tt = tag.toEventTag()\n      if (tt) {\n        this.tag(tt[0], [tt[1]])\n      }\n    }\n    return this\n  }\n\n  search(keyword?: string) {\n    if (!keyword) return this\n    this.#filter.search = keyword\n    return this\n  }\n\n  /**\n   * Get event from link\n   */\n  link(link: NostrLink | ToNostrEventTag) {\n    if (link instanceof NostrLink) {\n      if (link.type === NostrPrefix.Address) {\n        this.tag(\"d\", [link.id])\n          .kinds([unwrap(link.kind)])\n          .authors([unwrap(link.author)])\n      } else {\n        // dont query with ids when looking for replaceable events\n        if (!link.kind || !EventExt.isReplaceable(link.kind)) {\n          this.ids([link.id])\n        }\n        if (link.author) {\n          this.authors([link.author])\n        }\n        if (link.kind !== undefined) {\n          this.kinds([link.kind])\n        }\n      }\n      link.relays?.forEach(v => this.relay(v))\n    } else {\n      const [k, v] = link.toEventTag()!\n      this.#filter[`#${k}`] = appendDedupe(this.#filter[`#${k}`] as Array<string>, [v])\n    }\n    return this\n  }\n\n  /**\n   * Get replies to link with e/a tags\n   */\n  replyToLink(links: Array<NostrLink>) {\n    const types = dedupe(links.map(a => a.type))\n    if (types.length > 1) throw new Error(\"Cannot add multiple links of different kinds\")\n\n    const tags = removeUndefined(links.map(a => a.toEventTag()))\n    this.tag(\n      tags[0][0],\n      tags.map(v => v[1]),\n    )\n    this.relay(removeUndefined(links.flatMap(a => a.relays)))\n    return this\n  }\n\n  /**\n   * Build/expand this filter into a set of relay specific queries\n   */\n  build(model?: RequestRouter, options?: RequestBuilderOptions): Array<ReqFilter> {\n    if (model) {\n      return model.forRequest(this.filter, options?.outboxPickN)\n    }\n\n    return [this.filter]\n  }\n}\n"
  },
  {
    "path": "packages/system/src/request-matcher.ts",
    "content": "import type { NostrEvent, ReqFilter, TaggedNostrEvent } from \"./nostr\"\n\nexport function eventMatchesFilter(ev: NostrEvent, filter: ReqFilter) {\n  if (filter.since && ev.created_at < filter.since) {\n    return false\n  }\n  if (filter.until && ev.created_at > filter.until) {\n    return false\n  }\n  if (!(filter.ids?.includes(ev.id) ?? true)) {\n    return false\n  }\n  if (!(filter.authors?.includes(ev.pubkey) ?? true)) {\n    return false\n  }\n  if (!(filter.kinds?.includes(ev.kind) ?? true)) {\n    return false\n  }\n  return true\n}\n\nexport function isRequestSatisfied(filter: ReqFilter, results: Array<TaggedNostrEvent>) {\n  if (filter.ids && filter.ids.every(a => results.some(b => b.id === a))) {\n    return true\n  }\n}\n"
  },
  {
    "path": "packages/system/src/request-router.ts",
    "content": "import { unwrap } from \"@snort/shared\"\nimport type { NostrEvent, ReqFilter } from \"./nostr\"\nimport type { FlatReqFilter } from \"./query-optimizer\"\n\n/**\n * Request router managed splitting of requests to one or more relays, and which relay to send events to.\n */\nexport interface RequestRouter {\n  /**\n   * Pick relays to send an event to\n   * @param pk The pubkey you are replying to\n   * @param system Nostr system interface\n   * @param pickN Number of relays to pick per recipient\n   * @returns\n   */\n  forReplyTo(pk: string, pickN?: number): Promise<Array<string>>\n\n  /**\n   * Pick relays to send an event to\n   * @param ev The reply event to send\n   * @param system Nostr system interface\n   * @param pickN Number of relays to pick per recipient\n   * @returns\n   */\n  forReply(ev: NostrEvent, pickN?: number): Promise<Array<string>>\n\n  /**\n   * Split a request filter to one or more relays.\n   * @param filter Filter to split\n   * @param pickN Number of relays to pick\n   * @returns\n   */\n  forRequest(filter: ReqFilter, pickN?: number): Array<ReqFilter>\n\n  /**\n   * Split a request filter to one or more relays.\n   * @param filter Filters to split\n   * @param pickN Number of relays to pick\n   * @returns\n   */\n  forFlatRequest(filter: Array<FlatReqFilter>, pickN?: number): Array<FlatReqFilter>\n\n  /**\n   * Same as forRequest, but merges the results\n   * @param filters\n   */\n  forAllRequest(filters: Array<ReqFilter>): Array<ReqFilter>\n}\n\nexport abstract class BaseRequestRouter implements RequestRouter {\n  abstract forReplyTo(pk: string, pickN?: number): Promise<Array<string>>\n  abstract forReply(ev: NostrEvent, pickN?: number): Promise<Array<string>>\n  abstract forRequest(filter: ReqFilter, pickN?: number): Array<ReqFilter>\n  abstract forFlatRequest(filter: FlatReqFilter[], pickN?: number): Array<FlatReqFilter>\n\n  forAllRequest(filters: Array<ReqFilter>) {\n    const allSplit = filters\n      .map(a => this.forRequest(a))\n      .reduce((acc, v) => {\n        for (const vn of v) {\n          for (const r of (vn.relays?.length ?? 0) > 0 ? unwrap(vn.relays) : [\"\"]) {\n            const existing = acc.get(r)\n            if (existing) {\n              existing.push(vn)\n            } else {\n              acc.set(r, [vn])\n            }\n          }\n        }\n        return acc\n      }, new Map<string, Array<ReqFilter>>())\n\n    return [...allSplit.values()].flat()\n  }\n}\n"
  },
  {
    "path": "packages/system/src/request-trim.ts",
    "content": "import type { ReqFilter } from \"./nostr\"\n\n/**\n * Remove empty filters, filters which would result in no results\n */\nexport function trimFilters(filters: Array<ReqFilter>) {\n  const fNew = []\n  for (const f of filters) {\n    const ent = Object.entries(f).filter(([, v]) => Array.isArray(v))\n    if (ent.every(([, v]) => (v as Array<string | number>).length > 0)) {\n      fNew.push(f)\n    }\n  }\n  return fNew\n}\n"
  },
  {
    "path": "packages/system/src/signer.ts",
    "content": "import { getPublicKey } from \"@snort/shared\"\nimport { EventExt } from \"./event-ext\"\nimport { Nip4WebCryptoEncryptor } from \"./impl/nip4\"\nimport { Nip44Encryptor } from \"./impl/nip44\"\nimport type { NostrEvent, NotSignedNostrEvent } from \"./nostr\"\nimport { bytesToHex, randomBytes } from \"@noble/hashes/utils.js\"\nimport { schnorr } from \"@noble/curves/secp256k1.js\"\n\nexport type SignerSupports = \"nip04\" | \"nip44\" | string\n\nexport interface EventSigner {\n  init(): Promise<void>\n  getPubKey(): Promise<string> | string\n  nip4Encrypt(content: string, key: string): Promise<string>\n  nip4Decrypt(content: string, otherKey: string): Promise<string>\n  nip44Encrypt(content: string, key: string): Promise<string>\n  nip44Decrypt(content: string, otherKey: string): Promise<string>\n  sign(ev: NostrEvent | NotSignedNostrEvent): Promise<NostrEvent>\n  get supports(): Array<SignerSupports>\n}\n\n/**\n * Helper function to decrypt either NIP-04 or NIP-44\n */\nexport async function decryptSigner(content: string, signer: EventSigner, otherKey?: string) {\n  const isNip4 = content.includes(\"?iv=\")\n  const key = otherKey ?? (await signer.getPubKey())\n  return await (isNip4 ? signer.nip4Decrypt(content, key) : signer.nip44Decrypt(content, key))\n}\n\nexport class PrivateKeySigner implements EventSigner {\n  #publicKey: string\n  #privateKey: string\n\n  constructor(privateKey: string | Uint8Array) {\n    if (typeof privateKey === \"string\") {\n      this.#privateKey = privateKey\n    } else {\n      this.#privateKey = bytesToHex(privateKey)\n    }\n    this.#publicKey = getPublicKey(this.#privateKey)\n  }\n\n  /**\n   * Generate a new private key\n   */\n  static random() {\n    const k = schnorr.keygen().secretKey\n    return new PrivateKeySigner(k)\n  }\n\n  get supports(): string[] {\n    return [\"nip04\", \"nip44\"]\n  }\n\n  get privateKey() {\n    return this.#privateKey\n  }\n\n  init(): Promise<void> {\n    return Promise.resolve()\n  }\n\n  getPubKey(): string {\n    return this.#publicKey\n  }\n\n  async nip4Encrypt(content: string, otherKey: string) {\n    const enc = new Nip4WebCryptoEncryptor(this.privateKey, otherKey)\n    return await enc.encryptData(content)\n  }\n\n  async nip4Decrypt(content: string, otherKey: string) {\n    const enc = new Nip4WebCryptoEncryptor(this.privateKey, otherKey)\n    return await enc.decryptData(content)\n  }\n\n  async nip44Encrypt(content: string, otherKey: string) {\n    const enc = new Nip44Encryptor(this.#privateKey, otherKey)\n    return enc.encryptData(content)\n  }\n\n  async nip44Decrypt(content: string, otherKey: string) {\n    const enc = new Nip44Encryptor(this.#privateKey, otherKey)\n    return enc.decryptData(content)\n  }\n\n  sign(ev: NostrEvent): Promise<NostrEvent> {\n    EventExt.sign(ev, this.#privateKey)\n    return Promise.resolve(ev)\n  }\n}\n"
  },
  {
    "path": "packages/system/src/sync/diff-sync.ts",
    "content": "import debug from \"debug\"\nimport { EventEmitter } from \"eventemitter3\"\nimport {\n  decryptSigner,\n  EventBuilder,\n  type EventSigner,\n  NostrEvent,\n  type NostrLink,\n  type NotSignedNostrEvent,\n  type SystemInterface,\n} from \"..\"\nimport { SafeSync } from \"./safe-sync\"\n\ninterface TagDiff {\n  type: \"add\" | \"remove\" | \"replace\" | \"update\"\n  tag: Array<string> | Array<Array<string>>\n}\n\ninterface DiffSyncTagsEvents {\n  change(): void\n}\n\n/**\n * Add/Remove tags from event\n */\nexport class DiffSyncTags extends EventEmitter<DiffSyncTagsEvents> {\n  #log = debug(\"DiffSyncTags\")\n  #sync: SafeSync\n  #changes: Array<TagDiff> = []\n  #changesEncrypted: Array<TagDiff> = []\n  #decryptedContent?: string\n\n  constructor(\n    readonly link: NostrLink,\n    readonly contentEncrypted: boolean,\n  ) {\n    super()\n    this.#sync = new SafeSync(link)\n  }\n\n  /**\n   * Get the raw storage event\n   */\n  get value() {\n    return this.#sync.value\n  }\n\n  /**\n   * Get the current tag set\n   */\n  get tags() {\n    return this.#applyChanges(this.#sync.value?.tags ?? [], this.#changes)\n  }\n\n  /**\n   * Get decrypted content\n   */\n  get encryptedTags() {\n    if (this.#decryptedContent && this.#decryptedContent.startsWith(\"[\") && this.#decryptedContent.endsWith(\"]\")) {\n      try {\n        const tags = JSON.parse(this.#decryptedContent) as Array<Array<string>>\n        return tags\n      } catch {\n        // Corrupted encrypted tag data — return empty rather than crashing\n        return []\n      }\n    }\n    return []\n  }\n\n  /**\n   * Add a tag\n   */\n  add(tag: Array<string> | Array<Array<string>>, encrypted = false) {\n    ;(encrypted ? this.#changesEncrypted : this.#changes).push({\n      type: \"add\",\n      tag,\n    })\n    this.emit(\"change\")\n  }\n\n  /**\n   * Remove a tag\n   */\n  remove(tag: Array<string> | Array<Array<string>>, encrypted = false) {\n    ;(encrypted ? this.#changesEncrypted : this.#changes).push({\n      type: \"remove\",\n      tag,\n    })\n    this.emit(\"change\")\n  }\n\n  /**\n   * Update a tag (remove+add)\n   */\n  update(tag: Array<string> | Array<Array<string>>, encrypted = false) {\n    ;(encrypted ? this.#changesEncrypted : this.#changes).push({\n      type: \"update\",\n      tag,\n    })\n    this.emit(\"change\")\n  }\n\n  /**\n   * Replace all the tags\n   */\n  replace(tag: Array<Array<string>>, encrypted = false) {\n    ;(encrypted ? this.#changesEncrypted : this.#changes).push({\n      type: \"replace\",\n      tag,\n    })\n    this.emit(\"change\")\n  }\n\n  async sync(signer: EventSigner | undefined, system: SystemInterface) {\n    const isSync = await this.#sync.sync(system)\n    await this.#afterSync(signer)\n    if (isSync) this.emit(\"change\")\n  }\n\n  /**\n   * Apply changes and save\n   */\n  async persist(signer: EventSigner, system: SystemInterface, content?: string) {\n    if (!this.#sync.didSync) {\n      await this.#sync.sync(system)\n      await this.#afterSync(signer)\n    }\n\n    const isNew = this.#sync.value === undefined\n    const next = this.#nextEvent(content)\n    let nextDecryptedContent\n    // content is populated as tags, encrypt it\n    if (next.content.length > 0 && !content) {\n      nextDecryptedContent = next.content\n      next.content = await signer.nip44Encrypt(next.content, await signer.getPubKey())\n    }\n    await this.#sync.update(next, signer, system, !isNew)\n\n    // update decrypted content after internal sync update\n    this.#decryptedContent = nextDecryptedContent\n    this.emit(\"change\")\n  }\n\n  async #afterSync(signer: EventSigner | undefined) {\n    if (this.#sync.value?.content && this.contentEncrypted && signer) {\n      const decrypted = await decryptSigner(this.#sync.value.content, signer)\n      this.#decryptedContent = decrypted\n      this.emit(\"change\")\n    }\n  }\n\n  #nextEvent(content?: string): NotSignedNostrEvent {\n    if (content !== undefined && this.#changesEncrypted.length > 0) {\n      throw new Error(\"Cannot have both encrypted tags and explicit content\")\n    }\n    let isNew = false\n    let next = this.#sync.value ? { ...this.#sync.value } : undefined\n    if (!next) {\n      const eb = new EventBuilder()\n      eb.fromLink(this.link)\n      next = eb.build()\n      isNew = true\n    }\n\n    // apply changes onto next\n    next.tags = this.#applyChanges(next.tags, this.#changes)\n    if (this.#changesEncrypted.length > 0 && !content) {\n      const encryptedTags = this.#applyChanges(isNew ? [] : this.encryptedTags, this.#changesEncrypted)\n      next.content = JSON.stringify(encryptedTags)\n    } else if (content) {\n      next.content = content\n    }\n\n    this.#log(\"Built next event %O\", next)\n    return next\n  }\n\n  #applyChanges(tags: Array<Array<string>>, changes: Array<TagDiff>) {\n    for (const change of changes) {\n      if (change.tag.length === 0 && change.type !== \"replace\") continue\n\n      switch (change.type) {\n        case \"add\": {\n          const changeTags = Array.isArray(change.tag[0])\n            ? (change.tag as Array<Array<string>>)\n            : [change.tag as Array<string>]\n          for (const changeTag of changeTags) {\n            const existing = tags.findIndex(a => changeTag[0] === a[0] && changeTag[1] === a[1])\n            if (existing === -1) {\n              tags.push(changeTag)\n            } else {\n              this.#log(\"Tag already exists: %O\", changeTag)\n            }\n          }\n          break\n        }\n        case \"remove\": {\n          const changeTags = Array.isArray(change.tag[0])\n            ? (change.tag as Array<Array<string>>)\n            : [change.tag as Array<string>]\n          for (const changeTag of changeTags) {\n            const existing = tags.findIndex(a => changeTag[0] === a[0] && changeTag[1] === a[1])\n            if (existing !== -1) {\n              tags.splice(existing, 1)\n            } else {\n              this.#log(\"Could not find tag to remove: %O\", changeTag)\n            }\n          }\n          break\n        }\n        case \"update\": {\n          const changeTags = Array.isArray(change.tag[0])\n            ? (change.tag as Array<Array<string>>)\n            : [change.tag as Array<string>]\n          for (const changeTag of changeTags) {\n            const existing = tags.findIndex(a => changeTag[0] === a[0] && changeTag[1] === a[1])\n            if (existing !== -1) {\n              tags[existing] = changeTag\n            } else {\n              this.#log(\"Could not find tag to update: %O\", changeTag)\n            }\n          }\n          break\n        }\n        case \"replace\": {\n          tags.splice(0, tags.length)\n          tags.push(...(change.tag as Array<Array<string>>))\n          break\n        }\n      }\n    }\n\n    // remove duplicates\n    return tags.filter((v, i, arr) => {\n      let hasAnother = false\n      for (let x = i + 1; x < arr.length; x++) {\n        if (arr[x][0] === v[0] && arr[x][1] === v[1]) {\n          hasAnother = true\n          break\n        }\n      }\n      return !hasAnother\n    })\n  }\n}\n"
  },
  {
    "path": "packages/system/src/sync/index.ts",
    "content": "export * from \"./safe-sync\"\nexport * from \"./range-sync\"\nexport * from \"./json-in-event-sync\"\nexport * from \"./diff-sync\"\n"
  },
  {
    "path": "packages/system/src/sync/json-in-event-sync.ts",
    "content": "import { SafeSync } from \"./safe-sync\"\nimport {\n  decryptSigner,\n  EventBuilder,\n  type EventSigner,\n  type NostrEvent,\n  type NostrLink,\n  type SystemInterface,\n} from \"..\"\nimport debug from \"debug\"\nimport EventEmitter from \"eventemitter3\"\n\ninterface JsonEventSyncEvents {\n  change(): void\n}\n\nexport class JsonEventSync<T> extends EventEmitter<JsonEventSyncEvents> {\n  #log = debug(\"JsonEventSync\")\n  #sync: SafeSync\n  #json: T\n\n  constructor(\n    initValue: T,\n    readonly link: NostrLink,\n    readonly encrypt: boolean,\n  ) {\n    super()\n    this.#sync = new SafeSync(link)\n    this.#json = initValue\n  }\n\n  get json(): T {\n    return { ...this.#json }\n  }\n\n  /**\n   * Check if there are pending changes (local value differs from synced value)\n   */\n  get hasPendingChanges(): boolean {\n    if (!this.#sync.value) return false\n\n    try {\n      const syncedJson = JSON.parse(this.#sync.value.content)\n      return JSON.stringify(syncedJson) !== JSON.stringify(this.#json)\n    } catch {\n      return false\n    }\n  }\n\n  /**\n   * Update the local JSON value without saving to Nostr\n   * Call persist() separately to save changes\n   */\n  setJson(val: T) {\n    this.#json = val\n    this.emit(\"change\")\n  }\n\n  async sync(signer: EventSigner | undefined, system: SystemInterface) {\n    const res = await this.#sync.sync(system)\n    this.#log(\"Sync result %O\", res)\n    if (res) {\n      if (this.encrypt) {\n        if (!signer) return\n        this.#json = JSON.parse(await decryptSigner(this.#sync.value!.content, signer)) as T\n      } else {\n        this.#json = JSON.parse(this.#sync.value!.content) as T\n      }\n    }\n\n    this.emit(\"change\")\n    return res\n  }\n\n  /**\n   * Persist the current local JSON state to Nostr\n   */\n  async persist(signer: EventSigner, system: SystemInterface) {\n    this.#log(\"Persisting: %O\", this.#json)\n    let next = this.#sync.value ? ({ ...this.#sync.value } as NostrEvent) : undefined\n    let isNew = false\n    if (!next) {\n      // create a new event if we already did sync and still undefined\n      if (this.#sync.didSync) {\n        const eb = new EventBuilder()\n        eb.fromLink(this.link)\n        next = eb.build()\n        isNew = true\n      } else {\n        throw new Error(\"Cannot persist with no previous value\")\n      }\n    }\n\n    next.content = JSON.stringify(this.#json)\n    if (this.encrypt) {\n      next.content = await signer.nip44Encrypt(next.content, await signer.getPubKey())\n    }\n\n    await this.#sync.update(next, signer, system, !isNew)\n    this.emit(\"change\")\n  }\n\n  /**\n   * Update the json content and immediately save to Nostr\n   * @deprecated Use setJson() + persist() for better control\n   */\n  async updateJson(val: T, signer: EventSigner, system: SystemInterface) {\n    this.setJson(val)\n    await this.persist(signer, system)\n  }\n}\n"
  },
  {
    "path": "packages/system/src/sync/range-sync.ts",
    "content": "import { unixNow } from \"@snort/shared\"\nimport EventEmitter from \"eventemitter3\"\nimport { type ReqFilter, RequestBuilder, type SystemInterface, type TaggedNostrEvent } from \"..\"\n\n/**\n * When nostr was created\n */\nconst NostrBirthday: number = new Date(2021, 1, 1).getTime() / 1000\n\ninterface RangeSyncEvents {\n  event: (ev: Array<TaggedNostrEvent>) => void\n  scan: (from: number) => void\n}\n\n/**\n * A simple time based sync for pulling lots of data from nostr\n */\nexport class RangeSync extends EventEmitter<RangeSyncEvents> {\n  #id = crypto.randomUUID()\n  #start: number = NostrBirthday\n  #windowSize: number = 60 * 60 * 12\n  #fetcher!: SystemInterface[\"Fetch\"]\n\n  private constructor() {\n    super()\n  }\n\n  static forSystem(system: SystemInterface) {\n    const rs = new RangeSync()\n    rs.#fetcher = (r, c) => system.Fetch(r, c)\n    return rs\n  }\n\n  static forFetcher(fn: SystemInterface[\"Fetch\"]) {\n    const rs = new RangeSync()\n    rs.#fetcher = fn\n    return rs\n  }\n\n  /**\n   * Set window size in seconds\n   */\n  setWindowSize(n: number) {\n    if (n < 60) {\n      throw new Error(\"Window size too small\")\n    }\n    this.#windowSize = n\n  }\n\n  /**\n   * Set start time for range sync\n   * @param n Unix timestamp\n   */\n  setStartPoint(n: number) {\n    if (n < NostrBirthday) {\n      throw new Error(\"Start point cannot be before nostr's birthday\")\n    }\n    this.#start = n\n  }\n\n  /**\n   * Request to sync with a given filter\n   */\n  async sync(filter: ReqFilter) {\n    if (filter.since !== undefined || filter.until !== undefined || filter.limit !== undefined) {\n      throw new Error(\"Filter must not contain since/until/limit\")\n    }\n\n    const now = unixNow()\n    let ctr = 1\n    for (let end = now; end > this.#start; end -= this.#windowSize) {\n      const rb = new RequestBuilder(`${this.#id}+${ctr++}`)\n      rb.withBareFilter(filter)\n        .since(end - this.#windowSize)\n        .until(end)\n      this.emit(\"scan\", end)\n      const results = await this.#fetcher(rb)\n      this.emit(\"event\", results)\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/sync/safe-sync.ts",
    "content": "import EventEmitter from \"eventemitter3\"\nimport {\n  EventExt,\n  type EventSigner,\n  EventType,\n  type NostrEvent,\n  type NostrLink,\n  type NotSignedNostrEvent,\n  RequestBuilder,\n  type SystemInterface,\n} from \"..\"\nimport { unixNow } from \"@snort/shared\"\nimport debug from \"debug\"\n\n/**\n * Safely sync replacable events to nostr\n *\n * Usefule for the following critical kinds:\n * 0 (Metadata)\n * 3 (Contacts)\n * 10002 (Relays)\n * 30078 (AppData)\n */\nexport class SafeSync {\n  #log = debug(\"SafeSync\")\n  #base: NostrEvent | undefined\n  #didSync = false\n\n  constructor(readonly link: NostrLink) {}\n\n  /**\n   * Return a copy of the internal value\n   */\n  get value() {\n    return this.#base ? { ...this.#base } : undefined\n  }\n\n  get didSync() {\n    return this.#didSync\n  }\n\n  /**\n   * Fetch the latest version\n   */\n  async sync(system: SystemInterface) {\n    if (this.link.kind === undefined || this.link.author === undefined) {\n      throw new Error(\"Kind must be set\")\n    }\n\n    return await this.#sync(system)\n  }\n\n  /**\n   * Set the base value\n   * @param ev\n   */\n  setBase(ev: NostrEvent) {\n    this.#checkForUpdate(ev, false)\n    this.#base = ev\n  }\n\n  /**\n   * Publish an update for this event\n   *\n   * Event will be signed again inside\n   * @param ev\n   */\n  async update(\n    next: NostrEvent | NotSignedNostrEvent,\n    signer: EventSigner,\n    system: SystemInterface,\n    mustExist?: boolean,\n  ) {\n    if (!this.#didSync) {\n      throw new Error(\"Cannot update, please call sync() first\")\n    }\n    if (\"sig\" in next) {\n      next.id = \"\"\n      next.sig = \"\"\n    }\n    const signed = await this.#signEvent(next, signer)\n    this.#checkForUpdate(signed, mustExist ?? true)\n\n    await system.BroadcastEvent(signed)\n    this.#base = signed\n  }\n\n  async #signEvent(next: NotSignedNostrEvent, signer: EventSigner) {\n    const toSign = { ...next, id: \"\", sig: \"\" } as NostrEvent\n    toSign.created_at = unixNow()\n    toSign.id = EventExt.createId(toSign)\n    return await signer.sign(toSign)\n  }\n\n  async #sync(system: SystemInterface) {\n    const rb = new RequestBuilder(\"sync\")\n    const f = rb.withFilter().link(this.link)\n    if (this.#base) {\n      f.since(this.#base.created_at)\n    }\n    const results = await system.Fetch(rb)\n    const res = results.find(a => this.link.matchesEvent(a))\n    this.#log(\"Got result %O\", res)\n    const isUpdate = res !== undefined && res.created_at > (this.#base?.created_at ?? 0)\n    if (isUpdate) {\n      this.#base = res\n    }\n    this.#didSync = true\n    return isUpdate\n  }\n\n  #checkForUpdate(ev: NostrEvent, mustExist: boolean) {\n    if (!this.#base) {\n      if (mustExist) {\n        throw new Error(\"No previous version detected\")\n      } else {\n        return\n      }\n    }\n    const prevTag = ev.tags.find(a => a[0] === \"previous\")\n    if (prevTag && prevTag[1] !== this.#base.id) {\n      throw new Error(\"Previous tag does not match our version\")\n    }\n    if (EventExt.getType(ev.kind) !== EventType.Replaceable && EventExt.getType(ev.kind) !== EventType.Addressable) {\n      throw new Error(\"Not a replacable event kind\")\n    }\n    if (this.#base.created_at >= ev.created_at) {\n      throw new Error(\"Same version, cannot update\")\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/system-base.ts",
    "content": "import type { CachedTable } from \"@snort/shared\"\nimport type { CachedMetadata, UsersFollows } from \"./cache\"\nimport type { CacheRelay } from \"./cache-relay\"\nimport { UserFollowsCache } from \"./cache/user-follows-lists\"\nimport { UserRelaysCache, UserProfileCache } from \"./index\"\nimport { DefaultOptimizer, type Optimizer } from \"./query-optimizer\"\nimport type { NostrSystemEvents, SystemConfig } from \"./system\"\nimport { EventEmitter } from \"eventemitter3\"\nimport { SocialGraph } from \"nostr-social-graph\"\n\nexport abstract class SystemBase extends EventEmitter<NostrSystemEvents> {\n  #config: SystemConfig\n\n  get config() {\n    return this.#config\n  }\n\n  constructor(props: Partial<SystemConfig>) {\n    super()\n\n    this.#config = {\n      relays: props.relays ?? new UserRelaysCache(),\n      profiles: props.profiles ?? new UserProfileCache(),\n      contactLists: props.contactLists ?? new UserFollowsCache(),\n      optimizer: props.optimizer ?? DefaultOptimizer,\n      checkSigs: props.checkSigs ?? false,\n      cachingRelay: props.cachingRelay,\n      automaticOutboxModel: props.automaticOutboxModel ?? true,\n      buildFollowGraph: props.buildFollowGraph ?? false,\n      fallbackSync: props.fallbackSync ?? \"since\",\n      socialGraphInstance: props.socialGraphInstance ?? new SocialGraph(\"00\".repeat(32)),\n      disableSyncModule: props.disableSyncModule ?? false,\n    }\n  }\n\n  /**\n   * Storage class for user profiles\n   */\n  get profileCache(): CachedTable<CachedMetadata> {\n    return this.#config.profiles\n  }\n\n  /**\n   * Optimizer instance, contains optimized functions for processing data\n   */\n  get optimizer(): Optimizer {\n    return this.#config.optimizer\n  }\n\n  get userFollowsCache(): CachedTable<UsersFollows> {\n    return this.#config.contactLists\n  }\n\n  get cacheRelay(): CacheRelay | undefined {\n    return this.#config.cachingRelay\n  }\n\n  /**\n   * Check event signatures (recommended)\n   */\n  get checkSigs(): boolean {\n    return this.#config.checkSigs\n  }\n\n  set checkSigs(v: boolean) {\n    this.#config.checkSigs = v\n  }\n}\n"
  },
  {
    "path": "packages/system/src/system.ts",
    "content": "import type { CachedTable } from \"@snort/shared\"\nimport type { UsersRelays, CachedMetadata, UsersFollows } from \"./cache\"\nimport type { CacheRelay } from \"./cache-relay\"\nimport type { RelaySettings } from \"./connection\"\nimport type { ConnectionPool } from \"./connection-pool\"\nimport type { TaggedNostrEvent, OkResponse, ReqFilter, NostrEvent } from \"./nostr\"\nimport type { RelayMetadataLoader } from \"./outbox\"\nimport type { ProfileLoaderService } from \"./profile-cache\"\nimport type { Optimizer } from \"./query-optimizer\"\nimport type { RequestBuilder } from \"./request-builder\"\nimport type { RequestRouter } from \"./request-router\"\nimport type { QueryEvents } from \"./query\"\nimport type { TraceTimeline } from \"./trace-timeline\"\nimport type EventEmitter from \"eventemitter3\"\nimport type { SocialGraph } from \"nostr-social-graph\"\n\nexport type QueryLike = {\n  get progress(): number\n  feed: {\n    add: (evs: Array<TaggedNostrEvent>) => void\n    clear: () => void\n  }\n  /**\n   * Mark query for cancellation\n   */\n  cancel: () => void\n  /**\n   * Un-mark query for cancellation\n   */\n  uncancel: () => void\n  /**\n   * Start query request flow\n   */\n  start: () => void\n  /**\n   * Flush any buffered data\n   */\n  flush: () => void\n  get snapshot(): Array<TaggedNostrEvent>\n} & EventEmitter<QueryEvents>\n\nexport interface NostrSystemEvents {\n  change: (state: SystemSnapshot) => void\n  auth: (challenge: string, relay: string, cb: (ev: NostrEvent) => void) => void\n}\n\n/**\n * Configuration used for all sub-systems in SystemInterface impl\n */\nexport interface SystemConfig {\n  /**\n   * Users configured relays (via kind 3 or kind 10_002)\n   */\n  relays: CachedTable<UsersRelays>\n\n  /**\n   * Cache of user profiles, (kind 0)\n   */\n  profiles: CachedTable<CachedMetadata>\n\n  /**\n   * Cache of user ContactLists (kind 3)\n   */\n  contactLists: CachedTable<UsersFollows>\n\n  /**\n   * Optimized cache relay, usually `@snort/worker-relay`\n   */\n  cachingRelay?: CacheRelay\n\n  /**\n   * Optimized functions, usually `@snort/system-wasm`\n   */\n  optimizer: Optimizer\n\n  /**\n   * Check event sigs on receive from relays\n   */\n  checkSigs: boolean\n\n  /**\n   * Automatically handle outbox model\n   *\n   * 1. Fetch relay lists automatically for queried authors\n   * 2. Write to inbox for all `p` tagged users in broadcasting events\n   */\n  automaticOutboxModel: boolean\n\n  /**\n   * Automatically populate SocialGraph from kind 3 events fetched.\n   *\n   * This is basically free because we always load relays (which includes kind 3 contact lists)\n   * for users when fetching by author.\n   */\n  buildFollowGraph: boolean\n\n  /**\n   * Pick a fallback sync method when negentropy is not available\n   */\n  fallbackSync: \"since\" | \"range-sync\"\n\n  /**\n   * Internal social graph used for WoT filtering\n   */\n  socialGraphInstance: SocialGraph\n\n  /**\n   * Disable negentropy / range-sync modules\n   */\n  disableSyncModule: boolean\n}\n\nexport interface SystemInterface {\n  /**\n   * Check event signatures (reccomended)\n   */\n  checkSigs: boolean\n\n  /**\n   * Do some initialization\n   * @param follows A follower list to preload content for\n   */\n  Init(follows?: Array<string>): Promise<void>\n\n  /**\n   * Get an active query by ID\n   * @param id Query ID\n   */\n  GetQuery(id: string): QueryLike | undefined\n\n  /**\n   * Open a new query to relays\n   * @param req Request to send to relays\n   */\n  Query(req: RequestBuilder): QueryLike\n\n  /**\n   * Fetch data from nostr relays asynchronously\n   * @param req Request to send to relays\n   * @param cb A callback which will fire every 100ms when new data is received\n   */\n  Fetch(req: RequestBuilder, cb?: (evs: Array<TaggedNostrEvent>) => void): Promise<Array<TaggedNostrEvent>>\n\n  /**\n   * Create a new permanent connection to a relay\n   * @param address Relay URL\n   * @param options Read/Write settings\n   */\n  ConnectToRelay(address: string, options: RelaySettings): Promise<void>\n\n  /**\n   * Disconnect permanent relay connection\n   * @param address Relay URL\n   */\n  DisconnectRelay(address: string): void\n\n  /**\n   * Push an event into the system from external source\n   */\n  HandleEvent(subId: string, ev: TaggedNostrEvent): void\n\n  /**\n   * Send an event to all permanent connections\n   * @param ev Event to broadcast\n   * @param cb Callback to handle OkResponse as they arrive\n   */\n  BroadcastEvent(ev: NostrEvent, cb?: (rsp: OkResponse) => void): Promise<Array<OkResponse>>\n\n  /**\n   * Connect to a specific relay and send an event and wait for the response\n   * @param relay Relay URL\n   * @param ev Event to send\n   */\n  WriteOnceToRelay(relay: string, ev: NostrEvent): Promise<OkResponse>\n\n  /**\n   * Profile cache/loader\n   */\n  get profileLoader(): ProfileLoaderService\n\n  /**\n   * Query optimizer\n   */\n  get optimizer(): Optimizer\n\n  /**\n   * ContactList cache\n   */\n  get userFollowsCache(): CachedTable<UsersFollows>\n\n  /**\n   * Relay loader loads relay metadata for a set of profiles\n   */\n  get relayLoader(): RelayMetadataLoader\n\n  /**\n   * Main connection pool\n   */\n  get pool(): ConnectionPool\n\n  /**\n   * Local relay cache service\n   */\n  get cacheRelay(): CacheRelay | undefined\n\n  /**\n   * Request router instance\n   */\n  get requestRouter(): RequestRouter | undefined\n\n  /**\n   * Trace timeline for debugging and performance monitoring\n   */\n  get traceTimeline(): TraceTimeline | undefined\n\n  /**\n   * Get internal system config\n   */\n  get config(): SystemConfig\n}\n\nexport interface SystemSnapshot {\n  queries: Array<{\n    id: string\n    filters: Array<ReqFilter>\n    subFilters: Array<ReqFilter>\n  }>\n}\n"
  },
  {
    "path": "packages/system/src/text.ts",
    "content": "import { removeUndefined } from \"@snort/shared\"\n\nimport {\n  CashuRegex,\n  FileExtensionRegex,\n  HashtagRegex,\n  InlineCodeRegex,\n  InvoiceRegex,\n  MarkdownCodeRegex,\n  MentionNostrEntityRegex,\n  TagRefRegex,\n} from \"./const\"\nimport { NostrLink, tryParseNostrLink } from \"./nostr-link\"\nimport { extensionToMime, UrlRegex } from \"./utils\"\nimport { type Nip94Tags, readNip94TagsFromIMeta } from \".\"\n\nexport enum FragmentType {\n  /**\n   * Plain test fragment\n   */\n  Text = \"text\",\n  /**\n   * Link to external site\n   */\n  Link = \"link\",\n  /**\n   * @ mention of a nostr entity\n   */\n  Mention = \"mention\",\n  /**\n   * Lightning invoice\n   */\n  Invoice = \"invoice\",\n  /**\n   * Image or Video link (http/https)\n   */\n  Media = \"media\",\n  /**\n   * Cashu token\n   */\n  Cashu = \"cashu\",\n  /**\n   * Hashtag topic link\n   */\n  Hashtag = \"hashtag\",\n  /**\n   * Custom emoji link\n   */\n  CustomEmoji = \"custom_emoji\",\n  /**\n   * Highlighted text (handled externally)\n   */\n  HighlightedText = \"highlighted_text\",\n  /**\n   * Code block (```)\n   */\n  CodeBlock = \"code_block\",\n  /**\n   * Inline code (`)\n   */\n  InlineCode = \"inline_code\",\n  /**\n   * Blossom url\n   */\n  BlossomBlob = \"blossom\",\n  /**\n   * Magnet torrent link\n   */\n  MagnetLink = \"magnet\",\n}\n\nexport interface ParsedFragment {\n  type: FragmentType\n  /**\n   * The raw fragment content string\n   */\n  content: string\n  /**\n   * Media mime type for \"media\" fragments\n   */\n  mimeType?: string\n  /**\n   * Code language or spoken language\n   */\n  language?: string\n  /**\n   * Opaque object based on the fragment type\n   */\n  data?: object\n}\n\nexport type Fragment = string | ParsedFragment\n\n/**\n * Process fragments by applying a function to string fragments only.\n *\n * @param fragments - Array of fragments to process\n * @param fn - Function to apply to each string fragment\n * @param filterEmpty - Whether to filter out empty string fragments\n * @returns Processed and flattened array of fragments\n */\nfunction mapFragments(\n  fragments: Fragment[],\n  fn: (str: string) => Fragment | Fragment[],\n  filterEmpty = true,\n): Fragment[] {\n  const result = fragments.flatMap(f => {\n    if (typeof f === \"string\") {\n      return fn(f)\n    }\n    return f\n  })\n\n  if (filterEmpty) {\n    return result.filter(f => typeof f !== \"string\" || f.length > 0)\n  }\n\n  return result\n}\n\n/**\n * Efficiently split a string by a regex pattern and create parsed fragments for matches,\n * without needing to test the regex multiple times.\n *\n * @param str - The string to parse\n * @param regex - The regex pattern to match (must have the 'g' flag)\n * @param type - The FragmentType to assign to matched parts\n * @param transform - Optional function to transform the matched content. Return undefined to treat match as text.\n * @returns Array of strings (non-matches) and ParsedFragments (matches)\n */\nfunction splitAndParseRegex(\n  str: string,\n  regex: RegExp,\n  type: FragmentType,\n  transform?: (match: string) => Partial<ParsedFragment> | undefined,\n): Array<Fragment> {\n  const result = []\n  let lastIndex = 0\n\n  // Reset regex before using matchAll\n  regex.lastIndex = 0\n\n  for (const match of str.matchAll(regex)) {\n    // Add text before match (if non-empty)\n    if (match.index! > lastIndex) {\n      result.push(str.substring(lastIndex, match.index))\n    }\n\n    if (transform) {\n      const transformed = transform(match[0])\n\n      // If transform returns undefined, treat the match as text\n      if (transformed === undefined) {\n        result.push(match[0])\n      } else {\n        // Create parsed fragment with transformed data\n        const fragment: ParsedFragment = {\n          type,\n          content: match[0],\n          ...transformed,\n        }\n        result.push(fragment)\n      }\n    } else {\n      // No transform, create basic parsed fragment\n      const fragment: ParsedFragment = {\n        type,\n        content: match[0],\n      }\n      result.push(fragment)\n    }\n\n    lastIndex = match.index! + match[0].length\n  }\n\n  // Add remaining text after last match (if non-empty)\n  if (lastIndex < str.length) {\n    result.push(str.substring(lastIndex))\n  }\n\n  return result\n}\n\nfunction extractLinks(fragments: Fragment[]) {\n  return mapFragments(fragments, f =>\n    splitAndParseRegex(f, UrlRegex, FragmentType.Link, a => {\n      // check for regular http media link\n      const normalizedStr = a.toLowerCase()\n      if (normalizedStr.startsWith(\"http:\") || normalizedStr.startsWith(\"https:\")) {\n        const url = new URL(a)\n        const extension = url.pathname.match(FileExtensionRegex)\n\n        if (extension && extension.length > 1) {\n          // media links have special type\n          const mediaType = extensionToMime(extension[1])\n          return {\n            type: \"media\",\n            content: a,\n            mimeType: mediaType ?? `unknown/${extension[1]}`,\n          } as ParsedFragment\n        }\n      }\n      if (\n        normalizedStr.startsWith(\"nostr:\") ||\n        (normalizedStr.startsWith(\"web+nostr:\") && tryParseNostrLink(normalizedStr))\n      ) {\n        // nostr links\n        return {\n          type: \"mention\",\n          content: a,\n        } as ParsedFragment\n      }\n      if (normalizedStr.startsWith(\"magnet:\")) {\n        // magnet links\n        return {\n          type: \"magnet\",\n          content: a,\n        } as ParsedFragment\n      }\n      if (normalizedStr.startsWith(\"blossom:\")) {\n        // magnet links\n        return {\n          type: \"blossom\",\n          content: a,\n        } as ParsedFragment\n      }\n\n      // generic link\n      return {\n        type: \"link\",\n        content: a,\n      } as ParsedFragment\n    }),\n  )\n}\n\nfunction extractMentions(fragments: Fragment[]) {\n  return mapFragments(fragments, f => splitAndParseRegex(f, MentionNostrEntityRegex, FragmentType.Mention))\n}\n\nfunction extractCashuTokens(fragments: Fragment[]) {\n  return mapFragments(fragments, f => {\n    if (f.includes(\"cashuA\")) {\n      return splitAndParseRegex(f, CashuRegex, FragmentType.Cashu)\n    }\n    return f\n  })\n}\n\nfunction extractInvoices(fragments: Fragment[]) {\n  return mapFragments(fragments, f => splitAndParseRegex(f, InvoiceRegex, FragmentType.Invoice))\n}\n\nfunction extractHashtags(fragments: Fragment[]) {\n  return mapFragments(fragments, f =>\n    splitAndParseRegex(f, HashtagRegex, FragmentType.Hashtag, match => ({\n      content: match.substring(1), // Remove the # prefix\n    })),\n  )\n}\n\nfunction extractTagRefs(fragments: Fragment[], tags: Array<Array<string>>) {\n  return mapFragments(fragments, f =>\n    splitAndParseRegex(f, TagRefRegex, FragmentType.Mention, match => {\n      // Extract tag index from #[0] pattern\n      const tagIndex = Number(match.slice(2, -1))\n      const tag = tags[tagIndex]\n\n      if (tag) {\n        try {\n          return {\n            content: `nostr:${NostrLink.fromTag(tag).encode()}`,\n          }\n        } catch (e) {\n          // If NostrLink.fromTag fails, treat as text\n          return undefined\n        }\n      }\n\n      // No tag found, treat as text\n      return undefined\n    }),\n  )\n}\n\nfunction extractCustomEmoji(fragments: Fragment[], tags: Array<Array<string>>) {\n  const emojiRegex = /:(\\w+):/g\n\n  return mapFragments(fragments, f =>\n    splitAndParseRegex(f, emojiRegex, FragmentType.CustomEmoji, match => {\n      // Extract emoji name from :name: pattern\n      const emojiName = match.slice(1, -1)\n      const tag = tags.find(a => a[0] === \"emoji\" && a[1] === emojiName)\n\n      if (tag) {\n        return { content: tag[2] } // URL of the emoji\n      }\n\n      // Return undefined to treat as text if emoji not found\n      return undefined\n    }),\n  )\n}\n\nfunction extractMarkdownCode(fragments: Fragment[]): (string | ParsedFragment)[] {\n  return mapFragments(fragments, f =>\n    splitAndParseRegex(f, MarkdownCodeRegex, FragmentType.CodeBlock, match => {\n      const cleaned = match.slice(3, match.length - 3)\n      const isMultiLine = cleaned.includes(\"\\n\")\n      const language = isMultiLine ? cleaned.slice(0, cleaned.indexOf(\"\\n\")).trim() : undefined\n      const content = isMultiLine ? cleaned.slice(cleaned.indexOf(\"\\n\") + 1) : cleaned\n      return {\n        content,\n        language,\n      }\n    }),\n  )\n}\n\nfunction extractInlineCode(fragments: Fragment[]): (string | ParsedFragment)[] {\n  return mapFragments(fragments, f =>\n    splitAndParseRegex(f, InlineCodeRegex, FragmentType.InlineCode, match => ({\n      content: match.slice(1, match.length - 1), // Remove backticks\n    })),\n  )\n}\n\nexport function parseIMeta(tags: Array<Array<string>>) {\n  let ret: Record<string, Nip94Tags> | undefined\n  const imetaTags = tags.filter(a => a[0] === \"imeta\")\n  for (const imetaTag of imetaTags) {\n    const meta = readNip94TagsFromIMeta(imetaTag)\n    if (meta.url) {\n      ret ??= {}\n      ret[meta.url] = meta\n    }\n  }\n  return ret\n}\n\nexport function transformText(body: string, tags: Array<Array<string>>) {\n  let fragments = extractLinks([body])\n  fragments = extractMentions(fragments)\n  fragments = extractTagRefs(fragments, tags)\n  fragments = extractHashtags(fragments)\n  fragments = extractInvoices(fragments)\n  fragments = extractCashuTokens(fragments)\n  fragments = extractCustomEmoji(fragments, tags)\n  fragments = extractMarkdownCode(fragments)\n  fragments = extractInlineCode(fragments)\n  const frags = removeUndefined(\n    fragments.map(a => {\n      if (typeof a === \"string\") {\n        if (a.length > 0) {\n          return { type: \"text\", content: a } as ParsedFragment\n        }\n      } else {\n        return a\n      }\n    }),\n  )\n\n  // attach imeta data\n  const imeta = parseIMeta(tags)\n  if (imeta) {\n    for (const f of frags) {\n      const ix = imeta[f.content]\n      if (ix) {\n        f.data = ix\n        f.mimeType = ix.mimeType ?? f.mimeType\n      }\n    }\n  }\n  return frags\n}\n"
  },
  {
    "path": "packages/system/src/trace-timeline.ts",
    "content": "import { ExternalStore } from \"@snort/shared\"\nimport { type QueryTraceEvent, QueryTraceState } from \"./query\"\n\nexport interface TimelineEntry {\n  event: QueryTraceEvent\n  queryName?: string\n  runtime?: number // Duration spent in this state in ms\n}\n\nexport interface TraceTimelineSnapshot {\n  entries: ReadonlyArray<TimelineEntry>\n  enabled: boolean\n}\n\n/**\n * Collects and manages trace reports in a timeline\n */\nexport class TraceTimeline extends ExternalStore<TraceTimelineSnapshot> {\n  #entries: Array<TimelineEntry> = []\n  #enabled: boolean = true\n  // Track last entry index for each trace ID to update runtime\n  #lastEntryIndex: Map<string, number> = new Map()\n  // Track start timestamp for each trace ID to compute total elapsed time\n  #startTimestamp: Map<string, number> = new Map()\n\n  constructor() {\n    super()\n  }\n\n  /**\n   * Enable/disable timeline collection\n   */\n  setEnabled(enabled: boolean) {\n    this.#enabled = enabled\n    if (!enabled) {\n      this.clear()\n    } else {\n      this.notifyChange()\n    }\n  }\n\n  get enabled() {\n    return this.#enabled\n  }\n\n  takeSnapshot(): TraceTimelineSnapshot {\n    return {\n      entries: [...this.#entries],\n      enabled: this.#enabled,\n    }\n  }\n\n  /**\n   * Add a trace event to the timeline\n   */\n  addTrace(event: QueryTraceEvent, queryName?: string) {\n    if (!this.#enabled) return\n\n    // Record start timestamp on first state for this trace\n    if (!this.#startTimestamp.has(event.id)) {\n      this.#startTimestamp.set(event.id, event.timestamp)\n    }\n\n    // Update runtime of previous entry for this trace\n    const lastIndex = this.#lastEntryIndex.get(event.id)\n    if (lastIndex !== undefined && lastIndex < this.#entries.length) {\n      const lastEntry = this.#entries[lastIndex]\n      lastEntry.runtime = event.timestamp - lastEntry.event.timestamp\n    }\n\n    // For terminal/EOSE states, set runtime to total elapsed time from start\n    const isTerminal = [\n      QueryTraceState.EOSE,\n      QueryTraceState.LOCAL_CLOSE,\n      QueryTraceState.REMOTE_CLOSE,\n      QueryTraceState.TIMEOUT,\n      QueryTraceState.DROP,\n    ].includes(event.state)\n    const totalRuntime = isTerminal\n      ? event.timestamp - (this.#startTimestamp.get(event.id) ?? event.timestamp)\n      : undefined\n\n    // Create new entry\n    const entry: TimelineEntry = {\n      event,\n      queryName,\n      runtime: totalRuntime, // Will be set when next state change occurs (non-terminal), or total elapsed (terminal)\n    }\n\n    // Add entry and update index tracking\n    const newIndex = this.#entries.length\n    this.#entries.push(entry)\n    this.#lastEntryIndex.set(event.id, newIndex)\n    this.notifyChange()\n  }\n\n  /**\n   * Get all timeline entries\n   */\n  getEntries(): ReadonlyArray<TimelineEntry> {\n    return this.#entries\n  }\n\n  /**\n   * Get entries within a time range\n   */\n  getEntriesInRange(startTime: number, endTime: number): Array<TimelineEntry> {\n    return this.#entries.filter(e => e.event.timestamp >= startTime && e.event.timestamp <= endTime)\n  }\n\n  /**\n   * Get entries for a specific relay\n   */\n  getEntriesForRelay(relayAddress: string): Array<TimelineEntry> {\n    return this.#entries.filter(e => e.event.relay === relayAddress)\n  }\n\n  /**\n   * Get entries for a specific query\n   */\n  getEntriesForQuery(queryId: string): Array<TimelineEntry> {\n    return this.#entries.filter(e => e.event.id === queryId)\n  }\n\n  /**\n   * Clear all timeline entries\n   */\n  clear() {\n    this.#entries = []\n    this.#lastEntryIndex.clear()\n    this.#startTimestamp.clear()\n    this.notifyChange()\n  }\n\n  /**\n   * Export timeline to Google Trace Event Format (for Chrome tracing / Perfetto)\n   * https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview\n   */\n  exportGoogleTrace() {\n    const traceEvents: Array<Record<string, unknown>> = []\n\n    // Add trace events - use duration events if runtime is available, instant events otherwise\n    this.#entries.forEach(entry => {\n      const timestamp = entry.event.timestamp * 1000 // Convert to microseconds\n\n      const pid = entry.event.relay // Process ID = relay name\n      const tid = entry.event.id // Thread ID = query trace ID\n      const queryName = entry.queryName || \"Query\"\n\n      const isTerminal = [\n        QueryTraceState.EOSE,\n        QueryTraceState.LOCAL_CLOSE,\n        QueryTraceState.REMOTE_CLOSE,\n        QueryTraceState.TIMEOUT,\n        QueryTraceState.DROP,\n      ].includes(entry.event.state)\n\n      if (entry.runtime !== undefined && !isTerminal) {\n        // Duration event - shows as a bar (non-terminal states only)\n        const duration = entry.runtime * 1000 // Convert to microseconds\n        traceEvents.push({\n          name: `${queryName} (${entry.event.state})`,\n          cat: [QueryTraceState.TIMEOUT, QueryTraceState.DROP].includes(entry.event.state) ? \"timeout\" : \"complete\",\n          ph: \"X\", // Complete/duration event\n          ts: timestamp,\n          dur: duration,\n          pid: pid,\n          tid: tid,\n          args: {\n            queryName: entry.queryName,\n            relay: entry.event.relay,\n            subscriptionId: entry.event.id,\n            connectionId: entry.event.connId,\n            state: entry.event.state,\n            runtime: entry.runtime,\n            filters: entry.event.filters,\n          },\n        })\n      } else {\n        // Instant event - shows as a point (terminal states, or states without a runtime yet)\n        traceEvents.push({\n          name: `${queryName} (${entry.event.state})`,\n          cat: [QueryTraceState.TIMEOUT, QueryTraceState.DROP].includes(entry.event.state) ? \"timeout\" : \"complete\",\n          ph: \"i\", // Instant event\n          ts: timestamp,\n          pid: pid,\n          tid: tid,\n          s: \"t\", // Thread scope\n          args: {\n            queryName: entry.queryName,\n            relay: entry.event.relay,\n            subscriptionId: entry.event.id,\n            connectionId: entry.event.connId,\n            state: entry.event.state,\n            runtime: entry.runtime, // Total elapsed ms from QUEUED to this terminal state\n            filters: entry.event.filters,\n          },\n        })\n      }\n    })\n\n    return {\n      traceEvents,\n      displayTimeUnit: \"ms\",\n      metadata: {\n        \"trace-type\": \"Nostr Relay Query Traces\",\n      },\n    }\n  }\n}\n"
  },
  {
    "path": "packages/system/src/user-state.ts",
    "content": "import { NostrLink, type ToNostrEventTag } from \"./nostr-link\"\nimport { DiffSyncTags, JsonEventSync } from \"./sync\"\nimport EventKind from \"./event-kind\"\nimport {\n  type EventSigner,\n  type FullRelaySettings,\n  type RelaySettings,\n  type SystemInterface,\n  type UserMetadata,\n  parseRelayTags,\n  parseRelaysFromKind,\n  settingsToRelayTag,\n} from \".\"\nimport { dedupe, removeUndefined, sanitizeRelayUrl, NostrPrefix } from \"@snort/shared\"\nimport debug from \"debug\"\nimport EventEmitter from \"eventemitter3\"\n\nexport interface UserStateOptions<T> {\n  appdataId: string\n  initAppdata: T\n  encryptAppdata: boolean\n}\n\n/**\n * Data which can be stored locally to quickly resume the state at startup\n */\nexport interface UserStateObject<TAppData> {\n  profile?: UserMetadata\n  follows?: Array<string>\n  relays?: Array<FullRelaySettings>\n  appdata?: TAppData\n}\n\nexport enum UserStateChangeType {\n  Profile,\n  Contacts,\n  Relays,\n  AppData,\n  MuteList,\n  GenericList,\n}\n\nexport interface UserStateEvents {\n  change: (t: UserStateChangeType) => void\n}\n\n/**\n * Manages a users state, mostly to improve safe syncing\n */\nexport class UserState<TAppData> extends EventEmitter<UserStateEvents> {\n  #log = debug(\"UserState\")\n  #profile?: JsonEventSync<UserMetadata | undefined> // kind 0\n  #contacts?: DiffSyncTags // kind 3\n  #relays?: DiffSyncTags // kind 10_003\n  #appdata?: JsonEventSync<TAppData> // kind 30_0078\n  #standardLists?: Map<EventKind, DiffSyncTags> // NIP-51 lists\n\n  #signer?: EventSigner\n  #system?: SystemInterface\n\n  // state object will be used in the getters as a fallback value when not yet synced\n  #stateObj?: UserStateObject<TAppData>\n  #initPromise?: Promise<void>\n  #version = 0\n\n  constructor(\n    readonly pubkey: string,\n    options?: Partial<UserStateOptions<TAppData>>,\n    stateObj?: UserStateObject<TAppData>,\n  ) {\n    super()\n    this.#stateObj = stateObj\n    this.#standardLists = pubkey ? new Map() : undefined\n\n    this.#profile = pubkey\n      ? new JsonEventSync<UserMetadata | undefined>(\n          undefined,\n          new NostrLink(NostrPrefix.Event, pubkey, EventKind.SetMetadata, pubkey),\n          false,\n        )\n      : undefined\n    this.#contacts = pubkey\n      ? new DiffSyncTags(new NostrLink(NostrPrefix.Event, pubkey, EventKind.ContactList, pubkey), false)\n      : undefined\n    this.#relays = pubkey\n      ? new DiffSyncTags(new NostrLink(NostrPrefix.Event, pubkey, EventKind.Relays, pubkey), false)\n      : undefined\n    if (options?.appdataId && options.initAppdata) {\n      const link = new NostrLink(NostrPrefix.Address, options.appdataId, EventKind.AppData, pubkey)\n      this.#appdata = new JsonEventSync<TAppData>(options.initAppdata, link, options.encryptAppdata ?? false)\n      this.#appdata.on(\"change\", () => this.emit(\"change\", UserStateChangeType.AppData))\n    }\n\n    // always track mute list\n    this.checkIsStandardList(EventKind.MuteList)\n\n    this.#profile?.on(\"change\", () => this.emit(\"change\", UserStateChangeType.Profile))\n    this.#contacts?.on(\"change\", () => this.emit(\"change\", UserStateChangeType.Contacts))\n    this.#relays?.on(\"change\", () => this.emit(\"change\", UserStateChangeType.Relays))\n    this.on(\"change\", () => this.#version++)\n  }\n\n  get didInit() {\n    return this.#initPromise !== undefined\n  }\n\n  destroy() {\n    this.#log(\"Shutdown\")\n    this.removeAllListeners()\n  }\n\n  /**\n   * Initialize and sync user state from Nostr relays.\n   * This method is idempotent - calling it multiple times will only initialize once.\n   */\n  async init(signer: EventSigner | undefined, system: SystemInterface) {\n    if (this.#initPromise) {\n      return this.#initPromise\n    }\n\n    this.#signer = signer\n    this.#system = system\n\n    this.#initPromise = this.#performInit(signer, system)\n    return this.#initPromise\n  }\n\n  async #performInit(signer: EventSigner | undefined, system: SystemInterface) {\n    this.#log(\"Init start\")\n    const tasks = [\n      this.#profile?.sync(signer, system).catch(e => this.#log(\"Failed to sync profile: %O\", e)),\n      this.#contacts?.sync(signer, system).catch(e => this.#log(\"Failed to sync contacts: %O\", e)),\n      this.#relays?.sync(signer, system).catch(e => this.#log(\"Failed to sync relays: %O\", e)),\n    ]\n    if (this.#appdata) {\n      tasks.push(this.#appdata.sync(signer, system).catch(e => this.#log(\"Failed to sync appdata: %O\", e)))\n    }\n    if (this.#standardLists) {\n      for (const list of this.#standardLists.values()) {\n        tasks.push(list.sync(signer, system).catch(e => this.#log(\"Failed to sync list %O: \", list.link, e)))\n      }\n    }\n    await Promise.all(tasks)\n    this.#log(\n      \"Init results: signer=%s, profile=%O, contacts=%O, relays=%O, appdata=%O, lists=%O\",\n      signer ? \"yes\" : \"no\",\n      this.#profile?.json,\n      this.#contacts?.value,\n      this.#relays?.value,\n      this.#appdata?.json,\n      [...(this.#standardLists?.values() ?? [])].map(a => [a.link.kind, a.value, a.encryptedTags]),\n    )\n\n    // update relay metadata with value from contact list if not found\n    if (this.#relays?.value === undefined && this.#contacts?.value?.content !== undefined && signer) {\n      this.#log(\"Saving relays to NIP-65 relay list using %O\", this.relays)\n      for (const r of this.relays ?? []) {\n        this.#addRelay(r.url, r.settings)\n      }\n\n      await this.#relays?.persist(signer, system)\n    }\n  }\n\n  get signer() {\n    return this.#signer\n  }\n\n  get version() {\n    return this.#version\n  }\n\n  /**\n   * Get the number of pending changes that haven't been saved to Nostr yet\n   */\n  get pendingChanges() {\n    let count = 0\n\n    // Check contacts for pending changes\n    if (this.#contacts) {\n      // DiffSyncTags stores changes in private #changes array, but we can check if tags differ from value\n      // If there's a value (synced event) and tags differ from value.tags, there are pending changes\n      const syncedTags = this.#contacts.value?.tags ?? []\n      const currentTags = this.#contacts.tags\n      if (JSON.stringify(syncedTags) !== JSON.stringify(currentTags)) {\n        count++\n      }\n    }\n\n    // Check relays for pending changes\n    if (this.#relays) {\n      const syncedTags = this.#relays.value?.tags ?? []\n      const currentTags = this.#relays.tags\n      if (JSON.stringify(syncedTags) !== JSON.stringify(currentTags)) {\n        count++\n      }\n    }\n\n    // Check app data for pending changes\n    if (this.#appdata && this.#appdata.hasPendingChanges) {\n      count++\n    }\n\n    // Check all standard lists for pending changes\n    if (this.#standardLists) {\n      for (const list of this.#standardLists.values()) {\n        const syncedTags = list.value?.tags ?? []\n        const currentTags = list.tags\n        let syncedEncrypted = list.value?.content ?? \"\"\n        const currentEncrypted = list.encryptedTags\n\n        try {\n          syncedEncrypted = JSON.stringify(JSON.parse(syncedEncrypted))\n        } catch {\n          //ignore\n          syncedEncrypted = JSON.stringify(currentEncrypted)\n        }\n\n        // Check both regular tags and encrypted content\n        if (\n          JSON.stringify(syncedTags) !== JSON.stringify(currentTags) ||\n          syncedEncrypted !== JSON.stringify(currentEncrypted)\n        ) {\n          count++\n        }\n      }\n    }\n\n    return count\n  }\n\n  /**\n   * Users profile\n   */\n  get profile() {\n    return this.#profile?.json ?? this.#stateObj?.profile\n  }\n\n  /**\n   * Users configured relays\n   */\n  get relays() {\n    if (this.#relays?.value) {\n      return parseRelayTags(this.#relays.tags)\n    } else if (this.#contacts?.value) {\n      return parseRelaysFromKind(this.#contacts.value)\n    } else {\n      return this.#stateObj?.relays\n    }\n  }\n\n  /**\n   * Followed pubkeys\n   */\n  get follows() {\n    if (this.#contacts?.value) {\n      const pTags = this.#contacts.tags.filter(a => a[0] === \"p\" && a[1].length === 64).map(a => a[1]) ?? []\n      return dedupe(pTags)\n    } else {\n      return this.#stateObj?.follows\n    }\n  }\n\n  /**\n   * App specific data\n   */\n  get appdata() {\n    return this.#appdata?.json ?? this.#stateObj?.appdata\n  }\n\n  /**\n   * Get the standard mute list\n   */\n  get muted() {\n    const list = this.#standardLists?.get(EventKind.MuteList)\n    if (list) {\n      return NostrLink.fromAllTags(list.encryptedTags)\n    }\n    return []\n  }\n\n  /**\n   * Follow a user\n   */\n  follow(link: NostrLink) {\n    this.#ensureInit()\n    if (link.type !== NostrPrefix.Profile && link.type !== NostrPrefix.PublicKey) {\n      throw new Error(\"Cannot follow this type of link\")\n    }\n\n    const tag = link.toEventTag()\n    if (tag && this.#contacts) {\n      this.#contacts.add(tag)\n    } else if (!tag) {\n      throw new Error(\"Invalid link\")\n    }\n  }\n\n  /**\n   * Unfollow a user\n   */\n  unfollow(link: NostrLink) {\n    this.#ensureInit()\n    if (link.type !== NostrPrefix.Profile && link.type !== NostrPrefix.PublicKey) {\n      throw new Error(\"Cannot follow this type of link\")\n    }\n\n    const tag = link.toEventTag()\n    if (tag && this.#contacts) {\n      this.#contacts.remove(tag)\n    } else if (!tag) {\n      throw new Error(\"Invalid link\")\n    }\n  }\n\n  /**\n   * Replace the entire follow list\n   */\n  replaceFollows(links: Array<NostrLink>) {\n    this.#ensureInit()\n    if (links.some(link => link.type !== NostrPrefix.Profile && link.type !== NostrPrefix.PublicKey)) {\n      throw new Error(\"Cannot follow this type of link\")\n    }\n\n    if (this.#contacts) {\n      const tags = removeUndefined(links.map(link => link.toEventTag()))\n      this.#contacts.replace(tags)\n    }\n  }\n\n  /**\n   * Save all pending contact list changes to Nostr\n   */\n  async saveContacts() {\n    this.#ensureInit()\n    const content = JSON.stringify(this.#relaysObject())\n    await this.#contacts?.persist(this.#signer!, this.#system!, content)\n  }\n\n  /**\n   * Save all pending changes (contacts + relays + app data + all lists) to Nostr\n   * This is a convenience method for saving everything at once\n   */\n  async saveAll() {\n    this.#ensureInit()\n    const tasks: Promise<void>[] = []\n\n    // Save contacts if there are changes\n    if (this.#contacts) {\n      const content = JSON.stringify(this.#relaysObject())\n      tasks.push(this.#contacts.persist(this.#signer!, this.#system!, content))\n    }\n\n    // Save relays if there are changes\n    if (this.#relays) {\n      tasks.push(this.#relays.persist(this.#signer!, this.#system!))\n    }\n\n    // Save app data if there are changes\n    if (this.#appdata && this.#appdata.hasPendingChanges) {\n      tasks.push(this.#appdata.persist(this.#signer!, this.#system!))\n    }\n\n    // Save all standard lists\n    if (this.#standardLists) {\n      for (const list of this.#standardLists.values()) {\n        tasks.push(list.persist(this.#signer!, this.#system!))\n      }\n    }\n\n    await Promise.all(tasks)\n  }\n\n  /**\n   * Add a relay to the relay list\n   */\n  addRelay(addr: string, settings: RelaySettings) {\n    this.#ensureInit()\n    this.#addRelay(addr, settings)\n  }\n\n  #addRelay(addr: string, settings: RelaySettings) {\n    const tag = settingsToRelayTag({\n      url: addr,\n      settings,\n    })\n    if (tag && this.#relays) {\n      this.#relays.add(tag)\n    } else if (!tag) {\n      throw new Error(\"Invalid relay options\")\n    }\n  }\n\n  /**\n   * Remove a relay from the relay list\n   */\n  removeRelay(addr: string) {\n    this.#ensureInit()\n\n    const url = sanitizeRelayUrl(addr)\n    if (url && this.#relays) {\n      this.#relays.remove([\"r\", url])\n    } else if (!url) {\n      throw new Error(\"Invalid relay options\")\n    }\n  }\n\n  /**\n   * Update relay settings\n   */\n  updateRelay(addr: string, settings: RelaySettings) {\n    this.#ensureInit()\n\n    const tag = settingsToRelayTag({\n      url: addr,\n      settings,\n    })\n    const url = sanitizeRelayUrl(addr)\n    if (url && tag && this.#relays) {\n      this.#relays.update(tag)\n    } else if (!url && !tag) {\n      throw new Error(\"Invalid relay options\")\n    }\n  }\n\n  /**\n   * Save all pending relay changes to Nostr\n   */\n  async saveRelays() {\n    this.#ensureInit()\n    await this.#relays?.persist(this.#signer!, this.#system!)\n  }\n\n  /**\n   * Update app-specific data locally without saving to Nostr\n   * Call saveAppData() to persist changes\n   */\n  setAppData(data: TAppData) {\n    if (!this.#appdata) {\n      throw new Error(\"Not using appdata, please use options when constructing this class\")\n    }\n    this.#appdata.setJson(data)\n  }\n\n  /**\n   * Save pending app data changes to Nostr\n   */\n  async saveAppData() {\n    this.#ensureInit()\n    if (!this.#appdata) {\n      throw new Error(\"Not using appdata, please use options when constructing this class\")\n    }\n    await this.#appdata.persist(this.#signer!, this.#system!)\n  }\n\n  /**\n   * Add an item to a list\n   * @param kind List kind (must be 10000-19999 range for standard lists)\n   * @param links Tag(s) to add\n   * @param encrypted Whether the tag should be encrypted in the content\n   */\n  addToList(kind: EventKind, links: ToNostrEventTag | Array<ToNostrEventTag>, encrypted = false) {\n    this.checkIsStandardList(kind)\n    this.#ensureInit()\n    const list = this.#standardLists?.get(kind)\n    const tags = removeUndefined(Array.isArray(links) ? links.map(a => a.toEventTag()) : [links.toEventTag()])\n    if (list && tags.length > 0) {\n      list.add(tags, encrypted)\n    }\n  }\n\n  /**\n   * Remove an item from a list\n   * @param kind List kind (must be 10000-19999 range for standard lists)\n   * @param links Tag(s) to remove\n   * @param encrypted Whether the tag is encrypted in the content\n   */\n  removeFromList(kind: EventKind, links: ToNostrEventTag | Array<ToNostrEventTag>, encrypted = false) {\n    this.checkIsStandardList(kind)\n    this.#ensureInit()\n    const list = this.#standardLists?.get(kind)\n    const tags = removeUndefined(Array.isArray(links) ? links.map(a => a.toEventTag()) : [links.toEventTag()])\n    if (list && tags.length > 0) {\n      list.remove(tags, encrypted)\n    }\n  }\n\n  /**\n   * Save pending changes to a specific list\n   */\n  async saveList(kind: EventKind, content?: string) {\n    this.#ensureInit()\n    const list = this.#standardLists?.get(kind)\n    await list?.persist(this.#signer!, this.#system!, content)\n  }\n\n  /**\n   * Mute a user, event, or other item (added to encrypted mute list)\n   */\n  mute(link: NostrLink) {\n    this.addToList(EventKind.MuteList, link, true)\n  }\n\n  /**\n   * Unmute a user, event, or other item (removed from encrypted mute list)\n   */\n  unmute(link: NostrLink) {\n    this.removeFromList(EventKind.MuteList, link, true)\n  }\n\n  isOnList(kind: EventKind, link: ToNostrEventTag) {\n    const list = this.#standardLists?.get(kind)\n    const tag = link.toEventTag()\n    if (list && tag) {\n      return list.tags.some(a => a[0] === tag[0] && a[1] === tag[1])\n    }\n    return false\n  }\n\n  getList(kind: EventKind): Array<ToNostrEventTag> {\n    const list = this.#standardLists?.get(kind)\n    return NostrLink.fromAllTags(list?.tags ?? [])\n  }\n\n  serialize(): UserStateObject<TAppData> {\n    return {\n      profile: this.profile,\n      relays: this.relays,\n      follows: this.follows,\n      appdata: this.appdata,\n    }\n  }\n\n  checkIsStandardList(kind: EventKind) {\n    if (!(kind >= 10_000 && kind < 20_000)) {\n      throw new Error(\"Not a standard list\")\n    }\n    if (this.#standardLists?.has(kind) === false) {\n      const list = new DiffSyncTags(new NostrLink(NostrPrefix.Event, this.pubkey, kind, this.pubkey), true)\n      list.on(\"change\", () => this.emit(\"change\", UserStateChangeType.GenericList))\n      this.#standardLists?.set(kind, list)\n    }\n  }\n\n  /**\n   * Ensures init has been called before performing mutations\n   */\n  #ensureInit() {\n    if (this.#signer === undefined || this.#system === undefined) {\n      throw new Error(\"Please call init() first before making changes\")\n    }\n  }\n\n  #relaysObject() {\n    return Object.fromEntries(this.relays?.map(a => [a.url, a.settings]) ?? []) as Record<string, RelaySettings>\n  }\n}\n"
  },
  {
    "path": "packages/system/src/utils.ts",
    "content": "import { equalProp } from \"@snort/shared\"\nimport type { FlatReqFilter } from \"./query-optimizer\"\nimport type { NostrEvent, ReqFilter } from \"./nostr\"\n\nexport function findTag(e: NostrEvent, tag: string) {\n  const maybeTag = e.tags.find(evTag => {\n    return evTag[0] === tag\n  })\n  return maybeTag && maybeTag[1]\n}\n\nexport function findWholeTag(e: NostrEvent, tag: string) {\n  const maybeTag = e.tags.find(evTag => {\n    return evTag[0] === tag\n  })\n  return maybeTag\n}\n\nexport function reqFilterEq(a: FlatReqFilter | ReqFilter, b: FlatReqFilter | ReqFilter): boolean {\n  return (\n    equalProp(a.ids, b.ids) &&\n    equalProp(a.kinds, b.kinds) &&\n    equalProp(a.authors, b.authors) &&\n    equalProp(a.limit, b.limit) &&\n    equalProp(a.since, b.since) &&\n    equalProp(a.until, b.until) &&\n    equalProp(a.search, b.search) &&\n    equalProp(a[\"#e\"], b[\"#e\"]) &&\n    equalProp(a[\"#p\"], b[\"#p\"]) &&\n    equalProp(a[\"#t\"], b[\"#t\"]) &&\n    equalProp(a[\"#d\"], b[\"#d\"]) &&\n    equalProp(a[\"#r\"], b[\"#r\"])\n  )\n}\n\nexport function flatFilterEq(a: FlatReqFilter, b: FlatReqFilter): boolean {\n  return (\n    a.keys === b.keys &&\n    a.since === b.since &&\n    a.until === b.until &&\n    a.limit === b.limit &&\n    a.search === b.search &&\n    a.ids === b.ids &&\n    a.kinds === b.kinds &&\n    a.authors === b.authors &&\n    a[\"#e\"] === b[\"#e\"] &&\n    a[\"#p\"] === b[\"#p\"] &&\n    a[\"#t\"] === b[\"#t\"] &&\n    a[\"#d\"] === b[\"#d\"] &&\n    a[\"#r\"] === b[\"#r\"]\n  )\n}\n\nexport const UrlRegex =\n  /((?:http|ftp|https|nostr|web\\+nostr|magnet|lnurl[p|w]?|blossom):\\/?\\/?(?:[\\w+?.\\w+])+(?:[\\p{L}\\p{N}~!@#$%^&*()_\\-=+\\\\/?.:;',]*)?(?:[-a-z0-9+&@#/%=~()_|]))/giu\n\nexport function splitByUrl(str: string) {\n  return str.split(UrlRegex)\n}\n\n/**\n * Image file extensions\n */\nexport const ImageExtensions = [\"gif\", \"jpg\", \"jpeg\", \"jfif\", \"png\", \"bmp\", \"webp\"]\n\n/**\n * Audio file extensions\n */\nexport const AudioExtensions = [\"wav\", \"mp3\", \"ogg\", \"m4a\"]\n\n/**\n * Video file extensions\n */\nexport const VideoExtensions = [\"mp4\", \"mov\", \"mkv\", \"avi\", \"m4v\", \"webm\", \"m3u8\"]\n\n/**\n * Converts a file extension into mime type string\n */\nexport function extensionToMime(e: string) {\n  let ext = e.toLowerCase()\n  if (ext.startsWith(\".\")) {\n    ext = ext.slice(1)\n  }\n  if (ImageExtensions.includes(ext)) {\n    return `image/${ext}`\n  } else if (AudioExtensions.includes(ext)) {\n    return `audio/${ext}`\n  } else if (VideoExtensions.includes(ext)) {\n    return `video/${ext}`\n  }\n}\n"
  },
  {
    "path": "packages/system/tests/background-loader.test.ts",
    "content": "/**\n * Tests for the refactored BackgroundLoader:\n *   - Priority tiers (high / normal / low) with separate debounce timers\n *   - Chunking: authors split into groups of ≤100 per relay filter\n *   - In-flight deduplication: a key being fetched is never re-dispatched\n *   - Blacklisting: keys with no results are skipped for BlacklistTtl\n *   - Fresh-cache skip: keys that are within the expire cutoff are not fetched\n *   - UntrackKeys: removes from all priority sets\n */\n\nimport { afterEach, beforeEach, describe, expect, mock, test } from \"bun:test\"\nimport type { CachedTable, CacheEvents } from \"@snort/shared\"\nimport { EventEmitter } from \"eventemitter3\"\nimport type { RequestBuilder, SystemInterface, TaggedNostrEvent } from \"../src\"\nimport { BackgroundLoader, type ProfilePriority } from \"../src/background-loader\"\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction sleep(ms: number) {\n  return new Promise<void>(resolve => setTimeout(resolve, ms))\n}\n\n/** Generate a valid 64-char hex pubkey */\nfunction pubkey(seed: number): string {\n  return seed.toString(16).padStart(64, \"0\")\n}\n\n/** Generate 'count' unique pubkeys starting from offset */\nfunction pubkeys(count: number, offset = 0): string[] {\n  return Array.from({ length: count }, (_, i) => pubkey(offset + i + 1))\n}\n\n// ---------------------------------------------------------------------------\n// Minimal in-memory CachedTable implementation\n// ---------------------------------------------------------------------------\n\ntype TestEntry = { pubkey: string; loaded: number; created: number }\n\nclass MemoryCache extends EventEmitter<CacheEvents<TestEntry>> implements CachedTable<TestEntry> {\n  #data = new Map<string, TestEntry>()\n  #keyListeners = new Map<string, Set<() => void>>()\n\n  key(of: TestEntry) {\n    return of.pubkey\n  }\n\n  getFromCache(k?: string) {\n    return k ? this.#data.get(k) : undefined\n  }\n\n  async get(k?: string) {\n    return this.getFromCache(k)\n  }\n\n  async bulkGet(keys: string[]) {\n    return keys.map(k => this.#data.get(k)).filter(Boolean) as TestEntry[]\n  }\n\n  async set(obj: TestEntry) {\n    this.#data.set(obj.pubkey, obj)\n    this.emit(\"change\", [obj.pubkey])\n    this.#notifyKey(obj.pubkey)\n  }\n\n  async bulkSet(objs: TestEntry[] | Readonly<TestEntry[]>) {\n    for (const obj of objs) {\n      this.#data.set(obj.pubkey, obj)\n    }\n    const keys = objs.map(o => o.pubkey)\n    this.emit(\"change\", keys)\n    for (const k of keys) this.#notifyKey(k)\n  }\n\n  async update(m: TestEntry) {\n    const existing = this.#data.get(m.pubkey)\n    if (existing && existing.created >= m.created) return \"no_change\" as const\n    await this.set(m)\n    return existing ? (\"updated\" as const) : (\"new\" as const)\n  }\n\n  async buffer(keys: string[]) {\n    // in-memory only; nothing on \"disk\"\n    return keys.filter(k => !this.#data.has(k))\n  }\n\n  async preload() {}\n  keysOnTable() {\n    return [...this.#data.keys()]\n  }\n  async clear() {\n    this.#data.clear()\n  }\n  snapshot() {\n    return [...this.#data.values()]\n  }\n  async search() {\n    return []\n  }\n\n  subscribe(key: string, cb: () => void): () => void {\n    let s = this.#keyListeners.get(key)\n    if (!s) {\n      s = new Set()\n      this.#keyListeners.set(key, s)\n    }\n    s.add(cb)\n    return () => {\n      const set = this.#keyListeners.get(key)\n      if (set) {\n        set.delete(cb)\n        if (set.size === 0) this.#keyListeners.delete(key)\n      }\n    }\n  }\n\n  #notifyKey(key: string) {\n    const listeners = this.#keyListeners.get(key)\n    if (listeners) {\n      for (const cb of listeners) cb()\n    }\n  }\n\n  /** Seed a key with a loaded timestamp so it appears fresh */\n  seed(pk: string, loadedMs: number, createdSecs = 1) {\n    this.#data.set(pk, { pubkey: pk, loaded: loadedMs, created: createdSecs })\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Concrete BackgroundLoader for testing\n// ---------------------------------------------------------------------------\n\n/** Captures every RequestBuilder passed to buildSub */\nclass TestLoader extends BackgroundLoader<TestEntry> {\n  fetchCalls: Array<string[]> = [] // authors per Fetch call\n  fetchResolve: ((results: TestEntry[]) => void) | undefined\n\n  // Return Fetch call index → authors\n  subIds: string[] = []\n\n  constructor(system: SystemInterface, cache: CachedTable<TestEntry>) {\n    super(system, cache)\n  }\n\n  override name() {\n    return \"TestLoader\"\n  }\n  override onEvent(e: Readonly<TaggedNostrEvent>): TestEntry | undefined {\n    return undefined\n  }\n  override getExpireCutoff() {\n    return Date.now() - 1\n  } // anything not loaded in the last ms is \"expired\"\n\n  override buildSub(missing: string[]): RequestBuilder {\n    // Return a minimal stub that satisfies the RequestBuilder shape used by #buildChunkSub\n    return {\n      id: \"test-sub\",\n      withOptions: () => ({}),\n      withFilter: () => ({ kinds: () => ({ authors: () => ({}) }) }),\n    } as unknown as RequestBuilder\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Minimal mock system — captures Fetch calls\n// ---------------------------------------------------------------------------\n\ntype FetchCallback = (evs: TaggedNostrEvent[]) => Promise<void>\n\nfunction makeMockSystem(onFetch: (req: RequestBuilder, authors: string[]) => Promise<TestEntry[]>) {\n  return {\n    Fetch: async (req: RequestBuilder, cb?: FetchCallback) => {\n      // Extract the authors the loader put into the filter — we capture them from\n      // the stub filter built in TestLoader.buildSub above; instead, we read\n      // the req.id which embeds the chunk index, and the test records authors\n      // via a spy.\n      if (cb) await cb([])\n      return []\n    },\n  } as unknown as SystemInterface\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe(\"BackgroundLoader — priority tiers\", () => {\n  let cache: MemoryCache\n  let fetchedBatches: string[][]\n  let system: SystemInterface\n  let loader: TestLoader\n\n  beforeEach(() => {\n    cache = new MemoryCache()\n    fetchedBatches = []\n\n    // Intercept Fetch calls by overriding buildSub to record authors\n    system = {\n      Fetch: async (_req: RequestBuilder, cb?: FetchCallback) => {\n        if (cb) await cb([])\n        return []\n      },\n    } as unknown as SystemInterface\n  })\n\n  afterEach(() => {\n    loader?.destroy()\n  })\n\n  test(\"TrackKeys with high priority schedules flush within 50ms\", async () => {\n    let dispatched = false\n    system = {\n      Fetch: async (_req: RequestBuilder, cb?: FetchCallback) => {\n        dispatched = true\n        if (cb) await cb([])\n        return []\n      },\n    } as unknown as SystemInterface\n\n    loader = new TestLoader(system, cache)\n    loader.TrackKeys(pubkey(1), \"high\")\n\n    // Should not have dispatched immediately (debounced)\n    expect(dispatched).toBe(false)\n\n    // After 60ms the 50ms debounce should have fired\n    await sleep(100)\n    expect(dispatched).toBe(true)\n  })\n\n  test(\"TrackKeys with normal priority flushes after 500ms\", async () => {\n    let dispatched = false\n    system = {\n      Fetch: async (_req: RequestBuilder, cb?: FetchCallback) => {\n        dispatched = true\n        if (cb) await cb([])\n        return []\n      },\n    } as unknown as SystemInterface\n\n    loader = new TestLoader(system, cache)\n    loader.TrackKeys(pubkey(1), \"normal\")\n\n    // At 200ms the normal 500ms debounce should NOT have fired yet\n    await sleep(200)\n    expect(dispatched).toBe(false)\n\n    // After 600ms total it should have fired\n    await sleep(400)\n    expect(dispatched).toBe(true)\n  })\n\n  test(\"multiple TrackKeys calls within debounce window collapse into one dispatch\", async () => {\n    let fetchCount = 0\n    system = {\n      Fetch: async (_req: RequestBuilder, cb?: FetchCallback) => {\n        fetchCount++\n        if (cb) await cb([])\n        return []\n      },\n    } as unknown as SystemInterface\n\n    loader = new TestLoader(system, cache)\n\n    // Add 5 keys in rapid succession — all within the 50ms high-priority window\n    for (const pk of pubkeys(5)) {\n      loader.TrackKeys(pk, \"high\")\n    }\n\n    await sleep(100)\n\n    // All 5 keys fit in one chunk (< 100), so exactly 1 Fetch call\n    expect(fetchCount).toBe(1)\n  })\n\n  test(\"UntrackKeys removes key from all priority sets\", async () => {\n    const fetchedKeys: string[] = []\n    const pk1 = pubkey(1)\n    const pk2 = pubkey(2)\n\n    // Spy on buildSub to capture which keys are fetched\n    class SpyLoader extends TestLoader {\n      override buildSub(missing: string[]) {\n        fetchedKeys.push(...missing)\n        return super.buildSub(missing)\n      }\n    }\n\n    loader = new SpyLoader(system, cache)\n    loader.TrackKeys(pk1, \"high\")\n    loader.TrackKeys(pk2, \"high\")\n    loader.UntrackKeys(pk1)\n\n    await sleep(100)\n\n    expect(fetchedKeys).not.toContain(pk1)\n    expect(fetchedKeys).toContain(pk2)\n  })\n\n  test(\"destroy() prevents dispatch after being called\", async () => {\n    let fetchCount = 0\n    system = {\n      Fetch: async (_req: RequestBuilder, cb?: FetchCallback) => {\n        fetchCount++\n        if (cb) await cb([])\n        return []\n      },\n    } as unknown as SystemInterface\n\n    loader = new TestLoader(system, cache)\n    loader.TrackKeys(pubkey(1), \"high\")\n    loader.destroy()\n\n    await sleep(100)\n    expect(fetchCount).toBe(0)\n  })\n})\n\ndescribe(\"BackgroundLoader — chunking\", () => {\n  afterEach(() => {})\n\n  test(\"101 keys produce 2 Fetch calls (chunks of 100)\", async () => {\n    const cache = new MemoryCache()\n    const fetchCalls: number[] = []\n\n    const system = {\n      Fetch: async (_req: RequestBuilder, cb?: FetchCallback) => {\n        fetchCalls.push(1)\n        if (cb) await cb([])\n        return []\n      },\n    } as unknown as SystemInterface\n\n    class ChunkSpyLoader extends BackgroundLoader<TestEntry> {\n      override name() {\n        return \"ChunkSpyLoader\"\n      }\n      override onEvent() {\n        return undefined\n      }\n      override getExpireCutoff() {\n        return Date.now() - 1\n      }\n      override buildSub(missing: string[]): RequestBuilder {\n        return {\n          id: \"chunk-sub\",\n          withOptions: () => ({}),\n          withFilter: () => ({ kinds: () => ({ authors: () => ({}) }) }),\n        } as unknown as RequestBuilder\n      }\n    }\n\n    const loader = new ChunkSpyLoader(system, cache)\n    // Track 101 keys — should produce 2 chunks (100 + 1)\n    loader.TrackKeys(pubkeys(101), \"high\")\n\n    await sleep(150)\n    loader.destroy()\n\n    expect(fetchCalls.length).toBe(2)\n  })\n\n  test(\"100 keys produce exactly 1 Fetch call\", async () => {\n    const cache = new MemoryCache()\n    const fetchCalls: number[] = []\n\n    const system = {\n      Fetch: async (_req: RequestBuilder, cb?: FetchCallback) => {\n        fetchCalls.push(1)\n        if (cb) await cb([])\n        return []\n      },\n    } as unknown as SystemInterface\n\n    class ChunkSpyLoader extends BackgroundLoader<TestEntry> {\n      override name() {\n        return \"ChunkSpyLoader100\"\n      }\n      override onEvent() {\n        return undefined\n      }\n      override getExpireCutoff() {\n        return Date.now() - 1\n      }\n      override buildSub(missing: string[]): RequestBuilder {\n        return {\n          id: \"chunk-sub\",\n          withOptions: () => ({}),\n          withFilter: () => ({ kinds: () => ({ authors: () => ({}) }) }),\n        } as unknown as RequestBuilder\n      }\n    }\n\n    const loader = new ChunkSpyLoader(system, cache)\n    loader.TrackKeys(pubkeys(100), \"high\")\n\n    await sleep(150)\n    loader.destroy()\n\n    expect(fetchCalls.length).toBe(1)\n  })\n\n  test(\"each chunk gets a unique RequestBuilder ID\", async () => {\n    const cache = new MemoryCache()\n    const seenIds = new Set<string>()\n\n    const system = {\n      Fetch: async (req: RequestBuilder, cb?: FetchCallback) => {\n        seenIds.add(req.id)\n        if (cb) await cb([])\n        return []\n      },\n    } as unknown as SystemInterface\n\n    class IdSpyLoader extends BackgroundLoader<TestEntry> {\n      override name() {\n        return \"IdSpyLoader\"\n      }\n      override onEvent() {\n        return undefined\n      }\n      override getExpireCutoff() {\n        return Date.now() - 1\n      }\n      override buildSub(_missing: string[]): RequestBuilder {\n        // Return a mutable stub\n        const stub = {\n          id: \"initial\",\n          withOptions: () => stub,\n          withFilter: () => ({ kinds: () => ({ authors: () => ({}) }) }),\n        }\n        return stub as unknown as RequestBuilder\n      }\n    }\n\n    const loader = new IdSpyLoader(system, cache)\n    // 250 keys → 3 chunks\n    loader.TrackKeys(pubkeys(250), \"high\")\n\n    await sleep(150)\n    loader.destroy()\n\n    // All 3 chunk IDs must be distinct\n    expect(seenIds.size).toBe(3)\n  })\n})\n\ndescribe(\"BackgroundLoader — in-flight deduplication\", () => {\n  test(\"a key being fetched is not included in a second concurrent dispatch\", async () => {\n    const cache = new MemoryCache()\n    const fetchedBatches: string[][] = []\n    let resolveFetch!: () => void\n    const fetchLatch = new Promise<void>(resolve => {\n      resolveFetch = resolve\n    })\n\n    // First fetch call hangs until we release the latch\n    let callCount = 0\n    const system = {\n      Fetch: async (_req: RequestBuilder, cb?: FetchCallback) => {\n        callCount++\n        if (callCount === 1) {\n          // Hang the first fetch so the key stays in-flight\n          await fetchLatch\n        }\n        if (cb) await cb([])\n        return []\n      },\n    } as unknown as SystemInterface\n\n    class InFlightSpyLoader extends BackgroundLoader<TestEntry> {\n      override name() {\n        return \"InFlightSpyLoader\"\n      }\n      override onEvent() {\n        return undefined\n      }\n      override getExpireCutoff() {\n        return Date.now() - 1\n      }\n      override buildSub(missing: string[]): RequestBuilder {\n        fetchedBatches.push([...missing])\n        const stub = {\n          id: \"inflight-sub\",\n          withOptions: () => stub,\n          withFilter: () => ({ kinds: () => ({ authors: () => ({}) }) }),\n        }\n        return stub as unknown as RequestBuilder\n      }\n    }\n\n    const loader = new InFlightSpyLoader(system, cache)\n    const pk = pubkey(42)\n\n    // First TrackKeys — starts the first (hanging) fetch\n    loader.TrackKeys(pk, \"high\")\n    await sleep(80) // let the 50ms debounce fire and first fetch start\n\n    // Second TrackKeys — fires a second flush while first fetch is still in-flight\n    loader.TrackKeys(pk, \"high\")\n    await sleep(80)\n\n    // Release the latch so the first fetch can complete\n    resolveFetch()\n    await sleep(50)\n\n    loader.destroy()\n\n    // The key should only appear in the first batch; the second dispatch\n    // should have found it in-flight and skipped it\n    const allFetched = fetchedBatches.flat()\n    const countOfPk = allFetched.filter(k => k === pk).length\n    expect(countOfPk).toBe(1)\n  })\n})\n\ndescribe(\"BackgroundLoader — fresh cache skip\", () => {\n  test(\"a key loaded recently is not re-fetched\", async () => {\n    const cache = new MemoryCache()\n    let fetchCount = 0\n\n    const system = {\n      Fetch: async (_req: RequestBuilder, cb?: FetchCallback) => {\n        fetchCount++\n        if (cb) await cb([])\n        return []\n      },\n    } as unknown as SystemInterface\n\n    class FreshSkipLoader extends BackgroundLoader<TestEntry> {\n      override name() {\n        return \"FreshSkipLoader\"\n      }\n      override onEvent() {\n        return undefined\n      }\n      // Cutoff is 1 hour ago — anything loaded more recently than that is fresh\n      override getExpireCutoff() {\n        return Date.now() - 60 * 60 * 1_000\n      }\n      override buildSub(missing: string[]): RequestBuilder {\n        const stub = {\n          id: \"fresh-sub\",\n          withOptions: () => stub,\n          withFilter: () => ({ kinds: () => ({ authors: () => ({}) }) }),\n        }\n        return stub as unknown as RequestBuilder\n      }\n    }\n\n    const pk = pubkey(99)\n    // Seed as loaded \"just now\"\n    cache.seed(pk, Date.now(), 1)\n\n    const loader = new FreshSkipLoader(system, cache)\n    loader.TrackKeys(pk, \"high\")\n\n    await sleep(100)\n    loader.destroy()\n\n    // Should not have fetched since the cache entry is fresh\n    expect(fetchCount).toBe(0)\n  })\n\n  test(\"a key loaded before the expire cutoff IS re-fetched\", async () => {\n    const cache = new MemoryCache()\n    let fetchCount = 0\n\n    const system = {\n      Fetch: async (_req: RequestBuilder, cb?: FetchCallback) => {\n        fetchCount++\n        if (cb) await cb([])\n        return []\n      },\n    } as unknown as SystemInterface\n\n    class ExpiredLoader extends BackgroundLoader<TestEntry> {\n      override name() {\n        return \"ExpiredLoader\"\n      }\n      override onEvent() {\n        return undefined\n      }\n      // Cutoff is 1 hour ago — anything loaded more than 1 hour ago is expired\n      override getExpireCutoff() {\n        return Date.now() - 60 * 60 * 1_000\n      }\n      override buildSub(missing: string[]): RequestBuilder {\n        const stub = {\n          id: \"expired-sub\",\n          withOptions: () => stub,\n          withFilter: () => ({ kinds: () => ({ authors: () => ({}) }) }),\n        }\n        return stub as unknown as RequestBuilder\n      }\n    }\n\n    const pk = pubkey(100)\n    // Seed as loaded 2 hours ago — expired\n    cache.seed(pk, Date.now() - 2 * 60 * 60 * 1_000, 1)\n\n    const loader = new ExpiredLoader(system, cache)\n    loader.TrackKeys(pk, \"high\")\n\n    await sleep(100)\n    loader.destroy()\n\n    expect(fetchCount).toBe(1)\n  })\n})\n\ndescribe(\"BackgroundLoader — blacklisting\", () => {\n  test(\"keys that return no results are not re-fetched in the same session\", async () => {\n    const cache = new MemoryCache()\n    const fetchedBatches: string[][] = []\n\n    const system = {\n      // Returns empty — simulates relay knowing nothing about this pubkey\n      Fetch: async (_req: RequestBuilder, cb?: FetchCallback) => {\n        if (cb) await cb([])\n        return []\n      },\n    } as unknown as SystemInterface\n\n    class BlacklistSpyLoader extends BackgroundLoader<TestEntry> {\n      override name() {\n        return \"BlacklistSpyLoader\"\n      }\n      override onEvent() {\n        return undefined\n      }\n      override getExpireCutoff() {\n        return Date.now() - 1\n      }\n      override buildSub(missing: string[]): RequestBuilder {\n        fetchedBatches.push([...missing])\n        const stub = {\n          id: \"bl-sub\",\n          withOptions: () => stub,\n          withFilter: () => ({ kinds: () => ({ authors: () => ({}) }) }),\n        }\n        return stub as unknown as RequestBuilder\n      }\n    }\n\n    const pk = pubkey(77)\n    const loader = new BlacklistSpyLoader(system, cache)\n\n    // First TrackKeys — key has no result → gets blacklisted\n    loader.TrackKeys(pk, \"high\")\n    await sleep(100)\n\n    const firstBatchCount = fetchedBatches.length\n\n    // Second TrackKeys — key should be blacklisted, no second fetch\n    loader.TrackKeys(pk, \"high\")\n    await sleep(100)\n\n    loader.destroy()\n\n    // Total batches should be the same — blacklisted key was not re-queued\n    expect(fetchedBatches.length).toBe(firstBatchCount)\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/event-ext.test.ts",
    "content": "import { describe, expect, test } from \"bun:test\"\nimport { NostrPrefix } from \"@snort/shared\"\nimport { EventExt, EventType } from \"../src/event-ext\"\nimport EventKind from \"../src/event-kind\"\nimport type { NostrEvent } from \"../src/nostr\"\n\ndescribe(\"EventExt\", () => {\n  describe(\"NIP-10 - extractThread\", () => {\n    test(\"should parse reaction with non-hex author field in e tag\", () => {\n      // Real-world case where tag[3] is a pubkey (author) but tag looks like relay URL\n      const reaction = {\n        content: \":purple-heart:\",\n        created_at: 1761043616,\n        id: \"92723125c4a564f90a073ac4a0073f440d8b472453a42d7a32bbf710f1503d11\",\n        kind: 7,\n        pubkey: \"20d29810d6a5f92b045ade02ebbadc9036d741cc686b00415c42b4236fe4ad2f\",\n        sig: \"918404170b25a1f3f08f73ffcca60ea8fef7b077c99ae1dc44ac1e6c6f6341709f6f604b8134636c50f64ef86956ff8126b6beaa7ecef5d30fcde7faaa6dba9c\",\n        tags: [\n          [\n            \"e\",\n            \"2bcd9cf56db44d1a9f2499110ab1924450cd87fe7989ec0b1cce565f7b0465f7\",\n            \"wss://relay.damus.io/\",\n            \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\",\n          ],\n          [\"p\", \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\", \"wss://relay.damus.io/\"],\n          [\"k\", \"1\"],\n          [\"emoji\", \"purple-heart\", \"https://em-content.zobj.net/source/microsoft-teams/363/purple-heart_1f49c.png\"],\n        ],\n      }\n\n      const thread = EventExt.extractThread(reaction)\n\n      // Should extract the event reference with the relay and author\n      expect(thread).toMatchObject({\n        kind: \"nip10\",\n        root: {\n          type: NostrPrefix.Event,\n          id: \"2bcd9cf56db44d1a9f2499110ab1924450cd87fe7989ec0b1cce565f7b0465f7\",\n          relays: [\"wss://relay.damus.io/\"],\n          author: \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\",\n          scope: \"root\",\n        },\n      })\n\n      // Should also extract the pubkey mention from p tag\n      expect(thread?.pubKeys).toHaveLength(1)\n      expect(thread?.pubKeys[0]).toMatchObject({\n        type: NostrPrefix.Profile,\n        id: \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\",\n      })\n    })\n\n    test(\"should correctly handle thread with p tag before e tags without markers\", () => {\n      // NIP-10: Deprecated positional format should only consider e/a tags\n      // p tags in any position should not affect the positional interpretation\n      const event = {\n        content: \"Reply mentioning someone\",\n        id: \"0000000000000000000000000000000000000000000000000000000000000009\",\n        kind: 1,\n        created_at: 1,\n        pubkey: \"0000000000000000000000000000000000000000000000000000000000000001\",\n        sig: \"test\",\n        tags: [\n          [\"p\", \"1111111111111111111111111111111111111111111111111111111111111111\"], // p tag should not affect e tag positions\n          [\"e\", \"cbf2375078000000000000000000000000000000000000000000000000000001\"], // First e tag = root\n          [\"e\", \"977ac5d3b6000000000000000000000000000000000000000000000000000002\"], // Middle e tag = mention\n          [\"e\", \"8f99ca1363000000000000000000000000000000000000000000000000000003\"], // Last e tag = reply\n        ],\n      }\n\n      const thread = EventExt.extractThread(event)\n\n      // Positional interpretation should only count e/a tags, not p tags\n      expect(thread).toMatchObject({\n        kind: \"nip10\",\n        root: {\n          type: NostrPrefix.Event,\n          id: \"cbf2375078000000000000000000000000000000000000000000000000000001\",\n          scope: \"root\",\n        },\n        replyTo: {\n          type: NostrPrefix.Event,\n          id: \"8f99ca1363000000000000000000000000000000000000000000000000000003\",\n          scope: \"reply\",\n        },\n        mentions: [\n          {\n            type: NostrPrefix.Event,\n            id: \"977ac5d3b6000000000000000000000000000000000000000000000000000002\",\n            scope: \"mention\",\n          },\n        ],\n      })\n\n      // p tag should be extracted as a pubkey mention\n      expect(thread?.pubKeys).toHaveLength(1)\n      expect(thread?.pubKeys[0]?.id).toBe(\"1111111111111111111111111111111111111111111111111111111111111111\")\n    })\n\n    test(\"should extract thread with unmarked tags (deprecated format)\", () => {\n      const a = {\n        content: \"This is the problem with Lightning....\",\n        id: \"868187063f0000000000000000000000000000000000000000000000000000ab\",\n        kind: 1,\n        created_at: 1,\n        pubkey: \"0000000000000000000000000000000000000000000000000000000000000001\",\n        sig: \"test\",\n        tags: [\n          [\"e\", \"cbf2375078000000000000000000000000000000000000000000000000000001\"],\n          [\"e\", \"977ac5d3b6000000000000000000000000000000000000000000000000000002\"],\n          [\"e\", \"8f99ca1363000000000000000000000000000000000000000000000000000003\"],\n        ],\n      }\n\n      const b = {\n        content: \"This is a good point, but your ...\",\n        id: \"434ad4a646000000000000000000000000000000000000000000000000000004\",\n        kind: 1,\n        created_at: 1,\n        pubkey: \"0000000000000000000000000000000000000000000000000000000000000001\",\n        sig: \"test\",\n        tags: [\n          [\"e\", \"cbf2375078000000000000000000000000000000000000000000000000000001\"],\n          [\"e\", \"868187063f0000000000000000000000000000000000000000000000000000ab\"],\n          [\"e\", \"6834ffc491000000000000000000000000000000000000000000000000000005\"],\n        ],\n      }\n\n      expect(EventExt.extractThread(a)).toMatchObject({\n        kind: \"nip10\",\n        root: {\n          type: NostrPrefix.Event,\n          id: \"cbf2375078000000000000000000000000000000000000000000000000000001\",\n          scope: \"root\",\n        },\n        replyTo: {\n          type: NostrPrefix.Event,\n          id: \"8f99ca1363000000000000000000000000000000000000000000000000000003\",\n          scope: \"reply\",\n        },\n        mentions: [\n          {\n            type: NostrPrefix.Event,\n            id: \"977ac5d3b6000000000000000000000000000000000000000000000000000002\",\n            scope: \"mention\",\n          },\n        ],\n      })\n      expect(EventExt.extractThread(b)).toMatchObject({\n        kind: \"nip10\",\n        root: {\n          type: NostrPrefix.Event,\n          id: \"cbf2375078000000000000000000000000000000000000000000000000000001\",\n          scope: \"root\",\n        },\n        replyTo: {\n          type: NostrPrefix.Event,\n          id: \"6834ffc491000000000000000000000000000000000000000000000000000005\",\n          scope: \"reply\",\n        },\n        mentions: [\n          {\n            type: NostrPrefix.Event,\n            id: \"868187063f0000000000000000000000000000000000000000000000000000ab\",\n            scope: \"mention\",\n          },\n        ],\n      })\n    })\n\n    test(\"should extract thread with marked tags\", () => {\n      const event = {\n        content: \"There is some middle ground ...\",\n        id: \"6834ffc491000000000000000000000000000000000000000000000000000005\",\n        kind: 1,\n        created_at: 1,\n        pubkey: \"0000000000000000000000000000000000000000000000000000000000000001\",\n        sig: \"test\",\n        tags: [\n          [\"e\", \"cbf2375078000000000000000000000000000000000000000000000000000001\", \"\", \"root\"],\n          [\"e\", \"868187063f0000000000000000000000000000000000000000000000000000ab\", \"\", \"reply\"],\n        ],\n      }\n\n      expect(EventExt.extractThread(event)).toMatchObject({\n        root: {\n          type: NostrPrefix.Event,\n          id: \"cbf2375078000000000000000000000000000000000000000000000000000001\",\n          relays: [\"\"],\n          scope: \"root\",\n        },\n        replyTo: {\n          type: NostrPrefix.Event,\n          id: \"868187063f0000000000000000000000000000000000000000000000000000ab\",\n          relays: [\"\"],\n          scope: \"reply\",\n        },\n        mentions: [],\n      })\n    })\n\n    test(\"should return undefined for event with no thread tags\", () => {\n      const event = {\n        content: \"Just a regular note\",\n        id: \"aaaa111111111111111111111111111111111111111111111111111111111111\",\n        kind: 1,\n        created_at: 1,\n        pubkey: \"0000000000000000000000000000000000000000000000000000000000000001\",\n        sig: \"test\",\n        tags: [],\n      }\n\n      expect(EventExt.extractThread(event)).toBeUndefined()\n    })\n\n    test(\"should extract pubKeys from thread\", () => {\n      const event = {\n        content: \"Reply with mentions\",\n        id: \"bbbb222222222222222222222222222222222222222222222222222222222222\",\n        kind: 1,\n        created_at: 1,\n        pubkey: \"0000000000000000000000000000000000000000000000000000000000000001\",\n        sig: \"test\",\n        tags: [\n          [\"e\", \"cbf2375078000000000000000000000000000000000000000000000000000001\", \"\", \"root\"],\n          [\"e\", \"dddd333333333333333333333333333333333333333333333333333333333333\", \"\", \"reply\"],\n          [\"p\", \"1111111111111111111111111111111111111111111111111111111111111111\"],\n          [\"p\", \"2222222222222222222222222222222222222222222222222222222222222222\"],\n        ],\n      }\n\n      const thread = EventExt.extractThread(event)\n      expect(thread?.pubKeys).toHaveLength(2)\n      expect(thread?.pubKeys[0]).toMatchObject({\n        type: NostrPrefix.Profile,\n        id: \"1111111111111111111111111111111111111111111111111111111111111111\",\n      })\n    })\n  })\n\n  describe(\"getType\", () => {\n    test(\"should identify regular events\", () => {\n      expect(EventExt.getType(1)).toBe(EventType.Regular)\n      expect(EventExt.getType(7)).toBe(EventType.Regular)\n      expect(EventExt.getType(9999)).toBe(EventType.Regular)\n    })\n\n    test(\"should identify replaceable events\", () => {\n      expect(EventExt.getType(0)).toBe(EventType.Replaceable) // metadata\n      expect(EventExt.getType(3)).toBe(EventType.Replaceable) // contacts\n      expect(EventExt.getType(10000)).toBe(EventType.Replaceable)\n      expect(EventExt.getType(10002)).toBe(EventType.Replaceable)\n      expect(EventExt.getType(19999)).toBe(EventType.Replaceable)\n    })\n\n    test(\"should identify addressable events\", () => {\n      expect(EventExt.getType(30000)).toBe(EventType.Addressable)\n      expect(EventExt.getType(30023)).toBe(EventType.Addressable) // long-form\n      expect(EventExt.getType(39999)).toBe(EventType.Addressable)\n    })\n  })\n\n  describe(\"isReplaceable\", () => {\n    test(\"should return true for replaceable events\", () => {\n      expect(EventExt.isReplaceable(0)).toBe(true)\n      expect(EventExt.isReplaceable(3)).toBe(true)\n      expect(EventExt.isReplaceable(10002)).toBe(true)\n    })\n\n    test(\"should return true for addressable events\", () => {\n      expect(EventExt.isReplaceable(30023)).toBe(true)\n      expect(EventExt.isReplaceable(30001)).toBe(true)\n    })\n\n    test(\"should return false for regular events\", () => {\n      expect(EventExt.isReplaceable(1)).toBe(false)\n      expect(EventExt.isReplaceable(7)).toBe(false)\n    })\n  })\n\n  describe(\"keyOf\", () => {\n    test(\"should create key for regular event\", () => {\n      const event = {\n        id: \"abc123def456abc123def456abc123def456abc123def456abc123def456abc1\",\n        kind: 1,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [],\n        sig: \"test\",\n      } as NostrEvent\n\n      expect(EventExt.keyOf(event)).toBe(\"abc123def456abc123def456abc123def456abc123def456abc123def456abc1\")\n    })\n\n    test(\"should create key for replaceable event\", () => {\n      const event = {\n        id: \"abc123def456abc123def456abc123def456abc123def456abc123def456abc1\",\n        kind: 0,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [],\n        sig: \"test\",\n      } as NostrEvent\n\n      expect(EventExt.keyOf(event)).toBe(\"0:1111111111111111111111111111111111111111111111111111111111111111\")\n    })\n\n    test(\"should create key for addressable event\", () => {\n      const event = {\n        id: \"abc123def456abc123def456abc123def456abc123def456abc123def456abc1\",\n        kind: 30023,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [[\"d\", \"my-article\"]],\n        sig: \"test\",\n      } as NostrEvent\n\n      expect(EventExt.keyOf(event)).toBe(\n        \"30023:1111111111111111111111111111111111111111111111111111111111111111:my-article\",\n      )\n    })\n  })\n\n  describe(\"getRootPubKey\", () => {\n    test(\"should return event pubkey when no delegation\", () => {\n      const event = {\n        id: \"test\",\n        kind: 1,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [],\n        sig: \"test\",\n      } as NostrEvent\n\n      expect(EventExt.getRootPubKey(event)).toBe(\"1111111111111111111111111111111111111111111111111111111111111111\")\n    })\n\n    test(\"should ignore unverified delegation tag and return event pubkey\", () => {\n      // NIP-26 delegation tags without signature verification must not be trusted —\n      // any event could claim authorship by any pubkey. Until a full NIP-26\n      // implementation with delegation-token signature verification is added,\n      // getRootPubKey() falls back to e.pubkey.\n      const event = {\n        id: \"test\",\n        kind: 1,\n        pubkey: \"2222222222222222222222222222222222222222222222222222222222222222\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [[\"delegation\", \"1111111111111111111111111111111111111111111111111111111111111111\", \"kind=1\", \"sig=xxx\"]],\n        sig: \"test\",\n      } as NostrEvent\n\n      expect(EventExt.getRootPubKey(event)).toBe(\"2222222222222222222222222222222222222222222222222222222222222222\")\n    })\n  })\n\n  describe(\"createId\", () => {\n    test(\"should create consistent event ID\", () => {\n      const event = {\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        kind: 1,\n        created_at: 1234567890,\n        content: \"Hello, world!\",\n        tags: [],\n      }\n\n      const id1 = EventExt.createId(event)\n      const id2 = EventExt.createId(event)\n\n      expect(id1).toBe(id2)\n      expect(id1).toHaveLength(64)\n    })\n\n    test(\"should create different IDs for different content\", () => {\n      const event1 = {\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        kind: 1,\n        created_at: 1234567890,\n        content: \"Hello\",\n        tags: [],\n      }\n\n      const event2 = {\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        kind: 1,\n        created_at: 1234567890,\n        content: \"World\",\n        tags: [],\n      }\n\n      const id1 = EventExt.createId(event1)\n      const id2 = EventExt.createId(event2)\n\n      expect(id1).not.toBe(id2)\n    })\n  })\n\n  describe(\"forPubKey\", () => {\n    test(\"should create event template for pubkey\", () => {\n      const pubkey = \"1111111111111111111111111111111111111111111111111111111111111111\"\n      const event = EventExt.forPubKey(pubkey, EventKind.TextNote)\n\n      expect(event.pubkey).toBe(pubkey)\n      expect(event.kind).toBe(EventKind.TextNote)\n      expect(event.content).toBe(\"\")\n      expect(event.tags).toEqual([])\n      expect(event.created_at).toBeGreaterThan(0)\n    })\n  })\n\n  describe(\"fixupEvent\", () => {\n    test(\"should add missing properties\", () => {\n      const event = {\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n      } as any\n\n      EventExt.fixupEvent(event)\n\n      expect(event.tags).toEqual([])\n      expect(event.created_at).toBe(0)\n      expect(event.content).toBe(\"\")\n      expect(event.id).toBe(\"\")\n      expect(event.kind).toBe(0)\n      expect(event.sig).toBe(\"\")\n    })\n\n    test(\"should not override existing properties\", () => {\n      const event = {\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        kind: 1,\n        created_at: 123456,\n        content: \"test\",\n        tags: [[\"e\", \"abc\"]],\n        id: \"test-id\",\n        sig: \"test-sig\",\n      } as NostrEvent\n\n      EventExt.fixupEvent(event)\n\n      expect(event.kind).toBe(1)\n      expect(event.created_at).toBe(123456)\n      expect(event.content).toBe(\"test\")\n      expect(event.tags).toEqual([[\"e\", \"abc\"]])\n      expect(event.id).toBe(\"test-id\")\n      expect(event.sig).toBe(\"test-sig\")\n    })\n  })\n\n  describe(\"isWellFormed\", () => {\n    test(\"should return true for structurally valid regular event\", () => {\n      const event = {\n        id: \"test\",\n        kind: 1,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [],\n        sig: \"test-sig\",\n      } as NostrEvent\n\n      expect(EventExt.isWellFormed(event)).toBe(true)\n    })\n\n    test(\"should return false for event without signature\", () => {\n      const event = {\n        id: \"test\",\n        kind: 1,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [],\n      } as any\n\n      expect(EventExt.isWellFormed(event)).toBe(false)\n    })\n\n    test(\"should return false for addressable event without d tag\", () => {\n      const event = {\n        id: \"test\",\n        kind: 30023,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [],\n        sig: \"test-sig\",\n      } as NostrEvent\n\n      expect(EventExt.isWellFormed(event)).toBe(false)\n    })\n\n    test(\"should return true for addressable event with d tag\", () => {\n      const event = {\n        id: \"test\",\n        kind: 30023,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [[\"d\", \"my-article\"]],\n        sig: \"test-sig\",\n      } as NostrEvent\n\n      expect(EventExt.isWellFormed(event)).toBe(true)\n    })\n  })\n\n  describe(\"isValid\", () => {\n    const privateKey = \"0000000000000000000000000000000000000000000000000000000000000001\"\n\n    test(\"should return true for a properly signed event\", () => {\n      const event = {\n        pubkey: \"\",\n        kind: 1,\n        created_at: 1234567890,\n        content: \"Hello, isValid!\",\n        tags: [],\n        id: \"\",\n        sig: \"\",\n      } as NostrEvent\n      EventExt.sign(event, privateKey)\n      expect(EventExt.isValid(event)).toBe(true)\n    })\n\n    test(\"should return false for event with fake signature\", () => {\n      const event = {\n        id: \"test\",\n        kind: 1,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [],\n        sig: \"test-sig\",\n      } as NostrEvent\n      expect(EventExt.isValid(event)).toBe(false)\n    })\n\n    test(\"should return false for event without signature\", () => {\n      const event = {\n        id: \"test\",\n        kind: 1,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [],\n      } as any\n      expect(EventExt.isValid(event)).toBe(false)\n    })\n\n    test(\"should return false for properly signed addressable event without d tag\", () => {\n      const event = {\n        pubkey: \"\",\n        kind: 30023,\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [],\n        id: \"\",\n        sig: \"\",\n      } as NostrEvent\n      EventExt.sign(event, privateKey)\n      expect(EventExt.isValid(event)).toBe(false)\n    })\n  })\n\n  describe(\"sign and verify\", () => {\n    test(\"should sign and verify event\", () => {\n      const privateKey = \"0000000000000000000000000000000000000000000000000000000000000001\"\n      const event = {\n        pubkey: \"\",\n        kind: 1,\n        created_at: 1234567890,\n        content: \"Hello, world!\",\n        tags: [],\n        id: \"\",\n        sig: \"\",\n      } as NostrEvent\n\n      EventExt.sign(event, privateKey)\n\n      expect(event.pubkey).toHaveLength(64)\n      expect(event.id).toHaveLength(64)\n      expect(event.sig).toHaveLength(128)\n      expect(EventExt.verify(event)).toBe(true)\n    })\n\n    test(\"should fail verification with modified content\", () => {\n      const privateKey = \"0000000000000000000000000000000000000000000000000000000000000001\"\n      const event = {\n        pubkey: \"\",\n        kind: 1,\n        created_at: 1234567890,\n        content: \"Hello, world!\",\n        tags: [],\n        id: \"\",\n        sig: \"\",\n      } as NostrEvent\n\n      EventExt.sign(event, privateKey)\n      event.content = \"Modified content\"\n\n      expect(EventExt.verify(event)).toBe(false)\n    })\n\n    test(\"should fail verification with invalid signature\", () => {\n      const event = {\n        id: \"abc123def456abc123def456abc123def456abc123def456abc123def456abc1\",\n        kind: 1,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [],\n        sig: \"invalidsig\",\n      } as NostrEvent\n\n      expect(EventExt.verify(event)).toBe(false)\n    })\n\n    test(\"should return false (not throw) for non-hex sig of valid length\", () => {\n      const event = {\n        id: \"abc123def456abc123def456abc123def456abc123def456abc123def456abc1\",\n        kind: 1,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [],\n        sig: \"g\".repeat(128), // correct length but non-hex\n      } as NostrEvent\n\n      expect(() => EventExt.verify(event)).not.toThrow()\n      expect(EventExt.verify(event)).toBe(false)\n      expect(() => EventExt.isValid(event)).not.toThrow()\n      expect(EventExt.isValid(event)).toBe(false)\n    })\n\n    test(\"should return false (not throw) for odd-length hex sig\", () => {\n      const event = {\n        id: \"abc123def456abc123def456abc123def456abc123def456abc123def456abc1\",\n        kind: 1,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [],\n        sig: \"a\".repeat(127), // odd-length hex\n      } as NostrEvent\n\n      expect(() => EventExt.verify(event)).not.toThrow()\n      expect(EventExt.verify(event)).toBe(false)\n    })\n\n    test(\"should return false (not throw) for invalid pubkey length\", () => {\n      const event = {\n        id: \"abc123def456abc123def456abc123def456abc123def456abc123def456abc1\",\n        kind: 1,\n        pubkey: \"abcd\", // too short\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [],\n        sig: \"b\".repeat(128),\n      } as NostrEvent\n\n      expect(() => EventExt.verify(event)).not.toThrow()\n      expect(EventExt.verify(event)).toBe(false)\n    })\n\n    test(\"should return false when id field does not match computed hash\", () => {\n      const privateKey = \"0000000000000000000000000000000000000000000000000000000000000001\"\n      const event = {\n        pubkey: \"\",\n        kind: 1,\n        created_at: 1234567890,\n        content: \"hello\",\n        tags: [],\n        id: \"\",\n        sig: \"\",\n      } as NostrEvent\n      EventExt.sign(event, privateKey)\n      // Tamper with the id field without changing content\n      event.id = event.id.replace(/^./, \"0\")\n\n      expect(EventExt.verify(event)).toBe(false)\n      expect(EventExt.isValid(event)).toBe(false)\n    })\n  })\n\n  describe(\"isWellFormed\", () => {\n    test(\"should return false (not throw) when tags is missing\", () => {\n      const event = {\n        id: \"test\",\n        kind: 1,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        sig: \"test-sig\",\n      } as any // tags deliberately omitted\n\n      expect(() => EventExt.isWellFormed(event)).not.toThrow()\n      expect(EventExt.isWellFormed(event)).toBe(false)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/feed-cache-subscribe.test.ts",
    "content": "/**\n * Tests for FeedCache.subscribe() — the O(1) per-key notification mechanism.\n *\n * The subscribe() API replaces the broad \"change\" event + keys.includes() linear\n * scan that was used in useUserProfile. Each subscriber is only invoked when\n * its specific key changes, not on every cache mutation.\n */\n\nimport { describe, expect, test } from \"bun:test\"\nimport type { CacheStore } from \"@snort/shared\"\nimport { FeedCache } from \"@snort/shared\"\n\n// ---------------------------------------------------------------------------\n// Minimal FeedCache implementation for testing\n// ---------------------------------------------------------------------------\n\ntype TestItem = { id: string; value: string; created: number; loaded: number }\n\nclass TestFeedCache extends FeedCache<TestItem> {\n  constructor() {\n    super(\"TestFeedCache\")\n  }\n\n  key(of: TestItem) {\n    return of.id\n  }\n\n  takeSnapshot() {\n    return this.snapshot()\n  }\n\n  async search() {\n    return []\n  }\n}\n\nfunction item(id: string, value = \"v1\", created = 1, loaded = Date.now()): TestItem {\n  return { id, value, created, loaded }\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe(\"FeedCache.subscribe()\", () => {\n  test(\"callback fires when the subscribed key is set\", async () => {\n    const cache = new TestFeedCache()\n    let callCount = 0\n\n    cache.subscribe(\"key-a\", () => {\n      callCount++\n    })\n    await cache.set(item(\"key-a\"))\n\n    expect(callCount).toBe(1)\n  })\n\n  test(\"callback does NOT fire for a different key\", async () => {\n    const cache = new TestFeedCache()\n    let callCount = 0\n\n    cache.subscribe(\"key-a\", () => {\n      callCount++\n    })\n    await cache.set(item(\"key-b\")) // different key\n\n    expect(callCount).toBe(0)\n  })\n\n  test(\"multiple subscribers on the same key all receive the notification\", async () => {\n    const cache = new TestFeedCache()\n    let count1 = 0\n    let count2 = 0\n    let count3 = 0\n\n    cache.subscribe(\"shared-key\", () => {\n      count1++\n    })\n    cache.subscribe(\"shared-key\", () => {\n      count2++\n    })\n    cache.subscribe(\"shared-key\", () => {\n      count3++\n    })\n\n    await cache.set(item(\"shared-key\"))\n\n    expect(count1).toBe(1)\n    expect(count2).toBe(1)\n    expect(count3).toBe(1)\n  })\n\n  test(\"unsubscribe stops further notifications\", async () => {\n    const cache = new TestFeedCache()\n    let callCount = 0\n\n    const unsub = cache.subscribe(\"key-a\", () => {\n      callCount++\n    })\n\n    await cache.set(item(\"key-a\")) // fires once\n    unsub()\n    await cache.set(item(\"key-a\", \"v2\")) // should NOT fire\n\n    expect(callCount).toBe(1)\n  })\n\n  test(\"unsubscribing one of two subscribers leaves the other active\", async () => {\n    const cache = new TestFeedCache()\n    let count1 = 0\n    let count2 = 0\n\n    const unsub1 = cache.subscribe(\"key-a\", () => {\n      count1++\n    })\n    cache.subscribe(\"key-a\", () => {\n      count2++\n    })\n\n    await cache.set(item(\"key-a\")) // both fire\n    unsub1()\n    await cache.set(item(\"key-a\", \"v2\")) // only count2 fires\n\n    expect(count1).toBe(1)\n    expect(count2).toBe(2)\n  })\n\n  test(\"bulkSet notifies each key individually\", async () => {\n    const cache = new TestFeedCache()\n    let countA = 0\n    let countB = 0\n    const countC = 0 // not subscribed\n\n    cache.subscribe(\"a\", () => {\n      countA++\n    })\n    cache.subscribe(\"b\", () => {\n      countB++\n    })\n\n    await cache.bulkSet([item(\"a\"), item(\"b\"), item(\"c\")])\n\n    expect(countA).toBe(1)\n    expect(countB).toBe(1)\n    expect(countC).toBe(0) // no subscriber, no call\n  })\n\n  test(\"subscriber is not called after unsubscribe even after bulkSet\", async () => {\n    const cache = new TestFeedCache()\n    let callCount = 0\n\n    const unsub = cache.subscribe(\"a\", () => {\n      callCount++\n    })\n    unsub()\n    await cache.bulkSet([item(\"a\"), item(\"b\")])\n\n    expect(callCount).toBe(0)\n  })\n\n  test('the broad \"change\" event still fires for backward compatibility', async () => {\n    const cache = new TestFeedCache()\n    const changedKeys: string[] = []\n\n    cache.on(\"change\", keys => changedKeys.push(...keys))\n    await cache.set(item(\"key-x\"))\n\n    expect(changedKeys).toContain(\"key-x\")\n  })\n\n  test(\"subscribe and broad change event both fire on the same set()\", async () => {\n    const cache = new TestFeedCache()\n    let subscribeCount = 0\n    const broadKeys: string[] = []\n\n    cache.subscribe(\"k\", () => {\n      subscribeCount++\n    })\n    cache.on(\"change\", keys => broadKeys.push(...keys))\n\n    await cache.set(item(\"k\"))\n\n    expect(subscribeCount).toBe(1)\n    expect(broadKeys).toContain(\"k\")\n  })\n\n  test(\"update() with newer data notifies subscriber\", async () => {\n    const cache = new TestFeedCache()\n    let callCount = 0\n\n    cache.subscribe(\"up\", () => {\n      callCount++\n    })\n    await cache.update(item(\"up\", \"v1\", 1, 100)) // new entry\n    await cache.update(item(\"up\", \"v2\", 2, 200)) // updated — newer created\n\n    expect(callCount).toBe(2)\n  })\n\n  test(\"update() with older data does NOT notify subscriber\", async () => {\n    const cache = new TestFeedCache()\n    let callCount = 0\n\n    cache.subscribe(\"up\", () => {\n      callCount++\n    })\n    await cache.update(item(\"up\", \"v2\", 2, 200)) // newest\n    await cache.update(item(\"up\", \"v1\", 1, 100)) // older — should be skipped\n\n    expect(callCount).toBe(1)\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/negentropy.test.ts",
    "content": "import { NegentropyStorageVector, VectorStorageItem } from \"../src/negentropy/vector-storage\"\nimport { describe, test } from \"bun:test\"\n\ndescribe(\"negentropy\", () => {\n  test(\"should decodeBound\", () => {})\n})\n"
  },
  {
    "path": "packages/system/tests/nip10.test.ts",
    "content": "import { Nip10 } from \"../src/impl/nip10\"\nimport { describe, expect, test } from \"bun:test\"\nimport { NostrPrefix } from \"@snort/shared\"\nimport type { TaggedNostrEvent } from \"../src/nostr\"\nimport { EventBuilder } from \"../src/event-builder\"\n\ndescribe(\"Nip10\", () => {\n  describe(\"parseThread\", () => {\n    test(\"should correctly handle thread with p tag before e tags without markers\", () => {\n      // NIP-10: Deprecated positional format should only consider e/a tags\n      // p tags in any position should not affect the positional interpretation\n      const event = {\n        content: \"Reply mentioning someone\",\n        id: \"0000000000000000000000000000000000000000000000000000000000000009\",\n        kind: 1,\n        created_at: 1,\n        pubkey: \"0000000000000000000000000000000000000000000000000000000000000001\",\n        sig: \"test\",\n        tags: [\n          [\"p\", \"1111111111111111111111111111111111111111111111111111111111111111\"], // p tag should not affect e tag positions\n          [\"e\", \"cbf2375078000000000000000000000000000000000000000000000000000001\"], // First e tag = root\n          [\"e\", \"977ac5d3b6000000000000000000000000000000000000000000000000000002\"], // Middle e tag = mention\n          [\"e\", \"8f99ca1363000000000000000000000000000000000000000000000000000003\"], // Last e tag = reply\n        ],\n      }\n\n      const thread = Nip10.parseThread(event)\n\n      // Positional interpretation should only count e/a tags, not p tags\n      expect(thread).toMatchObject({\n        root: {\n          type: NostrPrefix.Event,\n          id: \"cbf2375078000000000000000000000000000000000000000000000000000001\",\n        },\n        replyTo: {\n          type: NostrPrefix.Event,\n          id: \"8f99ca1363000000000000000000000000000000000000000000000000000003\",\n        },\n        mentions: [\n          {\n            type: NostrPrefix.Event,\n            id: \"977ac5d3b6000000000000000000000000000000000000000000000000000002\",\n          },\n        ],\n      })\n\n      // p tag should be extracted as a pubkey mention\n      expect(thread?.pubKeys).toHaveLength(1)\n      expect(thread?.pubKeys[0]?.id).toBe(\"1111111111111111111111111111111111111111111111111111111111111111\")\n    })\n\n    test(\"should extract thread with unmarked tags (deprecated format)\", () => {\n      const a = {\n        content: \"This is the problem with Lightning....\",\n        id: \"868187063f0000000000000000000000000000000000000000000000000000ab\",\n        kind: 1,\n        created_at: 1,\n        pubkey: \"0000000000000000000000000000000000000000000000000000000000000001\",\n        sig: \"test\",\n        tags: [\n          [\"e\", \"cbf2375078000000000000000000000000000000000000000000000000000001\"],\n          [\"e\", \"977ac5d3b6000000000000000000000000000000000000000000000000000002\"],\n          [\"e\", \"8f99ca1363000000000000000000000000000000000000000000000000000003\"],\n        ],\n      }\n\n      const b = {\n        content: \"This is a good point, but your ...\",\n        id: \"434ad4a646000000000000000000000000000000000000000000000000000004\",\n        kind: 1,\n        created_at: 1,\n        pubkey: \"0000000000000000000000000000000000000000000000000000000000000001\",\n        sig: \"test\",\n        tags: [\n          [\"e\", \"cbf2375078000000000000000000000000000000000000000000000000000001\"],\n          [\"e\", \"868187063f0000000000000000000000000000000000000000000000000000ab\"],\n          [\"e\", \"6834ffc491000000000000000000000000000000000000000000000000000005\"],\n        ],\n      }\n\n      expect(Nip10.parseThread(a)).toMatchObject({\n        root: {\n          type: NostrPrefix.Event,\n          id: \"cbf2375078000000000000000000000000000000000000000000000000000001\",\n        },\n        replyTo: {\n          type: NostrPrefix.Event,\n          id: \"8f99ca1363000000000000000000000000000000000000000000000000000003\",\n        },\n        mentions: [\n          {\n            type: NostrPrefix.Event,\n            id: \"977ac5d3b6000000000000000000000000000000000000000000000000000002\",\n          },\n        ],\n      })\n      expect(Nip10.parseThread(b)).toMatchObject({\n        root: {\n          type: NostrPrefix.Event,\n          id: \"cbf2375078000000000000000000000000000000000000000000000000000001\",\n        },\n        replyTo: {\n          type: NostrPrefix.Event,\n          id: \"6834ffc491000000000000000000000000000000000000000000000000000005\",\n        },\n        mentions: [\n          {\n            type: NostrPrefix.Event,\n            id: \"868187063f0000000000000000000000000000000000000000000000000000ab\",\n          },\n        ],\n      })\n    })\n\n    test(\"should extract thread with marked tags\", () => {\n      const event = {\n        content: \"There is some middle ground ...\",\n        id: \"6834ffc491000000000000000000000000000000000000000000000000000005\",\n        kind: 1,\n        created_at: 1,\n        pubkey: \"0000000000000000000000000000000000000000000000000000000000000001\",\n        sig: \"test\",\n        tags: [\n          [\"e\", \"cbf2375078000000000000000000000000000000000000000000000000000001\", \"\", \"root\"],\n          [\"e\", \"868187063f0000000000000000000000000000000000000000000000000000ab\", \"\", \"reply\"],\n        ],\n      }\n\n      const thread = Nip10.parseThread(event)\n      expect(thread).toMatchObject({\n        kind: \"nip10\",\n        root: {\n          type: NostrPrefix.Event,\n          id: \"cbf2375078000000000000000000000000000000000000000000000000000001\",\n          relays: [\"\"],\n          scope: \"root\",\n        },\n        replyTo: {\n          type: NostrPrefix.Event,\n          id: \"868187063f0000000000000000000000000000000000000000000000000000ab\",\n          relays: [\"\"],\n          scope: \"reply\",\n        },\n        mentions: [],\n      })\n      // No p-tags in the event, so pubKeys should be empty\n      expect(thread?.pubKeys).toHaveLength(0)\n    })\n\n    test(\"should return undefined for event with no thread tags\", () => {\n      const event = {\n        content: \"Just a regular note\",\n        id: \"6834ffc492000000000000000000000000000000000000000000000000000006\",\n        kind: 1,\n        created_at: 1,\n        pubkey: \"0000000000000000000000000000000000000000000000000000000000000001\",\n        sig: \"test\",\n        tags: [],\n      }\n\n      expect(Nip10.parseThread(event)).toBeUndefined()\n    })\n\n    test(\"should extract pubKeys from thread\", () => {\n      const event = {\n        content: \"Reply with mentions\",\n        id: \"6834ffc493000000000000000000000000000000000000000000000000000007\",\n        kind: 1,\n        created_at: 1,\n        pubkey: \"0000000000000000000000000000000000000000000000000000000000000001\",\n        sig: \"test\",\n        tags: [\n          [\"e\", \"cbf2375078000000000000000000000000000000000000000000000000000001\", \"\", \"root\"],\n          [\"p\", \"1111111111111111111111111111111111111111111111111111111111111111\"],\n          [\"p\", \"2222222222222222222222222222222222222222222222222222222222222222\"],\n        ],\n      }\n\n      const thread = Nip10.parseThread(event)\n      // Should have 2 p-tags from the event\n      expect(thread?.pubKeys).toHaveLength(2)\n      const pubKeyIds = thread?.pubKeys.map(p => p.id) || []\n      expect(pubKeyIds).toContain(\"1111111111111111111111111111111111111111111111111111111111111111\")\n      expect(pubKeyIds).toContain(\"2222222222222222222222222222222222222222222222222222222222222222\")\n    })\n  })\n\n  describe(\"replyTo\", () => {\n    test(\"should add replyTo pubkey when replying to a root note\", () => {\n      // Create a root note (no thread)\n      const rootNote: TaggedNostrEvent = {\n        id: \"aaaa000000000000000000000000000000000000000000000000000000000001\",\n        kind: 1,\n        pubkey: \"bbbb000000000000000000000000000000000000000000000000000000000002\",\n        created_at: 1234567890,\n        content: \"This is the root note\",\n        tags: [],\n        sig: \"test\",\n        relays: [\"wss://relay.example.com\"],\n      }\n\n      // Create an EventBuilder to reply to the root note\n      const eb = new EventBuilder()\n      eb.kind(1).pubKey(\"cccc000000000000000000000000000000000000000000000000000000000003\").content(\"This is a reply\")\n\n      // Call replyTo to add the reply tags\n      Nip10.replyTo(rootNote, eb)\n\n      // Build the event\n      const replyEvent = eb.build()\n\n      // Verify that the replyTo pubkey was added\n      const pTags = replyEvent.tags.filter(t => t[0] === \"p\")\n      expect(pTags.length).toBe(1)\n      expect(pTags[0][1]).toBe(\"bbbb000000000000000000000000000000000000000000000000000000000002\")\n\n      // Verify root tag was added\n      const eTags = replyEvent.tags.filter(t => t[0] === \"e\")\n      expect(eTags.length).toBe(1)\n      expect(eTags[0][1]).toBe(\"aaaa000000000000000000000000000000000000000000000000000000000001\")\n      expect(eTags[0][3]).toBe(\"root\")\n    })\n\n    test(\"should not add replyTo pubkey if it's the same as the author\", () => {\n      // Create a root note\n      const samePubkey = \"bbbb000000000000000000000000000000000000000000000000000000000002\"\n      const rootNote: TaggedNostrEvent = {\n        id: \"aaaa000000000000000000000000000000000000000000000000000000000002\",\n        kind: 1,\n        pubkey: samePubkey,\n        created_at: 1234567890,\n        content: \"This is the root note\",\n        tags: [],\n        sig: \"test\",\n        relays: [\"wss://relay.example.com\"],\n      }\n\n      // Create an EventBuilder to reply to their own note\n      const eb = new EventBuilder()\n      eb.kind(1).pubKey(samePubkey).content(\"This is a self-reply\")\n\n      // Call replyTo\n      Nip10.replyTo(rootNote, eb)\n\n      // Build the event\n      const replyEvent = eb.build()\n\n      // Verify that no p-tag was added (since it's a self-reply)\n      const pTags = replyEvent.tags.filter(t => t[0] === \"p\")\n      expect(pTags.length).toBe(0)\n    })\n\n    test(\"should add all thread participants when replying to a threaded note\", () => {\n      // Create a threaded note (reply to another note)\n      const threadedNote: TaggedNostrEvent = {\n        id: \"dddd000000000000000000000000000000000000000000000000000000000004\",\n        kind: 1,\n        pubkey: \"eeee000000000000000000000000000000000000000000000000000000000005\",\n        created_at: 1234567890,\n        content: \"This is a reply in a thread\",\n        tags: [\n          [\"e\", \"aaaa000000000000000000000000000000000000000000000000000000000001\", \"\", \"root\"],\n          [\"e\", \"cccc000000000000000000000000000000000000000000000000000000000003\", \"\", \"reply\"],\n          [\"p\", \"bbbb000000000000000000000000000000000000000000000000000000000002\"], // Original author\n          [\"p\", \"ffff000000000000000000000000000000000000000000000000000000000006\"], // Another participant\n        ],\n        sig: \"test\",\n        relays: [\"wss://relay.example.com\"],\n      }\n\n      // Create an EventBuilder to reply to the threaded note\n      const newAuthor = \"9999000000000000000000000000000000000000000000000000000000000009\"\n      const eb = new EventBuilder()\n      eb.kind(1).pubKey(newAuthor).content(\"Joining the thread\")\n\n      // Call replyTo\n      Nip10.replyTo(threadedNote, eb)\n\n      // Build the event\n      const replyEvent = eb.build()\n\n      // Verify that all participants are in p-tags (excluding the new author)\n      const pTags = replyEvent.tags.filter(t => t[0] === \"p\")\n      const pTagIds = pTags.map(t => t[1])\n\n      // Should include all previous participants\n      expect(pTagIds).toContain(\"bbbb000000000000000000000000000000000000000000000000000000000002\")\n      expect(pTagIds).toContain(\"ffff000000000000000000000000000000000000000000000000000000000006\")\n\n      // Should NOT include the new author's own pubkey\n      expect(pTagIds).not.toContain(newAuthor)\n\n      // Verify thread structure (root and reply tags)\n      const eTags = replyEvent.tags.filter(t => t[0] === \"e\")\n      expect(eTags.length).toBe(2)\n\n      // First should be the root tag\n      const rootTag = eTags.find(t => t[3] === \"root\")\n      expect(rootTag).toBeDefined()\n      expect(rootTag![1]).toBe(\"aaaa000000000000000000000000000000000000000000000000000000000001\")\n\n      // Second should be the reply tag (to the note we're replying to)\n      const replyTag = eTags.find(t => t[3] === \"reply\")\n      expect(replyTag).toBeDefined()\n      expect(replyTag![1]).toBe(\"dddd000000000000000000000000000000000000000000000000000000000004\")\n    })\n\n    test(\"should add replyTo pubkey for note author when replying to threaded note with p-tags\", () => {\n      // Create a threaded note WITH p-tags (including the author)\n      const threadedNote: TaggedNostrEvent = {\n        id: \"dddd000000000000000000000000000000000000000000000000000000000005\",\n        kind: 1,\n        pubkey: \"eeee000000000000000000000000000000000000000000000000000000000005\",\n        created_at: 1234567890,\n        content: \"This is a reply in a thread\",\n        tags: [\n          [\"e\", \"aaaa000000000000000000000000000000000000000000000000000000000001\", \"\", \"root\"],\n          [\"e\", \"cccc000000000000000000000000000000000000000000000000000000000003\", \"\", \"reply\"],\n          [\"p\", \"eeee000000000000000000000000000000000000000000000000000000000005\"], // Author's own pubkey\n          [\"p\", \"bbbb000000000000000000000000000000000000000000000000000000000002\"], // Original thread starter\n        ],\n        sig: \"test\",\n        relays: [\"wss://relay.example.com\"],\n      }\n\n      // Create an EventBuilder to reply to the threaded note\n      const newAuthor = \"9999000000000000000000000000000000000000000000000000000000000009\"\n      const eb = new EventBuilder()\n      eb.kind(1).pubKey(newAuthor).content(\"Joining the thread\")\n\n      // Call replyTo\n      Nip10.replyTo(threadedNote, eb)\n\n      // Build the event\n      const replyEvent = eb.build()\n\n      // Verify that all thread participants are included in p-tags\n      const pTags = replyEvent.tags.filter(t => t[0] === \"p\")\n      const pTagIds = pTags.map(t => t[1])\n\n      // Should include the author of the note we're replying to\n      expect(pTagIds).toContain(\"eeee000000000000000000000000000000000000000000000000000000000005\")\n      // Should include the original thread starter\n      expect(pTagIds).toContain(\"bbbb000000000000000000000000000000000000000000000000000000000002\")\n      // Should NOT include our own pubkey\n      expect(pTagIds).not.toContain(newAuthor)\n    })\n\n    test(\"should add replyTo pubkey when author is in e-tag but not p-tags\", () => {\n      // Real-world example: event has author in e-tags (4th element) but not in p-tags\n      const event: TaggedNostrEvent = {\n        id: \"9821c91621f391a49e340250b97c372811129935f0bea3c84e81191d23a7342d\",\n        kind: 1,\n        pubkey: \"266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5\",\n        created_at: 1761313035,\n        content: \"what were all the deletions?\",\n        tags: [\n          [\n            \"e\",\n            \"15c69902c1429b21023d2b7d8233f2f23ff14e24a29e63084bd357c7725310f3\",\n            \"wss://nos.lol/\",\n            \"root\",\n            \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\",\n          ],\n          [\n            \"e\",\n            \"15c69902c1429b21023d2b7d8233f2f23ff14e24a29e63084bd357c7725310f3\",\n            \"wss://nos.lol/\",\n            \"reply\",\n            \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\",\n          ],\n          [\"p\", \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\"],\n          [\n            \"client\",\n            \"noStrudel\",\n            \"31990:266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5:1686066542546\",\n          ],\n        ],\n        sig: \"9688006fb4f19a7ddf10f91fe509eac04546abc83c66abd3917b9f8e2b540a1fc3afdbc51f26e8c3ac3714b9b1ba1199aa93256eb18cc584e752cf186634f777\",\n        relays: [\"wss://relay.snort.social/\", \"wss://relay.damus.io/\"],\n      }\n\n      // Create an EventBuilder to reply to this event\n      const replyingAuthor = \"aaaa111111111111111111111111111111111111111111111111111111111111\"\n      const eb = new EventBuilder()\n      eb.kind(1).pubKey(replyingAuthor).content(\"Replying to your question\")\n\n      // Call replyTo\n      Nip10.replyTo(event, eb)\n\n      // Build the event\n      const replyEvent = eb.build()\n\n      // Verify p-tags\n      const pTags = replyEvent.tags.filter(t => t[0] === \"p\")\n      const pTagIds = pTags.map(t => t[1])\n\n      // Should include the person already mentioned in p-tags\n      expect(pTagIds).toContain(\"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\")\n\n      // IMPORTANT: Should also include the author of the event we're replying to\n      // (This is what the test is specifically checking)\n      expect(pTagIds).toContain(\"266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5\")\n\n      // Should NOT include our own pubkey\n      expect(pTagIds).not.toContain(replyingAuthor)\n\n      // Verify we have exactly 2 p-tags (the original p-tag + the author's pubkey)\n      expect(pTags.length).toBe(2)\n    })\n\n    test(\"should not add duplicate p-tag when author is already in thread p-tags\", () => {\n      // Event where the author's pubkey is already in the p-tags\n      const event: TaggedNostrEvent = {\n        id: \"aaaa000000000000000000000000000000000000000000000000000000000003\",\n        kind: 1,\n        pubkey: \"bbbb000000000000000000000000000000000000000000000000000000000002\",\n        created_at: 1234567890,\n        content: \"A threaded reply\",\n        tags: [\n          [\"e\", \"cccc000000000000000000000000000000000000000000000000000000000003\", \"\", \"root\"],\n          [\"e\", \"dddd000000000000000000000000000000000000000000000000000000000004\", \"\", \"reply\"],\n          [\"p\", \"eeee000000000000000000000000000000000000000000000000000000000005\"], // Other participant\n          [\"p\", \"bbbb000000000000000000000000000000000000000000000000000000000002\"], // Author's own pubkey\n        ],\n        sig: \"test\",\n        relays: [\"wss://relay.example.com\"],\n      }\n\n      // Create an EventBuilder to reply\n      const replyingAuthor = \"ffff000000000000000000000000000000000000000000000000000000000006\"\n      const eb = new EventBuilder()\n      eb.kind(1).pubKey(replyingAuthor).content(\"My reply\")\n\n      // Call replyTo\n      Nip10.replyTo(event, eb)\n\n      // Build the event\n      const replyEvent = eb.build()\n\n      // Verify p-tags\n      const pTags = replyEvent.tags.filter(t => t[0] === \"p\")\n      const pTagIds = pTags.map(t => t[1])\n\n      // Should include the other participant\n      expect(pTagIds).toContain(\"eeee000000000000000000000000000000000000000000000000000000000005\")\n\n      // Should include the author (bbbb...0002) exactly once\n      expect(pTagIds).toContain(\"bbbb000000000000000000000000000000000000000000000000000000000002\")\n\n      // Count occurrences of the author's pubkey - should be exactly 1\n      const authorCount = pTagIds.filter(\n        id => id === \"bbbb000000000000000000000000000000000000000000000000000000000002\",\n      ).length\n      expect(authorCount).toBe(1)\n\n      // Should have exactly 2 p-tags total (other participant + author, no duplicates)\n      expect(pTags.length).toBe(2)\n    })\n  })\n\n  describe(\"parsing non-text-note events\", () => {\n    test(\"should parse reaction (kind 7) per NIP-25\", () => {\n      // NIP-25: Reactions MUST have an e tag to the event being reacted to\n      // and SHOULD have a p tag to the author\n      const reaction: TaggedNostrEvent = {\n        id: \"92723125c4a564f90a073ac4a0073f440d8b472453a42d7a32bbf710f1503d12\",\n        kind: 7,\n        pubkey: \"20d29810d6a5f92b045ade02ebbadc9036d741cc686b00415c42b4236fe4ad2f\",\n        created_at: 1674164545,\n        content: \"+\", // \"+\" for like, \"-\" for dislike, or emoji\n        tags: [\n          [\"e\", \"3624762a1274dd9636e0c552b53086d70bc88c165bc4dc0f9e836a1eaf86c3b8\", \"wss://relay.damus.io/\"],\n          [\"p\", \"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\", \"wss://nos.lol/\"],\n          [\"k\", \"1\"], // Optional: kind of event being reacted to\n        ],\n        sig: \"918404170b25a1f3f08f73ffcca60ea8fef7b077c99ae1dc44ac1e6c6f6341709f6f604b8134636c50f64ef86956ff8126b6beaa7ecef5d30fcde7faaa6dba9c\",\n        relays: [\"wss://relay.damus.io/\"],\n      }\n\n      const thread = Nip10.parseThread(reaction)\n\n      // Should parse the single e tag as root (positional interpretation)\n      expect(thread).toBeDefined()\n      expect(thread?.root).toBeDefined()\n      expect(thread?.root?.id).toBe(\"3624762a1274dd9636e0c552b53086d70bc88c165bc4dc0f9e836a1eaf86c3b8\")\n      expect(thread?.root?.scope).toBe(\"root\")\n      expect(thread?.root?.relays).toContain(\"wss://relay.damus.io/\")\n\n      // Should extract the p tag (author of event being reacted to)\n      expect(thread?.pubKeys).toHaveLength(1)\n      expect(thread?.pubKeys[0]?.id).toBe(\"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\")\n    })\n\n    test(\"should parse repost (kind 6) per NIP-18\", () => {\n      // NIP-18: Reposts MUST include e tag with relay URL and SHOULD include p tag\n      const repost: TaggedNostrEvent = {\n        id: \"a8c2eb89f3c7f6d8b2e4a1c9d7f3e6b8a5c1d9e7f4b2a8c6e3d1f9b7a4c2e8d6\",\n        kind: 6,\n        pubkey: \"9630f464cca6a5147aa8a35f0bcdd3ce485324e732fd39e09233b1d848238f31\",\n        created_at: 1674165000,\n        content:\n          '{\"kind\":1,\"content\":\"Great insights!\",\"pubkey\":\"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\",...}',\n        tags: [\n          [\"e\", \"3624762a1274dd9636e0c552b53086d70bc88c165bc4dc0f9e836a1eaf86c3b8\", \"wss://relay.damus.io/\"],\n          [\"p\", \"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\"],\n        ],\n        sig: \"signature...\",\n        relays: [\"wss://nos.lol/\"],\n      }\n\n      const thread = Nip10.parseThread(repost)\n\n      // Should parse the e tag as root\n      expect(thread).toBeDefined()\n      expect(thread?.root).toBeDefined()\n      expect(thread?.root?.id).toBe(\"3624762a1274dd9636e0c552b53086d70bc88c165bc4dc0f9e836a1eaf86c3b8\")\n      expect(thread?.root?.relays).toContain(\"wss://relay.damus.io/\")\n\n      // Should extract the p tag (author of original event)\n      expect(thread?.pubKeys).toHaveLength(1)\n      expect(thread?.pubKeys[0]?.id).toBe(\"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\")\n    })\n\n    test(\"should parse zap receipt (kind 9735) per NIP-57\", () => {\n      // NIP-57: Zap receipts MUST include p tag (recipient), optional e tag (zapped event),\n      // and optional P tag (sender)\n      const zapReceipt: TaggedNostrEvent = {\n        id: \"67b48a14fb66c60c8f9070bdeb37afdfcc3d08ad01989460448e4081eddda446\",\n        kind: 9735,\n        pubkey: \"9630f464cca6a5147aa8a35f0bcdd3ce485324e732fd39e09233b1d848238f31\", // LNURL provider pubkey\n        created_at: 1674164545,\n        content: \"\",\n        tags: [\n          [\"p\", \"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\"], // Zap recipient\n          [\"P\", \"97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322\"], // Zap sender\n          [\"e\", \"3624762a1274dd9636e0c552b53086d70bc88c165bc4dc0f9e836a1eaf86c3b8\"], // Event being zapped\n          [\"bolt11\", \"lnbc10u1p3unwfupp5t9pcx73rn3j52qg7...\"],\n          [\"description\", '{\"pubkey\":\"97c70a44...\",\"content\":\"\",\"kind\":9734,...}'],\n          [\"preimage\", \"5d006d2cf1e73c7148e7519a4c68adc81642ce0e25a432b2434c99f97344c15f\"],\n        ],\n        sig: \"signature...\",\n        relays: [\"wss://relay.damus.io/\"],\n      }\n\n      const thread = Nip10.parseThread(zapReceipt)\n\n      // Should parse the e tag as root\n      expect(thread).toBeDefined()\n      expect(thread?.root).toBeDefined()\n      expect(thread?.root?.id).toBe(\"3624762a1274dd9636e0c552b53086d70bc88c165bc4dc0f9e836a1eaf86c3b8\")\n\n      // Should extract p tag (recipient) - P tag (sender) is not a standard profile tag\n      expect(thread?.pubKeys.length).toBeGreaterThanOrEqual(1)\n      const pubKeyIds = thread?.pubKeys.map(p => p.id)\n      expect(pubKeyIds).toContain(\"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\")\n    })\n\n    test(\"should parse emoji reaction with relay hints\", () => {\n      // Real-world emoji reaction with proper relay hints\n      const reaction: TaggedNostrEvent = {\n        id: \"f8b3d9e1a2c4f6e8d0b2a4c6e8f0d2b4a6c8e0f2d4b6a8c0e2f4d6b8a0c2e4f6\",\n        kind: 7,\n        pubkey: \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\",\n        created_at: 1674165200,\n        content: \"🔥\", // Emoji reaction\n        tags: [\n          [\"e\", \"2bcd9cf56db44d1a9f2499110ab1924450cd87fe7989ec0b1cce565f7b0465f7\", \"wss://relay.damus.io/\"],\n          [\"p\", \"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\", \"wss://nos.lol/\"],\n          [\"k\", \"1\"],\n        ],\n        sig: \"sig...\",\n        relays: [\"wss://relay.damus.io/\"],\n      }\n\n      const thread = Nip10.parseThread(reaction)\n\n      expect(thread?.root?.id).toBe(\"2bcd9cf56db44d1a9f2499110ab1924450cd87fe7989ec0b1cce565f7b0465f7\")\n      expect(thread?.pubKeys[0]?.id).toBe(\"32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245\")\n    })\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/nip18.test.ts",
    "content": "import { Nip18 } from \"../src/impl/nip18\"\nimport { describe, expect, test } from \"bun:test\"\nimport { NostrPrefix } from \"@snort/shared\"\nimport { NostrLink, LinkScope } from \"../src/nostr-link\"\n\ndescribe(\"Nip18\", () => {\n  describe(\"linkToTag\", () => {\n    test(\"should throw error if link is not a quote\", () => {\n      // Create a link without Quote scope\n      const link = new NostrLink(NostrPrefix.Event, \"bbbb111111111111111111111111111111111111111111111111111111111111\")\n      link.scope = LinkScope.Root\n\n      expect(() => Nip18.linkToTag(link)).toThrow(\"Link is not a quote\")\n    })\n\n    test(\"q tags should contain 4 elements without markers when author is present\", () => {\n      // Create a NostrLink with Quote scope and author\n      const quoteLink = new NostrLink(\n        NostrPrefix.Event,\n        \"bbbb111111111111111111111111111111111111111111111111111111111111\",\n        1, // kind hint\n        \"cccc222222222222222222222222222222222222222222222222222222222222\", // author\n        [\"wss://relay.example.com\"],\n      )\n      quoteLink.scope = LinkScope.Quote\n\n      // Convert to tag using Nip18\n      const tag = Nip18.linkToTag(quoteLink)\n\n      // Verify the q tag has exactly 4 elements: tag name, event id, relay, author\n      expect(tag).toBeDefined()\n      expect(tag.length).toBe(4)\n      expect(tag[0]).toBe(\"q\")\n      expect(tag[1]).toBe(\"bbbb111111111111111111111111111111111111111111111111111111111111\")\n      expect(tag[2]).toBe(\"wss://relay.example.com\")\n      expect(tag[3]).toBe(\"cccc222222222222222222222222222222222222222222222222222222222222\")\n\n      // Verify there's no marker (element at index 3 should be author, not a marker)\n      expect([\"root\", \"reply\", \"mention\"]).not.toContain(tag[3])\n    })\n\n    test(\"q tags should contain 3 elements when only relay is present\", () => {\n      // Create a quote link without author\n      const quoteLink = new NostrLink(\n        NostrPrefix.Event,\n        \"aaaa000000000000000000000000000000000000000000000000000000000001\",\n        1,\n        undefined, // no author\n        [\"wss://relay.example.com\"],\n      )\n      quoteLink.scope = LinkScope.Quote\n\n      const tag = Nip18.linkToTag(quoteLink)\n\n      expect(tag.length).toBe(3)\n      expect(tag[0]).toBe(\"q\")\n      expect(tag[1]).toBe(\"aaaa000000000000000000000000000000000000000000000000000000000001\")\n      expect(tag[2]).toBe(\"wss://relay.example.com\")\n    })\n\n    test(\"q tags should contain 2 elements when no relay or author\", () => {\n      // Minimal quote link\n      const quoteLink = new NostrLink(\n        NostrPrefix.Event,\n        \"aaaa000000000000000000000000000000000000000000000000000000000001\",\n      )\n      quoteLink.scope = LinkScope.Quote\n\n      const tag = Nip18.linkToTag(quoteLink)\n\n      expect(tag.length).toBe(2)\n      expect(tag[0]).toBe(\"q\")\n      expect(tag[1]).toBe(\"aaaa000000000000000000000000000000000000000000000000000000000001\")\n    })\n\n    test(\"q tags should add empty relay when author is present but relay is missing\", () => {\n      // Quote link with author but no relay\n      const quoteLink = new NostrLink(\n        NostrPrefix.Event,\n        \"aaaa000000000000000000000000000000000000000000000000000000000001\",\n        1,\n        \"bbbb111111111111111111111111111111111111111111111111111111111111\", // author\n        undefined, // no relays\n      )\n      quoteLink.scope = LinkScope.Quote\n\n      const tag = Nip18.linkToTag(quoteLink)\n\n      // Should have 4 elements with empty string for relay\n      expect(tag.length).toBe(4)\n      expect(tag[0]).toBe(\"q\")\n      expect(tag[1]).toBe(\"aaaa000000000000000000000000000000000000000000000000000000000001\")\n      expect(tag[2]).toBe(\"\") // empty relay\n      expect(tag[3]).toBe(\"bbbb111111111111111111111111111111111111111111111111111111111111\")\n    })\n\n    test(\"q tags for addresses (NIP-33) should use kind:author:d-tag format with 3 elements\", () => {\n      // Create an address link with Quote scope (for parameterized replaceable events)\n      const addressLink = new NostrLink(\n        NostrPrefix.Address,\n        \"my-article-slug\", // d-tag identifier\n        30023, // kind for long-form content\n        \"cccc222222222222222222222222222222222222222222222222222222222222\", // author\n        [\"wss://relay.example.com\"],\n      )\n      addressLink.scope = LinkScope.Quote\n\n      // Convert to tag using Nip18\n      const tag = Nip18.linkToTag(addressLink)\n\n      // Per NIP-18 spec: pubkey only added \"if-a-regular-event\"\n      // For addresses, author is already encoded in kind:author:d-tag\n      expect(tag).toBeDefined()\n      expect(tag.length).toBe(3) // q tags for addresses: [\"q\", \"kind:author:d-tag\", relay]\n      expect(tag[0]).toBe(\"q\")\n      expect(tag[1]).toBe(\"30023:cccc222222222222222222222222222222222222222222222222222222222222:my-article-slug\")\n      expect(tag[2]).toBe(\"wss://relay.example.com\")\n    })\n\n    test(\"q tags for addresses without relay should contain 2 elements\", () => {\n      // Address link without relay\n      const addressLink = new NostrLink(\n        NostrPrefix.Address,\n        \"test-article\",\n        30023,\n        \"aaaa000000000000000000000000000000000000000000000000000000000001\",\n      )\n      addressLink.scope = LinkScope.Quote\n\n      const tag = Nip18.linkToTag(addressLink)\n\n      // No relay, no author (author already in tagKey for addresses)\n      expect(tag.length).toBe(2)\n      expect(tag[0]).toBe(\"q\")\n      expect(tag[1]).toBe(\"30023:aaaa000000000000000000000000000000000000000000000000000000000001:test-article\")\n    })\n\n    test(\"q tags should handle empty relay array\", () => {\n      // Quote link with empty relay array\n      const quoteLink = new NostrLink(\n        NostrPrefix.Event,\n        \"aaaa000000000000000000000000000000000000000000000000000000000001\",\n        1,\n        \"bbbb111111111111111111111111111111111111111111111111111111111111\",\n        [], // empty array\n      )\n      quoteLink.scope = LinkScope.Quote\n\n      const tag = Nip18.linkToTag(quoteLink)\n\n      // Should add empty relay when author is present\n      expect(tag.length).toBe(4)\n      expect(tag[0]).toBe(\"q\")\n      expect(tag[1]).toBe(\"aaaa000000000000000000000000000000000000000000000000000000000001\")\n      expect(tag[2]).toBe(\"\") // empty relay\n      expect(tag[3]).toBe(\"bbbb111111111111111111111111111111111111111111111111111111111111\")\n    })\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/node.ts",
    "content": "import { NostrSystem, type SystemInterface } from \"..\"\n\nconst Relay = \"wss://relay.snort.social/\"\n\nconst system = new NostrSystem({}) as SystemInterface\n\nasync function test() {\n  await system.ConnectToRelay(Relay, { read: true, write: true })\n  setTimeout(() => {\n    system.DisconnectRelay(Relay)\n  }, 1000)\n}\n\ntest().catch(console.error)\n"
  },
  {
    "path": "packages/system/tests/nostr-link.test.ts",
    "content": "import { describe, expect, test } from \"bun:test\"\nimport { NostrLink, parseNostrLink } from \"../src/nostr-link\"\nimport { NostrPrefix } from \"@snort/shared\"\nimport type { NostrEvent } from \"../src/nostr\"\n\ndescribe(\"NostrLink\", () => {\n  describe(\"d tag handling\", () => {\n    test(\"should not decode 'd' tag when it's hex\", () => {\n      // Create an addressable event with a hex-looking d tag\n      const hexDTag = \"deadbeef1234567890abcdef\"\n      const event: NostrEvent = {\n        id: \"test123\",\n        kind: 30023, // addressable event kind\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test content\",\n        tags: [[\"d\", hexDTag]],\n        sig: \"test-sig\",\n      }\n\n      // Create a NostrLink from the event\n      const link = NostrLink.fromEvent(event)\n\n      // The id should be the raw hex string, not decoded\n      expect(link.id).toBe(hexDTag)\n      expect(link.type).toBe(NostrPrefix.Address)\n      expect(link.kind).toBe(30023)\n      expect(link.author).toBe(event.pubkey)\n\n      // Encode the link to naddr\n      const encoded = link.encode()\n      expect(encoded.startsWith(\"naddr\")).toBe(true)\n\n      // Parse it back\n      const parsed = parseNostrLink(encoded)\n      expect(parsed.type).toBe(NostrPrefix.Address)\n      expect(parsed.id).toBe(hexDTag) // Should remain as the original string\n      expect(parsed.kind).toBe(30023)\n      expect(parsed.author).toBe(event.pubkey)\n    })\n\n    test(\"should handle non-hex 'd' tag values correctly\", () => {\n      const textDTag = \"my-article-slug\"\n      const event: NostrEvent = {\n        id: \"test456\",\n        kind: 30023,\n        pubkey: \"2222222222222222222222222222222222222222222222222222222222222222\",\n        created_at: 1234567890,\n        content: \"test content\",\n        tags: [[\"d\", textDTag]],\n        sig: \"test-sig\",\n      }\n\n      const link = NostrLink.fromEvent(event)\n      expect(link.id).toBe(textDTag)\n      expect(link.type).toBe(NostrPrefix.Address)\n\n      // Round-trip encoding\n      const encoded = link.encode()\n      const parsed = parseNostrLink(encoded)\n      expect(parsed.id).toBe(textDTag)\n    })\n\n    test(\"should handle empty 'd' tag\", () => {\n      const emptyDTag = \"\"\n      const event: NostrEvent = {\n        id: \"test789\",\n        kind: 30023,\n        pubkey: \"3333333333333333333333333333333333333333333333333333333333333333\",\n        created_at: 1234567890,\n        content: \"test content\",\n        tags: [[\"d\", emptyDTag]],\n        sig: \"test-sig\",\n      }\n\n      const link = NostrLink.fromEvent(event)\n      expect(link.id).toBe(emptyDTag)\n\n      // Round-trip encoding\n      const encoded = link.encode()\n      const parsed = parseNostrLink(encoded)\n      expect(parsed.id).toBe(emptyDTag)\n    })\n\n    test(\"should handle 'd' tag with special characters\", () => {\n      const specialDTag = \"test:tag/with-special_chars\"\n      const event: NostrEvent = {\n        id: \"testabc\",\n        kind: 30000,\n        pubkey: \"4444444444444444444444444444444444444444444444444444444444444444\",\n        created_at: 1234567890,\n        content: \"test content\",\n        tags: [[\"d\", specialDTag]],\n        sig: \"test-sig\",\n      }\n\n      const link = NostrLink.fromEvent(event)\n      expect(link.id).toBe(specialDTag)\n\n      // Round-trip encoding\n      const encoded = link.encode()\n      const parsed = parseNostrLink(encoded)\n      expect(parsed.id).toBe(specialDTag)\n    })\n  })\n\n  describe(\"tagKey\", () => {\n    test(\"should create correct tagKey for address link\", () => {\n      const link = new NostrLink(\n        NostrPrefix.Address,\n        \"my-article\",\n        30023,\n        \"1111111111111111111111111111111111111111111111111111111111111111\",\n      )\n\n      expect(link.tagKey).toBe(\"30023:1111111111111111111111111111111111111111111111111111111111111111:my-article\")\n    })\n\n    test(\"should create correct tagKey for event link\", () => {\n      const eventId = \"abc123def456abc123def456abc123def456abc123def456abc123def456abc1\"\n      const link = new NostrLink(NostrPrefix.Event, eventId)\n\n      expect(link.tagKey).toBe(eventId)\n    })\n  })\n\n  describe(\"matchesEvent\", () => {\n    test(\"should match addressable event with correct d tag\", () => {\n      const dTag = \"my-article\"\n      const pubkey = \"1111111111111111111111111111111111111111111111111111111111111111\"\n      const kind = 30023\n\n      const link = new NostrLink(NostrPrefix.Address, dTag, kind, pubkey)\n\n      const event: NostrEvent = {\n        id: \"test\",\n        kind,\n        pubkey,\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [[\"d\", dTag]],\n        sig: \"test-sig\",\n      }\n\n      expect(link.matchesEvent(event)).toBe(true)\n    })\n\n    test(\"should not match addressable event with different d tag\", () => {\n      const link = new NostrLink(\n        NostrPrefix.Address,\n        \"article-1\",\n        30023,\n        \"1111111111111111111111111111111111111111111111111111111111111111\",\n      )\n\n      const event: NostrEvent = {\n        id: \"test\",\n        kind: 30023,\n        pubkey: \"1111111111111111111111111111111111111111111111111111111111111111\",\n        created_at: 1234567890,\n        content: \"test\",\n        tags: [[\"d\", \"article-2\"]], // different d tag\n        sig: \"test-sig\",\n      }\n\n      expect(link.matchesEvent(event)).toBe(false)\n    })\n  })\n\n  describe(\"fromTag\", () => {\n    test(\"should parse 'a' tag correctly\", () => {\n      const dTag = \"my-article\"\n      const kind = \"30023\"\n      const author = \"1111111111111111111111111111111111111111111111111111111111111111\"\n      const relay = \"wss://relay.example.com\"\n\n      const tag = [\"a\", `${kind}:${author}:${dTag}`, relay]\n      const link = NostrLink.fromTag(tag)\n\n      expect(link?.type).toBe(NostrPrefix.Address)\n      expect(link?.id).toBe(dTag)\n      expect(link?.kind).toBe(Number(kind))\n      expect(link?.author).toBe(author)\n      expect(link?.relays).toEqual([relay])\n    })\n\n    test(\"should parse 'a' tag with hex-like d tag\", () => {\n      const hexDTag = \"deadbeef\"\n      const kind = \"30023\"\n      const author = \"2222222222222222222222222222222222222222222222222222222222222222\"\n\n      const tag = [\"a\", `${kind}:${author}:${hexDTag}`]\n      const link = NostrLink.fromTag(tag)\n\n      expect(link?.type).toBe(NostrPrefix.Address)\n      expect(link?.id).toBe(hexDTag) // Should remain as string, not decoded\n      expect(link?.kind).toBe(Number(kind))\n      expect(link?.author).toBe(author)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/note-collection-comprehensive.test.ts",
    "content": "import { describe, expect, test } from \"bun:test\"\nimport type { TaggedNostrEvent } from \"../src/nostr\"\nimport { KeyedReplaceableNoteStore, NoteCollection } from \"../src/note-collection\"\n\nfunction ev(\n  id: string,\n  kind: number,\n  created_at: number,\n  pubkey = \"aa\",\n  tags: string[][] = [],\n  relays: string[] = [],\n): TaggedNostrEvent {\n  return { id, kind, created_at, pubkey, tags, content: \"\", sig: \"\", relays }\n}\n\nfunction sleep(ms: number) {\n  return new Promise(r => setTimeout(r, ms))\n}\n\ndescribe(\"KeyedReplaceableNoteStore\", () => {\n  describe(\"key function behavior\", () => {\n    test(\"custom key function groups events correctly\", () => {\n      const store = new KeyedReplaceableNoteStore(e => `custom:${e.pubkey}`)\n      store.add(ev(\"a\", 1, 100, \"alice\"))\n      store.add(ev(\"b\", 1, 200, \"alice\"))\n      expect(store.snapshot).toHaveLength(1)\n      expect(store.snapshot[0].id).toBe(\"b\")\n    })\n\n    test(\"different keys coexist\", () => {\n      const store = new KeyedReplaceableNoteStore(e => e.pubkey)\n      store.add(ev(\"a\", 1, 100, \"alice\"))\n      store.add(ev(\"b\", 1, 100, \"bob\"))\n      expect(store.snapshot).toHaveLength(2)\n    })\n\n    test(\"key function receives the full event object\", () => {\n      let receivedEvent: TaggedNostrEvent | undefined\n      const store = new KeyedReplaceableNoteStore(e => {\n        receivedEvent = e\n        return e.id\n      })\n      const event = ev(\"test-id\", 1, 100, \"alice\", [[\"t\", \"tag1\"]])\n      store.add(event)\n      expect(receivedEvent).toBeDefined()\n      expect(receivedEvent?.id).toBe(\"test-id\")\n      expect(receivedEvent?.tags).toEqual([[\"t\", \"tag1\"]])\n    })\n  })\n\n  describe(\"created_at boundary conditions\", () => {\n    test(\"event with created_at=0 is never stored (strict > check)\", () => {\n      const store = new KeyedReplaceableNoteStore(() => \"key\")\n      const result = store.add(ev(\"a\", 1, 0))\n      expect(result).toBe(0)\n      expect(store.snapshot).toHaveLength(0)\n    })\n\n    test(\"event with created_at=1 is stored\", () => {\n      const store = new KeyedReplaceableNoteStore(() => \"key\")\n      store.add(ev(\"a\", 1, 1))\n      expect(store.snapshot).toHaveLength(1)\n    })\n\n    test(\"event with negative created_at is never stored (fails > 0 check)\", () => {\n      const store = new KeyedReplaceableNoteStore(() => \"key\")\n      const result = store.add(ev(\"a\", 1, -1))\n      expect(result).toBe(0)\n      expect(store.snapshot).toHaveLength(0)\n    })\n\n    test(\"exact same timestamp does not replace (strict > not >=)\", () => {\n      const store = new KeyedReplaceableNoteStore(() => \"key\")\n      store.add(ev(\"first\", 1, 100))\n      const result = store.add(ev(\"second\", 1, 100))\n      expect(result).toBe(0)\n      expect(store.snapshot[0].id).toBe(\"first\")\n    })\n\n    test(\"very large created_at values work\", () => {\n      const store = new KeyedReplaceableNoteStore(() => \"key\")\n      store.add(ev(\"a\", 1, Number.MAX_SAFE_INTEGER - 1))\n      store.add(ev(\"b\", 1, Number.MAX_SAFE_INTEGER))\n      expect(store.snapshot[0].id).toBe(\"b\")\n    })\n  })\n\n  describe(\"relay merging\", () => {\n    test(\"replacing event inherits relays from old event\", () => {\n      const store = new KeyedReplaceableNoteStore(() => \"key\")\n      store.add(ev(\"old\", 1, 100, \"aa\", [], [\"wss://r1.test\"]))\n      store.add(ev(\"new\", 1, 200, \"aa\", [], [\"wss://r2.test\"]))\n      const snap = store.snapshot\n      expect(snap[0].relays).toContain(\"wss://r1.test\")\n      expect(snap[0].relays).toContain(\"wss://r2.test\")\n    })\n\n    test(\"relay merging deduplicates\", () => {\n      const store = new KeyedReplaceableNoteStore(() => \"key\")\n      store.add(ev(\"old\", 1, 100, \"aa\", [], [\"wss://r1.test\"]))\n      store.add(ev(\"new\", 1, 200, \"aa\", [], [\"wss://r1.test\", \"wss://r2.test\"]))\n      const relays = store.snapshot[0].relays!\n      const uniqueRelays = [...new Set(relays)]\n      expect(relays.length).toBe(uniqueRelays.length)\n    })\n\n    test(\"relay merging with undefined relays on old event\", () => {\n      const store = new KeyedReplaceableNoteStore(() => \"key\")\n      store.add({ ...ev(\"old\", 1, 100), relays: undefined } as any)\n      store.add(ev(\"new\", 1, 200, \"aa\", [], [\"wss://r1.test\"]))\n      expect(store.snapshot[0].relays).toContain(\"wss://r1.test\")\n    })\n\n    test(\"relay merging with undefined relays on new event\", () => {\n      const store = new KeyedReplaceableNoteStore(() => \"key\")\n      store.add(ev(\"old\", 1, 100, \"aa\", [], [\"wss://r1.test\"]))\n      store.add({ ...ev(\"new\", 1, 200), relays: undefined } as any)\n      expect(store.snapshot[0].relays).toContain(\"wss://r1.test\")\n    })\n\n    test(\"non-replacing event does NOT merge relays (older event ignored)\", () => {\n      const store = new KeyedReplaceableNoteStore(() => \"key\")\n      store.add(ev(\"new\", 1, 200, \"aa\", [], [\"wss://r1.test\"]))\n      store.add(ev(\"old\", 1, 100, \"aa\", [], [\"wss://r2.test\"]))\n      expect(store.snapshot[0].relays).toEqual([\"wss://r1.test\"])\n    })\n  })\n\n  describe(\"sorted order\", () => {\n    test(\"snapshot is sorted by created_at descending\", () => {\n      const store = new KeyedReplaceableNoteStore(e => e.id)\n      store.add(ev(\"a\", 1, 100))\n      store.add(ev(\"c\", 1, 300))\n      store.add(ev(\"b\", 1, 200))\n      const snap = store.snapshot\n      expect(snap[0].created_at).toBe(300)\n      expect(snap[1].created_at).toBe(200)\n      expect(snap[2].created_at).toBe(100)\n    })\n\n    test(\"sorted order is maintained after replacement\", () => {\n      const store = new KeyedReplaceableNoteStore(e => e.pubkey)\n      store.add(ev(\"a1\", 1, 100, \"alice\"))\n      store.add(ev(\"b1\", 1, 300, \"bob\"))\n      store.add(ev(\"a2\", 1, 400, \"alice\"))\n      const snap = store.snapshot\n      expect(snap[0].id).toBe(\"a2\")\n      expect(snap[1].id).toBe(\"b1\")\n    })\n  })\n\n  describe(\"batch add\", () => {\n    test(\"empty array add returns 0 and does not emit\", async () => {\n      const store = new KeyedReplaceableNoteStore(e => e.id)\n      const emissions: TaggedNostrEvent[][] = []\n      store.on(\"event\", evs => emissions.push(evs))\n      const result = store.add([])\n      expect(result).toBe(0)\n      await sleep(400)\n      expect(emissions).toHaveLength(0)\n    })\n\n    test(\"batch with mix of new and duplicate events\", () => {\n      const store = new KeyedReplaceableNoteStore(e => e.id)\n      store.add(ev(\"a\", 1, 100))\n      const result = store.add([ev(\"a\", 1, 100), ev(\"b\", 1, 200), ev(\"c\", 1, 300)])\n      expect(result).toBe(2)\n      expect(store.snapshot).toHaveLength(3)\n    })\n\n    test(\"batch with replaceable events — newer replaces within batch\", () => {\n      const store = new KeyedReplaceableNoteStore(() => \"key\")\n      const result = store.add([ev(\"old\", 1, 100), ev(\"new\", 1, 200)])\n      expect(result).toBe(2)\n      expect(store.snapshot).toHaveLength(1)\n      expect(store.snapshot[0].id).toBe(\"new\")\n    })\n  })\n\n  describe(\"snapshot laziness\", () => {\n    test(\"multiple adds without reading snapshot only compute once on read\", () => {\n      const store = new KeyedReplaceableNoteStore(e => e.id)\n      store.add(ev(\"a\", 1, 100))\n      store.add(ev(\"b\", 1, 200))\n      store.add(ev(\"c\", 1, 300))\n      const snap = store.snapshot\n      expect(snap).toHaveLength(3)\n    })\n\n    test(\"snapshot reference changes after add\", () => {\n      const store = new KeyedReplaceableNoteStore(e => e.id)\n      store.add(ev(\"a\", 1, 100))\n      const snap1 = store.snapshot\n      store.add(ev(\"b\", 1, 200))\n      const snap2 = store.snapshot\n      expect(snap1).not.toBe(snap2)\n    })\n\n    test(\"snapshot reference is stable when no changes\", () => {\n      const store = new KeyedReplaceableNoteStore(e => e.id)\n      store.add(ev(\"a\", 1, 100))\n      const snap1 = store.snapshot\n      const snap2 = store.snapshot\n      expect(snap1).toBe(snap2)\n    })\n\n    test(\"snapshot is fresh after clear + add\", () => {\n      const store = new KeyedReplaceableNoteStore(e => e.id)\n      store.add(ev(\"a\", 1, 100))\n      const snap1 = store.snapshot\n      store.clear()\n      store.add(ev(\"b\", 1, 200))\n      const snap2 = store.snapshot\n      expect(snap1).toHaveLength(1)\n      expect(snap1[0].id).toBe(\"a\")\n      expect(snap2).toHaveLength(1)\n      expect(snap2[0].id).toBe(\"b\")\n    })\n  })\n\n  describe(\"emission timing\", () => {\n    test(\"onChange debounces — adds within interval are batched, next interval starts fresh\", async () => {\n      const store = new KeyedReplaceableNoteStore(e => e.id)\n      const emissions: TaggedNostrEvent[][] = []\n      store.on(\"event\", evs => emissions.push(evs))\n\n      store.add(ev(\"a\", 1, 100))\n      store.add(ev(\"b\", 1, 200))\n\n      await sleep(400)\n      expect(emissions).toHaveLength(1)\n      expect(emissions[0]).toHaveLength(2)\n\n      store.add(ev(\"c\", 1, 300))\n      await sleep(400)\n      expect(emissions).toHaveLength(2)\n      expect(emissions[1]).toHaveLength(1)\n      expect(emissions[1][0].id).toBe(\"c\")\n    })\n\n    test(\"flushEmit forces immediate emission of buffered events\", () => {\n      const store = new KeyedReplaceableNoteStore(e => e.id)\n      const emissions: TaggedNostrEvent[][] = []\n      store.on(\"event\", evs => emissions.push(evs))\n\n      store.add(ev(\"a\", 1, 100))\n      store.add(ev(\"b\", 1, 200))\n      expect(emissions).toHaveLength(0)\n\n      store.flushEmit()\n      expect(emissions).toHaveLength(1)\n      expect(emissions[0]).toHaveLength(2)\n    })\n\n    test(\"flushEmit on empty buffer is safe no-op\", () => {\n      const store = new KeyedReplaceableNoteStore(e => e.id)\n      const emissions: TaggedNostrEvent[][] = []\n      store.on(\"event\", evs => emissions.push(evs))\n      store.flushEmit()\n      expect(emissions).toHaveLength(0)\n    })\n\n    test(\"flushEmit clears timer so next add creates fresh timer\", async () => {\n      const store = new KeyedReplaceableNoteStore(e => e.id)\n      const emissions: TaggedNostrEvent[][] = []\n      store.on(\"event\", evs => emissions.push(evs))\n\n      store.add(ev(\"a\", 1, 100))\n      store.flushEmit()\n      expect(emissions).toHaveLength(1)\n\n      store.add(ev(\"b\", 1, 200))\n      await sleep(400)\n      expect(emissions).toHaveLength(2)\n      expect(emissions[1][0].id).toBe(\"b\")\n    })\n\n    test(\"clear during pending emit cancels buffered events\", async () => {\n      const store = new KeyedReplaceableNoteStore(e => e.id)\n      const emissions: TaggedNostrEvent[][] = []\n      store.on(\"event\", evs => emissions.push(evs))\n\n      store.add(ev(\"a\", 1, 100))\n      store.add(ev(\"b\", 1, 200))\n      store.clear()\n\n      await sleep(400)\n      expect(emissions).toHaveLength(1)\n      expect(emissions[0]).toHaveLength(0)\n    })\n\n    test(\"rapid add-clear-add cycle emits correctly\", async () => {\n      const store = new KeyedReplaceableNoteStore(e => e.id)\n      const emissions: TaggedNostrEvent[][] = []\n      store.on(\"event\", evs => emissions.push(evs))\n\n      store.add(ev(\"a\", 1, 100))\n      store.clear()\n      store.add(ev(\"b\", 1, 200))\n\n      await sleep(400)\n      expect(emissions).toHaveLength(2)\n      expect(emissions[0]).toHaveLength(0)\n      expect(emissions[1]).toHaveLength(1)\n      expect(emissions[1][0].id).toBe(\"b\")\n    })\n  })\n})\n\ndescribe(\"NoteCollection kind routing\", () => {\n  describe(\"Regular events (kind 1, ephemeral, etc.)\", () => {\n    test(\"kind 1 events keyed by id — same pubkey different ids coexist\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 1, 100, \"alice\"))\n      c.add(ev(\"b\", 1, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(2)\n    })\n\n    test(\"kind 1 events with same id — only stored once\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"same\", 1, 100, \"alice\"))\n      c.add(ev(\"same\", 1, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(1)\n      expect(c.snapshot[0].created_at).toBe(200)\n    })\n\n    test(\"ephemeral kind 20000 is Regular\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 20000, 100, \"alice\"))\n      c.add(ev(\"b\", 20000, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(2)\n    })\n\n    test(\"kind 7 (reaction) is Regular\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 7, 100, \"alice\"))\n      c.add(ev(\"b\", 7, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(2)\n    })\n  })\n\n  describe(\"Replaceable events (kind 0, 3, 41, 10000-19999)\", () => {\n    test(\"kind 0 (metadata) keyed by kind:pubkey\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"old\", 0, 100, \"alice\"))\n      c.add(ev(\"new\", 0, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(1)\n      expect(c.snapshot[0].id).toBe(\"new\")\n    })\n\n    test(\"kind 3 (contacts) keyed by kind:pubkey\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"old\", 3, 100, \"alice\"))\n      c.add(ev(\"new\", 3, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(1)\n      expect(c.snapshot[0].id).toBe(\"new\")\n    })\n\n    test(\"kind 10002 (relay list) is Replaceable\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"old\", 10002, 100, \"alice\"))\n      c.add(ev(\"new\", 10002, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(1)\n      expect(c.snapshot[0].id).toBe(\"new\")\n    })\n\n    test(\"kind 19999 boundary — is Replaceable\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"old\", 19999, 100, \"alice\"))\n      c.add(ev(\"new\", 19999, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(1)\n    })\n\n    test(\"replaceable events from different pubkeys are independent\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 0, 100, \"alice\"))\n      c.add(ev(\"b\", 0, 100, \"bob\"))\n      expect(c.snapshot).toHaveLength(2)\n    })\n\n    test(\"replaceable events of different kinds from same pubkey are independent\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 0, 100, \"alice\"))\n      c.add(ev(\"b\", 3, 100, \"alice\"))\n      expect(c.snapshot).toHaveLength(2)\n    })\n  })\n\n  describe(\"Addressable events (kind 30000-39999)\", () => {\n    test(\"keyed by kind:pubkey:d-tag\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"old\", 30000, 100, \"alice\", [[\"d\", \"slug\"]]))\n      c.add(ev(\"new\", 30000, 200, \"alice\", [[\"d\", \"slug\"]]))\n      expect(c.snapshot).toHaveLength(1)\n      expect(c.snapshot[0].id).toBe(\"new\")\n    })\n\n    test(\"different d-tags are independent\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 30000, 100, \"alice\", [[\"d\", \"one\"]]))\n      c.add(ev(\"b\", 30000, 100, \"alice\", [[\"d\", \"two\"]]))\n      expect(c.snapshot).toHaveLength(2)\n    })\n\n    test(\"different pubkeys with same d-tag are independent\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 30000, 100, \"alice\", [[\"d\", \"slug\"]]))\n      c.add(ev(\"b\", 30000, 100, \"bob\", [[\"d\", \"slug\"]]))\n      expect(c.snapshot).toHaveLength(2)\n    })\n\n    test(\"different kinds with same pubkey and d-tag are independent\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 30000, 100, \"alice\", [[\"d\", \"slug\"]]))\n      c.add(ev(\"b\", 30001, 100, \"alice\", [[\"d\", \"slug\"]]))\n      expect(c.snapshot).toHaveLength(2)\n    })\n\n    test(\"missing d-tag uses undefined as key component\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 30000, 100, \"alice\"))\n      c.add(ev(\"b\", 30000, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(1)\n      expect(c.snapshot[0].id).toBe(\"b\")\n    })\n\n    test(\"empty d-tag value is distinct from missing d-tag\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 30000, 100, \"alice\", [[\"d\", \"\"]]))\n      c.add(ev(\"b\", 30000, 100, \"alice\"))\n      expect(c.snapshot).toHaveLength(2)\n    })\n\n    test(\"kind 39999 boundary — is Addressable\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"old\", 39999, 100, \"alice\", [[\"d\", \"x\"]]))\n      c.add(ev(\"new\", 39999, 200, \"alice\", [[\"d\", \"x\"]]))\n      expect(c.snapshot).toHaveLength(1)\n    })\n\n    test(\"kind 40000 boundary — is NOT Addressable (Regular)\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 40000, 100, \"alice\", [[\"d\", \"x\"]]))\n      c.add(ev(\"b\", 40000, 200, \"alice\", [[\"d\", \"x\"]]))\n      expect(c.snapshot).toHaveLength(2)\n    })\n  })\n\n  describe(\"concurrent-like add patterns\", () => {\n    test(\"interleaved adds from multiple pubkeys\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a1\", 0, 100, \"alice\"))\n      c.add(ev(\"b1\", 0, 100, \"bob\"))\n      c.add(ev(\"a2\", 0, 200, \"alice\"))\n      c.add(ev(\"b2\", 0, 200, \"bob\"))\n      expect(c.snapshot).toHaveLength(2)\n      const ids = c.snapshot.map(e => e.id).sort()\n      expect(ids).toEqual([\"a2\", \"b2\"])\n    })\n\n    test(\"large batch add\", () => {\n      const c = new NoteCollection()\n      const events = Array.from({ length: 1000 }, (_, i) => ev(`id-${i}`, 1, i + 1, \"alice\"))\n      c.add(events)\n      expect(c.snapshot).toHaveLength(1000)\n    })\n\n    test(\"add after listener removal does not throw\", async () => {\n      const c = new NoteCollection()\n      const handler = () => {}\n      c.on(\"event\", handler)\n      c.off(\"event\", handler)\n      c.add(ev(\"a\", 1, 100))\n      await sleep(400)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/note-collection.test.ts",
    "content": "import type { TaggedNostrEvent } from \"../src/nostr\"\nimport { describe, expect, test } from \"bun:test\"\nimport { NoteCollection, KeyedReplaceableNoteStore } from \"../src/note-collection\"\n\ndescribe(\"NoteStore\", () => {\n  describe(\"note collection\", () => {\n    test(\"one event\", () => {\n      const ev = { id: \"one\", kind: 1, created_at: 69 } as TaggedNostrEvent\n      const c = new NoteCollection()\n      c.add(ev)\n      expect(c.snapshot).toEqual([ev])\n    })\n    test(\"still one event\", () => {\n      const ev = { id: \"one\", kind: 1, created_at: 69 } as TaggedNostrEvent\n      const c = new NoteCollection()\n      c.add(ev)\n      c.add(ev)\n      expect(c.snapshot).toEqual([ev])\n    })\n    test(\"clears\", () => {\n      const ev = { id: \"one\", kind: 1, created_at: 69 } as TaggedNostrEvent\n      const c = new NoteCollection()\n      c.add(ev)\n      expect(c.snapshot).toEqual([ev])\n      c.clear()\n      expect(c.snapshot).toEqual([])\n    })\n  })\n  describe(\"replaceable\", () => {\n    test(\"one event\", () => {\n      const ev = { id: \"test\", created_at: 69 } as TaggedNostrEvent\n      const c = new KeyedReplaceableNoteStore(() => \"test\")\n      c.add(ev)\n      expect(c.snapshot).toEqual([ev])\n    })\n    test(\"dont replace with older\", () => {\n      const ev = { id: \"test\", created_at: 69 } as TaggedNostrEvent\n      const evOlder = { id: \"test2\", created_at: 68 } as TaggedNostrEvent\n      const c = new KeyedReplaceableNoteStore(() => \"test\")\n      c.add(ev)\n      c.add(evOlder)\n      expect(c.snapshot).toEqual([ev])\n    })\n    test(\"replace with newer\", () => {\n      const ev = { id: \"test\", created_at: 69 } as TaggedNostrEvent\n      const evNewer = { id: \"test2\", created_at: 70 } as TaggedNostrEvent\n      const c = new KeyedReplaceableNoteStore(() => \"test\")\n      c.add(ev)\n      c.add(evNewer)\n      expect(c.snapshot).toEqual([evNewer])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/pin-encrypted.test.ts",
    "content": "import { describe, expect, test } from \"bun:test\"\nimport { InvalidPinError, PinEncrypted } from \"../src/encryption/pin-encrypted\"\n\n// A valid 32-byte private key (64 hex chars)\nconst TEST_KEY = \"0000000000000000000000000000000000000000000000000000000000000001\"\nconst TEST_PIN = \"correct-pin\"\nconst WRONG_PIN = \"wrong-pin\"\n\ndescribe(\"PinEncrypted\", () => {\n  test(\"roundtrip: create with correct PIN then unlock\", async () => {\n    const enc = await PinEncrypted.create(TEST_KEY, TEST_PIN)\n\n    // Should be unlocked immediately after create\n    expect(enc.shouldUnlock()).toBe(false)\n    expect(enc.value).toBe(TEST_KEY)\n\n    // Serialize and restore, then unlock\n    const payload = enc.toPayload() as any\n    expect(payload.v).toBe(2)\n\n    const restored = new PinEncrypted(payload)\n    expect(restored.shouldUnlock()).toBe(true)\n    await restored.unlock(TEST_PIN)\n    expect(restored.value).toBe(TEST_KEY)\n  })\n\n  test(\"rejects wrong PIN\", async () => {\n    const enc = await PinEncrypted.create(TEST_KEY, TEST_PIN)\n    const payload = enc.toPayload()\n    const restored = new PinEncrypted(payload)\n\n    await expect(restored.unlock(WRONG_PIN)).rejects.toBeInstanceOf(InvalidPinError)\n  })\n\n  test(\"rejects tampered ciphertext\", async () => {\n    const enc = await PinEncrypted.create(TEST_KEY, TEST_PIN)\n    const payload = enc.toPayload() as any\n\n    // Flip a byte in the ciphertext\n    const ctBytes = Buffer.from(payload.ciphertext, \"base64\")\n    ctBytes[0] ^= 0xff\n    payload.ciphertext = ctBytes.toString(\"base64\")\n\n    const tampered = new PinEncrypted(payload)\n    await expect(tampered.unlock(TEST_PIN)).rejects.toBeInstanceOf(InvalidPinError)\n  })\n\n  test(\"rejects tampered nonce (iv)\", async () => {\n    const enc = await PinEncrypted.create(TEST_KEY, TEST_PIN)\n    const payload = enc.toPayload() as any\n\n    const nonceBytes = Buffer.from(payload.iv, \"base64\")\n    nonceBytes[0] ^= 0xff\n    payload.iv = nonceBytes.toString(\"base64\")\n\n    const tampered = new PinEncrypted(payload)\n    await expect(tampered.unlock(TEST_PIN)).rejects.toBeInstanceOf(InvalidPinError)\n  })\n\n  test(\"rejects tampered MAC\", async () => {\n    const enc = await PinEncrypted.create(TEST_KEY, TEST_PIN)\n    const payload = enc.toPayload() as any\n\n    const macBytes = Buffer.from(payload.mac, \"base64\")\n    macBytes[0] ^= 0xff\n    payload.mac = macBytes.toString(\"base64\")\n\n    const tampered = new PinEncrypted(payload)\n    await expect(tampered.unlock(TEST_PIN)).rejects.toBeInstanceOf(InvalidPinError)\n  })\n\n  test(\"rejects legacy v1 payload (no v field)\", async () => {\n    const enc = await PinEncrypted.create(TEST_KEY, TEST_PIN)\n    const payload = enc.toPayload() as any\n    delete payload.v\n\n    const legacy = new PinEncrypted(payload)\n    await expect(legacy.unlock(TEST_PIN)).rejects.toBeInstanceOf(InvalidPinError)\n  })\n\n  test(\"create() rejects content that is not 32 bytes\", async () => {\n    await expect(PinEncrypted.create(\"deadbeef\", TEST_PIN)).rejects.toThrow(\"32 bytes\")\n  })\n\n  test(\"value throws before unlock\", () => {\n    const enc = new PinEncrypted({ v: 2, salt: \"\", ciphertext: \"\", iv: \"\", mac: \"\" })\n    expect(() => enc.value).toThrow(\"not been decrypted\")\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/query-comprehensive.test.ts",
    "content": "import { beforeEach, describe, expect, test } from \"bun:test\"\nimport type { TaggedNostrEvent } from \"../src/nostr\"\nimport { Query, QueryTrace, QueryTraceState } from \"../src/query\"\nimport { RequestBuilder } from \"../src/request-builder\"\n\nfunction createEv(id: string, kind = 1, created_at = 100, pubkey = \"aa\", tags: string[][] = []): TaggedNostrEvent {\n  return { id, kind, created_at, pubkey, tags, content: \"\", sig: \"\", relays: [] }\n}\n\nfunction sleep(ms: number) {\n  return new Promise(r => setTimeout(r, ms))\n}\n\ndescribe(\"Query\", () => {\n  let rb: RequestBuilder\n\n  beforeEach(() => {\n    rb = new RequestBuilder(\"test-query\")\n    rb.withFilter().kinds([1])\n  })\n\n  describe(\"Initialization and RequestBuilder integration\", () => {\n    test(\"correctly initializes with RequestBuilder\", () => {\n      const q = new Query(rb)\n      expect(q.id).toBe(\"test-query\")\n      expect(q.requests).toHaveLength(1)\n      expect(q.requests[0].kinds).toContain(1)\n    })\n\n    test(\"addRequest deduplicates by builder instance\", () => {\n      const q = new Query(rb)\n      const result = q.addRequest(rb)\n      expect(result).toBeUndefined()\n      expect(q.requests).toHaveLength(1)\n    })\n\n    test(\"addRequest merges filters from different builder instances with same ID\", () => {\n      const q = new Query(rb)\n      const rb2 = new RequestBuilder(\"test-query\")\n      rb2.withFilter().kinds([2])\n      const result = q.addRequest(rb2)\n      expect(result).toBe(true)\n      expect(q.requests).toHaveLength(2)\n      expect(q.requests[0].kinds).toContain(1)\n      expect(q.requests[1].kinds).toContain(2)\n    })\n\n    test(\"addRequest handles extraEvents\", () => {\n      const q = new Query(rb)\n      const rbExtra = new RequestBuilder(\"test-query\")\n      const extraEv = createEv(\"extra\", 1, 100)\n      rbExtra.withOptions({ extraEvents: [extraEv] })\n      q.addRequest(rbExtra)\n      expect(q.snapshot).toContainEqual(extraEv)\n    })\n\n    test(\"addRequest ignores builders with no filters\", () => {\n      const q = new Query(rb)\n      const rbEmpty = new RequestBuilder(\"test-query\")\n      const result = q.addRequest(rbEmpty)\n      expect(result).toBe(false)\n      expect(q.requests).toHaveLength(1)\n    })\n  })\n\n  describe(\"Event Flow and Filtering\", () => {\n    test(\"addEvent filters out events that do not match trace filters\", () => {\n      const q = new Query(rb)\n      const trace = new QueryTrace(\"wss://r.test\", [{ kinds: [1] }], \"conn1\", false)\n      q.addTrace(trace)\n\n      const matchingEv = createEv(\"match\", 1, 100)\n      const nonMatchingEv = createEv(\"no-match\", 2, 100)\n\n      q.addEvent(trace.id, matchingEv)\n      q.addEvent(trace.id, nonMatchingEv)\n\n      expect(q.snapshot).toContainEqual(matchingEv)\n      expect(q.snapshot).not.toContainEqual(nonMatchingEv)\n    })\n\n    test(\"addEvent handles global events (sub === '*')\", () => {\n      const q = new Query(rb)\n      // Query has filters [kinds: [1]] from rb\n      const trace = new QueryTrace(\"wss://r.test\", [{ kinds: [1] }], \"conn1\", false)\n      q.addTrace(trace)\n\n      const matchingEv = createEv(\"match\", 1, 100)\n      q.addEvent(\"*\", matchingEv)\n\n      expect(q.snapshot).toContainEqual(matchingEv)\n    })\n\n    test(\"addEvent with non-existent sub is ignored\", () => {\n      const q = new Query(rb)\n      const matchingEv = createEv(\"match\", 1, 100)\n      q.addEvent(\"unknown-sub\", matchingEv)\n      expect(q.snapshot).toHaveLength(0)\n    })\n\n    test(\"addEvent tracks duplicates\", () => {\n      const q = new Query(rb)\n      const trace = new QueryTrace(\"wss://r.test\", [{ kinds: [1] }], \"conn1\", false)\n      q.addTrace(trace)\n      const ev1 = createEv(\"evt1\", 1, 100)\n\n      q.addEvent(trace.id, ev1)\n      q.addEvent(trace.id, ev1) // Duplicate\n\n      expect(q.snapshot).toHaveLength(1)\n    })\n  })\n\n  describe(\"Trace Management and Progress\", () => {\n    test(\"progress is calculated correctly\", () => {\n      const q = new Query(rb)\n      expect(q.progress).toBe(0)\n\n      const t1 = new QueryTrace(\"r1\", [], \"c1\", false)\n      const t2 = new QueryTrace(\"r2\", [], \"c2\", false)\n      q.addTrace(t1)\n      q.addTrace(t2)\n\n      expect(q.progress).toBe(0)\n\n      t1.eose()\n      expect(q.progress).toBe(0.5)\n\n      t2.timeout()\n      expect(q.progress).toBe(1)\n    })\n\n    test(\"eose event fires when all traces finish\", () => {\n      const q = new Query(rb)\n      let eoseFired = false\n      q.on(\"eose\", () => {\n        eoseFired = true\n      })\n\n      const t1 = new QueryTrace(\"r1\", [], \"c1\", false)\n      q.addTrace(t1)\n      t1.eose()\n\n      expect(eoseFired).toBe(true)\n    })\n\n    test(\"streaming traces (leaveOpen=true) do not contribute to finished progress\", () => {\n      const rbStream = new RequestBuilder(\"stream\")\n      rbStream.withOptions({ leaveOpen: true })\n      rbStream.withFilter().kinds([1])\n      const q = new Query(rbStream)\n\n      const t1 = new QueryTrace(\"r1\", [], \"c1\", true)\n      q.addTrace(t1)\n      t1.sent() // State: WAITING_STREAM\n\n      expect(t1.finished).toBe(false)\n      expect(q.progress).toBe(0)\n    })\n  })\n\n  describe(\"Lifecycle and Timers\", () => {\n    test(\"start() emits request synchronously if groupingDelay is 0\", () => {\n      rb.withOptions({ groupingDelay: 0 })\n      const q = new Query(rb)\n      let requestEmitted = false\n      q.on(\"request\", () => {\n        requestEmitted = true\n      })\n\n      q.start()\n      expect(requestEmitted).toBe(true)\n    })\n\n    test(\"start() debounces request emission if groupingDelay > 0\", async () => {\n      rb.withOptions({ groupingDelay: 100 })\n      const q = new Query(rb)\n      let requestEmitted = false\n      q.on(\"request\", () => {\n        requestEmitted = true\n      })\n\n      q.start()\n      expect(requestEmitted).toBe(false)\n\n      await sleep(150)\n      expect(requestEmitted).toBe(true)\n    })\n\n    test(\"cancel() sets grace window for removal\", async () => {\n      const q = new Query(rb)\n      expect(q.canRemove()).toBe(false)\n\n      q.cancel()\n      expect(q.canRemove()).toBe(false) // Still in grace window\n\n      await sleep(1100)\n      expect(q.canRemove()).toBe(true)\n    })\n\n    test(\"uncancel() clears the grace window\", async () => {\n      const q = new Query(rb)\n      q.cancel()\n      q.uncancel()\n      await sleep(1100)\n      expect(q.canRemove()).toBe(false)\n    })\n\n    test(\"closeQuery() closes all active traces and cleans up\", () => {\n      const q = new Query(rb)\n      const t1 = new QueryTrace(\"r1\", [], \"c1\", false)\n      q.addTrace(t1)\n\n      let endFired = false\n      q.on(\"end\", () => {\n        endFired = true\n      })\n\n      q.closeQuery()\n      expect(t1.currentState).toBe(QueryTraceState.LOCAL_CLOSE)\n      expect(endFired).toBe(true)\n    })\n  })\n\n  describe(\"Feed and Snapshot\", () => {\n    test(\"snapshot delegates to NoteCollection\", () => {\n      const q = new Query(rb)\n      const ev1 = createEv(\"evt1\", 1, 100)\n      q.feed.add(ev1)\n      expect(q.snapshot).toContainEqual(ev1)\n    })\n\n    test(\"flush() forces immediate feed emission and filter emission\", () => {\n      rb.withOptions({ groupingDelay: 100 })\n      const q = new Query(rb)\n      let eventFired = false\n      let requestFired = false\n\n      q.on(\"event\", () => {\n        eventFired = true\n      })\n      q.on(\"request\", () => {\n        requestFired = true\n      })\n\n      q.feed.add(createEv(\"evt1\", 1, 100))\n      q.start()\n\n      expect(eventFired).toBe(false)\n      expect(requestFired).toBe(false)\n\n      q.flush()\n      expect(eventFired).toBe(true)\n      expect(requestFired).toBe(true)\n    })\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/query-manager-comprehensive.test.ts",
    "content": "import { afterEach, beforeEach, describe, expect, test } from \"bun:test\"\nimport type { CachedTable } from \"@snort/shared\"\nimport { EventEmitter } from \"eventemitter3\"\nimport { SocialGraph } from \"nostr-social-graph\"\nimport type { RelayInfoDocument } from \"../src\"\nimport type { CachedMetadata, UsersFollows } from \"../src/cache\"\nimport type { RelaySettings } from \"../src/connection\"\nimport type { ConnectionPool, ConnectionPoolEvents, ConnectionType, ConnectionTypeEvents } from \"../src/connection-pool\"\nimport type { NostrEvent, OkResponse, ReqCommand, TaggedNostrEvent } from \"../src/nostr\"\nimport type { RelayMetadataLoader } from \"../src/outbox\"\nimport type { ProfileLoaderService } from \"../src/profile-cache\"\nimport { QueryTrace, QueryTraceState } from \"../src/query\"\nimport { QueryManager } from \"../src/query-manager\"\nimport { DefaultOptimizer } from \"../src/query-optimizer\"\nimport { RequestBuilder } from \"../src/request-builder\"\nimport type { SystemConfig, SystemInterface } from \"../src/system\"\n\nfunction createEv(\n  id: string,\n  kind = 1,\n  created_at = 100,\n  pubkey = \"aa\",\n  tags: string[][] = [],\n  relays: string[] = [],\n): TaggedNostrEvent {\n  return { id, kind, created_at, pubkey, tags, content: \"\", sig: \"\", relays }\n}\n\nfunction sleep(ms: number) {\n  return new Promise(r => setTimeout(r, ms))\n}\n\nfunction makeRb(id: string, groupingDelay = 0) {\n  const rb = new RequestBuilder(id)\n  rb.withOptions({ groupingDelay })\n  rb.withFilter().kinds([1]).limit(10)\n  return rb\n}\n\nclass MockConnection extends EventEmitter<ConnectionTypeEvents> implements ConnectionType {\n  readonly id = crypto.randomUUID()\n  readonly address: string\n  info: RelayInfoDocument | undefined = undefined\n  settings: RelaySettings = { read: true, write: true }\n  ephemeral = false\n  #open: boolean\n  #down = false\n  sentRequests: Array<ReqCommand> = []\n  closedRequests: string[] = []\n\n  constructor(address: string, open = true) {\n    super()\n    this.address = address\n    this.#open = open\n  }\n\n  get isOpen() {\n    return this.#open\n  }\n  get isDown() {\n    return this.#down\n  }\n  get activeSubscriptions() {\n    return this.sentRequests.filter(r => r[0] === \"REQ\").length\n  }\n  get maxSubscriptions() {\n    return 20\n  }\n\n  open() {\n    this.#open = true\n    this.emit(\"connected\", false)\n    this.emit(\"change\")\n  }\n\n  markDown() {\n    this.#down = true\n  }\n\n  async connect() {}\n  close() {}\n  async publish(ev: NostrEvent): Promise<OkResponse> {\n    return { ok: true, id: \"\", relay: this.address, event: ev }\n  }\n\n  request(req: ReqCommand, cbSent?: () => void) {\n    if (this.#open) {\n      this.sentRequests.push(req)\n      cbSent?.()\n    }\n  }\n\n  closeRequest(id: string) {\n    this.closedRequests.push(id)\n  }\n  sendRaw(_obj: object) {}\n}\n\nclass MockPool extends EventEmitter<ConnectionPoolEvents> implements ConnectionPool {\n  #conns = new Map<string, MockConnection>()\n\n  add(c: MockConnection) {\n    this.#conns.set(c.address, c)\n  }\n\n  getConnection(id: string) {\n    return this.#conns.get(id)\n  }\n\n  async connect(address: string) {\n    return this.#conns.get(address)\n  }\n  disconnect(_a: string) {}\n  async broadcast(): Promise<OkResponse[]> {\n    return []\n  }\n  async broadcastTo(_a: string, ev: NostrEvent): Promise<OkResponse> {\n    return { ok: true, id: \"\", relay: _a, event: ev }\n  }\n\n  *[Symbol.iterator]() {\n    yield* this.#conns\n  }\n}\n\nfunction makeSystem(pool: MockPool, opts?: { cacheRelay?: any }): SystemInterface {\n  const config: SystemConfig = {\n    relays: { preload: async () => {} } as unknown as CachedTable<any>,\n    profiles: {} as CachedTable<CachedMetadata>,\n    contactLists: {} as CachedTable<UsersFollows>,\n    optimizer: DefaultOptimizer,\n    checkSigs: false,\n    automaticOutboxModel: false,\n    buildFollowGraph: false,\n    fallbackSync: \"since\",\n    socialGraphInstance: new SocialGraph(\"00\".repeat(32)),\n    disableSyncModule: true,\n  }\n  return {\n    pool,\n    config,\n    cacheRelay: opts?.cacheRelay,\n    requestRouter: undefined,\n    checkSigs: false,\n    optimizer: DefaultOptimizer,\n    relayLoader: { TrackKeys: () => {} } as unknown as RelayMetadataLoader,\n    profileLoader: {} as ProfileLoaderService,\n    userFollowsCache: {} as CachedTable<UsersFollows>,\n    traceTimeline: undefined,\n    async Init() {},\n    GetQuery: () => undefined,\n    Query: () => {\n      throw new Error(\"not used\")\n    },\n    Fetch: () => Promise.resolve([]),\n    async ConnectToRelay() {},\n    DisconnectRelay() {},\n    HandleEvent() {},\n    async BroadcastEvent() {\n      return []\n    },\n    async WriteOnceToRelay() {\n      return { ok: true, id: \"\", relay: \"\", event: {} as NostrEvent }\n    },\n    emit: () => false,\n    on: () => ({}) as any,\n    off: () => ({}) as any,\n    once: () => ({}) as any,\n    removeAllListeners: () => ({}) as any,\n    listeners: () => [],\n    listenerCount: () => 0,\n    eventNames: () => [],\n    addListener: () => ({}) as any,\n    removeListener: () => ({}) as any,\n  } as unknown as SystemInterface\n}\n\ndescribe(\"QueryManager — event propagation\", () => {\n  let pool: MockPool\n  let system: SystemInterface\n  let qm: QueryManager\n\n  beforeEach(() => {\n    pool = new MockPool()\n    system = makeSystem(pool)\n    qm = new QueryManager(system)\n  })\n\n  afterEach(() => {\n    qm.destroy()\n  })\n\n  test(\"events from pool flow through trace into query feed\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = makeRb(\"event-flow\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(q.traces).toHaveLength(1)\n    const traceId = q.traces[0].id\n\n    const event = createEv(\"evt1\", 1, 500)\n    pool.emit(\"event\", \"wss://relay.test\", traceId, event)\n\n    expect(q.snapshot).toHaveLength(1)\n    expect(q.snapshot[0].id).toBe(\"evt1\")\n  })\n\n  test(\"events with wrong sub id are ignored\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = makeRb(\"wrong-sub\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    const event = createEv(\"evt1\", 1, 500)\n    pool.emit(\"event\", \"wss://relay.test\", \"wrong-trace-id\", event)\n\n    expect(q.snapshot).toHaveLength(0)\n  })\n\n  test(\"events that dont match trace filters are rejected\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = new RequestBuilder(\"filter-test\")\n    rb.withOptions({ groupingDelay: 0 })\n    rb.withFilter().kinds([1])\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    const traceId = q.traces[0].id\n    const badEvent = createEv(\"bad\", 999, 500)\n    pool.emit(\"event\", \"wss://relay.test\", traceId, badEvent)\n\n    expect(q.snapshot).toHaveLength(0)\n  })\n\n  test(\"handleEvent broadcasts to all active queries\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb1 = makeRb(\"q1\")\n    const rb2 = makeRb(\"q2\")\n    const q1 = qm.query(rb1)\n    const q2 = qm.query(rb2)\n    q1.start()\n    q2.start()\n    await sleep(50)\n\n    const event = createEv(\"broadcast\", 1, 500)\n    qm.handleEvent(\"*\", event)\n\n    expect(q1.snapshot).toHaveLength(1)\n    expect(q2.snapshot).toHaveLength(1)\n  })\n\n  test(\"handleEvent only adds events matching query filters\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb1 = new RequestBuilder(\"kinds-1\")\n    rb1.withOptions({ groupingDelay: 0 })\n    rb1.withFilter().kinds([1])\n    const q1 = qm.query(rb1)\n    q1.start()\n    await sleep(50)\n\n    const rb2 = new RequestBuilder(\"kinds-2\")\n    rb2.withOptions({ groupingDelay: 0 })\n    rb2.withFilter().kinds([2])\n    const q2 = qm.query(rb2)\n    q2.start()\n    await sleep(50)\n\n    const evKind1 = createEv(\"k1\", 1, 500)\n    qm.handleEvent(\"*\", evKind1)\n\n    expect(q1.snapshot).toHaveLength(1)\n    expect(q2.snapshot).toHaveLength(0)\n  })\n\n  test(\"eose from connection triggers trace eose and closes non-streaming request\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = makeRb(\"eose-test\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    const trace = q.traces[0]\n    expect(trace.currentState).toBe(QueryTraceState.WAITING)\n\n    conn.emit(\"eose\", trace.id)\n    expect(trace.currentState).toBe(QueryTraceState.LOCAL_CLOSE)\n    expect(conn.closedRequests).toContain(trace.id)\n  })\n\n  test(\"eose from connection on streaming query does not close\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = new RequestBuilder(\"stream-eose\")\n    rb.withOptions({ groupingDelay: 0, leaveOpen: true })\n    rb.withFilter().kinds([1])\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    const trace = q.traces[0]\n    expect(trace.currentState).toBe(QueryTraceState.WAITING_STREAM)\n\n    conn.emit(\"eose\", trace.id)\n    expect(trace.currentState).toBe(QueryTraceState.EOSE)\n    expect(conn.closedRequests).not.toContain(trace.id)\n  })\n\n  test(\"closed from connection triggers trace remoteClosed\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = makeRb(\"closed-test\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    const trace = q.traces[0]\n    conn.emit(\"closed\", trace.id, \"subscription limit reached\")\n    expect(trace.currentState).toBe(QueryTraceState.REMOTE_CLOSE)\n  })\n\n  test(\"query end event cleans up pool and connection listeners\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = makeRb(\"cleanup-test\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    const traceId = q.traces[0].id\n    const poolListenersBefore = pool.listenerCount(\"event\")\n    const connEoseListenersBefore = conn.listenerCount(\"eose\")\n\n    q.closeQuery()\n\n    expect(pool.listenerCount(\"event\")).toBeLessThan(poolListenersBefore)\n    expect(conn.listenerCount(\"eose\")).toBeLessThan(connEoseListenersBefore)\n  })\n})\n\ndescribe(\"QueryManager — query dedup and lifecycle\", () => {\n  let pool: MockPool\n  let system: SystemInterface\n  let qm: QueryManager\n\n  beforeEach(() => {\n    pool = new MockPool()\n    system = makeSystem(pool)\n    qm = new QueryManager(system)\n  })\n\n  afterEach(() => {\n    qm.destroy()\n  })\n\n  test(\"second query with same id reuses existing Query and merges filters\", () => {\n    const rb1 = new RequestBuilder(\"shared\")\n    rb1.withFilter().kinds([1])\n    const rb2 = new RequestBuilder(\"shared\")\n    rb2.withFilter().kinds([2])\n\n    const q1 = qm.query(rb1)\n    const q2 = qm.query(rb2)\n    expect(q1).toBe(q2)\n  })\n\n  test(\"get() returns query by id\", () => {\n    const rb = makeRb(\"findme\")\n    qm.query(rb)\n    expect(qm.get(\"findme\")).toBeDefined()\n    expect(qm.get(\"nope\")).toBeUndefined()\n  })\n\n  test(\"iterator yields all active queries\", () => {\n    qm.query(makeRb(\"q1\"))\n    qm.query(makeRb(\"q2\"))\n    const ids = [...qm].map(([id]) => id)\n    expect(ids).toContain(\"q1\")\n    expect(ids).toContain(\"q2\")\n  })\n\n  test(\"destroy clears all queries and stops cleanup interval\", () => {\n    qm.query(makeRb(\"q1\"))\n    qm.query(makeRb(\"q2\"))\n    qm.destroy()\n    expect(qm.get(\"q1\")).toBeUndefined()\n    expect(qm.get(\"q2\")).toBeUndefined()\n  })\n\n  test(\"cleanup removes queries past cancel grace window\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = makeRb(\"cleanup-q\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    q.cancel()\n    expect(qm.get(\"cleanup-q\")).toBeDefined()\n\n    await sleep(2200)\n    expect(qm.get(\"cleanup-q\")).toBeUndefined()\n  })\n\n  test(\"cleanup times out stale traces\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = new RequestBuilder(\"timeout-q\")\n    rb.withOptions({ groupingDelay: 0, timeout: 500 })\n    rb.withFilter().kinds([1])\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    const trace = q.traces[0]\n    expect(trace.currentState).toBe(QueryTraceState.WAITING)\n\n    await sleep(1500)\n    expect(trace.currentState).toBe(QueryTraceState.TIMEOUT)\n  })\n})\n\ndescribe(\"QueryManager — connection race conditions\", () => {\n  let pool: MockPool\n  let system: SystemInterface\n  let qm: QueryManager\n\n  beforeEach(() => {\n    pool = new MockPool()\n    system = makeSystem(pool)\n    qm = new QueryManager(system)\n  })\n\n  afterEach(() => {\n    qm.destroy()\n  })\n\n  test(\"query to not-yet-open relay queues trace, sends after open\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", false)\n    pool.add(conn)\n\n    const rb = makeRb(\"pending-test\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(q.traces).toHaveLength(1)\n    expect(q.traces[0].currentState).toBe(QueryTraceState.QUEUED)\n    expect(conn.sentRequests).toHaveLength(0)\n\n    conn.open()\n    pool.emit(\"connected\", conn.address, false)\n    await sleep(10)\n\n    expect(conn.sentRequests.length).toBeGreaterThanOrEqual(1)\n    expect(q.traces[0].currentState).toBe(QueryTraceState.WAITING)\n  })\n\n  test(\"multiple pending relays all receive REQ after opening\", async () => {\n    const c1 = new MockConnection(\"wss://r1.test\", false)\n    const c2 = new MockConnection(\"wss://r2.test\", false)\n    pool.add(c1)\n    pool.add(c2)\n\n    const rb = makeRb(\"multi-pending\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(q.traces).toHaveLength(2)\n    expect(c1.sentRequests).toHaveLength(0)\n    expect(c2.sentRequests).toHaveLength(0)\n\n    c1.open()\n    pool.emit(\"connected\", c1.address, false)\n    await sleep(10)\n\n    c2.open()\n    pool.emit(\"connected\", c2.address, false)\n    await sleep(10)\n\n    expect(c1.sentRequests.length).toBeGreaterThanOrEqual(1)\n    expect(c2.sentRequests.length).toBeGreaterThanOrEqual(1)\n  })\n\n  test(\"disconnect drops pending traces for that connection\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", false)\n    pool.add(conn)\n\n    const rb = makeRb(\"disconnect-test\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    const trace = q.traces[0]\n    expect(trace.currentState).toBe(QueryTraceState.QUEUED)\n\n    pool.emit(\"disconnect\", conn.address, 1006)\n    expect(trace.currentState).toBe(QueryTraceState.DROP)\n  })\n\n  test(\"events arriving before eose are collected correctly\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = makeRb(\"stream-collect\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    const traceId = q.traces[0].id\n\n    pool.emit(\"event\", conn.address, traceId, createEv(\"e1\", 1, 100))\n    pool.emit(\"event\", conn.address, traceId, createEv(\"e2\", 1, 200))\n    pool.emit(\"event\", conn.address, traceId, createEv(\"e3\", 1, 300))\n\n    conn.emit(\"eose\", traceId)\n\n    expect(q.snapshot).toHaveLength(3)\n    expect(q.progress).toBe(1)\n  })\n\n  test(\"events arriving after eose on streaming query are still collected\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = new RequestBuilder(\"post-eose-stream\")\n    rb.withOptions({ groupingDelay: 0, leaveOpen: true })\n    rb.withFilter().kinds([1])\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    const traceId = q.traces[0].id\n\n    pool.emit(\"event\", conn.address, traceId, createEv(\"before\", 1, 100))\n    conn.emit(\"eose\", traceId)\n    pool.emit(\"event\", conn.address, traceId, createEv(\"after\", 1, 200))\n\n    expect(q.snapshot).toHaveLength(2)\n  })\n})\n\ndescribe(\"QueryManager — cache relay integration\", () => {\n  let pool: MockPool\n  let qm: QueryManager\n\n  afterEach(() => {\n    qm.destroy()\n  })\n\n  test(\"cache results are added to feed before relay results\", async () => {\n    pool = new MockPool()\n    const cachedEvent = createEv(\"cached\", 1, 100)\n    const cacheRelay = {\n      query: async () => [cachedEvent],\n      event: async () => {},\n      close: () => {},\n    }\n    const system = makeSystem(pool, { cacheRelay })\n    qm = new QueryManager(system)\n\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = makeRb(\"cache-test\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(q.snapshot).toContainEqual(cachedEvent)\n  })\n\n  test(\"skipCache=true bypasses cache relay\", async () => {\n    pool = new MockPool()\n    let cacheQueried = false\n    const cacheRelay = {\n      query: async () => {\n        cacheQueried = true\n        return []\n      },\n      event: async () => {},\n      close: () => {},\n    }\n    const system = makeSystem(pool, { cacheRelay })\n    qm = new QueryManager(system)\n\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = new RequestBuilder(\"skip-cache\")\n    rb.withOptions({ groupingDelay: 0, skipCache: true })\n    rb.withFilter().kinds([1])\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(cacheQueried).toBe(false)\n  })\n\n  test(\"satisfied id filters are removed after cache hit\", async () => {\n    pool = new MockPool()\n    const cachedEvent = createEv(\"target-id\", 1, 100)\n    const cacheRelay = {\n      query: async () => [cachedEvent],\n      event: async () => {},\n      close: () => {},\n    }\n    const system = makeSystem(pool, { cacheRelay })\n    qm = new QueryManager(system)\n\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = new RequestBuilder(\"satisfied-filter\")\n    rb.withOptions({ groupingDelay: 0 })\n    rb.withFilter().ids([\"target-id\"])\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(q.snapshot).toHaveLength(1)\n    expect(conn.sentRequests).toHaveLength(0)\n  })\n})\n\ndescribe(\"QueryManager — multi-relay event aggregation\", () => {\n  let pool: MockPool\n  let system: SystemInterface\n  let qm: QueryManager\n\n  beforeEach(() => {\n    pool = new MockPool()\n    system = makeSystem(pool)\n    qm = new QueryManager(system)\n  })\n\n  afterEach(() => {\n    qm.destroy()\n  })\n\n  test(\"same event from multiple relays is deduplicated in feed\", async () => {\n    const c1 = new MockConnection(\"wss://r1.test\", true)\n    const c2 = new MockConnection(\"wss://r2.test\", true)\n    pool.add(c1)\n    pool.add(c2)\n\n    const rb = makeRb(\"dedup-relay\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(q.traces).toHaveLength(2)\n    const t1 = q.traces.find(t => t.relay === \"wss://r1.test\")!\n    const t2 = q.traces.find(t => t.relay === \"wss://r2.test\")!\n\n    const sameEvent = createEv(\"same\", 1, 500)\n    pool.emit(\"event\", \"wss://r1.test\", t1.id, { ...sameEvent })\n    pool.emit(\"event\", \"wss://r2.test\", t2.id, { ...sameEvent })\n\n    expect(q.snapshot).toHaveLength(1)\n  })\n\n  test(\"different events from multiple relays are all collected\", async () => {\n    const c1 = new MockConnection(\"wss://r1.test\", true)\n    const c2 = new MockConnection(\"wss://r2.test\", true)\n    pool.add(c1)\n    pool.add(c2)\n\n    const rb = makeRb(\"multi-events\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    const t1 = q.traces.find(t => t.relay === \"wss://r1.test\")!\n    const t2 = q.traces.find(t => t.relay === \"wss://r2.test\")!\n\n    pool.emit(\"event\", \"wss://r1.test\", t1.id, createEv(\"from-r1\", 1, 100))\n    pool.emit(\"event\", \"wss://r2.test\", t2.id, createEv(\"from-r2\", 1, 200))\n\n    expect(q.snapshot).toHaveLength(2)\n  })\n\n  test(\"eose from all relays results in query progress=1\", async () => {\n    const c1 = new MockConnection(\"wss://r1.test\", true)\n    const c2 = new MockConnection(\"wss://r2.test\", true)\n    pool.add(c1)\n    pool.add(c2)\n\n    const rb = makeRb(\"eose-all\")\n    const q = qm.query(rb)\n    let eoseFired = false\n    q.on(\"eose\", () => {\n      eoseFired = true\n    })\n    q.start()\n    await sleep(50)\n\n    expect(q.traces).toHaveLength(2)\n    for (const trace of q.traces) {\n      c1.emit(\"eose\", trace.id)\n      c2.emit(\"eose\", trace.id)\n    }\n\n    expect(q.progress).toBe(1)\n    expect(eoseFired).toBe(true)\n  })\n})\n\ndescribe(\"QueryManager — canSendQuery validation\", () => {\n  let pool: MockPool\n  let system: SystemInterface\n  let qm: QueryManager\n\n  beforeEach(() => {\n    pool = new MockPool()\n    system = makeSystem(pool)\n    qm = new QueryManager(system)\n  })\n\n  afterEach(() => {\n    qm.destroy()\n  })\n\n  test(\"down connection is skipped\", async () => {\n    const conn = new MockConnection(\"wss://down.test\", true)\n    conn.markDown()\n    pool.add(conn)\n\n    const rb = makeRb(\"down-test\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(q.traces).toHaveLength(0)\n    expect(conn.sentRequests).toHaveLength(0)\n  })\n\n  test(\"ephemeral connection is skipped for broadcast\", async () => {\n    const conn = new MockConnection(\"wss://ephemeral.test\", true)\n    conn.ephemeral = true\n    pool.add(conn)\n\n    const rb = makeRb(\"ephemeral-test\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(q.traces).toHaveLength(0)\n  })\n\n  test(\"search query skipped on relay without NIP-50\", async () => {\n    const conn = new MockConnection(\"wss://no-search.test\", true)\n    pool.add(conn)\n\n    const rb = new RequestBuilder(\"search-no-nip50\")\n    rb.withOptions({ groupingDelay: 0 })\n    rb.withFilter().kinds([1]).search(\"test\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(conn.sentRequests).toHaveLength(0)\n  })\n\n  test(\"search query sent to relay with NIP-50\", async () => {\n    const conn = new MockConnection(\"wss://search.test\", true)\n    conn.info = { supported_nips: [50] } as any\n    pool.add(conn)\n\n    const rb = new RequestBuilder(\"search-nip50\")\n    rb.withOptions({ groupingDelay: 0 })\n    rb.withFilter().kinds([1]).search(\"test\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(conn.sentRequests).toHaveLength(1)\n  })\n\n  test(\"cancelled query past grace window is cleaned up and not reusable\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = makeRb(\"cancel-test\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    q.cancel()\n    expect(q.canRemove()).toBe(false)\n\n    await sleep(2200)\n    expect(q.canRemove()).toBe(true)\n    expect(qm.get(\"cancel-test\")).toBeUndefined()\n  })\n})\n\ndescribe(\"QueryTrace state machine\", () => {\n  test(\"NEW -> QUEUED -> WAITING -> EOSE\", () => {\n    const t = new QueryTrace(\"wss://r.test\", [], \"c1\", false)\n    expect(t.currentState).toBe(QueryTraceState.NEW)\n    expect(t.finished).toBe(false)\n\n    t.queued()\n    expect(t.currentState).toBe(QueryTraceState.QUEUED)\n    expect(t.finished).toBe(false)\n\n    t.sent()\n    expect(t.currentState).toBe(QueryTraceState.WAITING)\n    expect(t.finished).toBe(false)\n\n    t.eose()\n    expect(t.currentState).toBe(QueryTraceState.EOSE)\n    expect(t.finished).toBe(true)\n  })\n\n  test(\"leaveOpen trace transitions to WAITING_STREAM on sent()\", () => {\n    const t = new QueryTrace(\"wss://r.test\", [], \"c1\", true)\n    t.queued()\n    t.sent()\n    expect(t.currentState).toBe(QueryTraceState.WAITING_STREAM)\n    expect(t.finished).toBe(false)\n  })\n\n  test(\"all terminal states are considered finished\", () => {\n    const terminals = [\"eose\", \"timeout\", \"drop\", \"remoteClosed\", \"close\"] as const\n    for (const method of terminals) {\n      const t = new QueryTrace(\"wss://r.test\", [], \"c1\", false)\n      t.queued()\n      ;(t[method] as () => void)()\n      expect(t.finished).toBe(true)\n    }\n  })\n\n  test(\"same-state transition does not emit stateChange\", () => {\n    const t = new QueryTrace(\"wss://r.test\", [], \"c1\", false)\n    const changes: string[] = []\n    t.on(\"stateChange\", e => changes.push(e.state))\n\n    t.queued()\n    t.queued()\n    expect(changes).toHaveLength(1)\n  })\n\n  test(\"stateChange event includes correct metadata\", () => {\n    const t = new QueryTrace(\"wss://relay.test\", [{ kinds: [1] }], \"conn-id\", false)\n    let event: any\n    t.on(\"stateChange\", e => {\n      event = e\n    })\n\n    t.queued()\n    expect(event.relay).toBe(\"wss://relay.test\")\n    expect(event.connId).toBe(\"conn-id\")\n    expect(event.state).toBe(QueryTraceState.QUEUED)\n    expect(event.filters).toEqual([{ kinds: [1] }])\n    expect(event.id).toBe(t.id)\n    expect(typeof event.timestamp).toBe(\"number\")\n  })\n\n  test(\"SYNC_WAITING and SYNC_FALLBACK states\", () => {\n    const t = new QueryTrace(\"wss://r.test\", [], \"c1\", false)\n    t.queued()\n    t.sentSync()\n    expect(t.currentState).toBe(QueryTraceState.SYNC_WAITING)\n    expect(t.finished).toBe(false)\n\n    t.syncFallback()\n    expect(t.currentState).toBe(QueryTraceState.SYNC_FALLBACK)\n    expect(t.finished).toBe(false)\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/query-manager-race.test.ts",
    "content": "/**\n * Tests for race conditions in QueryManager when relays are not yet connected\n * on page load.\n *\n * The bug: when useRequestBuilder fires on mount, relays may still be in\n * CONNECTING state (isOpen=false, isDown=false). The broadcast path in\n * #sendToRelays iterates the pool and calls sendTrace for each connection.\n * sendTrace only queues into #pendingTraces when maxSubscriptions is hit —\n * not when the socket is still opening. The REQ goes into Connection.PendingRaw\n * at the wire level, but if the query is cancelled/replaced before the socket\n * opens, the request is silently lost.\n */\n\nimport { afterEach, beforeEach, describe, expect, test } from \"bun:test\"\nimport type { CachedTable } from \"@snort/shared\"\nimport { EventEmitter } from \"eventemitter3\"\nimport { SocialGraph } from \"nostr-social-graph\"\nimport type { RelayInfoDocument, SystemInterface } from \"../src\"\nimport type { CachedMetadata, UsersFollows } from \"../src/cache\"\nimport type { CacheRelay } from \"../src/cache-relay\"\nimport type { RelaySettings } from \"../src/connection\"\nimport type { ConnectionPool, ConnectionPoolEvents, ConnectionType, ConnectionTypeEvents } from \"../src/connection-pool\"\nimport type { NostrEvent, OkResponse, ReqCommand, ReqFilter, TaggedNostrEvent } from \"../src/nostr\"\nimport type { RelayMetadataLoader } from \"../src/outbox\"\nimport type { ProfileLoaderService } from \"../src/profile-cache\"\nimport { QueryTraceState } from \"../src/query\"\nimport { QueryManager } from \"../src/query-manager\"\nimport { DefaultOptimizer } from \"../src/query-optimizer\"\nimport { RequestBuilder } from \"../src/request-builder\"\nimport type { RequestRouter } from \"../src/request-router\"\nimport type { SystemConfig, SystemSnapshot } from \"../src/system\"\nimport type { TraceTimeline } from \"../src/trace-timeline\"\n\n// ---------------------------------------------------------------------------\n// Minimal mock connection — starts in CONNECTING state, open on demand\n// ---------------------------------------------------------------------------\n\nclass MockConnection extends EventEmitter<ConnectionTypeEvents> implements ConnectionType {\n  readonly id: string\n  readonly address: string\n  info: RelayInfoDocument | undefined = undefined\n  settings: RelaySettings = { read: true, write: true }\n  ephemeral = false\n\n  #open = false\n  #down = false\n\n  /** REQ messages actually sent on the wire */\n  sentRequests: Array<ReqCommand> = []\n\n  /** REQ messages queued because socket was not open */\n  pendingRequests: Array<ReqCommand> = []\n\n  constructor(address: string) {\n    super()\n    this.id = crypto.randomUUID()\n    this.address = address\n  }\n\n  get isOpen() {\n    return this.#open\n  }\n\n  get isDown() {\n    return this.#down\n  }\n\n  get activeSubscriptions() {\n    return this.sentRequests.filter(r => r[0] === \"REQ\").length\n  }\n\n  get maxSubscriptions() {\n    return 20\n  }\n\n  async connect() {}\n  close() {}\n  async publish(_ev: NostrEvent): Promise<OkResponse> {\n    return { ok: true, id: \"\", message: \"\", relay: this.address, event: _ev }\n  }\n\n  request(req: ReqCommand, cbSent?: () => void) {\n    if (!this.#open) {\n      // Simulate Connection.PendingRaw behaviour\n      this.pendingRequests.push(req)\n      return\n    }\n    this.sentRequests.push(req)\n    cbSent?.()\n  }\n\n  closeRequest(_id: string) {}\n  sendRaw(_obj: object) {}\n\n  /** Simulate the WebSocket opening */\n  open() {\n    this.#open = true\n    // Drain pending queue (mirrors Connection.#sendPendingRaw / #onOpen)\n    for (const req of this.pendingRequests) {\n      this.sentRequests.push(req)\n    }\n    this.pendingRequests = []\n    this.emit(\"connected\", false)\n    this.emit(\"change\")\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Minimal mock pool\n// ---------------------------------------------------------------------------\n\nclass MockPool extends EventEmitter<ConnectionPoolEvents> implements ConnectionPool {\n  #connections = new Map<string, MockConnection>()\n\n  add(conn: MockConnection) {\n    this.#connections.set(conn.address, conn)\n  }\n\n  getConnection(id: string): ConnectionType | undefined {\n    return this.#connections.get(id)\n  }\n\n  async connect(address: string, _options: RelaySettings, _ephemeral: boolean) {\n    return this.#connections.get(address)\n  }\n\n  disconnect(_address: string) {}\n\n  async broadcast(_ev: NostrEvent): Promise<OkResponse[]> {\n    return []\n  }\n\n  async broadcastTo(_address: string, _ev: NostrEvent): Promise<OkResponse> {\n    return { ok: true, id: \"\", message: \"\", relay: _address, event: _ev }\n  }\n\n  *[Symbol.iterator]() {\n    for (const kv of this.#connections) {\n      yield kv\n    }\n  }\n\n  /** Simulate pool.on('connected') being fired when a connection opens */\n  connectionOpened(conn: MockConnection) {\n    this.emit(\"connected\", conn.address, false)\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Minimal mock system\n// ---------------------------------------------------------------------------\n\nfunction makeSystem(pool: MockPool): SystemInterface {\n  const config: SystemConfig = {\n    relays: { preload: async () => {} } as unknown as CachedTable<any>,\n    profiles: {} as CachedTable<CachedMetadata>,\n    contactLists: {} as CachedTable<UsersFollows>,\n    optimizer: DefaultOptimizer,\n    checkSigs: false,\n    automaticOutboxModel: false,\n    buildFollowGraph: false,\n    fallbackSync: \"since\",\n    socialGraphInstance: new SocialGraph(\"00\".repeat(32)),\n    disableSyncModule: true,\n  }\n\n  return {\n    pool,\n    config,\n    cacheRelay: undefined,\n    requestRouter: undefined,\n    checkSigs: false,\n    optimizer: DefaultOptimizer,\n    relayLoader: { TrackKeys: () => {} } as unknown as RelayMetadataLoader,\n    profileLoader: {} as ProfileLoaderService,\n    userFollowsCache: {} as CachedTable<UsersFollows>,\n    traceTimeline: undefined,\n    async Init() {},\n    GetQuery: () => undefined,\n    Query: () => {\n      throw new Error(\"not used\")\n    },\n    Fetch: () => Promise.resolve([]),\n    async ConnectToRelay() {},\n    DisconnectRelay() {},\n    HandleEvent() {},\n    async BroadcastEvent() {\n      return []\n    },\n    async WriteOnceToRelay() {\n      return { ok: true, id: \"\", message: \"\", relay: \"\" }\n    },\n    takeSnapshot(): SystemSnapshot {\n      return { queries: [] }\n    },\n    emit: () => false,\n    on: () => ({}) as any,\n    off: () => ({}) as any,\n    once: () => ({}) as any,\n    removeAllListeners: () => ({}) as any,\n    listeners: () => [],\n    listenerCount: () => 0,\n    eventNames: () => [],\n    addListener: () => ({}) as any,\n    removeListener: () => ({}) as any,\n  } as unknown as SystemInterface\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction sleep(ms: number) {\n  return new Promise(resolve => setTimeout(resolve, ms))\n}\n\nfunction makeRb(id: string) {\n  const rb = new RequestBuilder(id)\n  rb.withOptions({ groupingDelay: 0, disableSyncModule: true } as any)\n  rb.withFilter().kinds([1]).limit(10)\n  return rb\n}\n\n// ---------------------------------------------------------------------------\n// Tests\n// ---------------------------------------------------------------------------\n\ndescribe(\"QueryManager — relay connection race conditions\", () => {\n  let pool: MockPool\n  let system: SystemInterface\n  let qm: QueryManager\n\n  beforeEach(() => {\n    pool = new MockPool()\n    system = makeSystem(pool)\n    qm = new QueryManager(system)\n  })\n\n  afterEach(() => {\n    qm.destroy()\n  })\n\n  /**\n   * RACE CONDITION 1\n   *\n   * A relay is in the pool but still connecting (isOpen=false).\n   * When a query is issued the REQ should eventually reach the relay.\n   * With the bug, the trace stays in QUEUED state because the connection\n   * is not open — the wire-level PendingRaw queue flushes, but the trace\n   * `cbSent` is never called, so the trace never transitions to WAITING.\n   * Once the connection opens, `#retryPendingTraces` is not called for\n   * this trace because it was never put into `#pendingTraces`.\n   */\n  test(\"REQ is sent to relay that was still connecting when query was created\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\")\n    pool.add(conn)\n    // conn is NOT open yet — simulates page load before WebSocket handshake\n\n    const rb = makeRb(\"test-connecting\")\n    const q = qm.query(rb)\n    q.start()\n\n    // Give the grouping timer a tick to fire\n    await sleep(50)\n\n    // At this point the relay is still connecting. The REQ should be queued.\n    // Before the fix: trace exists but stays QUEUED; sendTrace never retried.\n    const tracesBefore = q.traces\n    expect(tracesBefore.length).toBe(1)\n    expect(tracesBefore[0].currentState).toBe(QueryTraceState.QUEUED)\n\n    // No REQ should have been sent on the wire yet\n    expect(conn.sentRequests.length).toBe(0)\n\n    // Now the relay connects\n    conn.open()\n    pool.connectionOpened(conn)\n\n    // Allow microtasks / event callbacks to process\n    await sleep(10)\n\n    // After fix: the trace should have been retried and sent\n    expect(conn.sentRequests.length).toBeGreaterThanOrEqual(1)\n    expect(conn.sentRequests[0][0]).toBe(\"REQ\")\n    expect(q.traces[0].currentState).toBe(QueryTraceState.WAITING)\n  })\n\n  /**\n   * RACE CONDITION 2\n   *\n   * Multiple relays in the pool, all still connecting.\n   * Query is issued before any of them are open.\n   * After they all open, every relay should have received the REQ.\n   */\n  test(\"REQ is sent to all relays that were still connecting\", async () => {\n    const conn1 = new MockConnection(\"wss://relay1.test\")\n    const conn2 = new MockConnection(\"wss://relay2.test\")\n    pool.add(conn1)\n    pool.add(conn2)\n\n    const rb = makeRb(\"test-multi-connecting\")\n    const q = qm.query(rb)\n    q.start()\n\n    await sleep(50)\n\n    // Both relays still connecting — 2 traces, both QUEUED\n    expect(q.traces.length).toBe(2)\n    expect(q.traces.every(t => t.currentState === QueryTraceState.QUEUED)).toBe(true)\n    expect(conn1.sentRequests.length).toBe(0)\n    expect(conn2.sentRequests.length).toBe(0)\n\n    // Open both relays\n    conn1.open()\n    pool.connectionOpened(conn1)\n    await sleep(10)\n\n    conn2.open()\n    pool.connectionOpened(conn2)\n    await sleep(10)\n\n    // After fix: both connections received the REQ\n    expect(conn1.sentRequests.length).toBeGreaterThanOrEqual(1)\n    expect(conn2.sentRequests.length).toBeGreaterThanOrEqual(1)\n    expect(q.traces.every(t => t.currentState === QueryTraceState.WAITING)).toBe(true)\n  })\n\n  /**\n   * RACE CONDITION 3\n   *\n   * Relay is already open when the query is issued (happy path).\n   * Ensure the normal open-relay flow still works after the fix.\n   */\n  test(\"REQ is sent immediately when relay is already open\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\")\n    conn.open() // already open before query\n    pool.add(conn)\n\n    const rb = makeRb(\"test-already-open\")\n    const q = qm.query(rb)\n    q.start()\n\n    await sleep(50)\n\n    expect(conn.sentRequests.length).toBeGreaterThanOrEqual(1)\n    expect(conn.sentRequests[0][0]).toBe(\"REQ\")\n    expect(q.traces[0].currentState).toBe(QueryTraceState.WAITING)\n  })\n\n  /**\n   * KNOWN LIMITATION (not fixed by Option A):\n   *\n   * Relay is added to the pool AFTER the query is already running AND\n   * the pool was empty when #sendToRelays ran — so no trace was ever\n   * created for this connection. There is nothing in #pendingTraces to\n   * retry, so the query is silently lost for this relay.\n   *\n   * A future Option C fix (\"re-query on connect\") would address this by\n   * re-running active queries against newly-connected relays.\n   */\n  test.skip(\"pending trace is dispatched when relay is added after query started (known limitation)\", async () => {\n    // Start with no connections\n    const rb = makeRb(\"test-new-relay\")\n    const q = qm.query(rb)\n    q.start()\n\n    await sleep(50)\n\n    // No traces yet — no connections in pool\n    expect(q.traces.length).toBe(0)\n\n    // Now a relay is added and connects\n    const conn = new MockConnection(\"wss://relay-late.test\")\n    pool.add(conn)\n\n    conn.open()\n    pool.connectionOpened(conn)\n\n    await sleep(10)\n\n    // Would require Option C to pass\n    expect(conn.sentRequests.length).toBeGreaterThanOrEqual(1)\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/query-system-edge-cases.test.ts",
    "content": "/**\n * Edge-case tests for the query system:\n *   - NoteCollection / KeyedReplaceableNoteStore\n *   - trimFilters\n *   - eventMatchesFilter / isRequestSatisfied\n *   - Query lifecycle (cancel/uncancel, groupingDelay, progress, addRequest dedup)\n *   - QueryManager (dedup, destroy cleanup, canSendQuery branches)\n */\n\nimport { afterEach, beforeEach, describe, expect, mock, test } from \"bun:test\"\nimport type { CachedTable } from \"@snort/shared\"\nimport { EventEmitter } from \"eventemitter3\"\nimport { SocialGraph } from \"nostr-social-graph\"\nimport type { RelayInfoDocument } from \"../src\"\nimport type { CachedMetadata, UsersFollows } from \"../src/cache\"\nimport type { RelaySettings } from \"../src/connection\"\nimport type { ConnectionPool, ConnectionPoolEvents, ConnectionType, ConnectionTypeEvents } from \"../src/connection-pool\"\nimport type { NostrEvent, OkResponse, ReqCommand, TaggedNostrEvent } from \"../src/nostr\"\nimport { KeyedReplaceableNoteStore, NoteCollection } from \"../src/note-collection\"\nimport type { RelayMetadataLoader } from \"../src/outbox\"\nimport type { ProfileLoaderService } from \"../src/profile-cache\"\nimport { Query, QueryTraceState } from \"../src/query\"\nimport { QueryManager } from \"../src/query-manager\"\nimport { DefaultOptimizer } from \"../src/query-optimizer\"\nimport { RequestBuilder } from \"../src/request-builder\"\nimport { eventMatchesFilter, isRequestSatisfied } from \"../src/request-matcher\"\nimport { trimFilters } from \"../src/request-trim\"\nimport type { SystemConfig, SystemInterface } from \"../src/system\"\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction ev(id: string, kind: number, created_at: number, pubkey = \"aa\", tags: string[][] = []): TaggedNostrEvent {\n  return { id, kind, created_at, pubkey, tags, content: \"\", sig: \"\", relays: [] }\n}\n\nfunction sleep(ms: number) {\n  return new Promise(r => setTimeout(r, ms))\n}\n\nfunction makeRb(id: string, groupingDelay = 0) {\n  const rb = new RequestBuilder(id)\n  rb.withOptions({ groupingDelay })\n  rb.withFilter().kinds([1]).limit(10)\n  return rb\n}\n\n// ---------------------------------------------------------------------------\n// Minimal mock connection\n// ---------------------------------------------------------------------------\n\nclass MockConnection extends EventEmitter<ConnectionTypeEvents> implements ConnectionType {\n  readonly id = crypto.randomUUID()\n  readonly address: string\n  info: RelayInfoDocument | undefined = undefined\n  settings: RelaySettings = { read: true, write: true }\n  ephemeral = false\n  #open: boolean\n  #down = false\n  sentRequests: Array<ReqCommand> = []\n\n  constructor(address: string, open = true) {\n    super()\n    this.address = address\n    this.#open = open\n  }\n\n  get isOpen() {\n    return this.#open\n  }\n  get isDown() {\n    return this.#down\n  }\n  get activeSubscriptions() {\n    return this.sentRequests.filter(r => r[0] === \"REQ\").length\n  }\n  get maxSubscriptions() {\n    return 20\n  }\n\n  open() {\n    this.#open = true\n    this.emit(\"connected\", false)\n    this.emit(\"change\")\n  }\n\n  markDown() {\n    this.#down = true\n  }\n\n  async connect() {}\n  close() {}\n  async publish(ev: NostrEvent): Promise<OkResponse> {\n    return { ok: true, id: \"\", relay: this.address, event: ev }\n  }\n\n  request(req: ReqCommand, cbSent?: () => void) {\n    if (this.#open) {\n      this.sentRequests.push(req)\n      cbSent?.()\n    }\n  }\n\n  closeRequest(_id: string) {}\n  sendRaw(_obj: object) {}\n}\n\n// ---------------------------------------------------------------------------\n// Minimal mock pool\n// ---------------------------------------------------------------------------\n\nclass MockPool extends EventEmitter<ConnectionPoolEvents> implements ConnectionPool {\n  #conns = new Map<string, MockConnection>()\n\n  add(c: MockConnection) {\n    this.#conns.set(c.address, c)\n  }\n\n  getConnection(id: string) {\n    return this.#conns.get(id)\n  }\n\n  async connect(address: string) {\n    return this.#conns.get(address)\n  }\n  disconnect(_a: string) {}\n  async broadcast(): Promise<OkResponse[]> {\n    return []\n  }\n  async broadcastTo(_a: string, ev: NostrEvent): Promise<OkResponse> {\n    return { ok: true, id: \"\", relay: _a, event: ev }\n  }\n\n  fireConnected(conn: MockConnection) {\n    this.emit(\"connected\", conn.address, false)\n  }\n\n  *[Symbol.iterator]() {\n    yield* this.#conns\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Mock system factory\n// ---------------------------------------------------------------------------\n\nfunction makeSystem(pool: MockPool): SystemInterface {\n  const config: SystemConfig = {\n    relays: { preload: async () => {} } as unknown as CachedTable<any>,\n    profiles: {} as CachedTable<CachedMetadata>,\n    contactLists: {} as CachedTable<UsersFollows>,\n    optimizer: DefaultOptimizer,\n    checkSigs: false,\n    automaticOutboxModel: false,\n    buildFollowGraph: false,\n    fallbackSync: \"since\",\n    socialGraphInstance: new SocialGraph(\"00\".repeat(32)),\n    disableSyncModule: true,\n  }\n  return {\n    pool,\n    config,\n    cacheRelay: undefined,\n    requestRouter: undefined,\n    checkSigs: false,\n    optimizer: DefaultOptimizer,\n    relayLoader: { TrackKeys: () => {} } as unknown as RelayMetadataLoader,\n    profileLoader: {} as ProfileLoaderService,\n    userFollowsCache: {} as CachedTable<UsersFollows>,\n    traceTimeline: undefined,\n    async Init() {},\n    GetQuery: () => undefined,\n    Query: () => {\n      throw new Error(\"not used\")\n    },\n    Fetch: () => Promise.resolve([]),\n    async ConnectToRelay() {},\n    DisconnectRelay() {},\n    HandleEvent() {},\n    async BroadcastEvent() {\n      return []\n    },\n    async WriteOnceToRelay() {\n      return { ok: true, id: \"\", relay: \"\", event: {} as NostrEvent }\n    },\n    emit: () => false,\n    on: () => ({}) as any,\n    off: () => ({}) as any,\n    once: () => ({}) as any,\n    removeAllListeners: () => ({}) as any,\n    listeners: () => [],\n    listenerCount: () => 0,\n    eventNames: () => [],\n    addListener: () => ({}) as any,\n    removeListener: () => ({}) as any,\n  } as unknown as SystemInterface\n}\n\n// ===========================================================================\n// 1. NoteCollection / KeyedReplaceableNoteStore\n// ===========================================================================\n\ndescribe(\"NoteCollection\", () => {\n  describe(\"kind-based keying\", () => {\n    test(\"regular events (kind 1) are stored by id — two different events coexist\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 1, 100))\n      c.add(ev(\"b\", 1, 100))\n      expect(c.snapshot).toHaveLength(2)\n    })\n\n    test(\"replaceable kind 0 — newer replaces older\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"old\", 0, 100, \"alice\"))\n      c.add(ev(\"new\", 0, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(1)\n      expect(c.snapshot[0].id).toBe(\"new\")\n    })\n\n    test(\"replaceable kind 0 — older does NOT replace newer\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"new\", 0, 200, \"alice\"))\n      c.add(ev(\"old\", 0, 100, \"alice\"))\n      expect(c.snapshot).toHaveLength(1)\n      expect(c.snapshot[0].id).toBe(\"new\")\n    })\n\n    test(\"replaceable kind 0 — same-timestamp: first event wins\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"first\", 0, 100, \"alice\"))\n      c.add(ev(\"second\", 0, 100, \"alice\"))\n      expect(c.snapshot[0].id).toBe(\"first\")\n    })\n\n    test(\"replaceable kind 3 — different pubkeys stored separately\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 3, 100, \"alice\"))\n      c.add(ev(\"b\", 3, 100, \"bob\"))\n      expect(c.snapshot).toHaveLength(2)\n    })\n\n    test(\"legacy replaceable kind 41 — treated as replaceable\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"old\", 41, 100, \"alice\"))\n      c.add(ev(\"new\", 41, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(1)\n      expect(c.snapshot[0].id).toBe(\"new\")\n    })\n\n    test(\"addressable kind 30000 — keyed by kind:pubkey:d-tag\", () => {\n      const c = new NoteCollection()\n      const e1 = ev(\"a\", 30000, 100, \"alice\", [[\"d\", \"my-article\"]])\n      const e2 = ev(\"b\", 30000, 200, \"alice\", [[\"d\", \"my-article\"]])\n      c.add(e1)\n      c.add(e2)\n      expect(c.snapshot).toHaveLength(1)\n      expect(c.snapshot[0].id).toBe(\"b\")\n    })\n\n    test(\"addressable kind 30000 — different d-tags stored separately\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 30000, 100, \"alice\", [[\"d\", \"article-1\"]]))\n      c.add(ev(\"b\", 30000, 100, \"alice\", [[\"d\", \"article-2\"]]))\n      expect(c.snapshot).toHaveLength(2)\n    })\n\n    test(\"kind boundary: kind 29999 is Regular (stored by id)\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 29999, 100, \"alice\"))\n      c.add(ev(\"b\", 29999, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(2)\n    })\n\n    test(\"kind boundary: kind 30000 is Addressable (dedups by kind:pubkey:d)\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 30000, 100, \"alice\", [[\"d\", \"x\"]]))\n      c.add(ev(\"b\", 30000, 200, \"alice\", [[\"d\", \"x\"]]))\n      expect(c.snapshot).toHaveLength(1)\n    })\n\n    test(\"kind boundary: kind 9999 is Regular\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 9999, 100, \"alice\"))\n      c.add(ev(\"b\", 9999, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(2)\n    })\n\n    test(\"kind boundary: kind 10000 is Replaceable\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 10000, 100, \"alice\"))\n      c.add(ev(\"b\", 10000, 200, \"alice\"))\n      expect(c.snapshot).toHaveLength(1)\n      expect(c.snapshot[0].id).toBe(\"b\")\n    })\n\n    test('addressable event missing d-tag — key is \"kind:pubkey:undefined\", two missing-d events from same pubkey+kind merge', () => {\n      const c = new NoteCollection()\n      // No d tag — key will be \"30000:alice:undefined\"\n      c.add(ev(\"a\", 30000, 100, \"alice\"))\n      c.add(ev(\"b\", 30000, 200, \"alice\"))\n      // Both share the \"undefined\" d-tag key, so the newer one wins\n      expect(c.snapshot).toHaveLength(1)\n      expect(c.snapshot[0].id).toBe(\"b\")\n    })\n  })\n\n  describe(\"relay merging on replacement\", () => {\n    test(\"replacing event merges relay lists from old into new\", () => {\n      const c = new NoteCollection()\n      const old = { ...ev(\"old\", 0, 100, \"alice\"), relays: [\"wss://r1.test\"] }\n      const newer = { ...ev(\"new\", 0, 200, \"alice\"), relays: [\"wss://r2.test\"] }\n      c.add(old)\n      c.add(newer)\n      // The stored event should carry both relays\n      expect(c.snapshot[0].relays).toContain(\"wss://r1.test\")\n      expect(c.snapshot[0].relays).toContain(\"wss://r2.test\")\n    })\n  })\n\n  describe(\"event with created_at === 0\", () => {\n    test(\"is never stored (strict > 0 check)\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"zero\", 1, 0))\n      expect(c.snapshot).toHaveLength(0)\n    })\n  })\n\n  describe(\"add() return value\", () => {\n    test(\"returns 1 when event is added\", () => {\n      const c = new NoteCollection()\n      expect(c.add(ev(\"a\", 1, 100))).toBe(1)\n    })\n\n    test(\"returns 0 when event is a duplicate (same id)\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 1, 100))\n      expect(c.add(ev(\"a\", 1, 100))).toBe(0)\n    })\n\n    test(\"returns 0 when older replaceable event does not replace existing\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"new\", 0, 200, \"alice\"))\n      expect(c.add(ev(\"old\", 0, 100, \"alice\"))).toBe(0)\n    })\n  })\n\n  describe(\"snapshot laziness\", () => {\n    test(\"snapshot is invalidated after add and recomputed on next read\", () => {\n      const c = new NoteCollection()\n      const snap1 = c.snapshot // initial: []\n      c.add(ev(\"a\", 1, 100))\n      const snap2 = c.snapshot\n      // snap1 should still be empty; snap2 has the event\n      expect(snap1).toHaveLength(0)\n      expect(snap2).toHaveLength(1)\n    })\n\n    test(\"takeSnapshot() is always fresh, independent of cached snapshot\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 1, 100))\n      const cached = c.snapshot\n      c.add(ev(\"b\", 1, 200))\n      // cached is stale (still just 'a') — snapshot gets recomputed\n      const fresh = c.takeSnapshot()\n      expect(fresh).toHaveLength(2)\n      // now access snapshot again — should also reflect both\n      expect(c.snapshot).toHaveLength(2)\n    })\n  })\n\n  describe(\"clear()\", () => {\n    test(\"snapshot is empty after clear\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 1, 100))\n      c.clear()\n      expect(c.snapshot).toHaveLength(0)\n    })\n\n    test(\"new events can be added after clear\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 1, 100))\n      c.clear()\n      c.add(ev(\"b\", 1, 200))\n      expect(c.snapshot).toHaveLength(1)\n      expect(c.snapshot[0].id).toBe(\"b\")\n    })\n\n    test(\"clear() emits event immediately with empty array\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 1, 100))\n      const emissions: Array<TaggedNostrEvent[]> = []\n      c.on(\"event\", evs => emissions.push(evs))\n      c.clear()\n      expect(emissions).toHaveLength(1)\n      expect(emissions[0]).toHaveLength(0)\n    })\n\n    test(\"clear() cancels any pending buffered emit\", async () => {\n      const c = new NoteCollection()\n      const emissions: Array<TaggedNostrEvent[]> = []\n      c.on(\"event\", evs => emissions.push(evs))\n\n      c.add(ev(\"a\", 1, 100)) // schedules 300ms timer, buffers 'a'\n      c.clear() // should cancel timer and emit [] immediately\n\n      await sleep(400) // wait past the 300ms emit interval\n\n      // Should have exactly one emission from clear() — the buffered 'a' add\n      // must NOT fire separately after clear()\n      expect(emissions).toHaveLength(1)\n      expect(emissions[0]).toHaveLength(0)\n    })\n\n    test(\"events added after clear() emit correctly\", async () => {\n      const c = new NoteCollection()\n      const emissions: Array<TaggedNostrEvent[]> = []\n      c.on(\"event\", evs => emissions.push(evs))\n\n      c.clear() // clear an already-empty store\n      c.add(ev(\"a\", 1, 100))\n\n      await sleep(400)\n\n      // The clear() emits [], then the add should emit normally\n      expect(emissions).toHaveLength(2)\n      expect(emissions[0]).toHaveLength(0) // from clear()\n      expect(emissions[1][0].id).toBe(\"a\") // from add()\n    })\n  })\n\n  describe(\"emission\", () => {\n    test(\"add() emits event after 300ms interval\", async () => {\n      const c = new NoteCollection()\n      const emissions: Array<TaggedNostrEvent[]> = []\n      c.on(\"event\", evs => emissions.push(evs))\n\n      c.add(ev(\"a\", 1, 100))\n      expect(emissions).toHaveLength(0) // not yet\n\n      await sleep(400)\n      expect(emissions).toHaveLength(1)\n      expect(emissions[0][0].id).toBe(\"a\")\n    })\n\n    test(\"multiple adds within the interval are batched into one emission\", async () => {\n      const c = new NoteCollection()\n      const emissions: Array<TaggedNostrEvent[]> = []\n      c.on(\"event\", evs => emissions.push(evs))\n\n      c.add(ev(\"a\", 1, 100))\n      c.add(ev(\"b\", 1, 200))\n      c.add(ev(\"c\", 1, 300))\n\n      await sleep(400)\n      expect(emissions).toHaveLength(1)\n      expect(emissions[0]).toHaveLength(3)\n    })\n\n    test(\"duplicate events do not emit\", async () => {\n      const c = new NoteCollection()\n      const emissions: Array<TaggedNostrEvent[]> = []\n      c.on(\"event\", evs => emissions.push(evs))\n\n      c.add(ev(\"a\", 1, 100))\n      await sleep(400)\n      emissions.length = 0 // reset\n\n      c.add(ev(\"a\", 1, 100)) // exact duplicate\n      await sleep(400)\n      expect(emissions).toHaveLength(0)\n    })\n\n    test(\"older replaceable event does not emit\", async () => {\n      const c = new NoteCollection()\n      c.add(ev(\"new\", 0, 200, \"alice\"))\n      await sleep(400)\n\n      const emissions: Array<TaggedNostrEvent[]> = []\n      c.on(\"event\", evs => emissions.push(evs))\n\n      c.add(ev(\"old\", 0, 100, \"alice\"))\n      await sleep(400)\n      expect(emissions).toHaveLength(0)\n    })\n\n    test(\"flushEmit() on empty buffer does not block future emissions\", async () => {\n      const c = new NoteCollection()\n      const emissions: Array<TaggedNostrEvent[]> = []\n      c.on(\"event\", evs => emissions.push(evs))\n\n      // Call flushEmit() manually when nothing is buffered (ghost-timer scenario)\n      c.flushEmit()\n\n      // Now add an event — it must still emit\n      c.add(ev(\"a\", 1, 100))\n      await sleep(400)\n      expect(emissions).toHaveLength(1)\n      expect(emissions[0][0].id).toBe(\"a\")\n    })\n  })\n\n  describe(\"batch add\", () => {\n    test(\"array of events is added correctly\", () => {\n      const c = new NoteCollection()\n      c.add([ev(\"a\", 1, 100), ev(\"b\", 1, 200)])\n      expect(c.snapshot).toHaveLength(2)\n    })\n\n    test(\"returns count of actually-stored events in batch\", () => {\n      const c = new NoteCollection()\n      c.add(ev(\"a\", 1, 100))\n      // second call: 'a' is dup (0), 'b' is new (1)\n      const count = c.add([ev(\"a\", 1, 100), ev(\"b\", 1, 200)])\n      expect(count).toBe(1)\n    })\n  })\n})\n\n// ===========================================================================\n// 2. trimFilters\n// ===========================================================================\n\ndescribe(\"trimFilters\", () => {\n  test(\"keeps filter with no array fields (scalar only)\", () => {\n    expect(trimFilters([{ since: 100 }])).toHaveLength(1)\n  })\n\n  test(\"keeps empty filter {} — vacuously passes (every on empty array)\", () => {\n    // An empty filter {} means \"fetch everything\" — trimFilters does NOT remove it\n    expect(trimFilters([{}])).toHaveLength(1)\n  })\n\n  test(\"removes filter with empty kinds array\", () => {\n    expect(trimFilters([{ kinds: [] }])).toHaveLength(0)\n  })\n\n  test(\"removes filter with empty authors array\", () => {\n    expect(trimFilters([{ authors: [] }])).toHaveLength(0)\n  })\n\n  test(\"removes filter with empty ids array\", () => {\n    expect(trimFilters([{ ids: [] }])).toHaveLength(0)\n  })\n\n  test(\"removes filter where any array field is empty (even if others are non-empty)\", () => {\n    expect(trimFilters([{ kinds: [1], authors: [] }])).toHaveLength(0)\n  })\n\n  test(\"keeps filter where all array fields are non-empty\", () => {\n    expect(trimFilters([{ kinds: [1], authors: [\"aa\"] }])).toHaveLength(1)\n  })\n\n  test(\"removes filter with empty tag array (#e)\", () => {\n    expect(trimFilters([{ \"#e\": [] }])).toHaveLength(0)\n  })\n\n  test(\"keeps filter with non-empty tag array\", () => {\n    expect(trimFilters([{ \"#e\": [\"someid\"] }])).toHaveLength(1)\n  })\n\n  test(\"handles multiple filters, only removes the bad ones\", () => {\n    const result = trimFilters([{ kinds: [1] }, { kinds: [] }, { authors: [\"aa\"], kinds: [1] }])\n    expect(result).toHaveLength(2)\n  })\n\n  test(\"returns empty array when all filters are empty-array\", () => {\n    expect(trimFilters([{ kinds: [] }, { authors: [] }])).toHaveLength(0)\n  })\n})\n\n// ===========================================================================\n// 3. eventMatchesFilter\n// ===========================================================================\n\ndescribe(\"eventMatchesFilter\", () => {\n  const base: TaggedNostrEvent = {\n    id: \"evt1\",\n    kind: 1,\n    pubkey: \"aa\",\n    created_at: 500,\n    tags: [],\n    content: \"\",\n    sig: \"\",\n    relays: [],\n  }\n\n  test(\"empty filter matches any event\", () => {\n    expect(eventMatchesFilter(base, {})).toBe(true)\n  })\n\n  test(\"ids match\", () => {\n    expect(eventMatchesFilter(base, { ids: [\"evt1\"] })).toBe(true)\n    expect(eventMatchesFilter(base, { ids: [\"other\"] })).toBe(false)\n  })\n\n  test(\"ids: [] (empty) — event does NOT match\", () => {\n    expect(eventMatchesFilter(base, { ids: [] })).toBe(false)\n  })\n\n  test(\"authors match\", () => {\n    expect(eventMatchesFilter(base, { authors: [\"aa\"] })).toBe(true)\n    expect(eventMatchesFilter(base, { authors: [\"bb\"] })).toBe(false)\n  })\n\n  test(\"kinds match\", () => {\n    expect(eventMatchesFilter(base, { kinds: [1] })).toBe(true)\n    expect(eventMatchesFilter(base, { kinds: [2] })).toBe(false)\n  })\n\n  test(\"since: event at exactly since is NOT rejected (created_at === since passes)\", () => {\n    // filter.since = 500, ev.created_at = 500 → 500 < 500 is false → passes\n    expect(eventMatchesFilter(base, { since: 500 })).toBe(true)\n  })\n\n  test(\"since: event older than since is rejected\", () => {\n    expect(eventMatchesFilter(base, { since: 501 })).toBe(false)\n  })\n\n  test(\"since: 0 is treated as falsy — does NOT filter anything (known quirk)\", () => {\n    const oldEv = { ...base, created_at: 1 }\n    // since: 0 is falsy, so the check `if (filter.since && ...)` never fires\n    expect(eventMatchesFilter(oldEv, { since: 0 })).toBe(true)\n  })\n\n  test(\"until: event at exactly until is NOT rejected\", () => {\n    // filter.until = 500, ev.created_at = 500 → 500 > 500 is false → passes\n    expect(eventMatchesFilter(base, { until: 500 })).toBe(true)\n  })\n\n  test(\"until: event newer than until is rejected\", () => {\n    expect(eventMatchesFilter(base, { until: 499 })).toBe(false)\n  })\n\n  test(\"until: 0 is treated as falsy — does NOT filter anything (known quirk)\", () => {\n    const futureEv = { ...base, created_at: 9999999 }\n    expect(eventMatchesFilter(futureEv, { until: 0 })).toBe(true)\n  })\n\n  test(\"tag filters (#e, #p) are NOT checked — any event passes regardless of tags\", () => {\n    const noTags = { ...base, tags: [] }\n    // Even though filter requests specific #e values, matcher ignores them\n    expect(eventMatchesFilter(noTags, { \"#e\": [\"someEventId\"] })).toBe(true)\n  })\n\n  test(\"combined filter: all matching fields pass\", () => {\n    expect(\n      eventMatchesFilter(base, {\n        ids: [\"evt1\"],\n        authors: [\"aa\"],\n        kinds: [1],\n        since: 100,\n        until: 1000,\n      }),\n    ).toBe(true)\n  })\n\n  test(\"combined filter: one failing field fails the whole match\", () => {\n    expect(\n      eventMatchesFilter(base, {\n        ids: [\"evt1\"],\n        kinds: [2], // wrong kind\n      }),\n    ).toBe(false)\n  })\n})\n\n// ===========================================================================\n// 4. isRequestSatisfied\n// ===========================================================================\n\ndescribe(\"isRequestSatisfied\", () => {\n  const results: TaggedNostrEvent[] = [ev(\"id1\", 1, 100), ev(\"id2\", 1, 200)]\n\n  test(\"satisfied when all requested ids are in results\", () => {\n    expect(isRequestSatisfied({ ids: [\"id1\", \"id2\"] }, results)).toBe(true)\n  })\n\n  test(\"not satisfied when one id is missing\", () => {\n    expect(isRequestSatisfied({ ids: [\"id1\", \"id3\"] }, results)).toBeUndefined()\n  })\n\n  test(\"not satisfied when ids field is absent — returns undefined for any author/kind filter\", () => {\n    expect(isRequestSatisfied({ authors: [\"aa\"], kinds: [1] }, results)).toBeUndefined()\n  })\n\n  test(\"not satisfied with empty ids array (no ids to satisfy)\", () => {\n    // ids: [] — every() on empty is vacuously true, but there are no ids to actually satisfy\n    // Actually: [].every(...) === true, so filter.ids is [], filter.ids.every(...) === true → returns true\n    // This is a quirk: an empty ids filter is considered \"satisfied\"\n    expect(isRequestSatisfied({ ids: [] }, results)).toBe(true)\n  })\n\n  test(\"not satisfied when results is empty\", () => {\n    expect(isRequestSatisfied({ ids: [\"id1\"] }, [])).toBeUndefined()\n  })\n\n  test(\"returns undefined (not false) when not satisfied\", () => {\n    const result = isRequestSatisfied({ ids: [\"missing\"] }, results)\n    expect(result).toBeUndefined()\n  })\n})\n\n// ===========================================================================\n// 5. Query lifecycle\n// ===========================================================================\n\ndescribe(\"Query lifecycle\", () => {\n  test(\"progress is 0 when there are no traces\", () => {\n    const rb = makeRb(\"test\")\n    const q = new Query(rb)\n    expect(q.progress).toBe(0)\n  })\n\n  test(\"groupingDelay 0 emits request synchronously\", () => {\n    const rb = makeRb(\"test\", 0)\n    const q = new Query(rb)\n    const requests: unknown[] = []\n    q.on(\"request\", (_id, filters) => requests.push(filters))\n    q.start()\n    // synchronous — no need to await\n    expect(requests).toHaveLength(1)\n  })\n\n  test(\"groupingDelay > 0 does not emit request synchronously\", () => {\n    const rb = makeRb(\"test\", 50)\n    const q = new Query(rb)\n    const requests: unknown[] = []\n    q.on(\"request\", (_id, filters) => requests.push(filters))\n    q.start()\n    // Not yet fired\n    expect(requests).toHaveLength(0)\n  })\n\n  test(\"groupingDelay > 0 emits after delay\", async () => {\n    const rb = makeRb(\"test\", 50)\n    const q = new Query(rb)\n    const requests: unknown[] = []\n    q.on(\"request\", (_id, filters) => requests.push(filters))\n    q.start()\n    await sleep(100)\n    expect(requests).toHaveLength(1)\n  })\n\n  test(\"start() is re-entrant safe — second call while timer pending is a no-op\", async () => {\n    const rb = makeRb(\"test\", 50)\n    const q = new Query(rb)\n    const requests: unknown[] = []\n    q.on(\"request\", (_id, filters) => requests.push(filters))\n    q.start()\n    q.start() // second call — should NOT add a second timer\n    await sleep(100)\n    expect(requests).toHaveLength(1)\n  })\n\n  test(\"cancel() + uncancel() within grace window preserves query\", async () => {\n    const rb = makeRb(\"test\")\n    const q = new Query(rb)\n    q.cancel()\n    expect(q.canRemove()).toBe(false) // within 1s grace window\n    q.uncancel()\n    await sleep(1100) // past grace window\n    expect(q.canRemove()).toBe(false) // uncancel cleared #cancelAt\n  })\n\n  test(\"cancel() causes canRemove() to return true after 1 second\", async () => {\n    const rb = makeRb(\"test\")\n    const q = new Query(rb)\n    q.cancel()\n    expect(q.canRemove()).toBe(false)\n    await sleep(1100)\n    expect(q.canRemove()).toBe(true)\n  })\n\n  test(\"addRequest with same builder instance is a no-op (returns undefined)\", () => {\n    const rb = makeRb(\"test\")\n    const q = new Query(rb)\n    // Same instance — dedup by rb.instance UUID\n    const result = q.addRequest(rb)\n    expect(result).toBeUndefined()\n  })\n\n  test(\"addRequest with different builder instance but same id merges filters\", () => {\n    const rb1 = new RequestBuilder(\"shared-id\")\n    rb1.withFilter().kinds([1])\n    const q = new Query(rb1)\n\n    const rb2 = new RequestBuilder(\"shared-id\") // different instance, same id\n    rb2.withFilter().kinds([2])\n    const result = q.addRequest(rb2)\n    expect(result).toBe(true)\n    // Both filter sets should now be in q.requests\n    expect(q.requests.length).toBe(2)\n  })\n\n  test(\"addRequest with zero filters returns false and does not queue requests\", () => {\n    const rb1 = makeRb(\"test\")\n    const q = new Query(rb1)\n\n    const rbEmpty = new RequestBuilder(\"test\") // no filters added\n    const result = q.addRequest(rbEmpty)\n    expect(result).toBe(false)\n  })\n\n  test(\"'eose' query event fires when all traces reach terminal state (including TIMEOUT)\", async () => {\n    const rb = makeRb(\"test\", 0)\n    const q = new Query(rb)\n    let eoseFired = false\n    q.on(\"eose\", () => {\n      eoseFired = true\n    })\n\n    // Manually add a trace and drive it to timeout\n    const { QueryTrace } = await import(\"../src/query\")\n    const trace = new QueryTrace(\"wss://r.test\", [{ kinds: [1] }], \"conn1\", false)\n    q.addTrace(trace)\n    trace.queued()\n    trace.sent()\n    trace.timeout()\n\n    expect(eoseFired).toBe(true)\n    expect(q.progress).toBe(1)\n  })\n\n  test(\"'eose' query event fires on DROP too\", async () => {\n    const rb = makeRb(\"test\", 0)\n    const q = new Query(rb)\n    let eoseFired = false\n    q.on(\"eose\", () => {\n      eoseFired = true\n    })\n\n    const { QueryTrace } = await import(\"../src/query\")\n    const trace = new QueryTrace(\"wss://r.test\", [{ kinds: [1] }], \"conn1\", false)\n    q.addTrace(trace)\n    trace.queued()\n    trace.drop()\n\n    expect(eoseFired).toBe(true)\n  })\n\n  test(\"streaming trace (leaveOpen=true) never reaches finished state after eose\", async () => {\n    const rb = new RequestBuilder(\"streaming\")\n    rb.withOptions({ leaveOpen: true, groupingDelay: 0 })\n    rb.withFilter().kinds([1])\n    const q = new Query(rb)\n\n    const { QueryTrace } = await import(\"../src/query\")\n    const trace = new QueryTrace(\"wss://r.test\", [{ kinds: [1] }], \"conn1\", true)\n    q.addTrace(trace)\n    trace.queued()\n    trace.sent() // transitions to WAITING_STREAM\n\n    // WAITING_STREAM is not a terminal state — progress stays < 1\n    expect(trace.finished).toBe(false)\n    expect(q.progress).toBe(0)\n  })\n\n  test(\"QueryTrace same-state transition is a no-op (no event emitted)\", async () => {\n    const rb = makeRb(\"test\")\n    const q = new Query(rb)\n\n    const { QueryTrace } = await import(\"../src/query\")\n    const trace = new QueryTrace(\"wss://r.test\", [], \"conn1\", false)\n    const changes: string[] = []\n    trace.on(\"stateChange\", e => changes.push(e.state))\n\n    trace.queued()\n    trace.queued() // duplicate — no-op\n    expect(changes).toHaveLength(1)\n    expect(changes[0]).toBe(QueryTraceState.QUEUED)\n  })\n})\n\n// ===========================================================================\n// 6. QueryManager — dedup, canSendQuery branches, destroy\n// ===========================================================================\n\ndescribe(\"QueryManager\", () => {\n  let pool: MockPool\n  let system: SystemInterface\n  let qm: QueryManager\n\n  beforeEach(() => {\n    pool = new MockPool()\n    system = makeSystem(pool)\n    qm = new QueryManager(system)\n  })\n\n  afterEach(() => {\n    qm.destroy()\n  })\n\n  test(\"query() dedup by id — returns same Query object for same id\", () => {\n    const rb1 = new RequestBuilder(\"same-id\")\n    rb1.withFilter().kinds([1])\n    const rb2 = new RequestBuilder(\"same-id\")\n    rb2.withFilter().kinds([2])\n\n    const q1 = qm.query(rb1)\n    const q2 = qm.query(rb2)\n    expect(q1).toBe(q2) // same object\n  })\n\n  test(\"query() different ids — returns different Query objects\", () => {\n    const rb1 = makeRb(\"id-one\")\n    const rb2 = makeRb(\"id-two\")\n    expect(qm.query(rb1)).not.toBe(qm.query(rb2))\n  })\n\n  test(\"query() with zero-filter builder — query exists but no request is emitted\", async () => {\n    const rb = new RequestBuilder(\"no-filters\") // no withFilter() call\n    const q = qm.query(rb)\n    const requests: unknown[] = []\n    q.on(\"request\", (_, f) => requests.push(f))\n    q.start()\n    await sleep(50)\n    expect(requests).toHaveLength(0)\n  })\n\n  test(\"#canSendQuery: isDown connection is skipped\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    conn.markDown()\n    pool.add(conn)\n\n    const rb = makeRb(\"test-down\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(conn.sentRequests).toHaveLength(0)\n    expect(q.traces).toHaveLength(0)\n  })\n\n  test(\"#canSendQuery: ephemeral connection is skipped for broadcast queries\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    conn.ephemeral = true\n    pool.add(conn)\n\n    const rb = makeRb(\"test-ephemeral\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(conn.sentRequests).toHaveLength(0)\n  })\n\n  test(\"#canSendQuery: search query skipped when relay has no NIP-11 info\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    // conn.info is undefined — no NIP-50 search support known\n    pool.add(conn)\n\n    const rb = new RequestBuilder(\"search-test\")\n    rb.withOptions({ groupingDelay: 0 })\n    rb.withFilter().kinds([1]).search(\"hello\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    // Should not send to a relay with unknown NIP support\n    expect(conn.sentRequests).toHaveLength(0)\n  })\n\n  test(\"#canSendQuery: search query sent when relay advertises NIP-50\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    conn.info = { supported_nips: [50] } as any\n    pool.add(conn)\n\n    const rb = new RequestBuilder(\"search-test-supported\")\n    rb.withOptions({ groupingDelay: 0 })\n    rb.withFilter().kinds([1]).search(\"hello\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(conn.sentRequests).toHaveLength(1)\n    expect(conn.sentRequests[0][0]).toBe(\"REQ\")\n  })\n\n  test(\"empty filters are dropped — no REQ sent\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    // Build a query that will produce an empty filter after trimming\n    const rb = new RequestBuilder(\"empty-filter-test\")\n    rb.withOptions({ groupingDelay: 0 })\n    rb.withFilter().kinds([]) // empty kinds → trimmed away\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    expect(conn.sentRequests).toHaveLength(0)\n  })\n\n  test(\"destroy() removes all queries from internal map\", async () => {\n    const rb = makeRb(\"test-destroy\")\n    qm.query(rb)\n\n    expect(qm.get(\"test-destroy\")).toBeDefined()\n    qm.destroy()\n    expect(qm.get(\"test-destroy\")).toBeUndefined()\n  })\n\n  test(\"destroy() cancels all queries so they can be removed\", async () => {\n    const rb = makeRb(\"test-destroy-cancel\")\n    const q = qm.query(rb)\n    expect(q.canRemove()).toBe(false)\n\n    qm.destroy()\n    // destroy() calls q.cancel() which sets a 1-second grace window\n    // canRemove() will become true after the grace window — verify cancel was called\n    await sleep(1100)\n    expect(q.canRemove()).toBe(true)\n  })\n\n  test(\"query is cleaned up after cancel grace window expires\", async () => {\n    const conn = new MockConnection(\"wss://relay.test\", true)\n    pool.add(conn)\n\n    const rb = makeRb(\"test-cleanup\")\n    const q = qm.query(rb)\n    q.start()\n    await sleep(50)\n\n    // Cancel the query\n    q.cancel()\n    // The query should still be gettable during the grace window\n    expect(qm.get(\"test-cleanup\")).toBeDefined()\n\n    // Wait for the 1-second grace + 1-second cleanup interval\n    await sleep(2200)\n    expect(qm.get(\"test-cleanup\")).toBeUndefined()\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/request-builder.test.ts",
    "content": "import { RequestBuilder } from \"../src/request-builder\"\nimport { describe, expect, test } from \"bun:test\"\n\ndescribe(\"RequestBuilder\", () => {\n  describe(\"basic\", () => {\n    test(\"empty filter\", () => {\n      const b = new RequestBuilder(\"test\")\n      b.withFilter()\n      expect(b.buildRaw()).toEqual([{}])\n    })\n    test(\"only kind\", () => {\n      const b = new RequestBuilder(\"test\")\n      b.withFilter().kinds([0])\n      expect(b.buildRaw()).toMatchObject([{ kinds: [0] }])\n    })\n    test(\"empty authors\", () => {\n      const b = new RequestBuilder(\"test\")\n      b.withFilter().authors([])\n      expect(b.buildRaw()).toMatchObject([{ authors: [] }])\n    })\n    test(\"search\", () => {\n      const b = new RequestBuilder(\"test\")\n      b.withFilter().kinds([1]).search(\"test-search\")\n      expect(b.buildRaw()).toMatchObject([{ kinds: [1], search: \"test-search\" }])\n    })\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/request-expander.test.ts",
    "content": "import { expandFilter } from \"../src/query-optimizer/request-expander\"\n\ndescribe(\"RequestExpander\", () => {\n  test(\"expand filter\", () => {\n    const a = {\n      authors: [\"a\", \"b\", \"c\"],\n      kinds: [1, 2, 3],\n      ids: [\"x\", \"y\"],\n      \"#p\": [\"a\"],\n      since: 99,\n      limit: 10,\n    }\n    expect(expandFilter(a)).toMatchObject([\n      { authors: \"a\", kinds: 1, ids: \"x\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"a\", kinds: 1, ids: \"y\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"a\", kinds: 2, ids: \"x\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"a\", kinds: 2, ids: \"y\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"a\", kinds: 3, ids: \"x\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"a\", kinds: 3, ids: \"y\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"b\", kinds: 1, ids: \"x\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"b\", kinds: 1, ids: \"y\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"b\", kinds: 2, ids: \"x\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"b\", kinds: 2, ids: \"y\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"b\", kinds: 3, ids: \"x\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"b\", kinds: 3, ids: \"y\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"c\", kinds: 1, ids: \"x\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"c\", kinds: 1, ids: \"y\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"c\", kinds: 2, ids: \"x\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"c\", kinds: 2, ids: \"y\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"c\", kinds: 3, ids: \"x\", \"#p\": \"a\", since: 99, limit: 10 },\n      { authors: \"c\", kinds: 3, ids: \"y\", \"#p\": \"a\", since: 99, limit: 10 },\n    ])\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/request-matcher.test.ts",
    "content": "import { eventMatchesFilter } from \"../src/request-matcher\"\nimport { describe, expect, test } from \"bun:test\"\n\ndescribe(\"RequestMatcher\", () => {\n  test(\"should match simple filter\", () => {\n    const ev = {\n      id: \"test\",\n      kind: 1,\n      pubkey: \"pubkey\",\n      created_at: 99,\n      tags: [],\n      content: \"test\",\n      sig: \"\",\n    }\n    const filter = {\n      ids: [\"test\"],\n      authors: [\"pubkey\", \"other\"],\n      kinds: [1, 2, 3],\n      since: 1,\n      before: 100,\n    }\n    expect(eventMatchesFilter(ev, filter)).toBe(true)\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/request-merger.test.ts",
    "content": "import type { ReqFilter } from \"../src\"\nimport {\n  canMergeFilters,\n  filterIncludes,\n  flatMerge,\n  mergeSimilar,\n  simpleMerge,\n} from \"../src/query-optimizer/request-merger\"\nimport type { FlatReqFilter } from \"../src/query-optimizer\"\nimport { expandFilter } from \"../src/query-optimizer/request-expander\"\nimport { describe, expect, test } from \"bun:test\"\n\ndescribe(\"RequestMerger\", () => {\n  test(\"should simple merge authors\", () => {\n    const a = {\n      authors: [\"a\"],\n    } as ReqFilter\n    const b = {\n      authors: [\"b\"],\n    } as ReqFilter\n\n    const merged = mergeSimilar([a, b])\n    expect(merged).toEqual([\n      {\n        authors: [\"a\", \"b\"],\n      },\n    ])\n  })\n\n  test(\"should append non-mergable filters\", () => {\n    const a = {\n      authors: [\"a\"],\n    } as ReqFilter\n    const b = {\n      authors: [\"b\"],\n    } as ReqFilter\n    const c = {\n      limit: 5,\n      authors: [\"a\"],\n    }\n\n    const merged = mergeSimilar([a, b, c])\n    expect(merged).toEqual([\n      {\n        authors: [\"a\", \"b\"],\n      },\n      {\n        limit: 5,\n        authors: [\"a\"],\n      },\n    ])\n  })\n\n  test(\"filterIncludes\", () => {\n    const bigger = {\n      authors: [\"a\", \"b\", \"c\"],\n      since: 99,\n    } as ReqFilter\n    const smaller = {\n      authors: [\"c\"],\n      since: 100,\n    } as ReqFilter\n    expect(filterIncludes(bigger, smaller)).toBe(true)\n  })\n\n  test(\"simpleMerge\", () => {\n    const a = {\n      authors: [\"a\", \"b\", \"c\"],\n      since: 99,\n    } as ReqFilter\n    const b = {\n      authors: [\"c\", \"d\", \"e\"],\n      since: 100,\n    } as ReqFilter\n    expect(simpleMerge([a, b])).toEqual({\n      authors: [\"a\", \"b\", \"c\", \"d\", \"e\"],\n      since: 100,\n    })\n  })\n})\n\ndescribe(\"flatMerge\", () => {\n  test(\"should flat merge simple\", () => {\n    const input = [\n      { ids: \"0\", authors: \"a\", resultSetId: \"\" },\n      { ids: \"0\", authors: \"b\", resultSetId: \"\" },\n      { kinds: 1, resultSetId: \"\" },\n      { kinds: 2, resultSetId: \"\" },\n      { kinds: 2, resultSetId: \"\" },\n      { ids: \"0\", authors: \"c\", resultSetId: \"\" },\n      { authors: \"c\", kinds: 1, resultSetId: \"\" },\n      { authors: \"c\", limit: 100, resultSetId: \"limit-c-100\" },\n      { authors: \"b\", limit: 100, resultSetId: \"limit-b-100\" },\n      { ids: \"1\", authors: \"c\", resultSetId: \"\" },\n    ] as Array<FlatReqFilter>\n    const output = [\n      { ids: [\"0\"], authors: [\"a\", \"b\", \"c\"] },\n      { kinds: [1, 2] },\n      { authors: [\"c\"], kinds: [1] },\n      { authors: [\"c\"], limit: 100 },\n      { authors: [\"b\"], limit: 100 },\n      { ids: [\"1\"], authors: [\"c\"] },\n    ] as Array<ReqFilter>\n\n    expect(flatMerge(input)).toMatchObject(output)\n  })\n\n  test(\"should expand and flat merge complex same\", () => {\n    const input = [\n      { kinds: [1, 6969, 6], authors: [\"kieran\", \"snort\", \"c\", \"d\", \"e\"], since: 1, until: 100 },\n      { kinds: [4], authors: [\"kieran\"] },\n      { kinds: [4], \"#p\": [\"kieran\"] },\n      { kinds: [1000], authors: [\"snort\"], \"#p\": [\"kieran\"] },\n    ] as Array<ReqFilter>\n\n    const dut = flatMerge(input.flatMap(expandFilter).sort(() => (Math.random() > 0.5 ? 1 : -1)))\n    expect(dut.every(a => input.some(b => canMergeFilters(b, a) === false))).toEqual(true)\n  })\n})\n\ndescribe(\"canMerge\", () => {\n  test(\"should have 0 distance\", () => {\n    const a = {\n      ids: \"a\",\n      resultSetId: \"\",\n    } as FlatReqFilter\n    const b = {\n      ids: \"a\",\n      resultSetId: \"\",\n    } as FlatReqFilter\n    expect(canMergeFilters(a, b)).toEqual(true)\n  })\n  test(\"should have 1 distance\", () => {\n    const a = {\n      ids: \"a\",\n      resultSetId: \"\",\n    } as FlatReqFilter\n    const b = {\n      ids: \"b\",\n      resultSetId: \"\",\n    } as FlatReqFilter\n    expect(canMergeFilters(a, b)).toEqual(true)\n  })\n  test(\"should have 10 distance\", () => {\n    const a = {\n      ids: \"a\",\n      resultSetId: \"\",\n    } as FlatReqFilter\n    const b = {\n      ids: \"a\",\n      kinds: 1,\n      resultSetId: \"\",\n    } as FlatReqFilter\n    expect(canMergeFilters(a, b)).toEqual(false)\n  })\n  test(\"should have 11 distance\", () => {\n    const a = {\n      ids: \"a\",\n      resultSetId: \"\",\n    } as FlatReqFilter\n    const b = {\n      ids: \"b\",\n      kinds: 1,\n      resultSetId: \"\",\n    } as FlatReqFilter\n    expect(canMergeFilters(a, b)).toEqual(false)\n  })\n  test(\"should have 1 distance, arrays\", () => {\n    const a = {\n      since: 1,\n      until: 100,\n      kinds: [1],\n      authors: [\"kieran\", \"snort\", \"c\", \"d\", \"e\"],\n    }\n    const b = {\n      since: 1,\n      until: 100,\n      kinds: [6969],\n      authors: [\"kieran\", \"snort\", \"c\", \"d\", \"e\"],\n    }\n    expect(canMergeFilters(a, b)).toEqual(true)\n  })\n  test(\"should have 1 distance, array change extra\", () => {\n    const a = {\n      since: 1,\n      until: 100,\n      kinds: [1],\n      authors: [\"f\", \"kieran\", \"snort\", \"c\", \"d\"],\n    }\n    const b = {\n      since: 1,\n      until: 100,\n      kinds: [1],\n      authors: [\"kieran\", \"snort\", \"c\", \"d\", \"e\"],\n    }\n    expect(canMergeFilters(a, b)).toEqual(true)\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/request-splitter.test.ts",
    "content": "import type { ReqFilter } from \"../src\"\nimport { describe, expect, test } from \"bun:test\"\nimport { diffFilters } from \"../src/query-optimizer/request-splitter\"\nimport { expandFilter } from \"../src/query-optimizer/request-expander\"\n\ndescribe(\"RequestSplitter\", () => {\n  test(\"single filter add value\", () => {\n    const a: Array<ReqFilter> = [{ kinds: [0], authors: [\"a\"] }]\n    const b: Array<ReqFilter> = [{ kinds: [0], authors: [\"a\", \"b\"] }]\n    const diff = diffFilters(a.flatMap(expandFilter), b.flatMap(expandFilter), true)\n    expect(diff).toMatchObject({\n      added: [{ kinds: 0, authors: \"b\" }],\n      removed: [],\n      changed: true,\n    })\n  })\n  test(\"single filter remove value\", () => {\n    const a: Array<ReqFilter> = [{ kinds: [0], authors: [\"a\"] }]\n    const b: Array<ReqFilter> = [{ kinds: [0], authors: [\"b\"] }]\n    const diff = diffFilters(a.flatMap(expandFilter), b.flatMap(expandFilter), true)\n    expect(diff).toMatchObject({\n      added: [{ kinds: 0, authors: \"b\" }],\n      removed: [{ kinds: 0, authors: \"a\" }],\n      changed: true,\n    })\n  })\n  test(\"single filter change critical key\", () => {\n    const a: Array<ReqFilter> = [{ kinds: [0], authors: [\"a\"], since: 100 }]\n    const b: Array<ReqFilter> = [{ kinds: [0], authors: [\"a\", \"b\"], since: 101 }]\n    const diff = diffFilters(a.flatMap(expandFilter), b.flatMap(expandFilter), true)\n    expect(diff).toMatchObject({\n      added: [\n        { kinds: 0, authors: \"a\", since: 101 },\n        { kinds: 0, authors: \"b\", since: 101 },\n      ],\n      removed: [{ kinds: 0, authors: \"a\", since: 100 }],\n      changed: true,\n    })\n  })\n  test(\"multiple filter add value\", () => {\n    const a: Array<ReqFilter> = [\n      { kinds: [0], authors: [\"a\"] },\n      { kinds: [69], authors: [\"a\"] },\n    ]\n    const b: Array<ReqFilter> = [\n      { kinds: [0], authors: [\"a\", \"b\"] },\n      { kinds: [69], authors: [\"a\", \"c\"] },\n    ]\n    const diff = diffFilters(a.flatMap(expandFilter), b.flatMap(expandFilter), true)\n    expect(diff).toMatchObject({\n      added: [\n        { kinds: 0, authors: \"b\" },\n        { kinds: 69, authors: \"c\" },\n      ],\n      removed: [],\n      changed: true,\n    })\n  })\n  test(\"multiple filter remove value\", () => {\n    const a: Array<ReqFilter> = [\n      { kinds: [0], authors: [\"a\"] },\n      { kinds: [69], authors: [\"a\"] },\n    ]\n    const b: Array<ReqFilter> = [\n      { kinds: [0], authors: [\"b\"] },\n      { kinds: [69], authors: [\"c\"] },\n    ]\n    const diff = diffFilters(a.flatMap(expandFilter), b.flatMap(expandFilter), true)\n    expect(diff).toMatchObject({\n      added: [\n        { kinds: 0, authors: \"b\" },\n        { kinds: 69, authors: \"c\" },\n      ],\n      removed: [\n        { kinds: 0, authors: \"a\" },\n        { kinds: 69, authors: \"a\" },\n      ],\n      changed: true,\n    })\n  })\n  test(\"add filter\", () => {\n    const a: Array<ReqFilter> = [{ kinds: [0], authors: [\"a\"] }]\n    const b: Array<ReqFilter> = [\n      { kinds: [0], authors: [\"a\"] },\n      { kinds: [69], authors: [\"c\"] },\n    ]\n    const diff = diffFilters(a.flatMap(expandFilter), b.flatMap(expandFilter), true)\n    expect(diff).toMatchObject({\n      added: [{ kinds: 69, authors: \"c\" }],\n      removed: [],\n      changed: true,\n    })\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/setupTests.ts",
    "content": "import { TextEncoder, TextDecoder } from \"util\"\nimport { Crypto } from \"@peculiar/webcrypto\"\n\nObject.assign(global, { TextDecoder, TextEncoder })\nObject.assign(globalThis.window.crypto, new Crypto())\n"
  },
  {
    "path": "packages/system/tests/text.test.ts",
    "content": "import { describe, expect, test } from \"bun:test\"\nimport { transformText } from \"../src\"\nimport { sha256 } from \"@snort/shared\"\n\ndescribe(\"transformText\", () => {\n  describe(\"links\", () => {\n    test(\"parse youtube link\", () => {\n      const str = \"GM\\nhttps://music.youtube.com/watch?v=_ajDU1P9qmo\"\n\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"GM\\n\",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"link\",\n        content: \"https://music.youtube.com/watch?v=_ajDU1P9qmo\",\n      })\n    })\n\n    test(\"parse http link\", () => {\n      const str = \"Check this out http://example.com\"\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"Check this out \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"link\",\n        content: \"http://example.com\",\n      })\n    })\n\n    test(\"parse https link\", () => {\n      const str = \"Visit https://nostr.com\"\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"Visit \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"link\",\n        content: \"https://nostr.com\",\n      })\n    })\n\n    test(\"parse magnet link\", () => {\n      const magnet =\n        \"magnet:?xt=urn:btih:f21febdf8c54d2a9b09ed54f7eebb909537fb7b0&dn=bitcoin-core-27.2&tr=http%3A%2F%2Ftracker.loadpeers.org%3A8080%2FxvRKfvAlnfuf5EfxTT5T0KIVPtbqAHnX%2Fannounce&tr=udp%3A%2F%2Ftracker.coppersurfer.tk%3A6969%2Fannounce&tr=udp%3A%2F%2Ftracker.openbittorrent.com%3A6969%2Fannounce&tr=udp%3A%2F%2Fopen.stealth.si%3A80%2Fannounce&tr=udp%3A%2F%2Ftracker.torrent.eu.org%3A451%2Fannounce&tr=udp%3A%2F%2Ftracker.opentrackr.org%3A1337\"\n      const str = `Download ${magnet}`\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"Download \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"magnet\",\n        content: magnet,\n      })\n    })\n\n    test(\"parse blossom link\", () => {\n      const blossomUrl = `blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292`\n      const str = `Check out this cool meme ${blossomUrl}`\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"Check out this cool meme \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"blossom\",\n        content: blossomUrl,\n      })\n    })\n\n    test(\"parse multiple links\", () => {\n      const str = \"Visit https://example.com and http://test.com\"\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(4)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"Visit \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"link\",\n        content: \"https://example.com\",\n      })\n      expect(frags[2]).toMatchObject({\n        type: \"text\",\n        content: \" and \",\n      })\n      expect(frags[3]).toMatchObject({\n        type: \"link\",\n        content: \"http://test.com\",\n      })\n    })\n  })\n\n  describe(\"media\", () => {\n    test(\"parse image link\", () => {\n      const str = \"Check this image https://example.com/image.png\"\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[1]).toMatchObject({\n        type: \"media\",\n        content: \"https://example.com/image.png\",\n        mimeType: \"image/png\",\n      })\n    })\n\n    test(\"parse jpg image\", () => {\n      const str = \"Photo: https://example.com/photo.jpg\"\n      const frags = transformText(str, [])\n\n      expect(frags[1]).toMatchObject({\n        type: \"media\",\n        content: \"https://example.com/photo.jpg\",\n        mimeType: \"image/jpg\",\n      })\n    })\n\n    test(\"parse gif image\", () => {\n      const str = \"Animated https://example.com/animated.gif\"\n      const frags = transformText(str, [])\n\n      expect(frags[1]).toMatchObject({\n        type: \"media\",\n        content: \"https://example.com/animated.gif\",\n        mimeType: \"image/gif\",\n      })\n    })\n\n    test(\"parse webp image\", () => {\n      const str = \"https://example.com/image.webp\"\n      const frags = transformText(str, [])\n\n      expect(frags[0]).toMatchObject({\n        type: \"media\",\n        content: \"https://example.com/image.webp\",\n        mimeType: \"image/webp\",\n      })\n    })\n\n    test(\"parse audio file\", () => {\n      const str = \"Listen to https://example.com/song.mp3\"\n      const frags = transformText(str, [])\n\n      expect(frags[1]).toMatchObject({\n        type: \"media\",\n        content: \"https://example.com/song.mp3\",\n        mimeType: \"audio/mp3\",\n      })\n    })\n\n    test(\"parse ogg audio\", () => {\n      const str = \"Audio: https://example.com/sound.ogg\"\n      const frags = transformText(str, [])\n\n      expect(frags[1]).toMatchObject({\n        type: \"media\",\n        content: \"https://example.com/sound.ogg\",\n        mimeType: \"audio/ogg\",\n      })\n    })\n\n    test(\"parse wav audio\", () => {\n      const str = \"https://example.com/audio.wav\"\n      const frags = transformText(str, [])\n\n      expect(frags[0]).toMatchObject({\n        type: \"media\",\n        content: \"https://example.com/audio.wav\",\n        mimeType: \"audio/wav\",\n      })\n    })\n\n    test(\"parse video file\", () => {\n      const str = \"Watch this https://example.com/video.mp4\"\n      const frags = transformText(str, [])\n\n      expect(frags[1]).toMatchObject({\n        type: \"media\",\n        content: \"https://example.com/video.mp4\",\n        mimeType: \"video/mp4\",\n      })\n    })\n\n    test(\"parse webm video\", () => {\n      const str = \"Video: https://example.com/clip.webm\"\n      const frags = transformText(str, [])\n\n      expect(frags[1]).toMatchObject({\n        type: \"media\",\n        content: \"https://example.com/clip.webm\",\n        mimeType: \"video/webm\",\n      })\n    })\n\n    test(\"parse mov video\", () => {\n      const str = \"https://example.com/movie.mov\"\n      const frags = transformText(str, [])\n\n      expect(frags[0]).toMatchObject({\n        type: \"media\",\n        content: \"https://example.com/movie.mov\",\n        mimeType: \"video/mov\",\n      })\n    })\n\n    test(\"parse mkv video\", () => {\n      const str = \"https://example.com/video.mkv\"\n      const frags = transformText(str, [])\n\n      expect(frags[0]).toMatchObject({\n        type: \"media\",\n        content: \"https://example.com/video.mkv\",\n        mimeType: \"video/mkv\",\n      })\n    })\n  })\n\n  describe(\"hashtags\", () => {\n    test(\"parse single hashtag\", () => {\n      const str = \"Hello #nostr\"\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"Hello \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"hashtag\",\n        content: \"nostr\",\n      })\n    })\n\n    test(\"parse multiple hashtags\", () => {\n      const str = \"Check #bitcoin and #nostr\"\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(4)\n      expect(frags[1]).toMatchObject({\n        type: \"hashtag\",\n        content: \"bitcoin\",\n      })\n      expect(frags[3]).toMatchObject({\n        type: \"hashtag\",\n        content: \"nostr\",\n      })\n    })\n\n    test(\"parse hashtag at start\", () => {\n      const str = \"#winning the day\"\n      const frags = transformText(str, [])\n\n      expect(frags[0]).toMatchObject({\n        type: \"hashtag\",\n        content: \"winning\",\n      })\n    })\n\n    test(\"parse hashtag at end\", () => {\n      const str = \"Going to the moon #bitcoin\"\n      const frags = transformText(str, [])\n\n      expect(frags[1]).toMatchObject({\n        type: \"hashtag\",\n        content: \"bitcoin\",\n      })\n    })\n  })\n\n  describe(\"invoices\", () => {\n    test(\"parse lightning invoice\", () => {\n      const str = \"Pay me lnbc1000n1example\"\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"Pay me \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"invoice\",\n        content: \"lnbc1000n1example\",\n      })\n    })\n\n    test(\"parse uppercase invoice\", () => {\n      const str = \"LNBC1000N1EXAMPLE\"\n      const frags = transformText(str, [])\n\n      expect(frags[0]).toMatchObject({\n        type: \"invoice\",\n        content: \"LNBC1000N1EXAMPLE\",\n      })\n    })\n\n    test(\"parse invoice with text around it\", () => {\n      const str = \"Send payment: lnbc500n1test here\"\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(3)\n      expect(frags[1]).toMatchObject({\n        type: \"invoice\",\n        content: \"lnbc500n1test\",\n      })\n    })\n  })\n\n  describe(\"cashu tokens\", () => {\n    test(\"parse cashu token\", () => {\n      const emptyToken = `cashuA${btoa(JSON.stringify(\"{}\"))}`\n      const str = `Redeem ${emptyToken}`\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"Redeem \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"cashu\",\n        content: emptyToken,\n      })\n    })\n\n    test(\"parse cashu token at start\", () => {\n      const emptyToken = `cashuA${btoa(JSON.stringify(\"{}\"))}`\n      const str = `${emptyToken} is a token`\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[0]).toMatchObject({\n        type: \"cashu\",\n        content: emptyToken,\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"text\",\n        content: \" is a token\",\n      })\n    })\n  })\n\n  describe(\"custom emoji\", () => {\n    test(\"parse custom emoji\", () => {\n      const str = \"Hello :bitcoin: world\"\n      const tags = [[\"emoji\", \"bitcoin\", \"https://example.com/bitcoin.png\"]]\n      const frags = transformText(str, tags)\n\n      expect(frags.length).toBe(3)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"Hello \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"custom_emoji\",\n        content: \"https://example.com/bitcoin.png\",\n      })\n      expect(frags[2]).toMatchObject({\n        type: \"text\",\n        content: \" world\",\n      })\n    })\n\n    test(\"parse multiple custom emojis\", () => {\n      const str = \":fire: This is :cool:\"\n      const tags = [\n        [\"emoji\", \"fire\", \"https://example.com/fire.png\"],\n        [\"emoji\", \"cool\", \"https://example.com/cool.png\"],\n      ]\n      const frags = transformText(str, tags)\n\n      expect(frags[0]).toMatchObject({\n        type: \"custom_emoji\",\n        content: \"https://example.com/fire.png\",\n      })\n      expect(frags[2]).toMatchObject({\n        type: \"custom_emoji\",\n        content: \"https://example.com/cool.png\",\n      })\n    })\n\n    test(\"ignore emoji without tag\", () => {\n      const str = \"Hello :unknown: world\"\n      const tags: string[][] = []\n      const frags = transformText(str, tags)\n\n      // Should not create custom emoji fragment\n      expect(frags.every(f => f.type !== \"custom_emoji\")).toBe(true)\n    })\n  })\n\n  describe(\"code blocks\", () => {\n    test(\"parse code block without language\", () => {\n      const str = \"Here is code:\\n```\\nconst x = 1;\\n```\"\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[1]).toMatchObject({\n        type: \"code_block\",\n        content: \"const x = 1;\\n\",\n      })\n    })\n\n    test(\"parse code block with language\", () => {\n      const str = \"```javascript\\nconst x = 1;\\nconsole.log(x);\\n```\"\n      const frags = transformText(str, [])\n\n      expect(frags[0]).toMatchObject({\n        type: \"code_block\",\n        content: \"const x = 1;\\nconsole.log(x);\\n\",\n        language: \"javascript\",\n      })\n    })\n\n    test(\"parse code block with python\", () => {\n      const str = \"```python\\ndef hello():\\n    print('world')\\n```\"\n      const frags = transformText(str, [])\n\n      expect(frags[0]).toMatchObject({\n        type: \"code_block\",\n        content: \"def hello():\\n    print('world')\\n\",\n        language: \"python\",\n      })\n    })\n\n    test(\"parse inline code in code block context\", () => {\n      const str = \"```\\ncode\\n``` and some text\"\n      const frags = transformText(str, [])\n\n      expect(frags[0]).toMatchObject({\n        type: \"code_block\",\n        content: \"code\\n\",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"text\",\n        content: \" and some text\",\n      })\n    })\n  })\n\n  describe(\"inline code\", () => {\n    test(\"parse inline code\", () => {\n      const str = \"Use the `console.log()` function\"\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(3)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"Use the \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"inline_code\",\n        content: \"console.log()\",\n      })\n      expect(frags[2]).toMatchObject({\n        type: \"text\",\n        content: \" function\",\n      })\n    })\n\n    test(\"parse multiple inline code\", () => {\n      const str = \"Compare `foo` and `bar`\"\n      const frags = transformText(str, [])\n\n      expect(frags[1]).toMatchObject({\n        type: \"inline_code\",\n        content: \"foo\",\n      })\n      expect(frags[3]).toMatchObject({\n        type: \"inline_code\",\n        content: \"bar\",\n      })\n    })\n\n    test(\"parse inline code at start\", () => {\n      const str = \"`const` is a keyword\"\n      const frags = transformText(str, [])\n\n      expect(frags[0]).toMatchObject({\n        type: \"inline_code\",\n        content: \"const\",\n      })\n    })\n\n    test(\"parse inline code at end\", () => {\n      const str = \"Run the command `npm install`\"\n      const frags = transformText(str, [])\n\n      expect(frags[1]).toMatchObject({\n        type: \"inline_code\",\n        content: \"npm install\",\n      })\n    })\n  })\n\n  const KieranPubKey = \"npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\"\n  const EventId =\n    \"nevent1qqs9aulpzhm08la404nuc9g68qlx3f9xydtk6jl7hv24s0yr5694z5cppemhxue69uhkummn9ekx7mp0qy2hwumn8ghj7un9d3shjtnyv9kh2uewd9hj7q3qwmr34t36fy03m8hvgl96zl3znndyzyaqhwmwdtshwmtkg03fetaqxpqqqqqqzzckr8s\"\n\n  describe(\"mentions\", () => {\n    test(\"parse nostr mention with npub\", () => {\n      const str = `Hello @${KieranPubKey}`\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"Hello \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"mention\",\n        content: `@${KieranPubKey}`,\n      })\n    })\n\n    test(\"parse nostr mention with note\", () => {\n      const str = `See @${EventId}`\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"See \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"mention\",\n        content: `@${EventId}`,\n      })\n    })\n\n    test(\"parse nostr mention with note\", () => {\n      const str = `See nostr:${EventId}`\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(2)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"See \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"mention\",\n        content: `nostr:${EventId}`,\n      })\n    })\n\n    test(\"parse multiple mentions\", () => {\n      const str = `From @${KieranPubKey} to @${EventId}`\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(4)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"From \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"mention\",\n        content: `@${KieranPubKey}`,\n      })\n      expect(frags[2]).toMatchObject({\n        type: \"text\",\n        content: \" to \",\n      })\n      expect(frags[3]).toMatchObject({\n        type: \"mention\",\n        content: `@${EventId}`,\n      })\n    })\n  })\n\n  describe(\"tag references\", () => {\n    test(\"parse tag reference\", () => {\n      const str = \"Replying to #[0]\"\n      const tags = [[\"p\", \"3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d\"]]\n      const frags = transformText(str, tags)\n\n      expect(frags.length).toBe(2)\n      expect(frags[0]).toMatchObject({\n        type: \"text\",\n        content: \"Replying to \",\n      })\n      expect(frags[1]).toMatchObject({\n        type: \"mention\",\n      })\n      expect(frags[1].content).toContain(\"nostr:\")\n    })\n\n    test(\"parse multiple tag references\", () => {\n      const str = \"CC #[0] and #[1]\"\n      const tags = [\n        [\"p\", \"3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d\"],\n        [\"e\", \"5c83da77af1dec6d7289834998ad7aafbd9e2191396d75ec3cc27f5a77226f36\"],\n      ]\n      const frags = transformText(str, tags)\n\n      expect(frags[1].type).toBe(\"mention\")\n      expect(frags[3].type).toBe(\"mention\")\n    })\n\n    test(\"ignore invalid tag reference\", () => {\n      const str = \"Invalid #[99]\"\n      const tags = [[\"p\", \"3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d\"]]\n      const frags = transformText(str, tags)\n\n      // Should not crash, should leave as text\n      expect(frags.some(f => f.content === \"#[99]\")).toBe(true)\n    })\n  })\n\n  describe(\"mixed content\", () => {\n    test(\"parse text with link and hashtag\", () => {\n      const str = \"Check out https://example.com #awesome\"\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(4)\n      expect(frags[0].type).toBe(\"text\")\n      expect(frags[1].type).toBe(\"link\")\n      expect(frags[2].type).toBe(\"text\")\n      expect(frags[3].type).toBe(\"hashtag\")\n    })\n\n    test(\"parse complex mixed content\", () => {\n      const str = \"Hello #nostr! Check https://example.com/image.png and use `code` here\"\n      const frags = transformText(str, [])\n\n      expect(frags.length).toBe(7)\n      expect(frags[1].type).toBe(\"hashtag\")\n      expect(frags[3].type).toBe(\"media\")\n      expect(frags[5].type).toBe(\"inline_code\")\n    })\n\n    test(\"parse invoice with hashtag\", () => {\n      const str = \"Pay this lnbc1000n1test #bitcoin\"\n      const frags = transformText(str, [])\n\n      expect(frags[1].type).toBe(\"invoice\")\n      expect(frags[2].type).toBe(\"text\")\n      expect(frags[3].type).toBe(\"hashtag\")\n    })\n\n    test(\"parse link with custom emoji\", () => {\n      const str = \":fire: Check https://example.com :rocket:\"\n      const tags = [\n        [\"emoji\", \"fire\", \"https://example.com/fire.png\"],\n        [\"emoji\", \"rocket\", \"https://example.com/rocket.png\"],\n      ]\n      const frags = transformText(str, tags)\n\n      expect(frags[0].type).toBe(\"custom_emoji\")\n      expect(frags[2].type).toBe(\"link\")\n      expect(frags[4].type).toBe(\"custom_emoji\")\n    })\n\n    test(\"parse code block with hashtags around it\", () => {\n      const str = \"#code example:\\n```javascript\\nconst x = 1;\\n```\\n#programming\"\n      const frags = transformText(str, [])\n\n      expect(frags[0].type).toBe(\"hashtag\")\n      expect(frags[2].type).toBe(\"code_block\")\n      expect(frags[4].type).toBe(\"hashtag\")\n    })\n  })\n})\n"
  },
  {
    "path": "packages/system/tests/utils.test.ts",
    "content": "import { NostrPrefix } from \"@snort/shared\"\nimport { parseNostrLink, tryParseNostrLink } from \"../src/nostr-link\"\nimport { splitByUrl } from \"../src/utils\"\nimport { describe, expect, test } from \"bun:test\"\n\ndescribe(\"splitByUrl\", () => {\n  test(\"should split a string by URLs\", () => {\n    const inputStr =\n      \"@npub1q6mcr8t not https://example.com- sure what your stack is, https://example.com but I made a https://example.com! simple example (https://example.com) of how https://example.com/yo-yo https://example.example.com to do this https://example.com, https://example.com?q=asdf for Next.js apps hosted on Vercel https://example.com. Scarcity in money provides the incentive to create abundance in other things as there is a mechanism to reliably store value. https://i.imgur.com/rkqhjeq.png Every form of money that could be inflated by way of force or technological advancement has been. https://www.dw.com/de/amtsinhaber-mnangagwa-gewinnt-präsidentenwahl-in-simbabwe/a-66640006?maca=de-rss-de-all-1119-xml-atom and some shit.\"\n    const expectedOutput = [\n      \"@npub1q6mcr8t not \",\n      \"https://example.com-\",\n      \" sure what your stack is, \",\n      \"https://example.com\",\n      \" but I made a \",\n      \"https://example.com\",\n      \"! simple example (\",\n      \"https://example.com)\",\n      \" of how \",\n      \"https://example.com/yo-yo\",\n      \" \",\n      \"https://example.example.com\",\n      \" to do this \",\n      \"https://example.com\",\n      \", \",\n      \"https://example.com?q=asdf\",\n      \" for Next.js apps hosted on Vercel \",\n      \"https://example.com\",\n      \". Scarcity in money provides the incentive to create abundance in other things as there is a mechanism to reliably store value. \",\n      \"https://i.imgur.com/rkqhjeq.png\",\n      \" Every form of money that could be inflated by way of force or technological advancement has been. \",\n      \"https://www.dw.com/de/amtsinhaber-mnangagwa-gewinnt-präsidentenwahl-in-simbabwe/a-66640006?maca=de-rss-de-all-1119-xml-atom\",\n      \" and some shit.\",\n    ]\n\n    expect(splitByUrl(inputStr)).toEqual(expectedOutput)\n  })\n\n  test(\"should parse nostr links\", () => {\n    const input =\n      \"web+nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\\nnostr:note1jp6d36lmquhxqn2s5n4ce00pzu2jrpkek8udav6l0y3qcdngpnxsle6ngm\\nnostr:naddr1qqv8x6r0wf6x2um594cxzarg946x7ttpwajhxmmdv5pzqx78pgq53vlnzmdr8l3u38eru0n3438lnxqz0mr39wg9e5j0dfq3qvzqqqr4gu5d05rr\\nnostr is cool\"\n    const expected = [\n      \"\",\n      \"web+nostr:npub1v0lxxxxutpvrelsksy8cdhgfux9l6a42hsj2qzquu2zk7vc9qnkszrqj49\",\n      \"\\n\",\n      \"nostr:note1jp6d36lmquhxqn2s5n4ce00pzu2jrpkek8udav6l0y3qcdngpnxsle6ngm\",\n      \"\\n\",\n      \"nostr:naddr1qqv8x6r0wf6x2um594cxzarg946x7ttpwajhxmmdv5pzqx78pgq53vlnzmdr8l3u38eru0n3438lnxqz0mr39wg9e5j0dfq3qvzqqqr4gu5d05rr\",\n      \"\\nnostr is cool\",\n    ]\n    expect(splitByUrl(input)).toEqual(expected)\n  })\n\n  test(\"should return an array with a single string if no URLs are found\", () => {\n    const inputStr = \"This is a regular string with no URLs\"\n    const expectedOutput = [\"This is a regular string with no URLs\"]\n\n    expect(splitByUrl(inputStr)).toEqual(expectedOutput)\n  })\n})\n\ndescribe(\"tryParseNostrLink\", () => {\n  test(\"is a valid nostr link\", () => {\n    expect(parseNostrLink(\"nostr:npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg\")).toMatchObject({\n      id: \"7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e\",\n      type: NostrPrefix.PublicKey,\n    })\n    expect(parseNostrLink(\"web+nostr:npub10elfcs4fr0l0r8af98jlmgdh9c8tcxjvz9qkw038js35mp4dma8qzvjptg\")).toMatchObject({\n      id: \"7e7e9c42a91bfef19fa929e5fda1b72e0ebc1a4c1141673e2794234d86addf4e\",\n      type: NostrPrefix.PublicKey,\n    })\n    expect(parseNostrLink(\"nostr:note15449edq4qa5wzgqvh8td0q0dp6hwtes4pknsrm7eygeenhlj99xsq94wu9\")).toMatchObject({\n      id: \"a56a5cb4150768e1200cb9d6d781ed0eaee5e6150da701efd9223399dff2294d\",\n      type: NostrPrefix.Note,\n    })\n    expect(\n      parseNostrLink(\n        \"nostr:nprofile1qqsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8gpp4mhxue69uhhytnc9e3k7mgpz4mhxue69uhkg6nzv9ejuumpv34kytnrdaksjlyr9p\",\n      ),\n    ).toMatchObject({\n      id: \"3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d\",\n      type: NostrPrefix.Profile,\n      relays: [\"wss://r.x.com\", \"wss://djbas.sadkb.com\"],\n    })\n    expect(parseNostrLink(\"nostr:nevent1qqs226juks2sw68pyqxtn4khs8ksath9uc2smfcpalvjyvuemlezjngrd87dq\")).toMatchObject({\n      id: \"a56a5cb4150768e1200cb9d6d781ed0eaee5e6150da701efd9223399dff2294d\",\n      type: NostrPrefix.Event,\n    })\n    expect(\n      parseNostrLink(\n        \"nostr:naddr1qqzkjurnw4ksz9thwden5te0wfjkccte9ehx7um5wghx7un8qgs2d90kkcq3nk2jry62dyf50k0h36rhpdtd594my40w9pkal876jxgrqsqqqa28pccpzu\",\n      ),\n    ).toMatchObject({\n      id: \"ipsum\",\n      type: NostrPrefix.Address,\n      relays: [\"wss://relay.nostr.org\"],\n      author: \"a695f6b60119d9521934a691347d9f78e8770b56da16bb255ee286ddf9fda919\",\n      kind: 30023,\n    })\n  })\n  test.each([\"nostr:npub\", \"web+nostr:npub\", \"nostr:nevent1xxx\"])(\"should return false for invalid nostr links\", lb => {\n    expect(tryParseNostrLink(lb)).toBeUndefined()\n  })\n})\n"
  },
  {
    "path": "packages/system/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \"src\",\n    \"target\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"esModuleInterop\": true,\n    \"noImplicitOverride\": true,\n    \"module\": \"ESNext\",\n    \"strict\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"inlineSourceMap\": true,\n    \"outDir\": \"dist\",\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"./src/**/*.ts\"],\n  \"exclude\": [\"**/*.test.ts\"]\n}\n"
  },
  {
    "path": "packages/system/typedoc.json",
    "content": "{\n  \"entryPoints\": [\"src/index.ts\"]\n}\n"
  },
  {
    "path": "packages/system-react/README.md",
    "content": "## @snort/system-react\n\nReact hooks for @snort/system\n\n### Available hooks\n\n#### `useRequestBuilder(RequestBuilder)`\n\nThe main hook which allows you to subscribe to nostr relays and returns a reactive store.\n\n#### `useUserProfile(pubkey: string | undefined)`\n\nProfile hook, profile loading is automated, this hook will return the profile from cache and also refresh the cache in the background (`stale-while-revalidate`)\n\n#### `useEventFeed(NostrLink)` / `useEventsFeed(Array<NostrLink>)`\n\nA simple hook which can load events using the `NostrLink` class, this class contains one NIP-19 entity `nevent/naddr` etc.\n\n#### `useReactions(id, Array<NostrLink>)`\n\nLoads reactions for a set of events, this can be a set of posts on a profile or an arbitary list of events.\n\n#### `useEventReactions(NostrLink, Array<NostrEvent>)`\n\nProcess a set of related events (usually results from `useReactions`) and return likes/dislikes/reposts/zaps\n\n#### `useUserSearch()`\n\nSearch for profiles in the profile cache, this also returns exact links if they match\n\n#### `useSystemState(System)`\n\nHook state of the nostr system\n\n## Example:\n\n```js\nimport { useMemo } from \"react\";\nimport { SnortContext, useRequestBuilder, useUserProfile } from \"@snort/system-react\";\nimport { NostrSystem, NoteCollection, RequestBuilder, TaggedNostrEvent } from \"@snort/system\";\n\nconst System = new NostrSystem({});\n\n// some bootstrap relays\n[\"wss://relay.snort.social\", \"wss://nos.lol\"].forEach(r => System.ConnectToRelay(r, { read: true, write: false }));\n\nexport function Note({ ev }: { ev: TaggedNostrEvent }) {\n  const profile = useUserProfile(ev.pubkey);\n\n  return (\n    <div>\n      Post by: {profile.name ?? profile.display_name}\n      <p>{ev.content}</p>\n    </div>\n  );\n}\n\nexport function UserPosts(props: { pubkey: string }) {\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(\"get-posts\");\n    rb.withFilter().authors([props.pubkey]).kinds([1]).limit(10);\n\n    return rb;\n  }, [props.pubkey]);\n\n  const data = useRequestBuilder(sub);\n  return (\n    <>\n      {data.map(a => (\n        <Note ev={a} />\n      ))}\n    </>\n  );\n}\n\nexport function MyApp() {\n  return (\n    <SnortContext.Provider value={System}>\n      <UserPosts pubkey=\"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\" />\n    </SnortContext.Provider>\n  );\n}\n```\n"
  },
  {
    "path": "packages/system-react/example/example.tsx",
    "content": "import { useMemo } from \"react\"\nimport { SnortContext, useRequestBuilder, useUserProfile } from \"../src\"\n\nimport { NostrSystem, RequestBuilder, type TaggedNostrEvent } from \"@snort/system\"\n\nconst System = new NostrSystem({})\n\n// some bootstrap relays\n;[\"wss://relay.snort.social\", \"wss://nos.lol\"].forEach(r => System.ConnectToRelay(r, { read: true, write: false }))\n\nexport function Note({ ev }: { ev: TaggedNostrEvent }) {\n  const profile = useUserProfile(ev.pubkey)\n\n  return (\n    <div>\n      Post by: {profile?.name ?? profile?.display_name}\n      <p>{ev.content}</p>\n    </div>\n  )\n}\n\nexport function UserPosts(props: { pubkey: string }) {\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(\"get-posts\")\n    rb.withFilter().authors([props.pubkey]).kinds([1]).limit(10)\n\n    return rb\n  }, [props.pubkey])\n\n  const data = useRequestBuilder(sub)\n  return (\n    <>\n      {data.map(a => (\n        <Note ev={a} />\n      ))}\n    </>\n  )\n}\n\nexport function MyApp() {\n  return (\n    <SnortContext.Provider value={System}>\n      <UserPosts pubkey=\"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\" />\n    </SnortContext.Provider>\n  )\n}\n"
  },
  {
    "path": "packages/system-react/package.json",
    "content": "{\n  \"name\": \"@snort/system-react\",\n  \"version\": \"2.0.0-pre.14\",\n  \"description\": \"React hooks for @snort/system\",\n  \"main\": \"dist/index.js\",\n  \"module\": \"src/index.ts\",\n  \"types\": \"dist/index.d.ts\",\n  \"repository\": \"https://git.v0l.io/Kieran/snort\",\n  \"author\": \"Kieran\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"build\": \"rm -rf dist && bunx --bun tsc\"\n  },\n  \"files\": [\"src\", \"dist\"],\n  \"dependencies\": {\n    \"@snort/shared\": \"^2.0.0-pre.4\",\n    \"@snort/system\": \"^2.0.0-pre.11\",\n    \"react\": \"^19.2.3\",\n    \"react-dom\": \"^19.2.5\"\n  },\n  \"devDependencies\": {\n    \"@types/react\": \"^19.2.7\",\n    \"@types/react-dom\": \"^19.2.3\",\n    \"typescript\": \"^5.9.3\"\n  }\n}\n"
  },
  {
    "path": "packages/system-react/src/TraceTimeline/TraceStatsView.tsx",
    "content": "import { QueryTraceState, type TimelineEntry } from \"@snort/system\"\nimport { SnortContext } from \"../context\"\nimport { use, useMemo, useSyncExternalStore } from \"react\"\nimport \"./TraceTimeline.css\"\nimport { sanitizeRelayUrl } from \"@snort/shared\"\n\nexport function TraceStatsView() {\n  const system = use(SnortContext)\n\n  const emptyTimeline = { entries: [] as TimelineEntry[] }\n  const timeline = useSyncExternalStore(\n    c => system.traceTimeline?.hook(c) ?? (() => {}),\n    () => system.traceTimeline?.snapshot() ?? emptyTimeline,\n    () => emptyTimeline,\n  )\n\n  const entries = timeline.entries\n\n  const stats = useMemo(() => {\n    if (entries.length === 0) {\n      return null\n    }\n\n    // Group entries by trace ID and get the latest state for each trace\n    const latestStateByTrace = new Map<string, TimelineEntry>()\n    for (const entry of entries) {\n      const traceId = entry.event.id\n      const existing = latestStateByTrace.get(traceId)\n      // Keep the entry with the latest timestamp (most recent state)\n      if (!existing || entry.event.timestamp > existing.event.timestamp) {\n        latestStateByTrace.set(traceId, entry)\n      }\n    }\n\n    const latestEntries = Array.from(latestStateByTrace.values())\n\n    const forcedCount = latestEntries.filter(e =>\n      [QueryTraceState.TIMEOUT, QueryTraceState.DROP].includes(e.event.state),\n    ).length\n    const completedCount = latestEntries.filter(e =>\n      [QueryTraceState.EOSE, QueryTraceState.REMOTE_CLOSE, QueryTraceState.LOCAL_CLOSE].includes(e.event.state),\n    ).length\n    const queuedCount = latestEntries.filter(e => e.event.state === QueryTraceState.QUEUED).length\n    const waitingCount = latestEntries.filter(e => e.event.state === QueryTraceState.WAITING).length\n    const streamingCount = latestEntries.filter(e => e.event.state === QueryTraceState.WAITING_STREAM).length\n    const syncCount = latestEntries.filter(e =>\n      [QueryTraceState.SYNC_WAITING, QueryTraceState.SYNC_FALLBACK].includes(e.event.state),\n    ).length\n\n    // Calculate timing statistics - time from sent to first response\n    // Group entries by trace ID\n    const traceTimings = new Map<string, number>()\n    const traceGroups = new Map<string, Array<TimelineEntry>>()\n    for (const entry of entries) {\n      const traceId = entry.event.id\n      if (!traceGroups.has(traceId)) {\n        traceGroups.set(traceId, [])\n      }\n      traceGroups.get(traceId)!.push(entry)\n    }\n\n    // Calculate response time for each trace\n    for (const [traceId, traceEntries] of traceGroups) {\n      // Sort by timestamp\n      traceEntries.sort((a, b) => a.event.timestamp - b.event.timestamp)\n\n      // Find the first \"sent\" event (WAITING or WAITING_STREAM)\n      const sentEntry = traceEntries.find(e =>\n        [QueryTraceState.WAITING, QueryTraceState.WAITING_STREAM].includes(e.event.state),\n      )\n\n      // Find the first completion event\n      const completionEntry = traceEntries.find(e =>\n        [QueryTraceState.EOSE, QueryTraceState.REMOTE_CLOSE, QueryTraceState.LOCAL_CLOSE].includes(e.event.state),\n      )\n\n      if (sentEntry && completionEntry) {\n        const responseTime = completionEntry.event.timestamp - sentEntry.event.timestamp\n        traceTimings.set(traceId, responseTime)\n      }\n    }\n\n    const runtimes = Array.from(traceTimings.values())\n    const avgRuntime = runtimes.length > 0 ? runtimes.reduce((a, b) => a + b, 0) / runtimes.length : 0\n    const minRuntime = runtimes.length > 0 ? Math.min(...runtimes) : 0\n    const maxRuntime = runtimes.length > 0 ? Math.max(...runtimes) : 0\n    const medianRuntime = runtimes.length > 0 ? runtimes.sort((a, b) => a - b)[Math.floor(runtimes.length / 2)] : 0\n\n    interface RelayStatDetails {\n      count: number\n      timeoutCount: number\n      dropCount: number\n      queuedCount: number\n      streamingCount: number\n      completedCount: number\n      avgRuntime: number\n      minRuntime: number\n      maxRuntime: number\n    }\n\n    // Relay stats: count unique traces per relay, but use all entries for timing\n    const relayStats = new Map<string, RelayStatDetails>()\n    for (const entry of latestEntries) {\n      const addr = sanitizeRelayUrl(entry.event.relay)!\n      const existing = relayStats.get(addr) || {\n        count: 0,\n        timeoutCount: 0,\n        dropCount: 0,\n        queuedCount: 0,\n        streamingCount: 0,\n        completedCount: 0,\n        avgRuntime: 0,\n        minRuntime: Infinity,\n        maxRuntime: 0,\n      }\n      existing.count++\n      if (entry.event.state === QueryTraceState.TIMEOUT) existing.timeoutCount++\n      if (entry.event.state === QueryTraceState.DROP) existing.dropCount++\n      if (entry.event.state === QueryTraceState.QUEUED) existing.queuedCount++\n      if (entry.event.state === QueryTraceState.WAITING_STREAM) existing.streamingCount++\n      if (\n        [QueryTraceState.EOSE, QueryTraceState.REMOTE_CLOSE, QueryTraceState.LOCAL_CLOSE].includes(entry.event.state)\n      ) {\n        existing.completedCount++\n      }\n      relayStats.set(addr, existing)\n    }\n\n    // Add timing statistics per relay using the traceGroups already calculated above\n    for (const [traceId, traceEntries] of traceGroups) {\n      // Sort by timestamp to ensure correct order\n      traceEntries.sort((a, b) => a.event.timestamp - b.event.timestamp)\n\n      // Find the first \"sent\" event (WAITING or WAITING_STREAM)\n      const sentEntry = traceEntries.find(e =>\n        [QueryTraceState.WAITING, QueryTraceState.WAITING_STREAM].includes(e.event.state),\n      )\n\n      // Find the first completion event\n      const completionEntry = traceEntries.find(e =>\n        [QueryTraceState.EOSE, QueryTraceState.REMOTE_CLOSE, QueryTraceState.LOCAL_CLOSE].includes(e.event.state),\n      )\n\n      if (sentEntry && completionEntry) {\n        const responseTime = completionEntry.event.timestamp - sentEntry.event.timestamp\n        const addr = sanitizeRelayUrl(sentEntry.event.relay)!\n        const stat = relayStats.get(addr)\n        if (stat) {\n          stat.avgRuntime += responseTime\n          stat.minRuntime = Math.min(stat.minRuntime, responseTime)\n          stat.maxRuntime = Math.max(stat.maxRuntime, responseTime)\n        }\n      }\n    }\n\n    // Finalize averages\n    for (const [relay, stat] of relayStats) {\n      stat.avgRuntime = stat.completedCount > 0 ? stat.avgRuntime / stat.completedCount : 0\n      if (stat.minRuntime === Infinity) stat.minRuntime = 0\n    }\n\n    // Group by query name (count unique traces)\n    const queryNameStats = new Map<string, number>()\n    for (const entry of latestEntries) {\n      if (entry.queryName) {\n        queryNameStats.set(entry.queryName, (queryNameStats.get(entry.queryName) || 0) + 1)\n      }\n    }\n\n    return {\n      totalEntries: latestEntries.length, // Count unique traces, not all state transitions\n      forcedCount,\n      completedCount,\n      queuedCount,\n      waitingCount,\n      streamingCount,\n      syncCount,\n      avgRuntime,\n      minRuntime,\n      maxRuntime,\n      medianRuntime,\n      relayStats: [...relayStats.entries()].sort((a, b) => b[1].count - a[1].count),\n      queryNameStats: [...queryNameStats.entries()].sort((a, b) => b[1] - a[1]),\n    }\n  }, [entries])\n\n  const formatTime = (ms: number) => {\n    if (ms < 1000) return `${ms.toFixed(0)}ms`\n    return `${(ms / 1000).toFixed(2)}s`\n  }\n\n  const exportGoogleTrace = () => {\n    if (!system.traceTimeline) return\n    const traceData = system.traceTimeline.exportGoogleTrace()\n\n    // Download as JSON file\n    const blob = new Blob([JSON.stringify(traceData, null, 2)], {\n      type: \"application/json\",\n    })\n    const url = URL.createObjectURL(blob)\n    const a = document.createElement(\"a\")\n    a.href = url\n    a.download = `nostr-trace-${Date.now()}.json`\n    document.body.appendChild(a)\n    a.click()\n    document.body.removeChild(a)\n    URL.revokeObjectURL(url)\n  }\n\n  const openInPerfetto = () => {\n    if (!system.traceTimeline) return\n    const traceData = system.traceTimeline.exportGoogleTrace()\n    const jsonString = JSON.stringify(traceData)\n\n    // Convert JSON string to ArrayBuffer\n    const encoder = new TextEncoder()\n    const arrayBuffer = encoder.encode(jsonString).buffer\n\n    // Open Perfetto UI\n    const win = window.open(\"https://ui.perfetto.dev\")\n    if (!win) {\n      alert(\"Failed to open Perfetto UI. Please allow popups for this site.\")\n      return\n    }\n\n    // Use PING/PONG protocol to wait for Perfetto UI to be ready\n    const pingInterval = setInterval(() => {\n      win.postMessage(\"PING\", \"https://ui.perfetto.dev\")\n    }, 50)\n\n    const onMessageHandler = (evt: MessageEvent) => {\n      if (evt.data !== \"PONG\") return\n\n      // Clear the ping interval\n      clearInterval(pingInterval)\n      window.removeEventListener(\"message\", onMessageHandler)\n\n      // Send the trace data\n      win.postMessage(\n        {\n          perfetto: {\n            buffer: arrayBuffer,\n            title: \"Nostr Relay Query Traces\",\n            fileName: `nostr-trace-${Date.now()}.json`,\n          },\n        },\n        \"https://ui.perfetto.dev\",\n      )\n    }\n\n    window.addEventListener(\"message\", onMessageHandler)\n\n    // Timeout after 10 seconds\n    setTimeout(() => {\n      clearInterval(pingInterval)\n      window.removeEventListener(\"message\", onMessageHandler)\n    }, 10000)\n  }\n\n  if (!stats) {\n    return <div className=\"trace-stats-no-data\">No trace data available</div>\n  }\n\n  return (\n    <div className=\"trace-stats-container\">\n      {/* Export Buttons */}\n      <div className=\"trace-stats-export-buttons\">\n        <button\n          onClick={openInPerfetto}\n          disabled={entries.length === 0}\n          className=\"trace-timeline-btn-export\"\n          title=\"Open trace in Perfetto UI\"\n        >\n          Open in Perfetto\n        </button>\n        <button\n          onClick={exportGoogleTrace}\n          disabled={entries.length === 0}\n          className=\"trace-timeline-btn-export\"\n          title=\"Download trace as JSON\"\n        >\n          Export JSON\n        </button>\n      </div>\n\n      {/* Overview Stats */}\n      <div className=\"trace-stats-grid\">\n        <div className=\"trace-stats-card\">\n          <div className=\"trace-stats-card-label\">Total Queries</div>\n          <div className=\"trace-stats-card-value\">{stats.totalEntries}</div>\n        </div>\n        <div className=\"trace-stats-card\">\n          <div className=\"trace-stats-card-label\">Completed</div>\n          <div className=\"trace-stats-card-value-xl trace-stats-value-green\">\n            {stats.completedCount} ({((stats.completedCount / stats.totalEntries) * 100).toFixed(1)}%)\n          </div>\n        </div>\n        <div className=\"trace-stats-card\">\n          <div className=\"trace-stats-card-label\">Forced EOSE</div>\n          <div className=\"trace-stats-card-value-xl trace-stats-value-yellow\">\n            {stats.forcedCount} ({((stats.forcedCount / stats.totalEntries) * 100).toFixed(1)}%)\n          </div>\n        </div>\n        <div className=\"trace-stats-card\">\n          <div className=\"trace-stats-card-label\">Queued</div>\n          <div className=\"trace-stats-card-value-xl trace-stats-value-blue\">{stats.queuedCount}</div>\n        </div>\n      </div>\n\n      {/* State Breakdown */}\n      <div className=\"trace-stats-card\">\n        <h3 className=\"trace-stats-section-title\">State Distribution</h3>\n        <div className=\"trace-stats-grid\">\n          <div>\n            <div className=\"trace-stats-card-label\">Waiting</div>\n            <div className=\"trace-stats-card-value-lg\">{stats.waitingCount}</div>\n          </div>\n          <div>\n            <div className=\"trace-stats-card-label\">Streaming</div>\n            <div className=\"trace-stats-card-value-lg trace-stats-value-purple\">{stats.streamingCount}</div>\n          </div>\n          <div>\n            <div className=\"trace-stats-card-label\">Syncing</div>\n            <div className=\"trace-stats-card-value-lg\">{stats.syncCount}</div>\n          </div>\n          <div>\n            <div className=\"trace-stats-card-label\">Success Rate</div>\n            <div className=\"trace-stats-card-value-lg trace-stats-value-green\">\n              {((stats.completedCount / (stats.completedCount + stats.forcedCount || 1)) * 100).toFixed(1)}%\n            </div>\n          </div>\n        </div>\n      </div>\n\n      {/* Timing Statistics */}\n      <div className=\"trace-stats-card\">\n        <h3 className=\"trace-stats-section-title\">Query Performance</h3>\n        <div className=\"trace-stats-grid\">\n          <div>\n            <div className=\"trace-stats-card-label\">Average</div>\n            <div className=\"trace-stats-card-value-lg\">{formatTime(stats.avgRuntime)}</div>\n          </div>\n          <div>\n            <div className=\"trace-stats-card-label\">Median</div>\n            <div className=\"trace-stats-card-value-lg\">{formatTime(stats.medianRuntime)}</div>\n          </div>\n          <div>\n            <div className=\"trace-stats-card-label\">Min</div>\n            <div className=\"trace-stats-card-value-lg trace-stats-value-green\">{formatTime(stats.minRuntime)}</div>\n          </div>\n          <div>\n            <div className=\"trace-stats-card-label\">Max</div>\n            <div className=\"text-lg font-semibold text-yellow-600 dark:text-yellow-400\">\n              {formatTime(stats.maxRuntime)}\n            </div>\n          </div>\n        </div>\n      </div>\n\n      {/* Query Names */}\n      {stats.queryNameStats.length > 0 && (\n        <div className=\"trace-stats-card\">\n          <h3 className=\"trace-stats-section-title\">Query Names</h3>\n          <div className=\"flex flex-col gap-2\">\n            {stats.queryNameStats.map(([name, count]) => (\n              <div key={name} className=\"flex items-center justify-between\">\n                <div className=\"text-sm font-mono truncate flex-1\" title={name}>\n                  {name}\n                </div>\n                <div className=\"text-sm text-gray-600 dark:text-gray-400 ml-2\">\n                  {count} ({((count / stats.totalEntries) * 100).toFixed(1)}%)\n                </div>\n              </div>\n            ))}\n          </div>\n        </div>\n      )}\n\n      {/* Relay Statistics */}\n      <div className=\"trace-stats-card\">\n        <h3 className=\"trace-stats-section-title\">Relay Performance</h3>\n        <div className=\"overflow-x-auto\">\n          <table className=\"w-full text-sm\">\n            <thead>\n              <tr className=\"border-b dark:border-gray-700\">\n                <th className=\"text-left py-2 font-semibold\">Relay</th>\n                <th className=\"text-right py-2 font-semibold\">Queries</th>\n                <th className=\"text-right py-2 font-semibold\">Completed</th>\n                <th className=\"text-right py-2 font-semibold\">Queued</th>\n                <th className=\"text-right py-2 font-semibold\">Streaming</th>\n                <th className=\"text-right py-2 font-semibold\">Timeout</th>\n                <th className=\"text-right py-2 font-semibold\">Drop</th>\n                <th className=\"text-right py-2 font-semibold\">Avg Time</th>\n                <th className=\"text-right py-2 font-semibold\">Min/Max</th>\n              </tr>\n            </thead>\n            <tbody>\n              {stats.relayStats.map(([relay, stat]) => (\n                <tr key={relay} className=\"border-b dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-800\">\n                  <td className=\"py-2 font-mono text-xs truncate max-w-xs\" title={relay}>\n                    {new URL(relay).hostname}\n                  </td>\n                  <td className=\"text-right py-2\">{stat.count}</td>\n                  <td className=\"text-right py-2\">\n                    <span className=\"text-green-600 dark:text-green-400\">{stat.completedCount}</span>\n                  </td>\n                  <td className=\"text-right py-2\">\n                    {stat.queuedCount > 0 ? (\n                      <span className=\"text-blue-600 dark:text-blue-400\">{stat.queuedCount}</span>\n                    ) : (\n                      <span className=\"text-gray-400\">-</span>\n                    )}\n                  </td>\n                  <td className=\"text-right py-2\">\n                    {stat.streamingCount > 0 ? (\n                      <span className=\"text-purple-600 dark:text-purple-400\">{stat.streamingCount}</span>\n                    ) : (\n                      <span className=\"text-gray-400\">-</span>\n                    )}\n                  </td>\n                  <td className=\"text-right py-2\">\n                    {stat.timeoutCount > 0 ? (\n                      <span className=\"text-red-600 dark:text-red-400\">{stat.timeoutCount}</span>\n                    ) : (\n                      <span className=\"text-gray-400\">-</span>\n                    )}\n                  </td>\n                  <td className=\"text-right py-2\">\n                    {stat.dropCount > 0 ? (\n                      <span className=\"text-orange-600 dark:text-orange-400\">{stat.dropCount}</span>\n                    ) : (\n                      <span className=\"text-gray-400\">-</span>\n                    )}\n                  </td>\n                  <td className=\"text-right py-2 font-mono text-xs\">\n                    {stat.completedCount > 0 ? formatTime(stat.avgRuntime) : \"-\"}\n                  </td>\n                  <td className=\"text-right py-2 font-mono text-xs\">\n                    {stat.completedCount > 0 ? (\n                      <>\n                        <span className=\"text-green-600 dark:text-green-400\">{formatTime(stat.minRuntime)}</span>\n                        {\" / \"}\n                        <span className=\"text-yellow-600 dark:text-yellow-400\">{formatTime(stat.maxRuntime)}</span>\n                      </>\n                    ) : (\n                      \"-\"\n                    )}\n                  </td>\n                </tr>\n              ))}\n            </tbody>\n          </table>\n        </div>\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/system-react/src/TraceTimeline/TraceTimeline.css",
    "content": ".trace-timeline-container {\n  display: flex;\n  flex-direction: column;\n  gap: 0.5rem;\n}\n\n.dark .trace-timeline-container {\n  color: #f3f4f6;\n}\n\n.trace-timeline-controls {\n  display: flex;\n  gap: 0.5rem;\n  align-items: center;\n}\n\n.trace-timeline-controls-right {\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n}\n\n/* Input */\n.trace-timeline-filter-input {\n  flex: 1;\n  padding: 0.5rem;\n  border: 1px solid #d1d5db;\n  border-radius: 0.25rem;\n\n  font-size: 14px;\n  line-height: 1.5;\n  color: #111827;\n  background-color: white;\n}\n\n.trace-timeline-filter-input:focus {\n  outline: none;\n  border-color: #3b82f6;\n  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);\n}\n\n.dark .trace-timeline-filter-input {\n  background-color: #1f2937;\n  border-color: #374151;\n  color: #f3f4f6;\n}\n\n/* Buttons */\n.trace-timeline-btn {\n  padding: 0.25rem 0.5rem;\n  font-size: 12px;\n  border: 1px solid #d1d5db;\n  border-radius: 0.25rem;\n  background-color: white;\n  color: #111827;\n  cursor: pointer;\n\n  line-height: 1.5;\n}\n\n.trace-timeline-btn:hover:not(:disabled) {\n  background-color: #f3f4f6;\n}\n\n.trace-timeline-btn:disabled {\n  opacity: 0.5;\n  cursor: not-allowed;\n}\n\n.dark .trace-timeline-btn {\n  border-color: #374151;\n  background-color: #1f2937;\n  color: #f3f4f6;\n}\n\n.dark .trace-timeline-btn:hover:not(:disabled) {\n  background-color: #374151;\n}\n\n.trace-timeline-btn-export {\n  padding: 0.25rem 0.75rem;\n  font-size: 12px;\n  border: 1px solid #d1d5db;\n  border-radius: 0.25rem;\n  background-color: white;\n  color: #111827;\n  cursor: pointer;\n\n  line-height: 1.5;\n}\n\n.trace-timeline-btn-export:hover:not(:disabled) {\n  background-color: #f3f4f6;\n}\n\n.trace-timeline-btn-export:disabled {\n  opacity: 0.5;\n  cursor: not-allowed;\n}\n\n.dark .trace-timeline-btn-export {\n  border-color: #374151;\n  background-color: #1f2937;\n  color: #f3f4f6;\n}\n\n.dark .trace-timeline-btn-export:hover:not(:disabled) {\n  background-color: #374151;\n}\n\n/* Text Labels */\n.trace-timeline-scale-label {\n  font-size: 0.875rem;\n  color: #4b5563;\n  min-width: 60px;\n  text-align: center;\n}\n\n.dark .trace-timeline-scale-label {\n  color: #9ca3af;\n}\n\n.trace-timeline-entry-count {\n  font-size: 0.875rem;\n  color: #4b5563;\n}\n\n.dark .trace-timeline-entry-count {\n  color: #9ca3af;\n}\n\n/* Main Timeline Container */\n.trace-timeline-main {\n  display: flex;\n  gap: 1rem;\n  flex: 1;\n  min-height: 0;\n}\n\n.trace-timeline-chart {\n  flex: 1;\n  border: 1px solid #d1d5db;\n  border-radius: 0.25rem;\n  overflow: hidden;\n  display: flex;\n  flex-direction: column;\n}\n\n.dark .trace-timeline-chart {\n  border-color: #374151;\n}\n\n/* Timeline Header */\n.trace-timeline-header {\n  display: flex;\n  border-bottom: 1px solid #d1d5db;\n}\n\n.dark .trace-timeline-header {\n  border-bottom-color: #374151;\n}\n\n.trace-timeline-header-label {\n  border-right: 1px solid #d1d5db;\n  background-color: #f9fafb;\n}\n\n.dark .trace-timeline-header-label {\n  border-right-color: #374151;\n  background-color: #111827;\n}\n\n.trace-timeline-header-ruler {\n  flex: 1;\n  position: relative;\n  height: 1.5rem;\n  background-color: #f3f4f6;\n  font-size: 0.75rem;\n  color: #4b5563;\n}\n\n.dark .trace-timeline-header-ruler {\n  background-color: #1f2937;\n  color: #9ca3af;\n}\n\n.trace-timeline-ruler-mark {\n  position: absolute;\n}\n\n.trace-timeline-ruler-mark-inner {\n  position: relative;\n}\n\n.trace-timeline-ruler-mark-text {\n  position: absolute;\n  transform: translateX(-50%);\n  padding-left: 0.25rem;\n  padding-right: 0.25rem;\n}\n\n/* Swimlanes */\n.trace-timeline-swimlanes {\n  flex: 1;\n  overflow-y: auto;\n  overflow-x: auto;\n}\n\n.trace-timeline-swimlanes::-webkit-scrollbar {\n  height: 8px;\n}\n\n.trace-timeline-swimlanes::-webkit-scrollbar-track {\n  background: #f1f1f1;\n}\n\n.dark .trace-timeline-swimlanes::-webkit-scrollbar-track {\n  background: #374151;\n}\n\n.trace-timeline-swimlanes::-webkit-scrollbar-thumb {\n  background: #888;\n  border-radius: 4px;\n}\n\n.trace-timeline-swimlanes::-webkit-scrollbar-thumb:hover {\n  background: #555;\n}\n\n.trace-timeline-swimlanes-content {\n  position: relative;\n}\n\n.trace-timeline-lane {\n  display: flex;\n  border-bottom: 1px solid #d1d5db;\n}\n\n.dark .trace-timeline-lane {\n  border-bottom-color: #374151;\n}\n\n.trace-timeline-lane-label {\n  display: flex;\n  align-items: center;\n  padding-left: 0.75rem;\n  padding-right: 0.75rem;\n  font-size: 0.875rem;\n  font-weight: 500;\n  background-color: #f9fafb;\n  border-right: 1px solid #d1d5db;\n  flex-shrink: 0;\n}\n\n.dark .trace-timeline-lane-label {\n  background-color: #111827;\n  border-right-color: #374151;\n}\n\n.trace-timeline-lane-label-content {\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.trace-timeline-relay-color {\n  width: 0.75rem;\n  height: 0.75rem;\n  border-radius: 0.125rem;\n  flex-shrink: 0;\n}\n\n.trace-timeline-relay-name {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n.trace-timeline-lane-bars {\n  flex: 1;\n  position: relative;\n}\n\n/* Timeline Bars */\n.trace-timeline-bar {\n  position: absolute;\n  cursor: pointer;\n  transition: all 0.2s;\n}\n\n.trace-timeline-bar:hover {\n  filter: brightness(1.1);\n}\n\n.trace-timeline-bar-label {\n  font-size: 0.75rem;\n  color: white;\n  padding-left: 0.25rem;\n  padding-right: 0.25rem;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n/* Modal Overlay */\n.trace-timeline-overlay,\n.trace-timeline-overlay *,\n.trace-timeline-overlay input,\n.trace-timeline-overlay button {\n  box-sizing: border-box;\n  font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif;\n}\n\n.trace-timeline-overlay {\n  position: fixed;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  background-color: rgba(0, 0, 0, 0.5);\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  z-index: 50;\n  padding: 1rem;\n  font-size: 14px;\n  line-height: 1.5;\n  color: #111827;\n}\n\n.dark .trace-timeline-overlay {\n  color: #f3f4f6;\n}\n\n/* Modal Container */\n.trace-timeline-modal {\n  width: 90vw;\n  max-width: 1400px;\n  height: 80vh;\n  background-color: white;\n  color: #111827;\n  border-radius: 0.5rem;\n  display: flex;\n  flex-direction: column;\n  box-shadow:\n    0 20px 25px -5px rgba(0, 0, 0, 0.1),\n    0 10px 10px -5px rgba(0, 0, 0, 0.04);\n}\n\n.dark .trace-timeline-modal {\n  background-color: #1f2937;\n  color: #f3f4f6;\n}\n\n/* Modal Header */\n.trace-timeline-modal-header {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  padding: 0.75rem 1rem;\n  border-bottom: 1px solid #d1d5db;\n}\n\n.dark .trace-timeline-modal-header {\n  border-bottom-color: #374151;\n}\n\n.trace-timeline-modal-title {\n  font-size: 1.25rem;\n  font-weight: 600;\n  color: #111827;\n  margin: 0;\n}\n\n.dark .trace-timeline-modal-title {\n  color: #f3f4f6;\n}\n\n/* Modal Tabs */\n.trace-timeline-modal-tabs {\n  display: flex;\n  gap: 0.5rem;\n}\n\n.trace-timeline-modal-tab {\n  padding: 0.5rem 1rem;\n  background: transparent;\n  border: none;\n  border-bottom: 2px solid transparent;\n  cursor: pointer;\n  font-weight: 500;\n  color: #6b7280;\n\n  font-size: 14px;\n  line-height: 1.5;\n}\n\n.trace-timeline-modal-tab:hover {\n  color: #111827;\n}\n\n.dark .trace-timeline-modal-tab {\n  color: #9ca3af;\n}\n\n.dark .trace-timeline-modal-tab:hover {\n  color: #f3f4f6;\n}\n\n.trace-timeline-modal-tab.active {\n  color: #3b82f6;\n  border-bottom-color: #3b82f6;\n}\n\n/* Modal Controls */\n.trace-timeline-modal-controls {\n  display: flex;\n  gap: 0.5rem;\n}\n\n.trace-timeline-modal-control-btn {\n  width: 2rem;\n  height: 2rem;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  background: transparent;\n  border: none;\n  border-radius: 0.25rem;\n  cursor: pointer;\n  color: #6b7280;\n  font-size: 20px;\n\n  line-height: 1;\n}\n\n.trace-timeline-modal-control-btn:hover {\n  background-color: #f3f4f6;\n  color: #111827;\n}\n\n.dark .trace-timeline-modal-control-btn {\n  color: #9ca3af;\n}\n\n.dark .trace-timeline-modal-control-btn:hover {\n  background-color: #374151;\n  color: #f3f4f6;\n}\n\n/* Modal Content */\n.trace-timeline-modal-content {\n  padding: 1rem;\n  overflow: auto;\n}\n\n/* Minimized State */\n.trace-timeline-minimized {\n  position: fixed;\n  bottom: 1rem;\n  right: 1rem;\n  display: flex;\n  align-items: center;\n  gap: 0.5rem;\n  background-color: white;\n  border: 1px solid #d1d5db;\n  border-radius: 0.5rem;\n  padding: 0.5rem 1rem;\n  box-shadow:\n    0 4px 6px -1px rgba(0, 0, 0, 0.1),\n    0 2px 4px -1px rgba(0, 0, 0, 0.06);\n}\n\n.dark .trace-timeline-minimized {\n  background-color: #1f2937;\n  border-color: #374151;\n}\n\n.trace-timeline-restore-btn {\n  background: transparent;\n  border: none;\n  cursor: pointer;\n  font-weight: 500;\n  color: #3b82f6;\n}\n\n.trace-timeline-restore-btn:hover {\n  text-decoration: underline;\n}\n\n.trace-timeline-minimized-close {\n  background: transparent;\n  border: none;\n  cursor: pointer;\n  color: #6b7280;\n  font-size: 1.25rem;\n  width: 1.5rem;\n  height: 1.5rem;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  border-radius: 0.25rem;\n}\n\n.trace-timeline-minimized-close:hover {\n  background-color: #f3f4f6;\n  color: #111827;\n}\n\n.dark .trace-timeline-minimized-close {\n  color: #9ca3af;\n}\n\n.dark .trace-timeline-minimized-close:hover {\n  background-color: #374151;\n  color: #f3f4f6;\n}\n\n/* Details Panel (side panel for individual query details) */\n.trace-timeline-details {\n  width: 400px;\n  flex-shrink: 0;\n  border: 1px solid #d1d5db;\n  border-radius: 0.25rem;\n  background-color: white;\n  color: #111827;\n  display: flex;\n  flex-direction: column;\n  gap: 0.75rem;\n  overflow-y: auto;\n  padding: 1.5rem;\n\n  font-size: 14px;\n  line-height: 1.5;\n  align-self: stretch;\n}\n\n.dark .trace-timeline-details {\n  border-color: #374151;\n  background-color: #1f2937;\n  color: #f3f4f6;\n}\n\n.trace-timeline-details-title {\n  font-weight: bold;\n  font-size: 18px;\n  color: #111827;\n\n  line-height: 1.5;\n}\n\n.dark .trace-timeline-details-title {\n  color: #f3f4f6;\n}\n\n.trace-timeline-details-content {\n  display: flex;\n  flex-direction: column;\n  gap: 0.75rem;\n  font-size: 14px;\n  color: #111827;\n\n  line-height: 1.5;\n}\n\n.dark .trace-timeline-details-content {\n  color: #f3f4f6;\n}\n\n.trace-timeline-detail-row {\n  display: flex;\n  flex-direction: column;\n  gap: 0.25rem;\n}\n\n.trace-timeline-detail-row-inline {\n  display: flex;\n  justify-content: space-between;\n  align-items: center;\n  border-top: 1px solid #d1d5db;\n  padding-top: 0.5rem;\n}\n\n.dark .trace-timeline-detail-row-inline {\n  border-top-color: #374151;\n}\n\n.trace-timeline-detail-label {\n  color: #4b5563;\n  font-size: 12px;\n  text-transform: uppercase;\n  font-weight: 600;\n\n  line-height: 1.5;\n}\n\n.dark .trace-timeline-detail-label {\n  color: #9ca3af;\n}\n\n.trace-timeline-detail-value {\n  font-family:\n    ui-monospace, \"SF Mono\", Monaco, \"Cascadia Mono\", \"Segoe UI Mono\", \"Roboto Mono\", \"Oxygen Mono\", \"Ubuntu Monospace\",\n    \"Source Code Pro\", \"Fira Mono\", \"Droid Sans Mono\", \"Courier New\", monospace;\n  font-size: 12px;\n  word-break: break-all;\n  color: #111827;\n  line-height: 1.5;\n}\n\n.dark .trace-timeline-detail-value {\n  color: #f3f4f6;\n}\n\n.trace-timeline-detail-value-large {\n  font-weight: bold;\n  font-size: 18px;\n  color: #111827;\n\n  line-height: 1.5;\n}\n\n.dark .trace-timeline-detail-value-large {\n  color: #f3f4f6;\n}\n\n.trace-timeline-detail-value-streaming {\n  font-weight: bold;\n  font-size: 18px;\n  color: #9333ea;\n\n  line-height: 1.5;\n}\n\n.dark .trace-timeline-detail-value-streaming {\n  color: #c084fc;\n}\n\n.trace-timeline-detail-value-name {\n  font-family:\n    ui-monospace, \"SF Mono\", Monaco, \"Cascadia Mono\", \"Segoe UI Mono\", \"Roboto Mono\", \"Oxygen Mono\", \"Ubuntu Monospace\",\n    \"Source Code Pro\", \"Fira Mono\", \"Droid Sans Mono\", \"Courier New\", monospace;\n  font-size: 14px;\n  font-weight: bold;\n  color: #111827;\n  line-height: 1.5;\n}\n\n.dark .trace-timeline-detail-value-name {\n  color: #f3f4f6;\n}\n\n.trace-timeline-filters-list {\n  display: flex;\n  flex-direction: column;\n  gap: 0.5rem;\n}\n\n.trace-timeline-filter-box {\n  background-color: #f9fafb;\n  border-radius: 0.25rem;\n  padding: 0.5rem;\n  font-family: ui-monospace, monospace;\n  font-size: 0.75rem;\n  overflow-x: auto;\n}\n\n.dark .trace-timeline-filter-box {\n  background-color: #111827;\n}\n\n.trace-timeline-filter-pre {\n  white-space: pre-wrap;\n  word-break: break-all;\n}\n\n.trace-timeline-close-btn {\n  margin-top: 0.5rem;\n  padding: 0.375rem 0.75rem;\n  background-color: #f3f4f6;\n  color: #111827;\n  border-radius: 0.25rem;\n  font-size: 14px;\n  font-weight: 500;\n  cursor: pointer;\n  border: none;\n\n  line-height: 1.5;\n}\n\n.trace-timeline-close-btn:hover {\n  background-color: #e5e7eb;\n}\n\n.dark .trace-timeline-close-btn {\n  background-color: #1f2937;\n  color: #f3f4f6;\n}\n\n.dark .trace-timeline-close-btn:hover {\n  background-color: #374151;\n}\n\n/* Status Badge Styles */\n.status-badge {\n  padding: 0.25rem 0.5rem;\n  border-radius: 0.25rem;\n  font-size: 0.75rem;\n  font-weight: 500;\n}\n\n/* Streaming state - Purple */\n.status-streaming {\n  background-color: #f3e8ff;\n  color: #6b21a8;\n}\n\n.dark .status-streaming {\n  background-color: #581c87;\n  color: #e9d5ff;\n}\n\n/* Active/Pending states - Blue */\n.status-active {\n  background-color: #dbeafe;\n  color: #1e40af;\n}\n\n.dark .status-active {\n  background-color: #1e3a8a;\n  color: #bfdbfe;\n}\n\n/* Error states - Red */\n.status-error {\n  background-color: #fee2e2;\n  color: #991b1b;\n}\n\n.dark .status-error {\n  background-color: #7f1d1d;\n  color: #fecaca;\n}\n\n/* Success states - Green */\n.status-success {\n  background-color: #dcfce7;\n  color: #166534;\n}\n\n.dark .status-success {\n  background-color: #14532d;\n  color: #bbf7d0;\n}\n\n/* Fallback - Gray */\n.status-fallback {\n  background-color: #f3f4f6;\n  color: #1f2937;\n}\n\n.dark .status-fallback {\n  background-color: #111827;\n  color: #e5e7eb;\n}\n\n/* Animations */\n@keyframes pulse {\n  0%,\n  100% {\n    opacity: 1;\n  }\n  50% {\n    opacity: 0.7;\n  }\n}\n\n/* Stats View Styles */\n.trace-stats-container {\n  display: flex;\n  flex-direction: column;\n  gap: 1rem;\n}\n\n.trace-stats-export-buttons {\n  display: flex;\n  gap: 0.5rem;\n  justify-content: flex-end;\n}\n\n.trace-stats-no-data {\n  color: #6b7280;\n}\n\n.dark .trace-stats-no-data {\n  color: #9ca3af;\n}\n\n.trace-stats-grid {\n  display: grid;\n  grid-template-columns: repeat(2, 1fr);\n  gap: 1rem;\n}\n\n@media (min-width: 768px) {\n  .trace-stats-grid {\n    grid-template-columns: repeat(4, 1fr);\n  }\n}\n\n.trace-stats-card {\n  border: 1px solid #d1d5db;\n  border-radius: 0.25rem;\n  padding: 1rem;\n}\n\n.dark .trace-stats-card {\n  border-color: #374151;\n}\n\n.trace-stats-card-label {\n  font-size: 0.875rem;\n  color: #4b5563;\n}\n\n.dark .trace-stats-card-label {\n  color: #9ca3af;\n}\n\n.trace-stats-card-value {\n  font-size: 1.5rem;\n  font-weight: bold;\n}\n\n.trace-stats-card-value-xl {\n  font-size: 1.25rem;\n  font-weight: bold;\n}\n\n.trace-stats-card-value-lg {\n  font-size: 1.125rem;\n  font-weight: 600;\n}\n\n.trace-stats-value-green {\n  color: #16a34a;\n}\n\n.dark .trace-stats-value-green {\n  color: #4ade80;\n}\n\n.trace-stats-value-yellow {\n  color: #ca8a04;\n}\n\n.dark .trace-stats-value-yellow {\n  color: #facc15;\n}\n\n.trace-stats-value-blue {\n  color: #2563eb;\n}\n\n.dark .trace-stats-value-blue {\n  color: #60a5fa;\n}\n\n.trace-stats-value-purple {\n  color: #9333ea;\n}\n\n.dark .trace-stats-value-purple {\n  color: #c084fc;\n}\n\n.trace-stats-section-title {\n  font-weight: bold;\n  margin-bottom: 0.75rem;\n}\n\n.trace-stats-table {\n  width: 100%;\n  font-size: 0.875rem;\n}\n\n.trace-stats-table-overflow {\n  overflow-x: auto;\n}\n\n.trace-stats-table thead tr {\n  border-bottom: 1px solid #d1d5db;\n}\n\n.dark .trace-stats-table thead tr {\n  border-bottom-color: #374151;\n}\n\n.trace-stats-table th {\n  text-align: left;\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem;\n  font-weight: 600;\n}\n\n.trace-stats-table th.text-right {\n  text-align: right;\n}\n\n.trace-stats-table tbody tr {\n  border-bottom: 1px solid #d1d5db;\n}\n\n.dark .trace-stats-table tbody tr {\n  border-bottom-color: #374151;\n}\n\n.trace-stats-table tbody tr:hover {\n  background-color: #f9fafb;\n}\n\n.dark .trace-stats-table tbody tr:hover {\n  background-color: #1f2937;\n}\n\n.trace-stats-table td {\n  padding-top: 0.5rem;\n  padding-bottom: 0.5rem;\n}\n\n.trace-stats-table td.text-right {\n  text-align: right;\n}\n\n.trace-stats-relay-name {\n  font-family: ui-monospace, monospace;\n  font-size: 0.75rem;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  max-width: 20rem;\n}\n\n.trace-stats-list {\n  display: flex;\n  flex-direction: column;\n  gap: 0.5rem;\n}\n\n.trace-stats-list-item {\n  display: flex;\n  align-items: center;\n  justify-content: space-between;\n}\n\n.trace-stats-query-name {\n  font-family: ui-monospace, monospace;\n  font-size: 0.875rem;\n  overflow: hidden;\n  text-overflow: ellipsis;\n  flex: 1;\n}\n\n.trace-stats-count {\n  font-size: 0.875rem;\n  color: #4b5563;\n  margin-left: 0.5rem;\n}\n\n.dark .trace-stats-count {\n  color: #9ca3af;\n}\n\n.trace-stats-time {\n  font-family: ui-monospace, monospace;\n  font-size: 0.75rem;\n}\n\n.trace-stats-dash {\n  color: #9ca3af;\n}\n\n.dark .trace-stats-dash {\n  color: #6b7280;\n}\n"
  },
  {
    "path": "packages/system-react/src/TraceTimeline/TraceTimelineDetailPopup.tsx",
    "content": "import { QueryTraceState, type TimelineEntry } from \"@snort/system\"\nimport \"./TraceTimeline.css\"\n\ninterface TraceTimelineDetailPopupProps {\n  selectedEntry: TimelineEntry\n  onClose: () => void\n}\n\nexport function TraceTimelineDetailPopup({ selectedEntry, onClose }: TraceTimelineDetailPopupProps) {\n  const formatTime = (ms: number) => {\n    if (ms < 1) return `${(ms * 1000).toFixed(0)}μs`\n    if (ms < 1000) return `${ms.toFixed(0)}ms`\n    return `${(ms / 1000).toFixed(2)}s`\n  }\n\n  const formatTimestamp = (unixMs: number) => {\n    const date = new Date(unixMs)\n    return date.toLocaleString(undefined, {\n      year: \"numeric\",\n      month: \"short\",\n      day: \"numeric\",\n      hour: \"2-digit\",\n      minute: \"2-digit\",\n      second: \"2-digit\",\n      fractionalSecondDigits: 3,\n    })\n  }\n\n  const getStatusBadgeClass = (state: QueryTraceState): string => {\n    // Streaming\n    if (state === QueryTraceState.WAITING_STREAM) {\n      return \"status-badge status-streaming\"\n    }\n    // Active/pending states\n    if (\n      [\n        QueryTraceState.QUEUED,\n        QueryTraceState.WAITING,\n        QueryTraceState.SYNC_WAITING,\n        QueryTraceState.SYNC_FALLBACK,\n      ].includes(state)\n    ) {\n      return \"status-badge status-active\"\n    }\n    // Error states\n    if ([QueryTraceState.TIMEOUT, QueryTraceState.DROP].includes(state)) {\n      return \"status-badge status-error\"\n    }\n    // Success states\n    if ([QueryTraceState.EOSE, QueryTraceState.LOCAL_CLOSE, QueryTraceState.REMOTE_CLOSE].includes(state)) {\n      return \"status-badge status-success\"\n    }\n    // Fallback\n    return \"status-badge status-fallback\"\n  }\n\n  return (\n    <div className=\"trace-timeline-details\">\n      <h3 className=\"trace-timeline-details-title\">Query Details</h3>\n      <div className=\"trace-timeline-details-content\">\n        <div className=\"trace-timeline-detail-row\">\n          <span className=\"trace-timeline-detail-label\">Relay</span>\n          <span className=\"trace-timeline-detail-value\">{selectedEntry.event.relay}</span>\n        </div>\n\n        <div className=\"trace-timeline-detail-row\">\n          <span className=\"trace-timeline-detail-label\">Timestamp</span>\n          <span className=\"trace-timeline-detail-value\">{formatTimestamp(selectedEntry.event.timestamp)}</span>\n        </div>\n\n        {selectedEntry.runtime !== undefined && (\n          <div className=\"trace-timeline-detail-row-inline\">\n            <span className=\"trace-timeline-detail-label\">Runtime:</span>\n            <span className=\"trace-timeline-detail-value-large\">{formatTime(selectedEntry.runtime)}</span>\n          </div>\n        )}\n\n        {selectedEntry.event.state === QueryTraceState.WAITING_STREAM && (\n          <div className=\"trace-timeline-detail-row-inline\">\n            <span className=\"trace-timeline-detail-label\">Duration:</span>\n            <span className=\"trace-timeline-detail-value-streaming\">\n              {formatTime(Date.now() - selectedEntry.event.timestamp)} (streaming)\n            </span>\n          </div>\n        )}\n\n        <div className=\"trace-timeline-detail-row-inline\">\n          <span className=\"trace-timeline-detail-label\">Status:</span>\n          <span className={getStatusBadgeClass(selectedEntry.event.state)}>{selectedEntry.event.state}</span>\n        </div>\n\n        {selectedEntry.queryName && (\n          <div className=\"trace-timeline-detail-row trace-timeline-detail-row-inline\">\n            <span className=\"trace-timeline-detail-label\">Query Name</span>\n            <span className=\"trace-timeline-detail-value-name\">{selectedEntry.queryName}</span>\n          </div>\n        )}\n\n        <div className=\"trace-timeline-detail-row\">\n          <span className=\"trace-timeline-detail-label\">Trace ID</span>\n          <span className=\"trace-timeline-detail-value\">{selectedEntry.event.id}</span>\n        </div>\n\n        <div className=\"trace-timeline-detail-row\">\n          <span className=\"trace-timeline-detail-label\">Connection ID</span>\n          <span className=\"trace-timeline-detail-value\">{selectedEntry.event.connId}</span>\n        </div>\n\n        {selectedEntry.event.filters && selectedEntry.event.filters.length > 0 && (\n          <div className=\"trace-timeline-detail-row trace-timeline-detail-row-inline\">\n            <span className=\"trace-timeline-detail-label\">Filters ({selectedEntry.event.filters.length})</span>\n            <div className=\"trace-timeline-filters-list\">\n              {selectedEntry.event.filters.map((filter, idx) => (\n                <div key={idx} className=\"trace-timeline-filter-box\">\n                  <pre className=\"trace-timeline-filter-pre\">{JSON.stringify(filter, null, 2)}</pre>\n                </div>\n              ))}\n            </div>\n          </div>\n        )}\n      </div>\n\n      <button onClick={onClose} className=\"trace-timeline-close-btn\">\n        Close\n      </button>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/system-react/src/TraceTimeline/TraceTimelineOverlay.tsx",
    "content": "import { createPortal } from \"react-dom\"\nimport { TraceStatsView } from \"./TraceStatsView\"\nimport \"./TraceTimeline.css\"\n\ninterface TraceTimelineOverlayProps {\n  isOpen: boolean\n  onClose: () => void\n}\n\nexport function TraceTimelineOverlay({ isOpen, onClose }: TraceTimelineOverlayProps) {\n  if (!isOpen) return\n  if (typeof document === \"undefined\") return null\n\n  return createPortal(\n    <div className=\"trace-timeline-overlay\" onClick={onClose}>\n      <div className=\"trace-timeline-modal\" onClick={e => e.stopPropagation()}>\n        {/* Modal header */}\n        <div className=\"trace-timeline-modal-header\">\n          <h2 className=\"trace-timeline-modal-title\">Query Statistics</h2>\n\n          <div className=\"trace-timeline-modal-controls\">\n            <button className=\"trace-timeline-modal-control-btn\" onClick={onClose} title=\"Close\">\n              ✕\n            </button>\n          </div>\n        </div>\n\n        {/* Modal content */}\n        <div className=\"trace-timeline-modal-content\">\n          <TraceStatsView />\n        </div>\n      </div>\n    </div>,\n    document.body,\n  )\n}\n"
  },
  {
    "path": "packages/system-react/src/TraceTimeline/TraceTimelineView.tsx",
    "content": "/* eslint-disable max-lines */\nimport { QueryTraceState, type TimelineEntry } from \"@snort/system\"\nimport { use, useMemo, useState, useSyncExternalStore } from \"react\"\nimport { SnortContext } from \"../context\"\nimport \"./TraceTimeline.css\"\nimport { TraceTimelineDetailPopup } from \"./TraceTimelineDetailPopup\"\n\nexport function TraceTimelineView() {\n  const system = use(SnortContext)\n  const [selectedEntry, setSelectedEntry] = useState<TimelineEntry | null>(null)\n  const [filter, setFilter] = useState<string>(\"\")\n  const [timeScale, setTimeScale] = useState<number | null>(null) // null = auto (full range)\n\n  // Available time scales in ms\n  const timeScales = [10, 50, 100, 500, 1000, 5000, 10000, 30000, 60000]\n  const timeScaleLabels: Record<number, string> = {\n    10: \"10ms\",\n    50: \"50ms\",\n    100: \"100ms\",\n    500: \"500ms\",\n    1000: \"1s\",\n    5000: \"5s\",\n    10000: \"10s\",\n    30000: \"30s\",\n    60000: \"1m\",\n  }\n\n  const emptyTimeline = { entries: [] as TimelineEntry[], enabled: false }\n  const timeline = useSyncExternalStore(\n    c => system.traceTimeline!.hook(c),\n    () => system.traceTimeline!.snapshot(),\n    () => emptyTimeline,\n  )\n\n  const entries = timeline.entries\n\n  const filteredEntries = useMemo(() => {\n    if (!filter) return [...entries]\n    const lowerFilter = filter.toLowerCase()\n    return entries.filter(\n      e => e.event.relay.toLowerCase().includes(lowerFilter) || e.event.id?.toLowerCase().includes(lowerFilter),\n    )\n  }, [entries, filter])\n\n  const baseTimeRange = useMemo(() => {\n    if (filteredEntries.length === 0) return { min: 0, max: 0, range: 1 }\n    const timestamps = filteredEntries.map(e => e.event.timestamp)\n    const min = Math.min(...timestamps)\n    const max = Math.max(...timestamps)\n    return { min, max, range: max - min || 1000 }\n  }, [filteredEntries])\n\n  const timeRange = useMemo(() => {\n    const effectiveRange = timeScale ?? baseTimeRange.range\n    return {\n      min: baseTimeRange.min,\n      max: baseTimeRange.min + effectiveRange,\n      range: effectiveRange,\n    }\n  }, [baseTimeRange, timeScale])\n\n  // Group entries by relay for swimlanes\n  const swimlanes = useMemo(() => {\n    const lanes = new Map<string, TimelineEntry[]>()\n    for (const entry of filteredEntries) {\n      const relay = entry.event.relay\n      if (!lanes.has(relay)) {\n        lanes.set(relay, [])\n      }\n      lanes.get(relay)!.push(entry)\n    }\n\n    return Array.from(lanes.entries()).map(([relay, entries]) => {\n      // Sort streaming queries first, then by timestamp\n      const sorted = entries.sort((a, b) => {\n        const aStreaming = a.event.state === QueryTraceState.WAITING_STREAM\n        const bStreaming = b.event.state === QueryTraceState.WAITING_STREAM\n\n        // Streaming queries always come first\n        if (aStreaming && !bStreaming) return -1\n        if (!aStreaming && bStreaming) return 1\n\n        // Otherwise sort by timestamp\n        return a.event.timestamp - b.event.timestamp\n      })\n\n      // Group entries by trace ID to ensure each trace stays on one level\n      const traceGroups = new Map<string, Array<TimelineEntry>>()\n      for (const entry of sorted) {\n        const traceId = entry.event.id\n        if (!traceGroups.has(traceId)) {\n          traceGroups.set(traceId, [])\n        }\n        traceGroups.get(traceId)!.push(entry)\n      }\n\n      // Track which level each trace ID is assigned to\n      const traceLevels = new Map<string, number>()\n\n      // Track the end time of each level to find available slots\n      const levelEndTimes: Array<number> = []\n\n      // Track the next available level for streaming queries\n      let nextStreamingLevel = 0\n\n      // Create stacked bars with trace ID grouping\n      const stacked = sorted.map(entry => {\n        const startTime = entry.event.timestamp\n        const isStreaming = entry.event.state === QueryTraceState.WAITING_STREAM\n        // For stacking purposes, streaming queries only occupy their start point\n        // We'll render them longer, but they don't block the timeline\n        const endTime = isStreaming ? startTime : entry.runtime ? startTime + entry.runtime : startTime\n        const traceId = entry.event.id\n\n        // If this trace already has a level, use it\n        let level: number\n        if (traceLevels.has(traceId)) {\n          level = traceLevels.get(traceId)!\n        } else {\n          if (isStreaming) {\n            // Each streaming query gets its own dedicated level\n            level = nextStreamingLevel\n            nextStreamingLevel++\n            // Ensure level exists but don't extend it (streaming queries don't block)\n            if (level >= levelEndTimes.length) {\n              levelEndTimes.push(startTime)\n            }\n          } else {\n            // Non-streaming queries stack after all streaming queries\n            level = nextStreamingLevel\n            while (level < levelEndTimes.length && levelEndTimes[level] > startTime) {\n              level++\n            }\n          }\n          traceLevels.set(traceId, level)\n        }\n\n        // Update the end time for this level (only for non-streaming queries)\n        if (!isStreaming) {\n          if (level >= levelEndTimes.length) {\n            levelEndTimes.push(endTime)\n          } else {\n            levelEndTimes[level] = Math.max(levelEndTimes[level], endTime)\n          }\n        }\n\n        return { entry, startTime, endTime, level }\n      })\n\n      const maxLevel = Math.max(0, ...stacked.map(s => s.level))\n\n      return {\n        relay,\n        entries: stacked,\n        stackHeight: maxLevel + 1,\n      }\n    })\n  }, [filteredEntries])\n\n  const relayColors = useMemo(() => {\n    const colors = [\n      \"#3b82f6\", // blue\n      \"#10b981\", // green\n      \"#f59e0b\", // amber\n      \"#ef4444\", // red\n      \"#8b5cf6\", // purple\n      \"#ec4899\", // pink\n      \"#14b8a6\", // teal\n      \"#f97316\", // orange\n    ]\n    const relays = swimlanes.map(s => s.relay)\n    return new Map(relays.map((relay, i) => [relay, colors[i % colors.length]]))\n  }, [swimlanes])\n\n  const formatTime = (ms: number) => {\n    if (ms < 1000) return `${ms.toFixed(0)}ms`\n    return `${(ms / 1000).toFixed(2)}s`\n  }\n\n  const generateTraceData = () => {\n    // Convert timeline entries to Chrome Trace Event Format\n    const traceEvents: Array<Record<string, unknown>> = []\n\n    // Add trace events - use duration events if runtime is available, instant events otherwise\n    filteredEntries.forEach(entry => {\n      const timestamp = entry.event.timestamp * 1000 // Convert to microseconds\n\n      const pid = entry.event.relay // Process ID = relay name\n      const tid = entry.event.id // Thread ID = query trace ID\n      const queryName = entry.queryName || \"Query\"\n\n      if (entry.runtime !== undefined) {\n        // Duration event - shows as a bar\n        const duration = entry.runtime * 1000 // Convert to microseconds\n        traceEvents.push({\n          name: `${queryName} (${entry.event.state})`,\n          cat: [QueryTraceState.TIMEOUT, QueryTraceState.DROP].includes(entry.event.state) ? \"timeout\" : \"complete\",\n          ph: \"X\", // Complete/duration event\n          ts: timestamp,\n          dur: duration,\n          pid: pid,\n          tid: tid,\n          args: {\n            queryName: entry.queryName,\n            relay: entry.event.relay,\n            subscriptionId: entry.event.id,\n            connectionId: entry.event.connId,\n            state: entry.event.state,\n            runtime: entry.runtime,\n            filters: entry.event.filters,\n          },\n        })\n      } else {\n        // Instant event - shows as a point\n        traceEvents.push({\n          name: `${queryName} (${entry.event.state})`,\n          cat: [QueryTraceState.TIMEOUT, QueryTraceState.DROP].includes(entry.event.state) ? \"timeout\" : \"complete\",\n          ph: \"i\", // Instant event\n          ts: timestamp,\n          pid: pid,\n          tid: tid,\n          s: \"t\", // Thread scope\n          args: {\n            queryName: entry.queryName,\n            relay: entry.event.relay,\n            subscriptionId: entry.event.id,\n            connectionId: entry.event.connId,\n            state: entry.event.state,\n            filters: entry.event.filters,\n          },\n        })\n      }\n    })\n\n    return {\n      traceEvents,\n      displayTimeUnit: \"ms\",\n      metadata: {\n        \"trace-type\": \"Nostr Relay Query Traces\",\n      },\n    }\n  }\n\n  const exportGoogleTrace = () => {\n    const traceData = generateTraceData()\n\n    // Download as JSON file\n    const blob = new Blob([JSON.stringify(traceData, null, 2)], {\n      type: \"application/json\",\n    })\n    const url = URL.createObjectURL(blob)\n    const a = document.createElement(\"a\")\n    a.href = url\n    a.download = `nostr-trace-${Date.now()}.json`\n    document.body.appendChild(a)\n    a.click()\n    document.body.removeChild(a)\n    URL.revokeObjectURL(url)\n  }\n\n  const openInPerfetto = () => {\n    const traceData = generateTraceData()\n    const jsonString = JSON.stringify(traceData)\n\n    // Convert JSON string to ArrayBuffer\n    const encoder = new TextEncoder()\n    const arrayBuffer = encoder.encode(jsonString).buffer\n\n    // Open Perfetto UI\n    const win = window.open(\"https://ui.perfetto.dev\")\n    if (!win) {\n      alert(\"Failed to open Perfetto UI. Please allow popups for this site.\")\n      return\n    }\n\n    // Use PING/PONG protocol to wait for Perfetto UI to be ready\n    const pingInterval = setInterval(() => {\n      win.postMessage(\"PING\", \"https://ui.perfetto.dev\")\n    }, 50)\n\n    const onMessageHandler = (evt: MessageEvent) => {\n      if (evt.data !== \"PONG\") return\n\n      // Clear the ping interval\n      clearInterval(pingInterval)\n      window.removeEventListener(\"message\", onMessageHandler)\n\n      // Send the trace data\n      win.postMessage(\n        {\n          perfetto: {\n            buffer: arrayBuffer,\n            title: \"Nostr Relay Query Traces\",\n            fileName: `nostr-trace-${Date.now()}.json`,\n          },\n        },\n        \"https://ui.perfetto.dev\",\n      )\n    }\n\n    window.addEventListener(\"message\", onMessageHandler)\n\n    // Timeout after 10 seconds\n    setTimeout(() => {\n      clearInterval(pingInterval)\n      window.removeEventListener(\"message\", onMessageHandler)\n    }, 10000)\n  }\n\n  const getBarPosition = (entry: TimelineEntry) => {\n    const startTime = entry.event.timestamp\n    const isStreaming = entry.event.state === QueryTraceState.WAITING_STREAM\n\n    // For streaming queries, show as running until now\n    const now = Date.now()\n    const endTime = isStreaming ? now : entry.runtime ? startTime + entry.runtime : startTime\n\n    // Use the zoom scale for width calculation\n    const effectiveRange = timeScale ?? baseTimeRange.range\n\n    // Calculate position based on the full base time range\n    const startOffset = ((startTime - baseTimeRange.min) / baseTimeRange.range) * 100\n    const duration = endTime - startTime\n    // Width is based on the zoomed range to make bars wider when zoomed in\n    const width = (duration / effectiveRange) * 100\n\n    // Show as thin marker if no runtime, otherwise show as bar\n    return {\n      left: Math.max(0, startOffset),\n      width: entry.runtime || isStreaming ? Math.max(0.1, width) : 0.1,\n      isStreaming,\n    }\n  }\n\n  const handleZoomReset = () => {\n    setTimeScale(null)\n  }\n\n  const handleZoomIn = () => {\n    if (timeScale === null) {\n      // Start from the first scale smaller than the base range\n      const nextScale = [...timeScales].reverse().find(s => s < baseTimeRange.range)\n      if (nextScale !== undefined) {\n        setTimeScale(nextScale)\n      }\n    } else {\n      // Find next smaller scale\n      const currentIndex = timeScales.indexOf(timeScale)\n      if (currentIndex > 0) {\n        const nextScale = timeScales[currentIndex - 1]\n        setTimeScale(nextScale)\n      }\n    }\n  }\n\n  const handleZoomOut = () => {\n    if (timeScale === null) return\n\n    const currentIndex = timeScales.indexOf(timeScale)\n    if (currentIndex < timeScales.length - 1) {\n      // Go to next larger scale\n      const nextScale = timeScales[currentIndex + 1]\n      if (nextScale >= baseTimeRange.range) {\n        // If next scale is larger than base range, go to auto\n        setTimeScale(null)\n      } else {\n        setTimeScale(nextScale)\n      }\n    } else {\n      // Already at largest scale, go to auto\n      setTimeScale(null)\n    }\n  }\n\n  const TRACK_HEIGHT = 20 // Height per stack level\n  const HEADER_WIDTH = 200\n\n  return (\n    <div className=\"trace-timeline-container\">\n      <div className=\"trace-timeline-controls\">\n        <input\n          type=\"text\"\n          placeholder=\"Filter by relay or query ID...\"\n          value={filter}\n          onChange={e => setFilter(e.target.value)}\n          className=\"trace-timeline-filter-input\"\n        />\n        <div className=\"trace-timeline-controls-right\">\n          <button onClick={handleZoomOut} disabled={timeScale === null} className=\"trace-timeline-btn\" title=\"Zoom out\">\n            -\n          </button>\n          <div className=\"trace-timeline-scale-label\">{timeScale === null ? \"Auto\" : timeScaleLabels[timeScale]}</div>\n          <button\n            onClick={handleZoomIn}\n            disabled={timeScale === timeScales[0]}\n            className=\"trace-timeline-btn\"\n            title=\"Zoom in\"\n          >\n            +\n          </button>\n          <button\n            onClick={handleZoomReset}\n            disabled={timeScale === null}\n            className=\"trace-timeline-btn\"\n            title=\"Reset zoom\"\n          >\n            Reset\n          </button>\n          <button\n            onClick={openInPerfetto}\n            disabled={filteredEntries.length === 0}\n            className=\"trace-timeline-btn-export\"\n            title=\"Open trace in Perfetto UI\"\n          >\n            Open in Perfetto\n          </button>\n          <button\n            onClick={exportGoogleTrace}\n            disabled={filteredEntries.length === 0}\n            className=\"trace-timeline-btn-export\"\n            title=\"Download trace as JSON\"\n          >\n            Export\n          </button>\n          <div className=\"trace-timeline-entry-count\">\n            {filteredEntries.length} {filteredEntries.length === 1 ? \"entry\" : \"entries\"}\n          </div>\n        </div>\n      </div>\n\n      <div className=\"trace-timeline-main\">\n        <div className=\"trace-timeline-chart\">\n          {/* Time ruler - fixed at top */}\n          <div className=\"trace-timeline-header\">\n            <div className=\"trace-timeline-header-label\" style={{ width: HEADER_WIDTH, height: 24 }} />\n            <div className=\"trace-timeline-header-ruler\">\n              {[0, 25, 50, 75, 100].map(pct => (\n                <div key={pct} className=\"trace-timeline-ruler-mark\" style={{ left: `${pct}%` }}>\n                  <div className=\"trace-timeline-ruler-mark-inner\">\n                    <div className=\"trace-timeline-ruler-mark-text\">{formatTime((timeRange.range * pct) / 100)}</div>\n                  </div>\n                </div>\n              ))}\n            </div>\n          </div>\n\n          {/* Scrollable swimlanes */}\n          <div className=\"trace-timeline-swimlanes\">\n            <div\n              className=\"trace-timeline-swimlanes-content\"\n              style={{\n                width: timeScale ? `${(baseTimeRange.range / timeRange.range) * 100}%` : \"100%\",\n                minWidth: \"100%\",\n              }}\n            >\n              {swimlanes.map(lane => (\n                <div\n                  key={lane.relay}\n                  className=\"trace-timeline-lane\"\n                  style={{ height: lane.stackHeight * TRACK_HEIGHT }}\n                >\n                  {/* Relay label */}\n                  <div className=\"trace-timeline-lane-label\" style={{ width: HEADER_WIDTH, flexShrink: 0 }}>\n                    <div className=\"trace-timeline-lane-label-content\">\n                      <div\n                        className=\"trace-timeline-relay-color\"\n                        style={{ backgroundColor: relayColors.get(lane.relay) }}\n                      />\n                      <span className=\"trace-timeline-relay-name\" title={lane.relay}>\n                        {new URL(lane.relay).hostname}\n                      </span>\n                    </div>\n                  </div>\n\n                  {/* Timeline bars for this lane */}\n                  <div className=\"trace-timeline-lane-bars\">\n                    {lane.entries.map((stacked, entryIdx) => {\n                      const { left, width, isStreaming } = getBarPosition(stacked.entry)\n                      const color = relayColors.get(lane.relay) || \"#6b7280\"\n                      const isSelected = selectedEntry === stacked.entry\n                      const runtime = stacked.entry.runtime\n\n                      return (\n                        <div\n                          key={`${stacked.entry.event.timestamp}-${entryIdx}`}\n                          className=\"trace-timeline-bar\"\n                          style={{\n                            left: `${left}%`,\n                            width: width > 0.5 ? `${width}%` : \"4px\",\n                            top: stacked.level * TRACK_HEIGHT + 2,\n                            height: TRACK_HEIGHT - 4,\n                            background: isStreaming\n                              ? `repeating-linear-gradient(45deg, ${color}, ${color} 10px, ${color}dd 10px, ${color}dd 20px)`\n                              : color,\n                            opacity: [QueryTraceState.TIMEOUT, QueryTraceState.DROP].includes(stacked.entry.event.state)\n                              ? 0.6\n                              : 0.9,\n                            border: isSelected ? \"2px solid white\" : \"none\",\n                            zIndex: isSelected ? 10 : 1,\n                            animation: isStreaming ? \"pulse 2s ease-in-out infinite\" : \"none\",\n                          }}\n                          onClick={e => {\n                            e.stopPropagation()\n                            setSelectedEntry(stacked.entry)\n                          }}\n                          title={\n                            isStreaming\n                              ? `${stacked.entry.event.state} (streaming)`\n                              : runtime !== undefined\n                                ? `${stacked.entry.event.state} (${formatTime(runtime)})`\n                                : stacked.entry.event.state\n                          }\n                        >\n                          {width > 5 && !isStreaming && runtime !== undefined && (\n                            <div className=\"trace-timeline-bar-label\" style={{ lineHeight: `${TRACK_HEIGHT - 4}px` }}>\n                              {formatTime(runtime)}\n                            </div>\n                          )}\n                          {width > 5 && isStreaming && (\n                            <div className=\"trace-timeline-bar-label\" style={{ lineHeight: `${TRACK_HEIGHT - 4}px` }}>\n                              streaming...\n                            </div>\n                          )}\n                        </div>\n                      )\n                    })}\n                  </div>\n                </div>\n              ))}\n            </div>\n          </div>\n        </div>\n\n        {/* Query detail panel */}\n        {selectedEntry && (\n          <TraceTimelineDetailPopup selectedEntry={selectedEntry} onClose={() => setSelectedEntry(null)} />\n        )}\n      </div>\n    </div>\n  )\n}\n"
  },
  {
    "path": "packages/system-react/src/context.tsx",
    "content": "import { createContext } from \"react\"\nimport type { SystemInterface } from \"@snort/system\"\n\nexport const SnortContext = createContext<SystemInterface>(undefined!)\n"
  },
  {
    "path": "packages/system-react/src/index.ts",
    "content": "export * from \"./context\"\n\nexport * from \"./useRequestBuilder\"\nexport * from \"./useSystemState\"\nexport * from \"./useUserProfile\"\nexport * from \"./useUserSearch\"\nexport * from \"./useEventReactions\"\nexport * from \"./useReactions\"\nexport * from \"./useEventFeed\"\nexport * from \"./useCached\"\n\nexport * from \"./TraceTimeline/TraceTimelineView\"\nexport * from \"./TraceTimeline/TraceStatsView\"\nexport * from \"./TraceTimeline/TraceTimelineOverlay\"\n"
  },
  {
    "path": "packages/system-react/src/useCached.ts",
    "content": "import { unixNow } from \"@snort/shared\"\nimport { useEffect, useState } from \"react\"\n\ninterface CachedObj<T> {\n  cached: number\n  object: T\n  error?: string\n}\n\nfunction formatKey(key: string): string {\n  return `useCached:${key}`\n}\n\nfunction loadData<T>(key: string | undefined): CachedObj<T> | undefined {\n  if (!key) return\n  const k = formatKey(key)\n  const raw = window.localStorage.getItem(k)\n  try {\n    const obj: CachedObj<T> | undefined = JSON.parse(raw || \"\")\n    return obj\n  } catch {\n    window.localStorage.removeItem(k)\n  }\n}\n\n// cached async loader calls\nconst CallMap = new Map<string, Promise<any>>()\n\nasync function storeObj<T>(key: string | undefined, loader: () => Promise<T>): Promise<CachedObj<T> | undefined> {\n  if (!key) return\n  let cachedCall = CallMap.get(key)\n  if (!cachedCall) {\n    cachedCall = loader()\n    CallMap.set(key, cachedCall)\n  }\n  const newData = await cachedCall\n  CallMap.delete(key)\n  const obj = {\n    cached: unixNow(),\n    object: newData,\n  } as CachedObj<T>\n  window.localStorage.setItem(formatKey(key), JSON.stringify(obj))\n  return obj\n}\n\n/**\n * Simple cached hook backed by localStorage\n * @param key The key used to identify this cached object, use undefined for NOOP\n * @param loader Loader function to get the latest data\n * @param expires Relative expire time in seconds\n * @param cacheError How long to cache the error response\n * @returns\n */\nexport function useCached<T>(key: string | undefined, loader: () => Promise<T>, expires?: number, cacheError?: number) {\n  const initData = loadData<T>(key)\n  const [loading, setLoading] = useState(false)\n  const [error, setError] = useState<Error | undefined>(initData?.error ? new Error(initData?.error) : undefined)\n  const [data, setData] = useState<CachedObj<T> | undefined>(initData)\n\n  if (expires === undefined) {\n    expires = 120\n  }\n\n  async function loadNow() {\n    setLoading(true)\n    storeObj<T>(key, loader)\n      .then(setData)\n      .catch(e => {\n        if (e instanceof Error) {\n          setError(e)\n        } else {\n          setError(new Error(e.toString()))\n        }\n        const cacheFor = cacheError ?? expires\n        // save an empty cache object on error\n        if (cacheFor && cacheFor > 0 && key) {\n          const obj = {\n            cached: unixNow(),\n            error: e instanceof Error ? e.message : e.toString(),\n          } as CachedObj<T>\n          window.localStorage.setItem(formatKey(key), JSON.stringify(obj))\n        }\n      })\n      .finally(() => setLoading(false))\n  }\n\n  useEffect(() => {\n    if (!key) return\n    if (loading) return\n\n    // if key was undefined before try to load data now\n    const cached = loadData<T>(key)\n    if (cached?.cached !== data?.cached) {\n      setData(cached)\n      if (cached?.error) {\n        setError(new Error(cached.error))\n      }\n    }\n    const now = unixNow()\n    if (cached === undefined || cached.cached < now - expires) {\n      loadNow()\n    }\n  }, [key, loading, error, data, loader, expires])\n\n  return {\n    data: data?.object,\n    loading,\n    error,\n    reloadNow: () => loadNow(),\n  }\n}\n"
  },
  {
    "path": "packages/system-react/src/useEventFeed.ts",
    "content": "import { useMemo } from \"react\"\nimport { RequestBuilder, type NostrLink } from \"@snort/system\"\nimport { useRequestBuilder } from \"./useRequestBuilder\"\n\nexport function useEventFeed(link: NostrLink) {\n  const sub = useMemo(() => {\n    const b = new RequestBuilder(`event:${link.id.slice(0, 12)}`)\n    b.withFilter().link(link)\n    return b\n  }, [link])\n\n  return useRequestBuilder(sub).at(0)\n}\n\nexport function useEventsFeed(id: string, links: Array<NostrLink>) {\n  const linksKey = useMemo(\n    () =>\n      links\n        .map(l => l.encode())\n        .sort()\n        .join(\",\"),\n    [links],\n  )\n\n  const sub = useMemo(() => {\n    const b = new RequestBuilder(`events:${id}`)\n    links.forEach(v => b.withFilter().link(v))\n    return b\n  }, [id, linksKey])\n\n  return useRequestBuilder(sub)\n}\n"
  },
  {
    "path": "packages/system-react/src/useEventReactions.tsx",
    "content": "import { useMemo } from \"react\"\nimport { normalizeReaction, Reaction } from \"@snort/shared\"\nimport { EventKind, type NostrLink, parseZap, type TaggedNostrEvent } from \"@snort/system\"\n\n/**\n * Parse reactions to a given event from a set of related events\n * @param link Reactions to linked event\n * @param related\n * @returns\n */\nexport function useEventReactions(link: NostrLink, related: ReadonlyArray<TaggedNostrEvent>, assumeRelated = false) {\n  const reactionKinds = useMemo(() => {\n    return related.reduce(\n      (acc, v) => {\n        if (assumeRelated || link.isReplyToThis(v)) {\n          acc[v.kind.toString()] ??= []\n          acc[v.kind.toString()].push(v)\n        }\n        return acc\n      },\n      {} as Record<string, Array<TaggedNostrEvent>>,\n    )\n  }, [related])\n\n  return useMemo(() => {\n    const deletions = reactionKinds[String(EventKind.Deletion)] ?? []\n    const reactions = reactionKinds[String(EventKind.Reaction)] ?? []\n    const reposts = reactionKinds[String(EventKind.Repost)] ?? []\n\n    const groupReactions = reactions?.reduce(\n      (acc, reaction) => {\n        const kind = normalizeReaction(reaction.content)\n        acc[kind] ??= []\n        acc[kind].push(reaction)\n        return acc\n      },\n      {} as Record<Reaction, Array<TaggedNostrEvent>>,\n    )\n\n    const zaps = (reactionKinds[String(EventKind.ZapReceipt)] ?? [])\n      .map(a => parseZap(a))\n      .filter(a => a.valid)\n      .sort((a, b) => b.amount - a.amount)\n\n    return {\n      deletions,\n      reactions: {\n        all: reactions,\n        positive: groupReactions[Reaction.Positive] ?? [],\n        negative: groupReactions[Reaction.Negative] ?? [],\n      },\n      replies: reactionKinds[String(EventKind.TextNote)] ?? [],\n      reposts,\n      zaps,\n      others: Object.fromEntries(\n        Object.entries(reactionKinds).filter(\n          ([k]) =>\n            ![EventKind.Deletion, EventKind.Reaction, EventKind.Repost, EventKind.ZapReceipt].includes(Number(k)),\n        ),\n      ),\n    }\n  }, [reactionKinds])\n}\n"
  },
  {
    "path": "packages/system-react/src/useReactions.ts",
    "content": "import { useMemo } from \"react\"\nimport { RequestBuilder, EventKind, type NostrLink } from \"@snort/system\"\nimport { useRequestBuilder } from \"./useRequestBuilder\"\n\n/**\n * Subscribe to reactions (likes, reposts, zaps) for one or more events\n * @param subId - Subscription identifier\n * @param ids - NostrLink or array of NostrLinks to fetch reactions for\n * @param others - Optional callback to add custom filters. IMPORTANT: Must be wrapped in useCallback to prevent re-subscriptions\n * @param leaveOpen - Keep subscription open after EOSE\n * @returns Array of reaction events\n * @example\n * const others = useCallback((rb: RequestBuilder) => {\n *   rb.withFilter().authors([author1, author2]);\n * }, [author1, author2]);\n * const reactions = useReactions(\"sub-id\", eventLink, others);\n */\nexport function useReactions(\n  subId: string,\n  ids: NostrLink | Array<NostrLink>,\n  others?: (rb: RequestBuilder) => void,\n  leaveOpen?: boolean,\n) {\n  // Use stable keys for memoization to prevent unnecessary re-subscriptions\n  const idsKey = useMemo(() => {\n    const links = Array.isArray(ids) ? ids : [ids]\n    return links\n      .map(l => l.tagKey)\n      .sort()\n      .join(\",\")\n  }, [ids])\n\n  const sub = useMemo(() => {\n    const rb = new RequestBuilder(subId)\n    rb.withOptions({ leaveOpen })\n\n    const links = Array.isArray(ids) ? ids : [ids]\n    if (links.length > 0) {\n      const grouped = links.reduce(\n        (acc, v) => {\n          acc[v.type] ??= []\n          acc[v.type].push(v)\n          return acc\n        },\n        {} as Record<string, Array<NostrLink>>,\n      )\n\n      for (const v of Object.values(grouped)) {\n        rb.withFilter().kinds([EventKind.Reaction, EventKind.Repost, EventKind.ZapReceipt]).replyToLink(v)\n      }\n    }\n    others?.(rb)\n    return rb\n  }, [idsKey, others, subId, leaveOpen])\n\n  return useRequestBuilder(sub)\n}\n"
  },
  {
    "path": "packages/system-react/src/useRequestBuilder.tsx",
    "content": "import { use, useEffect, useMemo, useSyncExternalStore } from \"react\"\nimport { EmptySnapshot, type RequestBuilder, type TaggedNostrEvent } from \"@snort/system\"\nimport { SnortContext } from \"./context\"\n\n/**\n * Send a query to the relays and wait for data\n */\nexport function useRequestBuilder(rb: RequestBuilder): Array<TaggedNostrEvent> {\n  const system = use(SnortContext)\n  return useSyncExternalStore(\n    v => {\n      const q = system.Query(rb)\n      // race condition here\n      q.on(\"event\", v)\n      q.uncancel()\n      q.start()\n      return () => {\n        q.flush()\n        q.off(\"event\", v)\n        q.cancel()\n      }\n    },\n    () => {\n      const q = system.GetQuery(rb.id)\n      if (q) {\n        return q.snapshot\n      } else {\n        return EmptySnapshot\n      }\n    },\n    () => EmptySnapshot,\n  )\n}\n\n/**\n * More advanced hook which returns the Query object\n */\nexport function useRequestBuilderAdvanced(rb: RequestBuilder) {\n  const system = use(SnortContext)\n  const q = useMemo(() => {\n    const q = system.Query(rb)\n    return q\n  }, [rb])\n\n  return q\n}\n"
  },
  {
    "path": "packages/system-react/src/useSystemState.tsx",
    "content": "import { useSyncExternalStore } from \"react\"\nimport type { SystemSnapshot } from \"@snort/system\"\nimport type { ExternalStore } from \"@snort/shared\"\n\nconst emptySnapshot: SystemSnapshot = {\n  queries: [],\n}\n\nexport function useSystemState(system: ExternalStore<SystemSnapshot>) {\n  return useSyncExternalStore<SystemSnapshot>(\n    cb => system.hook(cb),\n    () => system.snapshot(),\n    () => emptySnapshot,\n  )\n}\n"
  },
  {
    "path": "packages/system-react/src/useUserProfile.ts",
    "content": "import type { CachedMetadata, ProfilePriority } from \"@snort/system\"\nimport type { RefObject } from \"react\"\nimport { use, useEffect, useRef, useSyncExternalStore } from \"react\"\nimport { SnortContext } from \"./context\"\n\n/**\n * Gets a profile from cache or requests it from the relays.\n *\n * @param pubKey - Hex pubkey of the profile to load.\n * @param ref - Optional ref to an element. When provided, an IntersectionObserver\n *              will automatically promote the priority to \"high\" while the element\n *              is visible in the viewport, and demote it to \"normal\" when off-screen.\n *              This avoids the need for callers to manually specify priority.\n */\nexport function useUserProfile(pubKey?: string, ref?: RefObject<Element | null>): CachedMetadata | undefined {\n  const system = use(SnortContext)\n\n  // Track the current priority in a ref so the IntersectionObserver callback\n  // can update it without causing a re-render on its own.\n  const priorityRef = useRef<ProfilePriority>(\"normal\")\n\n  // Attach an IntersectionObserver when a ref is provided.\n  // Promotes to \"high\" when the element enters the viewport, \"normal\" when it leaves.\n  useEffect(() => {\n    if (!pubKey || !ref) return\n\n    const el = ref.current\n    if (!el) return\n\n    const observer = new IntersectionObserver(\n      entries => {\n        const isVisible = entries.some(e => e.isIntersecting)\n        const nextPriority: ProfilePriority = isVisible ? \"high\" : \"normal\"\n        if (priorityRef.current !== nextPriority) {\n          priorityRef.current = nextPriority\n          system.profileLoader.TrackKeys(pubKey, nextPriority)\n        }\n      },\n      { threshold: 0 },\n    )\n\n    observer.observe(el)\n    return () => observer.disconnect()\n  }, [pubKey, ref, system])\n\n  return useSyncExternalStore<CachedMetadata | undefined>(\n    h => {\n      if (pubKey) {\n        // Use O(1) per-key subscription instead of the broad \"change\" event\n        const unsub = system.profileLoader.cache.subscribe(pubKey, h)\n        system.profileLoader.TrackKeys(pubKey, priorityRef.current)\n\n        return () => {\n          unsub()\n          system.profileLoader.UntrackKeys(pubKey)\n        }\n      }\n      return () => {\n        // noop\n      }\n    },\n    () => system.profileLoader.cache.getFromCache(pubKey),\n    () => undefined,\n  )\n}\n"
  },
  {
    "path": "packages/system-react/src/useUserSearch.tsx",
    "content": "import { useCallback, use } from \"react\"\nimport { tryParseNostrLink } from \"@snort/system\"\nimport { fetchNip05Pubkey, NostrPrefix } from \"@snort/shared\"\nimport { SnortContext } from \"./context\"\n\nexport function useUserSearch() {\n  const system = use(SnortContext)\n  const cache = system.config.profiles\n\n  const search = useCallback(\n    async (input: string): Promise<Array<string>> => {\n      // try exact match first\n      if (input.length === 64 && [...input].every(c => !isNaN(parseInt(c, 16)))) {\n        return [input]\n      }\n\n      if (input.startsWith(NostrPrefix.PublicKey) || input.startsWith(NostrPrefix.Profile)) {\n        const link = tryParseNostrLink(input)\n        if (link) {\n          return [link.id]\n        }\n      }\n\n      if (input.includes(\"@\")) {\n        const [name, domain] = input.split(\"@\")\n        const pk = await fetchNip05Pubkey(name, domain)\n        if (pk) {\n          return [pk]\n        }\n      }\n\n      // search cache\n      const cacheResults = await cache.search(input)\n      return cacheResults.map(v => v.pubkey)\n    },\n    [cache],\n  )\n\n  return search\n}\n"
  },
  {
    "path": "packages/system-react/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \"src\",\n    \"target\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"esModuleInterop\": true,\n    \"noImplicitOverride\": true,\n    \"module\": \"ESNext\",\n    \"jsx\": \"react-jsx\",\n    \"strict\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"inlineSourceMap\": true,\n    \"outDir\": \"dist\",\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"./src/**/*.ts*\"],\n  \"exclude\": [\"**/*.test.ts\"]\n}\n"
  },
  {
    "path": "packages/system-react/typedoc.json",
    "content": "{\n  \"entryPoints\": [\"src/index.ts\"]\n}\n"
  },
  {
    "path": "packages/system-svelte/README.md",
    "content": "## @snort/system-svelte\n\nSvelte hooks for @snort/system\n"
  },
  {
    "path": "packages/system-svelte/package.json",
    "content": "{\n  \"name\": \"@snort/system-svelte\",\n  \"version\": \"1.0.1\",\n  \"description\": \"Svelte functions for @snort/system\",\n  \"type\": \"module\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"repository\": \"https://git.v0l.io/Kieran/snort\",\n  \"author\": \"Kieran\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"build\": \"rm -rf dist && bunx --bun tsc\"\n  },\n  \"files\": [\"src\", \"dist\"],\n  \"dependencies\": {\n    \"@snort/shared\": \"^1.0.6\",\n    \"@snort/system\": \"^1.0.21\",\n    \"svelte\": \"^5.40.2\"\n  },\n  \"devDependencies\": {\n    \"typescript\": \"^5.9.3\"\n  }\n}\n"
  },
  {
    "path": "packages/system-svelte/src/index.ts",
    "content": "export * from \"./request-builder\"\n"
  },
  {
    "path": "packages/system-svelte/src/request-builder.ts",
    "content": "import type { TaggedNostrEvent, RequestBuilder, SystemInterface } from \"@snort/system\"\nimport { getContext } from \"svelte\"\n\nexport function useRequestBuilder(rb: RequestBuilder) {\n  const system = getContext(\"snort\") as SystemInterface\n  return {\n    subscribe: (set: (value: Array<TaggedNostrEvent>) => void) => {\n      const q = system.Query(rb)\n      const handle = () => {\n        set(q.snapshot)\n      }\n      q.uncancel()\n      q.on(\"event\", handle)\n      q.start()\n      return () => {\n        q.flush()\n        q.off(\"event\", handle)\n        q.cancel()\n      }\n    },\n  }\n}\n"
  },
  {
    "path": "packages/system-svelte/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \"src\",\n    \"target\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"esModuleInterop\": true,\n    \"noImplicitOverride\": true,\n    \"module\": \"ESNext\",\n    \"strict\": true,\n    \"declaration\": true,\n    \"inlineSourceMap\": true,\n    \"outDir\": \"dist\",\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"./src/**/*.ts\"],\n  \"exclude\": [\"**/*.test.ts\"]\n}\n"
  },
  {
    "path": "packages/system-svelte/typedoc.json",
    "content": "{\n  \"entryPoints\": [\"src/index.ts\"]\n}\n"
  },
  {
    "path": "packages/system-wasm/.gitignore",
    "content": ".idea/\ntarget/\n*.txt"
  },
  {
    "path": "packages/system-wasm/Cargo.toml",
    "content": "[package]\nname = \"system-wasm\"\nversion = \"0.1.0\"\nedition = \"2021\"\n\n[lib]\ncrate-type = [\"cdylib\", \"rlib\"]\n\n[dependencies]\nconsole_error_panic_hook = \"0.1.7\"\nhex = { version = \"0.4.3\", features = [], default-features = false }\nitertools = \"0.14.0\"\nsecp256k1 = { version = \"0.30.0\", features = [\"global-context\"] }\nserde = { version = \"1.0.228\", features = [\"derive\"], default-features = false }\nserde-wasm-bindgen = \"0.6.5\"\nserde_json = { version = \"1.0.105\", default-features = false, features = [\"alloc\"] }\nsha256 = { version = \"1.6.0\", features = [], default-features = false }\nwasm-bindgen = \"0.2.114\"\nweb-sys = { version = \"0.3\", features = [\"console\"] }\n\n[dev-dependencies]\nrand = \"0.8.5\"\nwasm-bindgen-test = \"0.3.37\"\nserde_json = \"1.0.105\"\ncriterion = { version = \"0.5\" }\n\n[[bench]]\nname = \"basic\"\nharness = false\n\n[profile.release]\nopt-level = 3\nlto = true\ncodegen-units = 1\npanic = \"abort\"\n\n[package.metadata.wasm-pack.profile.release]\nwasm-opt = [\"-O3\", \"--enable-simd\"]\n"
  },
  {
    "path": "packages/system-wasm/README.md",
    "content": "# system-wasm\n\n## Building\n\n### Ubuntu/Debian\n\n```bash\nsudo apt install clang\ncargo install wasm-pack\nbun run build\n```\n"
  },
  {
    "path": "packages/system-wasm/benches/basic.rs",
    "content": "use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};\nuse rand::prelude::*;\nuse std::collections::HashSet;\nuse system_wasm::diff::diff_filter;\nuse system_wasm::filter::{FlatReqFilter, ReqFilter};\nuse system_wasm::verify::{verify_batch, verify_event};\nuse system_wasm::{pow, Event};\n\nfn random_pubkey(rng: &mut ThreadRng) -> String {\n    let mut bytes = [0u8; 32];\n    rng.fill_bytes(&mut bytes);\n    bytes.iter().map(|byte| format!(\"{:02x}\", byte)).collect()\n}\n\n/// A real, valid Nostr event used for verification benchmarks.\nfn real_event() -> Event {\n    serde_json::from_value(serde_json::json!({\n      \"content\": \"Oh i think it doesnt work until you reload\",\n      \"created_at\": 1695568849,\n      \"id\": \"0000051bca8ee62220b34827358dca69284734a2e7420f3c4b814901a531c767\",\n      \"kind\": 1,\n      \"pubkey\": \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\",\n      \"sig\": \"0c18bfcde49fd42c7faf93b3ecd7caf10f0414c9ee3234fca96ea0bbb1a805cb2767fc067dc1a743420c499b34c232e19b73beb2f1fe47c18a2856c67bdef983\",\n      \"tags\": [\n        [\"e\",\"ad17146f086345a12583b537daabdf49ccc5cd09e2c0b4816c835f397b693e6b\",\"wss://nos.lol/\",\"root\"],\n        [\"e\",\"72759bf1f525e9715f4e6d22381f53dc4d2ab47d7aaac11340e7fced13e10b11\",\"wss://nos.lol/\",\"reply\"],\n        [\"p\",\"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\"],\n        [\"p\",\"1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411\"],\n        [\"nonce\",\"7403\",\"18\"]\n      ]\n    })).unwrap()\n}\n\nfn criterion_benchmark(c: &mut Criterion) {\n    let mut rng = thread_rng();\n    let mut random_pubkeys = HashSet::new();\n    for _ in 0..50 {\n        random_pubkeys.insert(random_pubkey(&mut rng));\n    }\n    let input_authors = ReqFilter {\n        authors: Some(random_pubkeys.clone()),\n        kinds: Some(HashSet::from([1, 2, 3])),\n        ..Default::default()\n    };\n\n    let input_authors_diff = ReqFilter {\n        authors: Some(random_pubkeys.clone()),\n        kinds: Some(HashSet::from([1, 2, 3, 4, 5])),\n        ..Default::default()\n    };\n\n    // ── filter benchmarks ────────────────────────────────────────────────────\n\n    c.bench_function(\"expand\", |b| {\n        b.iter(|| {\n            let _: Vec<FlatReqFilter> = (&input_authors).into();\n        })\n    });\n    c.bench_function(\"diff\", |b| {\n        b.iter(|| {\n            let prev: Vec<FlatReqFilter> = (&input_authors).into();\n            let next: Vec<FlatReqFilter> = (&input_authors_diff).into();\n            let _ = diff_filter(&prev, &next);\n        })\n    });\n\n    // ── PoW ──────────────────────────────────────────────────────────────────\n\n    c.bench_function(\"pow\", |b| {\n        b.iter(|| {\n            let mut ev = Event {\n                id: None,\n                kind: 1,\n                created_at: 1234567,\n                pubkey: \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\"\n                    .to_string(),\n                content: \"test\".to_owned(),\n                sig: None,\n                tags: vec![],\n            };\n            pow::pow(&mut ev, 12);\n        })\n    });\n\n    // ── single-event verification ─────────────────────────────────────────────\n\n    let ev = real_event();\n\n    c.bench_function(\"verify_single\", |b| {\n        b.iter(|| {\n            let _ = verify_event(&ev, false);\n        })\n    });\n\n    // trust_id=true skips sha256+JSON serialisation; measures pure secp256k1 cost\n    c.bench_function(\"verify_single_trust_id\", |b| {\n        b.iter(|| {\n            let _ = verify_event(&ev, true);\n        })\n    });\n\n    // ── batch verification: N events per call ─────────────────────────────────\n    //\n    // Compares verify_event called N times vs verify_batch with N events.\n    // The difference measures the cost of calling into verify logic N times\n    // vs once — relevant because in WASM, the JS→WASM call itself has\n    // per-call overhead on top of the cryptographic work.\n\n    let mut group = c.benchmark_group(\"verify_batch\");\n    for n in [1usize, 4, 16, 64, 256] {\n        let batch: Vec<Event> = (0..n).map(|_| ev.clone()).collect();\n\n        group.bench_with_input(BenchmarkId::new(\"sequential\", n), &batch, |b, events| {\n            b.iter(|| {\n                for e in events {\n                    let _ = verify_event(e, false);\n                }\n            })\n        });\n\n        group.bench_with_input(BenchmarkId::new(\"batch\", n), &batch, |b, events| {\n            b.iter(|| {\n                let _ = verify_batch(events);\n            })\n        });\n    }\n    group.finish();\n}\n\ncriterion_group!(benches, criterion_benchmark);\ncriterion_main!(benches);\n"
  },
  {
    "path": "packages/system-wasm/package.json",
    "content": "{\n  \"name\": \"@snort/system-wasm\",\n  \"version\": \"1.0.7\",\n  \"author\": \"Kieran\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"build\": \"wasm-pack build --release -t web -s snort && rm -f pkg/.gitignore\"\n  },\n  \"files\": [\"pkg/system_wasm_bg.wasm\", \"pkg/system_wasm.js\", \"pkg/system_wasm.d.ts\"],\n  \"module\": \"pkg/system_wasm.js\",\n  \"types\": \"pkg/system_wasm.d.ts\"\n}\n"
  },
  {
    "path": "packages/system-wasm/pkg/README.md",
    "content": "# system-wasm\n\n## Building\n\n### Ubuntu/Debian\n\n```bash\nsudo apt install clang\ncargo install wasm-pack\nbun run build\n```\n"
  },
  {
    "path": "packages/system-wasm/pkg/package.json",
    "content": "{\n  \"name\": \"@snort/system-wasm\",\n  \"type\": \"module\",\n  \"version\": \"0.1.0\",\n  \"files\": [\n    \"system_wasm_bg.wasm\",\n    \"system_wasm.js\",\n    \"system_wasm.d.ts\"\n  ],\n  \"main\": \"system_wasm.js\",\n  \"types\": \"system_wasm.d.ts\",\n  \"sideEffects\": [\n    \"./snippets/*\"\n  ]\n}"
  },
  {
    "path": "packages/system-wasm/pkg/system_wasm.d.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\n\nexport function compress(val: any): any;\n\nexport function diff_filters(prev: any, next: any): any;\n\nexport function expand_filter(val: any): any;\n\nexport function flat_merge(val: any): any;\n\nexport function get_diff(prev: any, next: any): any;\n\nexport function pow(val: any, target: any): any;\n\n/**\n * Verify a raw Schnorr signature given the message hash, signature, and\n * x-only public key — all as hex strings.\n *\n * Returns a `JsValue` error (rather than panicking) if any hex value is\n * malformed or the wrong length.\n */\nexport function schnorr_verify(hash: any, sig: any, pub_key: any): boolean;\n\nexport function schnorr_verify_batch(events: any): Uint8Array;\n\n/**\n * Verify a single Nostr event.\n *\n * Computes the canonical event ID from scratch (does not trust `event.id`)\n * then checks the Schnorr signature.  Returns `false` for any malformed\n * field rather than throwing — preserving existing call-site behaviour.\n */\nexport function schnorr_verify_event(event: any): boolean;\n\nexport type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;\n\nexport interface InitOutput {\n    readonly memory: WebAssembly.Memory;\n    readonly compress: (a: any) => [number, number, number];\n    readonly diff_filters: (a: any, b: any) => [number, number, number];\n    readonly expand_filter: (a: any) => [number, number, number];\n    readonly flat_merge: (a: any) => [number, number, number];\n    readonly get_diff: (a: any, b: any) => [number, number, number];\n    readonly pow: (a: any, b: any) => [number, number, number];\n    readonly schnorr_verify: (a: any, b: any, c: any) => [number, number, number];\n    readonly schnorr_verify_batch: (a: any) => [number, number, number, number];\n    readonly schnorr_verify_event: (a: any) => [number, number, number];\n    readonly rustsecp256k1_v0_10_0_context_create: (a: number) => number;\n    readonly rustsecp256k1_v0_10_0_context_destroy: (a: number) => void;\n    readonly rustsecp256k1_v0_10_0_default_error_callback_fn: (a: number, b: number) => void;\n    readonly rustsecp256k1_v0_10_0_default_illegal_callback_fn: (a: number, b: number) => void;\n    readonly __wbindgen_malloc: (a: number, b: number) => number;\n    readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;\n    readonly __wbindgen_exn_store: (a: number) => void;\n    readonly __externref_table_alloc: () => number;\n    readonly __wbindgen_externrefs: WebAssembly.Table;\n    readonly __wbindgen_free: (a: number, b: number, c: number) => void;\n    readonly __externref_table_dealloc: (a: number) => void;\n    readonly __wbindgen_start: () => void;\n}\n\nexport type SyncInitInput = BufferSource | WebAssembly.Module;\n\n/**\n * Instantiates the given `module`, which can either be bytes or\n * a precompiled `WebAssembly.Module`.\n *\n * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.\n *\n * @returns {InitOutput}\n */\nexport function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;\n\n/**\n * If `module_or_path` is {RequestInfo} or {URL}, makes a request and\n * for everything else, calls `WebAssembly.instantiate` directly.\n *\n * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.\n *\n * @returns {Promise<InitOutput>}\n */\nexport default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;\n"
  },
  {
    "path": "packages/system-wasm/pkg/system_wasm.js",
    "content": "/* @ts-self-types=\"./system_wasm.d.ts\" */\n\n/**\n * @param {any} val\n * @returns {any}\n */\nexport function compress(val) {\n    const ret = wasm.compress(val);\n    if (ret[2]) {\n        throw takeFromExternrefTable0(ret[1]);\n    }\n    return takeFromExternrefTable0(ret[0]);\n}\n\n/**\n * @param {any} prev\n * @param {any} next\n * @returns {any}\n */\nexport function diff_filters(prev, next) {\n    const ret = wasm.diff_filters(prev, next);\n    if (ret[2]) {\n        throw takeFromExternrefTable0(ret[1]);\n    }\n    return takeFromExternrefTable0(ret[0]);\n}\n\n/**\n * @param {any} val\n * @returns {any}\n */\nexport function expand_filter(val) {\n    const ret = wasm.expand_filter(val);\n    if (ret[2]) {\n        throw takeFromExternrefTable0(ret[1]);\n    }\n    return takeFromExternrefTable0(ret[0]);\n}\n\n/**\n * @param {any} val\n * @returns {any}\n */\nexport function flat_merge(val) {\n    const ret = wasm.flat_merge(val);\n    if (ret[2]) {\n        throw takeFromExternrefTable0(ret[1]);\n    }\n    return takeFromExternrefTable0(ret[0]);\n}\n\n/**\n * @param {any} prev\n * @param {any} next\n * @returns {any}\n */\nexport function get_diff(prev, next) {\n    const ret = wasm.get_diff(prev, next);\n    if (ret[2]) {\n        throw takeFromExternrefTable0(ret[1]);\n    }\n    return takeFromExternrefTable0(ret[0]);\n}\n\n/**\n * @param {any} val\n * @param {any} target\n * @returns {any}\n */\nexport function pow(val, target) {\n    const ret = wasm.pow(val, target);\n    if (ret[2]) {\n        throw takeFromExternrefTable0(ret[1]);\n    }\n    return takeFromExternrefTable0(ret[0]);\n}\n\n/**\n * Verify a raw Schnorr signature given the message hash, signature, and\n * x-only public key — all as hex strings.\n *\n * Returns a `JsValue` error (rather than panicking) if any hex value is\n * malformed or the wrong length.\n * @param {any} hash\n * @param {any} sig\n * @param {any} pub_key\n * @returns {boolean}\n */\nexport function schnorr_verify(hash, sig, pub_key) {\n    const ret = wasm.schnorr_verify(hash, sig, pub_key);\n    if (ret[2]) {\n        throw takeFromExternrefTable0(ret[1]);\n    }\n    return ret[0] !== 0;\n}\n\n/**\n * @param {any} events\n * @returns {Uint8Array}\n */\nexport function schnorr_verify_batch(events) {\n    const ret = wasm.schnorr_verify_batch(events);\n    if (ret[3]) {\n        throw takeFromExternrefTable0(ret[2]);\n    }\n    var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice();\n    wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);\n    return v1;\n}\n\n/**\n * Verify a single Nostr event.\n *\n * Computes the canonical event ID from scratch (does not trust `event.id`)\n * then checks the Schnorr signature.  Returns `false` for any malformed\n * field rather than throwing — preserving existing call-site behaviour.\n * @param {any} event\n * @returns {boolean}\n */\nexport function schnorr_verify_event(event) {\n    const ret = wasm.schnorr_verify_event(event);\n    if (ret[2]) {\n        throw takeFromExternrefTable0(ret[1]);\n    }\n    return ret[0] !== 0;\n}\n\nfunction __wbg_get_imports() {\n    const import0 = {\n        __proto__: null,\n        __wbg_Error_83742b46f01ce22d: (arg0, arg1) => {\n            const ret = Error(getStringFromWasm0(arg0, arg1));\n            return ret;\n        },\n        __wbg_Number_a5a435bd7bbec835: (arg0) => {\n            const ret = Number(arg0);\n            return ret;\n        },\n        __wbg___wbindgen_bigint_get_as_i64_447a76b5c6ef7bda: (arg0, arg1) => {\n            const v = arg1;\n            const ret = typeof(v) === 'bigint' ? v : undefined;\n            getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);\n            getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);\n        },\n        __wbg___wbindgen_boolean_get_c0f3f60bac5a78d1: (arg0) => {\n            const v = arg0;\n            const ret = typeof(v) === 'boolean' ? v : undefined;\n            return isLikeNone(ret) ? 0xFFFFFF : ret ? 1 : 0;\n        },\n        __wbg___wbindgen_debug_string_5398f5bb970e0daa: (arg0, arg1) => {\n            const ret = debugString(arg1);\n            const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n            const len1 = WASM_VECTOR_LEN;\n            getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);\n            getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);\n        },\n        __wbg___wbindgen_in_41dbb8413020e076: (arg0, arg1) => {\n            const ret = arg0 in arg1;\n            return ret;\n        },\n        __wbg___wbindgen_is_bigint_e2141d4f045b7eda: (arg0) => {\n            const ret = typeof(arg0) === 'bigint';\n            return ret;\n        },\n        __wbg___wbindgen_is_function_3c846841762788c1: (arg0) => {\n            const ret = typeof(arg0) === 'function';\n            return ret;\n        },\n        __wbg___wbindgen_is_object_781bc9f159099513: (arg0) => {\n            const val = arg0;\n            const ret = typeof(val) === 'object' && val !== null;\n            return ret;\n        },\n        __wbg___wbindgen_is_undefined_52709e72fb9f179c: (arg0) => {\n            const ret = arg0 === undefined;\n            return ret;\n        },\n        __wbg___wbindgen_jsval_eq_ee31bfad3e536463: (arg0, arg1) => {\n            const ret = arg0 === arg1;\n            return ret;\n        },\n        __wbg___wbindgen_jsval_loose_eq_5bcc3bed3c69e72b: (arg0, arg1) => {\n            const ret = arg0 == arg1;\n            return ret;\n        },\n        __wbg___wbindgen_number_get_34bb9d9dcfa21373: (arg0, arg1) => {\n            const obj = arg1;\n            const ret = typeof(obj) === 'number' ? obj : undefined;\n            getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);\n            getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);\n        },\n        __wbg___wbindgen_string_get_395e606bd0ee4427: (arg0, arg1) => {\n            const obj = arg1;\n            const ret = typeof(obj) === 'string' ? obj : undefined;\n            var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n            var len1 = WASM_VECTOR_LEN;\n            getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);\n            getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);\n        },\n        __wbg___wbindgen_throw_6ddd609b62940d55: (arg0, arg1) => {\n            throw new Error(getStringFromWasm0(arg0, arg1));\n        },\n        __wbg_call_e133b57c9155d22c: function() { return handleError((arg0, arg1) => {\n            const ret = arg0.call(arg1);\n            return ret;\n        }, arguments); },\n        __wbg_done_08ce71ee07e3bd17: (arg0) => {\n            const ret = arg0.done;\n            return ret;\n        },\n        __wbg_error_a6fa202b58aa1cd3: (arg0, arg1) => {\n            let deferred0_0;\n            let deferred0_1;\n            try {\n                deferred0_0 = arg0;\n                deferred0_1 = arg1;\n                console.error(getStringFromWasm0(arg0, arg1));\n            } finally {\n                wasm.__wbindgen_free(deferred0_0, deferred0_1, 1);\n            }\n        },\n        __wbg_error_cfce0f619500de52: (arg0, arg1) => {\n            console.error(arg0, arg1);\n        },\n        __wbg_get_326e41e095fb2575: function() { return handleError((arg0, arg1) => {\n            const ret = Reflect.get(arg0, arg1);\n            return ret;\n        }, arguments); },\n        __wbg_get_unchecked_329cfe50afab7352: (arg0, arg1) => {\n            const ret = arg0[arg1 >>> 0];\n            return ret;\n        },\n        __wbg_get_with_ref_key_6412cf3094599694: (arg0, arg1) => {\n            const ret = arg0[arg1];\n            return ret;\n        },\n        __wbg_instanceof_ArrayBuffer_101e2bf31071a9f6: (arg0) => {\n            let result;\n            try {\n                result = arg0 instanceof ArrayBuffer;\n            } catch (_) {\n                result = false;\n            }\n            const ret = result;\n            return ret;\n        },\n        __wbg_instanceof_Uint8Array_740438561a5b956d: (arg0) => {\n            let result;\n            try {\n                result = arg0 instanceof Uint8Array;\n            } catch (_) {\n                result = false;\n            }\n            const ret = result;\n            return ret;\n        },\n        __wbg_isArray_33b91feb269ff46e: (arg0) => {\n            const ret = Array.isArray(arg0);\n            return ret;\n        },\n        __wbg_isSafeInteger_ecd6a7f9c3e053cd: (arg0) => {\n            const ret = Number.isSafeInteger(arg0);\n            return ret;\n        },\n        __wbg_iterator_d8f549ec8fb061b1: () => {\n            const ret = Symbol.iterator;\n            return ret;\n        },\n        __wbg_length_b3416cf66a5452c8: (arg0) => {\n            const ret = arg0.length;\n            return ret;\n        },\n        __wbg_length_ea16607d7b61445b: (arg0) => {\n            const ret = arg0.length;\n            return ret;\n        },\n        __wbg_new_227d7c05414eb861: () => {\n            const ret = new Error();\n            return ret;\n        },\n        __wbg_new_5f486cdf45a04d78: (arg0) => {\n            const ret = new Uint8Array(arg0);\n            return ret;\n        },\n        __wbg_new_a70fbab9066b301f: () => {\n            const ret = [];\n            return ret;\n        },\n        __wbg_new_ab79df5bd7c26067: () => {\n            const ret = new Object();\n            return ret;\n        },\n        __wbg_next_11b99ee6237339e3: function() { return handleError((arg0) => {\n            const ret = arg0.next();\n            return ret;\n        }, arguments); },\n        __wbg_next_e01a967809d1aa68: (arg0) => {\n            const ret = arg0.next;\n            return ret;\n        },\n        __wbg_prototypesetcall_d62e5099504357e6: (arg0, arg1, arg2) => {\n            Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);\n        },\n        __wbg_set_282384002438957f: (arg0, arg1, arg2) => {\n            arg0[arg1 >>> 0] = arg2;\n        },\n        __wbg_set_6be42768c690e380: (arg0, arg1, arg2) => {\n            arg0[arg1] = arg2;\n        },\n        __wbg_stack_3b0d974bbf31e44f: (arg0, arg1) => {\n            const ret = arg1.stack;\n            const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);\n            const len1 = WASM_VECTOR_LEN;\n            getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);\n            getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);\n        },\n        __wbg_value_21fc78aab0322612: (arg0) => {\n            const ret = arg0.value;\n            return ret;\n        },\n        __wbindgen_cast_0000000000000001: (arg0) => {\n            // Cast intrinsic for `F64 -> Externref`.\n            const ret = arg0;\n            return ret;\n        },\n        __wbindgen_cast_0000000000000002: (arg0, arg1) => {\n            // Cast intrinsic for `Ref(String) -> Externref`.\n            const ret = getStringFromWasm0(arg0, arg1);\n            return ret;\n        },\n        __wbindgen_cast_0000000000000003: (arg0) => {\n            // Cast intrinsic for `U64 -> Externref`.\n            const ret = BigInt.asUintN(64, arg0);\n            return ret;\n        },\n        __wbindgen_init_externref_table: () => {\n            const table = wasm.__wbindgen_externrefs;\n            const offset = table.grow(4);\n            table.set(0, undefined);\n            table.set(offset + 0, undefined);\n            table.set(offset + 1, null);\n            table.set(offset + 2, true);\n            table.set(offset + 3, false);\n        },\n    };\n    return {\n        __proto__: null,\n        \"./system_wasm_bg.js\": import0,\n    };\n}\n\nfunction addToExternrefTable0(obj) {\n    const idx = wasm.__externref_table_alloc();\n    wasm.__wbindgen_externrefs.set(idx, obj);\n    return idx;\n}\n\nfunction debugString(val) {\n    // primitive types\n    const type = typeof val;\n    if (type == 'number' || type == 'boolean' || val == null) {\n        return  `${val}`;\n    }\n    if (type == 'string') {\n        return `\"${val}\"`;\n    }\n    if (type == 'symbol') {\n        const description = val.description;\n        if (description == null) {\n            return 'Symbol';\n        } else {\n            return `Symbol(${description})`;\n        }\n    }\n    if (type == 'function') {\n        const name = val.name;\n        if (typeof name == 'string' && name.length > 0) {\n            return `Function(${name})`;\n        } else {\n            return 'Function';\n        }\n    }\n    // objects\n    if (Array.isArray(val)) {\n        const length = val.length;\n        let debug = '[';\n        if (length > 0) {\n            debug += debugString(val[0]);\n        }\n        for(let i = 1; i < length; i++) {\n            debug += ', ' + debugString(val[i]);\n        }\n        debug += ']';\n        return debug;\n    }\n    // Test for built-in\n    const builtInMatches = /\\[object ([^\\]]+)\\]/.exec(toString.call(val));\n    let className;\n    if (builtInMatches && builtInMatches.length > 1) {\n        className = builtInMatches[1];\n    } else {\n        // Failed to match the standard '[object ClassName]'\n        return toString.call(val);\n    }\n    if (className == 'Object') {\n        // we're a user defined class or Object\n        // JSON.stringify avoids problems with cycles, and is generally much\n        // easier than looping through ownProperties of `val`.\n        try {\n            return 'Object(' + JSON.stringify(val) + ')';\n        } catch (_) {\n            return 'Object';\n        }\n    }\n    // errors\n    if (val instanceof Error) {\n        return `${val.name}: ${val.message}\\n${val.stack}`;\n    }\n    // TODO we could test for more things here, like `Set`s and `Map`s.\n    return className;\n}\n\nfunction getArrayU8FromWasm0(ptr, len) {\n    ptr = ptr >>> 0;\n    return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);\n}\n\nlet cachedDataViewMemory0 = null;\nfunction getDataViewMemory0() {\n    if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {\n        cachedDataViewMemory0 = new DataView(wasm.memory.buffer);\n    }\n    return cachedDataViewMemory0;\n}\n\nfunction getStringFromWasm0(ptr, len) {\n    ptr = ptr >>> 0;\n    return decodeText(ptr, len);\n}\n\nlet cachedUint8ArrayMemory0 = null;\nfunction getUint8ArrayMemory0() {\n    if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {\n        cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);\n    }\n    return cachedUint8ArrayMemory0;\n}\n\nfunction handleError(f, args) {\n    try {\n        return f.apply(this, args);\n    } catch (e) {\n        const idx = addToExternrefTable0(e);\n        wasm.__wbindgen_exn_store(idx);\n    }\n}\n\nfunction isLikeNone(x) {\n    return x === undefined || x === null;\n}\n\nfunction passStringToWasm0(arg, malloc, realloc) {\n    if (realloc === undefined) {\n        const buf = cachedTextEncoder.encode(arg);\n        const ptr = malloc(buf.length, 1) >>> 0;\n        getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);\n        WASM_VECTOR_LEN = buf.length;\n        return ptr;\n    }\n\n    let len = arg.length;\n    let ptr = malloc(len, 1) >>> 0;\n\n    const mem = getUint8ArrayMemory0();\n\n    let offset = 0;\n\n    for (; offset < len; offset++) {\n        const code = arg.charCodeAt(offset);\n        if (code > 0x7F) break;\n        mem[ptr + offset] = code;\n    }\n    if (offset !== len) {\n        if (offset !== 0) {\n            arg = arg.slice(offset);\n        }\n        ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;\n        const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);\n        const ret = cachedTextEncoder.encodeInto(arg, view);\n\n        offset += ret.written;\n        ptr = realloc(ptr, len, offset, 1) >>> 0;\n    }\n\n    WASM_VECTOR_LEN = offset;\n    return ptr;\n}\n\nfunction takeFromExternrefTable0(idx) {\n    const value = wasm.__wbindgen_externrefs.get(idx);\n    wasm.__externref_table_dealloc(idx);\n    return value;\n}\n\nlet cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });\ncachedTextDecoder.decode();\nconst MAX_SAFARI_DECODE_BYTES = 2146435072;\nlet numBytesDecoded = 0;\nfunction decodeText(ptr, len) {\n    numBytesDecoded += len;\n    if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {\n        cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });\n        cachedTextDecoder.decode();\n        numBytesDecoded = len;\n    }\n    return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));\n}\n\nconst cachedTextEncoder = new TextEncoder();\n\nif (!('encodeInto' in cachedTextEncoder)) {\n    cachedTextEncoder.encodeInto = (arg, view) => {\n        const buf = cachedTextEncoder.encode(arg);\n        view.set(buf);\n        return {\n            read: arg.length,\n            written: buf.length\n        };\n    };\n}\n\nlet WASM_VECTOR_LEN = 0;\n\nlet wasmModule, wasm;\nfunction __wbg_finalize_init(instance, module) {\n    wasm = instance.exports;\n    wasmModule = module;\n    cachedDataViewMemory0 = null;\n    cachedUint8ArrayMemory0 = null;\n    wasm.__wbindgen_start();\n    return wasm;\n}\n\nasync function __wbg_load(module, imports) {\n    if (typeof Response === 'function' && module instanceof Response) {\n        if (typeof WebAssembly.instantiateStreaming === 'function') {\n            try {\n                return await WebAssembly.instantiateStreaming(module, imports);\n            } catch (e) {\n                const validResponse = module.ok && expectedResponseType(module.type);\n\n                if (validResponse && module.headers.get('Content-Type') !== 'application/wasm') {\n                    console.warn(\"`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\\n\", e);\n\n                } else { throw e; }\n            }\n        }\n\n        const bytes = await module.arrayBuffer();\n        return await WebAssembly.instantiate(bytes, imports);\n    } else {\n        const instance = await WebAssembly.instantiate(module, imports);\n\n        if (instance instanceof WebAssembly.Instance) {\n            return { instance, module };\n        } else {\n            return instance;\n        }\n    }\n\n    function expectedResponseType(type) {\n        switch (type) {\n            case 'basic': case 'cors': case 'default': return true;\n        }\n        return false;\n    }\n}\n\nfunction initSync(module) {\n    if (wasm !== undefined) return wasm;\n\n\n    if (module !== undefined) {\n        if (Object.getPrototypeOf(module) === Object.prototype) {\n            ({module} = module)\n        } else {\n            console.warn('using deprecated parameters for `initSync()`; pass a single object instead')\n        }\n    }\n\n    const imports = __wbg_get_imports();\n    if (!(module instanceof WebAssembly.Module)) {\n        module = new WebAssembly.Module(module);\n    }\n    const instance = new WebAssembly.Instance(module, imports);\n    return __wbg_finalize_init(instance, module);\n}\n\nasync function __wbg_init(module_or_path) {\n    if (wasm !== undefined) return wasm;\n\n\n    if (module_or_path !== undefined) {\n        if (Object.getPrototypeOf(module_or_path) === Object.prototype) {\n            ({module_or_path} = module_or_path)\n        } else {\n            console.warn('using deprecated parameters for the initialization function; pass a single object instead')\n        }\n    }\n\n    if (module_or_path === undefined) {\n        module_or_path = new URL('system_wasm_bg.wasm', import.meta.url);\n    }\n    const imports = __wbg_get_imports();\n\n    if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {\n        module_or_path = fetch(module_or_path);\n    }\n\n    const { instance, module } = await __wbg_load(await module_or_path, imports);\n\n    return __wbg_finalize_init(instance, module);\n}\n\nexport { initSync, __wbg_init as default };\n"
  },
  {
    "path": "packages/system-wasm/pkg/system_wasm_bg.js",
    "content": "let wasm\nexport function __wbg_set_wasm(val) {\n  wasm = val\n}\n\nconst heap = new Array(128).fill(undefined)\n\nheap.push(undefined, null, true, false)\n\nfunction getObject(idx) {\n  return heap[idx]\n}\n\nlet heap_next = heap.length\n\nfunction dropObject(idx) {\n  if (idx < 132) return\n  heap[idx] = heap_next\n  heap_next = idx\n}\n\nfunction takeObject(idx) {\n  const ret = getObject(idx)\n  dropObject(idx)\n  return ret\n}\n\nlet WASM_VECTOR_LEN = 0\n\nlet cachedUint8Memory0 = null\n\nfunction getUint8Memory0() {\n  if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) {\n    cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer)\n  }\n  return cachedUint8Memory0\n}\n\nconst lTextEncoder = typeof TextEncoder === \"undefined\" ? (0, module.require)(\"util\").TextEncoder : TextEncoder\n\nconst cachedTextEncoder = new lTextEncoder(\"utf-8\")\n\nconst encodeString =\n  typeof cachedTextEncoder.encodeInto === \"function\"\n    ? (arg, view) => cachedTextEncoder.encodeInto(arg, view)\n    : (arg, view) => {\n        const buf = cachedTextEncoder.encode(arg)\n        view.set(buf)\n        return {\n          read: arg.length,\n          written: buf.length,\n        }\n      }\n\nfunction passStringToWasm0(arg, malloc, realloc) {\n  if (realloc === undefined) {\n    const buf = cachedTextEncoder.encode(arg)\n    const ptr = malloc(buf.length, 1) >>> 0\n    getUint8Memory0()\n      .subarray(ptr, ptr + buf.length)\n      .set(buf)\n    WASM_VECTOR_LEN = buf.length\n    return ptr\n  }\n\n  let len = arg.length\n  let ptr = malloc(len, 1) >>> 0\n\n  const mem = getUint8Memory0()\n\n  let offset = 0\n\n  for (; offset < len; offset++) {\n    const code = arg.charCodeAt(offset)\n    if (code > 0x7f) break\n    mem[ptr + offset] = code\n  }\n\n  if (offset !== len) {\n    if (offset !== 0) {\n      arg = arg.slice(offset)\n    }\n    ptr = realloc(ptr, len, (len = offset + arg.length * 3), 1) >>> 0\n    const view = getUint8Memory0().subarray(ptr + offset, ptr + len)\n    const ret = encodeString(arg, view)\n\n    offset += ret.written\n  }\n\n  WASM_VECTOR_LEN = offset\n  return ptr\n}\n\nfunction isLikeNone(x) {\n  return x === undefined || x === null\n}\n\nlet cachedInt32Memory0 = null\n\nfunction getInt32Memory0() {\n  if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) {\n    cachedInt32Memory0 = new Int32Array(wasm.memory.buffer)\n  }\n  return cachedInt32Memory0\n}\n\nfunction addHeapObject(obj) {\n  if (heap_next === heap.length) heap.push(heap.length + 1)\n  const idx = heap_next\n  heap_next = heap[idx]\n\n  heap[idx] = obj\n  return idx\n}\n\nconst lTextDecoder = typeof TextDecoder === \"undefined\" ? (0, module.require)(\"util\").TextDecoder : TextDecoder\n\nconst cachedTextDecoder = new lTextDecoder(\"utf-8\", { ignoreBOM: true, fatal: true })\n\ncachedTextDecoder.decode()\n\nfunction getStringFromWasm0(ptr, len) {\n  ptr = ptr >>> 0\n  return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len))\n}\n\nlet cachedFloat64Memory0 = null\n\nfunction getFloat64Memory0() {\n  if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) {\n    cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer)\n  }\n  return cachedFloat64Memory0\n}\n\nlet cachedBigInt64Memory0 = null\n\nfunction getBigInt64Memory0() {\n  if (cachedBigInt64Memory0 === null || cachedBigInt64Memory0.byteLength === 0) {\n    cachedBigInt64Memory0 = new BigInt64Array(wasm.memory.buffer)\n  }\n  return cachedBigInt64Memory0\n}\n\nfunction debugString(val) {\n  // primitive types\n  const type = typeof val\n  if (type == \"number\" || type == \"boolean\" || val == null) {\n    return `${val}`\n  }\n  if (type == \"string\") {\n    return `\"${val}\"`\n  }\n  if (type == \"symbol\") {\n    const description = val.description\n    if (description == null) {\n      return \"Symbol\"\n    } else {\n      return `Symbol(${description})`\n    }\n  }\n  if (type == \"function\") {\n    const name = val.name\n    if (typeof name == \"string\" && name.length > 0) {\n      return `Function(${name})`\n    } else {\n      return \"Function\"\n    }\n  }\n  // objects\n  if (Array.isArray(val)) {\n    const length = val.length\n    let debug = \"[\"\n    if (length > 0) {\n      debug += debugString(val[0])\n    }\n    for (let i = 1; i < length; i++) {\n      debug += \", \" + debugString(val[i])\n    }\n    debug += \"]\"\n    return debug\n  }\n  // Test for built-in\n  const builtInMatches = /\\[object ([^\\]]+)\\]/.exec(toString.call(val))\n  let className\n  if (builtInMatches.length > 1) {\n    className = builtInMatches[1]\n  } else {\n    // Failed to match the standard '[object ClassName]'\n    return toString.call(val)\n  }\n  if (className == \"Object\") {\n    // we're a user defined class or Object\n    // JSON.stringify avoids problems with cycles, and is generally much\n    // easier than looping through ownProperties of `val`.\n    try {\n      return \"Object(\" + JSON.stringify(val) + \")\"\n    } catch (_) {\n      return \"Object\"\n    }\n  }\n  // errors\n  if (val instanceof Error) {\n    return `${val.name}: ${val.message}\\n${val.stack}`\n  }\n  // TODO we could test for more things here, like `Set`s and `Map`s.\n  return className\n}\n/**\n * @param {any} prev\n * @param {any} next\n * @returns {any}\n */\nexport function diff_filters(prev, next) {\n  try {\n    const retptr = wasm.__wbindgen_add_to_stack_pointer(-16)\n    wasm.diff_filters(retptr, addHeapObject(prev), addHeapObject(next))\n    var r0 = getInt32Memory0()[retptr / 4 + 0]\n    var r1 = getInt32Memory0()[retptr / 4 + 1]\n    var r2 = getInt32Memory0()[retptr / 4 + 2]\n    if (r2) {\n      throw takeObject(r1)\n    }\n    return takeObject(r0)\n  } finally {\n    wasm.__wbindgen_add_to_stack_pointer(16)\n  }\n}\n\n/**\n * @param {any} val\n * @returns {any}\n */\nexport function expand_filter(val) {\n  try {\n    const retptr = wasm.__wbindgen_add_to_stack_pointer(-16)\n    wasm.expand_filter(retptr, addHeapObject(val))\n    var r0 = getInt32Memory0()[retptr / 4 + 0]\n    var r1 = getInt32Memory0()[retptr / 4 + 1]\n    var r2 = getInt32Memory0()[retptr / 4 + 2]\n    if (r2) {\n      throw takeObject(r1)\n    }\n    return takeObject(r0)\n  } finally {\n    wasm.__wbindgen_add_to_stack_pointer(16)\n  }\n}\n\n/**\n * @param {any} prev\n * @param {any} next\n * @returns {any}\n */\nexport function get_diff(prev, next) {\n  try {\n    const retptr = wasm.__wbindgen_add_to_stack_pointer(-16)\n    wasm.get_diff(retptr, addHeapObject(prev), addHeapObject(next))\n    var r0 = getInt32Memory0()[retptr / 4 + 0]\n    var r1 = getInt32Memory0()[retptr / 4 + 1]\n    var r2 = getInt32Memory0()[retptr / 4 + 2]\n    if (r2) {\n      throw takeObject(r1)\n    }\n    return takeObject(r0)\n  } finally {\n    wasm.__wbindgen_add_to_stack_pointer(16)\n  }\n}\n\n/**\n * @param {any} val\n * @returns {any}\n */\nexport function flat_merge(val) {\n  try {\n    const retptr = wasm.__wbindgen_add_to_stack_pointer(-16)\n    wasm.flat_merge(retptr, addHeapObject(val))\n    var r0 = getInt32Memory0()[retptr / 4 + 0]\n    var r1 = getInt32Memory0()[retptr / 4 + 1]\n    var r2 = getInt32Memory0()[retptr / 4 + 2]\n    if (r2) {\n      throw takeObject(r1)\n    }\n    return takeObject(r0)\n  } finally {\n    wasm.__wbindgen_add_to_stack_pointer(16)\n  }\n}\n\n/**\n * @param {any} val\n * @returns {any}\n */\nexport function compress(val) {\n  try {\n    const retptr = wasm.__wbindgen_add_to_stack_pointer(-16)\n    wasm.compress(retptr, addHeapObject(val))\n    var r0 = getInt32Memory0()[retptr / 4 + 0]\n    var r1 = getInt32Memory0()[retptr / 4 + 1]\n    var r2 = getInt32Memory0()[retptr / 4 + 2]\n    if (r2) {\n      throw takeObject(r1)\n    }\n    return takeObject(r0)\n  } finally {\n    wasm.__wbindgen_add_to_stack_pointer(16)\n  }\n}\n\n/**\n * @param {any} val\n * @param {any} target\n * @returns {any}\n */\nexport function pow(val, target) {\n  try {\n    const retptr = wasm.__wbindgen_add_to_stack_pointer(-16)\n    wasm.pow(retptr, addHeapObject(val), addHeapObject(target))\n    var r0 = getInt32Memory0()[retptr / 4 + 0]\n    var r1 = getInt32Memory0()[retptr / 4 + 1]\n    var r2 = getInt32Memory0()[retptr / 4 + 2]\n    if (r2) {\n      throw takeObject(r1)\n    }\n    return takeObject(r0)\n  } finally {\n    wasm.__wbindgen_add_to_stack_pointer(16)\n  }\n}\n\n/**\n * @param {any} password\n * @param {any} salt\n * @returns {any}\n */\nexport function argon2(password, salt) {\n  try {\n    const retptr = wasm.__wbindgen_add_to_stack_pointer(-16)\n    wasm.argon2(retptr, addHeapObject(password), addHeapObject(salt))\n    var r0 = getInt32Memory0()[retptr / 4 + 0]\n    var r1 = getInt32Memory0()[retptr / 4 + 1]\n    var r2 = getInt32Memory0()[retptr / 4 + 2]\n    if (r2) {\n      throw takeObject(r1)\n    }\n    return takeObject(r0)\n  } finally {\n    wasm.__wbindgen_add_to_stack_pointer(16)\n  }\n}\n\nfunction handleError(f, args) {\n  try {\n    return f.apply(this, args)\n  } catch (e) {\n    wasm.__wbindgen_exn_store(addHeapObject(e))\n  }\n}\n\nexport function __wbindgen_object_drop_ref(arg0) {\n  takeObject(arg0)\n}\n\nexport function __wbindgen_string_get(arg0, arg1) {\n  const obj = getObject(arg1)\n  const ret = typeof obj === \"string\" ? obj : undefined\n  var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc)\n  var len1 = WASM_VECTOR_LEN\n  getInt32Memory0()[arg0 / 4 + 1] = len1\n  getInt32Memory0()[arg0 / 4 + 0] = ptr1\n}\n\nexport function __wbindgen_is_object(arg0) {\n  const val = getObject(arg0)\n  const ret = typeof val === \"object\" && val !== null\n  return ret\n}\n\nexport function __wbindgen_is_undefined(arg0) {\n  const ret = getObject(arg0) === undefined\n  return ret\n}\n\nexport function __wbindgen_in(arg0, arg1) {\n  const ret = getObject(arg0) in getObject(arg1)\n  return ret\n}\n\nexport function __wbindgen_is_bigint(arg0) {\n  const ret = typeof getObject(arg0) === \"bigint\"\n  return ret\n}\n\nexport function __wbindgen_bigint_from_u64(arg0) {\n  const ret = BigInt.asUintN(64, arg0)\n  return addHeapObject(ret)\n}\n\nexport function __wbindgen_jsval_eq(arg0, arg1) {\n  const ret = getObject(arg0) === getObject(arg1)\n  return ret\n}\n\nexport function __wbindgen_error_new(arg0, arg1) {\n  const ret = new Error(getStringFromWasm0(arg0, arg1))\n  return addHeapObject(ret)\n}\n\nexport function __wbindgen_object_clone_ref(arg0) {\n  const ret = getObject(arg0)\n  return addHeapObject(ret)\n}\n\nexport function __wbindgen_jsval_loose_eq(arg0, arg1) {\n  const ret = getObject(arg0) == getObject(arg1)\n  return ret\n}\n\nexport function __wbindgen_boolean_get(arg0) {\n  const v = getObject(arg0)\n  const ret = typeof v === \"boolean\" ? (v ? 1 : 0) : 2\n  return ret\n}\n\nexport function __wbindgen_number_get(arg0, arg1) {\n  const obj = getObject(arg1)\n  const ret = typeof obj === \"number\" ? obj : undefined\n  getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret\n  getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret)\n}\n\nexport function __wbindgen_number_new(arg0) {\n  const ret = arg0\n  return addHeapObject(ret)\n}\n\nexport function __wbindgen_string_new(arg0, arg1) {\n  const ret = getStringFromWasm0(arg0, arg1)\n  return addHeapObject(ret)\n}\n\nexport function __wbg_getwithrefkey_5e6d9547403deab8(arg0, arg1) {\n  const ret = getObject(arg0)[getObject(arg1)]\n  return addHeapObject(ret)\n}\n\nexport function __wbg_set_841ac57cff3d672b(arg0, arg1, arg2) {\n  getObject(arg0)[takeObject(arg1)] = takeObject(arg2)\n}\n\nexport function __wbg_get_44be0491f933a435(arg0, arg1) {\n  const ret = getObject(arg0)[arg1 >>> 0]\n  return addHeapObject(ret)\n}\n\nexport function __wbg_length_fff51ee6522a1a18(arg0) {\n  const ret = getObject(arg0).length\n  return ret\n}\n\nexport function __wbg_new_898a68150f225f2e() {\n  const ret = []\n  return addHeapObject(ret)\n}\n\nexport function __wbindgen_is_function(arg0) {\n  const ret = typeof getObject(arg0) === \"function\"\n  return ret\n}\n\nexport function __wbg_next_526fc47e980da008(arg0) {\n  const ret = getObject(arg0).next\n  return addHeapObject(ret)\n}\n\nexport function __wbg_next_ddb3312ca1c4e32a() {\n  return handleError(arg0 => {\n    const ret = getObject(arg0).next()\n    return addHeapObject(ret)\n  }, arguments)\n}\n\nexport function __wbg_done_5c1f01fb660d73b5(arg0) {\n  const ret = getObject(arg0).done\n  return ret\n}\n\nexport function __wbg_value_1695675138684bd5(arg0) {\n  const ret = getObject(arg0).value\n  return addHeapObject(ret)\n}\n\nexport function __wbg_iterator_97f0c81209c6c35a() {\n  const ret = Symbol.iterator\n  return addHeapObject(ret)\n}\n\nexport function __wbg_get_97b561fb56f034b5() {\n  return handleError((arg0, arg1) => {\n    const ret = Reflect.get(getObject(arg0), getObject(arg1))\n    return addHeapObject(ret)\n  }, arguments)\n}\n\nexport function __wbg_call_cb65541d95d71282() {\n  return handleError((arg0, arg1) => {\n    const ret = getObject(arg0).call(getObject(arg1))\n    return addHeapObject(ret)\n  }, arguments)\n}\n\nexport function __wbg_new_b51585de1b234aff() {\n  const ret = new Object()\n  return addHeapObject(ret)\n}\n\nexport function __wbg_set_502d29070ea18557(arg0, arg1, arg2) {\n  getObject(arg0)[arg1 >>> 0] = takeObject(arg2)\n}\n\nexport function __wbg_isArray_4c24b343cb13cfb1(arg0) {\n  const ret = Array.isArray(getObject(arg0))\n  return ret\n}\n\nexport function __wbg_instanceof_ArrayBuffer_39ac22089b74fddb(arg0) {\n  let result\n  try {\n    result = getObject(arg0) instanceof ArrayBuffer\n  } catch {\n    result = false\n  }\n  const ret = result\n  return ret\n}\n\nexport function __wbg_isSafeInteger_bb8e18dd21c97288(arg0) {\n  const ret = Number.isSafeInteger(getObject(arg0))\n  return ret\n}\n\nexport function __wbg_buffer_085ec1f694018c4f(arg0) {\n  const ret = getObject(arg0).buffer\n  return addHeapObject(ret)\n}\n\nexport function __wbg_new_8125e318e6245eed(arg0) {\n  const ret = new Uint8Array(getObject(arg0))\n  return addHeapObject(ret)\n}\n\nexport function __wbg_set_5cf90238115182c3(arg0, arg1, arg2) {\n  getObject(arg0).set(getObject(arg1), arg2 >>> 0)\n}\n\nexport function __wbg_length_72e2208bbc0efc61(arg0) {\n  const ret = getObject(arg0).length\n  return ret\n}\n\nexport function __wbg_instanceof_Uint8Array_d8d9cb2b8e8ac1d4(arg0) {\n  let result\n  try {\n    result = getObject(arg0) instanceof Uint8Array\n  } catch {\n    result = false\n  }\n  const ret = result\n  return ret\n}\n\nexport function __wbg_new_abda76e883ba8a5f() {\n  const ret = new Error()\n  return addHeapObject(ret)\n}\n\nexport function __wbg_stack_658279fe44541cf6(arg0, arg1) {\n  const ret = getObject(arg1).stack\n  const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc)\n  const len1 = WASM_VECTOR_LEN\n  getInt32Memory0()[arg0 / 4 + 1] = len1\n  getInt32Memory0()[arg0 / 4 + 0] = ptr1\n}\n\nexport function __wbg_error_f851667af71bcfc6(arg0, arg1) {\n  let deferred0_0\n  let deferred0_1\n  try {\n    deferred0_0 = arg0\n    deferred0_1 = arg1\n    console.error(getStringFromWasm0(arg0, arg1))\n  } finally {\n    wasm.__wbindgen_free(deferred0_0, deferred0_1, 1)\n  }\n}\n\nexport function __wbindgen_bigint_get_as_i64(arg0, arg1) {\n  const v = getObject(arg1)\n  const ret = typeof v === \"bigint\" ? v : undefined\n  getBigInt64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? BigInt(0) : ret\n  getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret)\n}\n\nexport function __wbindgen_debug_string(arg0, arg1) {\n  const ret = debugString(getObject(arg1))\n  const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc)\n  const len1 = WASM_VECTOR_LEN\n  getInt32Memory0()[arg0 / 4 + 1] = len1\n  getInt32Memory0()[arg0 / 4 + 0] = ptr1\n}\n\nexport function __wbindgen_throw(arg0, arg1) {\n  throw new Error(getStringFromWasm0(arg0, arg1))\n}\n\nexport function __wbindgen_memory() {\n  const ret = wasm.memory\n  return addHeapObject(ret)\n}\n"
  },
  {
    "path": "packages/system-wasm/pkg/system_wasm_bg.wasm.d.ts",
    "content": "/* tslint:disable */\n/* eslint-disable */\nexport const memory: WebAssembly.Memory;\nexport const compress: (a: any) => [number, number, number];\nexport const diff_filters: (a: any, b: any) => [number, number, number];\nexport const expand_filter: (a: any) => [number, number, number];\nexport const flat_merge: (a: any) => [number, number, number];\nexport const get_diff: (a: any, b: any) => [number, number, number];\nexport const pow: (a: any, b: any) => [number, number, number];\nexport const schnorr_verify: (a: any, b: any, c: any) => [number, number, number];\nexport const schnorr_verify_batch: (a: any) => [number, number, number, number];\nexport const schnorr_verify_event: (a: any) => [number, number, number];\nexport const rustsecp256k1_v0_10_0_context_create: (a: number) => number;\nexport const rustsecp256k1_v0_10_0_context_destroy: (a: number) => void;\nexport const rustsecp256k1_v0_10_0_default_error_callback_fn: (a: number, b: number) => void;\nexport const rustsecp256k1_v0_10_0_default_illegal_callback_fn: (a: number, b: number) => void;\nexport const __wbindgen_malloc: (a: number, b: number) => number;\nexport const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;\nexport const __wbindgen_exn_store: (a: number) => void;\nexport const __externref_table_alloc: () => number;\nexport const __wbindgen_externrefs: WebAssembly.Table;\nexport const __wbindgen_free: (a: number, b: number, c: number) => void;\nexport const __externref_table_dealloc: (a: number) => void;\nexport const __wbindgen_start: () => void;\n"
  },
  {
    "path": "packages/system-wasm/src/diff.rs",
    "content": "use std::collections::HashSet;\n\nuse crate::FlatReqFilter;\n\n/// Return the filters in `next` that are not present in `prev`.\n///\n/// Previously used `itertools::Itertools::contains` which is O(n*m). Building\n/// a `HashSet` from `prev` reduces this to O(n + m) — critical when both slices\n/// can be very large (e.g. 50 pubkeys × 5 kinds = 250 entries each side).\npub fn diff_filter(prev: &[FlatReqFilter], next: &[FlatReqFilter]) -> Vec<FlatReqFilter> {\n    let prev_set: HashSet<&FlatReqFilter> = prev.iter().collect();\n    next.iter()\n        .filter(|n| !prev_set.contains(n))\n        .cloned()\n        .collect()\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn simple_diff_same() {\n        let prev = vec![FlatReqFilter {\n            id: Some(\"a\".to_owned()),\n            ..Default::default()\n        }];\n        let next = vec![FlatReqFilter {\n            id: Some(\"a\".to_owned()),\n            ..Default::default()\n        }];\n\n        let result = diff_filter(&prev, &next);\n        assert_eq!(result, vec![])\n    }\n\n    #[test]\n    fn simple_diff_add() {\n        let prev = vec![FlatReqFilter {\n            id: Some(\"a\".to_owned()),\n            ..Default::default()\n        }];\n        let next = vec![\n            FlatReqFilter {\n                id: Some(\"a\".to_owned()),\n                ..Default::default()\n            },\n            FlatReqFilter {\n                id: Some(\"b\".to_owned()),\n                ..Default::default()\n            },\n        ];\n\n        let result = diff_filter(&prev, &next);\n        assert_eq!(\n            result,\n            vec![FlatReqFilter {\n                id: Some(\"b\".to_owned()),\n                ..Default::default()\n            }]\n        )\n    }\n\n    #[test]\n    fn simple_diff_replace() {\n        let prev = vec![FlatReqFilter {\n            id: Some(\"a\".to_owned()),\n            ..Default::default()\n        }];\n        let next = vec![FlatReqFilter {\n            id: Some(\"b\".to_owned()),\n            ..Default::default()\n        }];\n\n        let result = diff_filter(&prev, &next);\n        assert_eq!(\n            result,\n            vec![FlatReqFilter {\n                id: Some(\"b\".to_owned()),\n                ..Default::default()\n            }]\n        )\n    }\n}\n"
  },
  {
    "path": "packages/system-wasm/src/filter.rs",
    "content": "use std::collections::HashSet;\n#[cfg(test)]\nuse std::fmt::Debug;\nuse std::hash::Hash;\n\nuse itertools::Itertools;\nuse serde::{Deserialize, Serialize};\n\n#[derive(PartialEq, Clone, Serialize, Deserialize, Default)]\npub struct ReqFilter {\n    #[serde(rename = \"ids\", skip_serializing_if = \"Option::is_none\")]\n    pub ids: Option<HashSet<String>>,\n    #[serde(rename = \"authors\", skip_serializing_if = \"Option::is_none\")]\n    pub authors: Option<HashSet<String>>,\n    #[serde(rename = \"kinds\", skip_serializing_if = \"Option::is_none\")]\n    pub kinds: Option<HashSet<i32>>,\n    #[serde(rename = \"#e\", skip_serializing_if = \"Option::is_none\")]\n    pub e_tag: Option<HashSet<String>>,\n    #[serde(rename = \"#p\", skip_serializing_if = \"Option::is_none\")]\n    pub p_tag: Option<HashSet<String>>,\n    #[serde(rename = \"#t\", skip_serializing_if = \"Option::is_none\")]\n    pub t_tag: Option<HashSet<String>>,\n    #[serde(rename = \"#d\", skip_serializing_if = \"Option::is_none\")]\n    pub d_tag: Option<HashSet<String>>,\n    #[serde(rename = \"#r\", skip_serializing_if = \"Option::is_none\")]\n    pub r_tag: Option<HashSet<String>>,\n    #[serde(rename = \"#a\", skip_serializing_if = \"Option::is_none\")]\n    pub a_tag: Option<HashSet<String>>,\n    #[serde(rename = \"#g\", skip_serializing_if = \"Option::is_none\")]\n    pub g_tag: Option<HashSet<String>>,\n    #[serde(rename = \"#k\", skip_serializing_if = \"Option::is_none\")]\n    pub k_tag: Option<HashSet<String>>,\n    #[serde(rename = \"#i\", skip_serializing_if = \"Option::is_none\")]\n    pub i_tag: Option<HashSet<String>>,\n    #[serde(rename = \"relays\", skip_serializing_if = \"Option::is_none\")]\n    pub relays: Option<HashSet<String>>,\n    #[serde(rename = \"search\", skip_serializing_if = \"Option::is_none\")]\n    pub search: Option<String>,\n    #[serde(rename = \"since\", skip_serializing_if = \"Option::is_none\")]\n    pub since: Option<i32>,\n    #[serde(rename = \"until\", skip_serializing_if = \"Option::is_none\")]\n    pub until: Option<i32>,\n    #[serde(rename = \"limit\", skip_serializing_if = \"Option::is_none\")]\n    pub limit: Option<i32>,\n}\n\n#[cfg(test)]\nimpl Debug for ReqFilter {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.write_str(&serde_json::to_string(self).unwrap().to_owned())\n    }\n}\n\n/// A single-valued (flat) filter — every multi-valued `ReqFilter` field is\n/// expanded to one value.  Derives `Eq + Hash` so `diff.rs` can put these\n/// into a `HashSet` for O(1) lookup.\n#[derive(PartialEq, Eq, Hash, PartialOrd, Clone, Serialize, Deserialize, Default)]\npub struct FlatReqFilter {\n    #[serde(rename = \"ids\", skip_serializing_if = \"Option::is_none\")]\n    pub id: Option<String>,\n    #[serde(rename = \"authors\", skip_serializing_if = \"Option::is_none\")]\n    pub author: Option<String>,\n    #[serde(rename = \"kinds\", skip_serializing_if = \"Option::is_none\")]\n    pub kind: Option<i32>,\n    #[serde(rename = \"#e\", skip_serializing_if = \"Option::is_none\")]\n    pub e_tag: Option<String>,\n    #[serde(rename = \"#p\", skip_serializing_if = \"Option::is_none\")]\n    pub p_tag: Option<String>,\n    #[serde(rename = \"#t\", skip_serializing_if = \"Option::is_none\")]\n    pub t_tag: Option<String>,\n    #[serde(rename = \"#d\", skip_serializing_if = \"Option::is_none\")]\n    pub d_tag: Option<String>,\n    #[serde(rename = \"#r\", skip_serializing_if = \"Option::is_none\")]\n    pub r_tag: Option<String>,\n    #[serde(rename = \"#a\", skip_serializing_if = \"Option::is_none\")]\n    pub a_tag: Option<String>,\n    #[serde(rename = \"#g\", skip_serializing_if = \"Option::is_none\")]\n    pub g_tag: Option<String>,\n    #[serde(rename = \"#k\", skip_serializing_if = \"Option::is_none\")]\n    pub k_tag: Option<String>,\n    #[serde(rename = \"#i\", skip_serializing_if = \"Option::is_none\")]\n    pub i_tag: Option<String>,\n    #[serde(rename = \"search\", skip_serializing_if = \"Option::is_none\")]\n    pub search: Option<String>,\n    #[serde(rename = \"relay\", skip_serializing_if = \"Option::is_none\")]\n    pub relay: Option<String>,\n    #[serde(rename = \"since\", skip_serializing_if = \"Option::is_none\")]\n    pub since: Option<i32>,\n    #[serde(rename = \"until\", skip_serializing_if = \"Option::is_none\")]\n    pub until: Option<i32>,\n    #[serde(rename = \"limit\", skip_serializing_if = \"Option::is_none\")]\n    pub limit: Option<i32>,\n}\n\n#[cfg(test)]\nimpl Debug for FlatReqFilter {\n    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {\n        f.write_str(&serde_json::to_string(self).unwrap().to_owned())\n    }\n}\n\npub trait Distance {\n    /// Calculate the distance in terms of similarity for merging.\n    fn distance(&self, other: &Self) -> u32;\n}\n\npub trait CanMerge {\n    fn can_merge(&self, other: &Self) -> bool;\n}\n\nimpl Distance for FlatReqFilter {\n    fn distance(&self, b: &Self) -> u32 {\n        let mut ret = 0u32;\n\n        ret += prop_dist(&self.id, &b.id);\n        ret += prop_dist(&self.kind, &b.kind);\n        ret += prop_dist(&self.author, &b.author);\n        ret += prop_dist(&self.relay, &b.relay);\n        ret += prop_dist(&self.e_tag, &b.e_tag);\n        ret += prop_dist(&self.p_tag, &b.p_tag);\n        ret += prop_dist(&self.d_tag, &b.d_tag);\n        ret += prop_dist(&self.r_tag, &b.r_tag);\n        ret += prop_dist(&self.t_tag, &b.t_tag);\n        ret += prop_dist(&self.g_tag, &b.g_tag);\n        ret += prop_dist(&self.k_tag, &b.k_tag);\n        ret += prop_dist(&self.i_tag, &b.i_tag);\n\n        ret\n    }\n}\n\nimpl CanMerge for FlatReqFilter {\n    fn can_merge(&self, other: &Self) -> bool {\n        if self.since != other.since\n            || self.until != other.until\n            || self.limit != other.limit\n            || self.search != other.search\n        {\n            return false;\n        }\n\n        self.distance(other) <= 1\n    }\n}\n\nimpl From<Vec<&FlatReqFilter>> for ReqFilter {\n    fn from(value: Vec<&FlatReqFilter>) -> Self {\n        let ret = Default::default();\n        value.iter().fold(ret, |mut acc, x| {\n            array_prop_append(&x.id, &mut acc.ids);\n            array_prop_append(&x.author, &mut acc.authors);\n            array_prop_append(&x.kind, &mut acc.kinds);\n            array_prop_append(&x.relay, &mut acc.relays);\n            array_prop_append(&x.e_tag, &mut acc.e_tag);\n            array_prop_append(&x.p_tag, &mut acc.p_tag);\n            array_prop_append(&x.t_tag, &mut acc.t_tag);\n            array_prop_append(&x.d_tag, &mut acc.d_tag);\n            array_prop_append(&x.r_tag, &mut acc.r_tag);\n            array_prop_append(&x.a_tag, &mut acc.a_tag);\n            array_prop_append(&x.g_tag, &mut acc.g_tag);\n            array_prop_append(&x.k_tag, &mut acc.k_tag);\n            array_prop_append(&x.i_tag, &mut acc.i_tag);\n            acc.search = x.search.to_owned();\n            acc.since = x.since;\n            acc.until = x.until;\n            acc.limit = x.limit;\n\n            acc\n        })\n    }\n}\n\nimpl From<Vec<&ReqFilter>> for ReqFilter {\n    fn from(value: Vec<&ReqFilter>) -> Self {\n        let ret = Default::default();\n        value.iter().fold(ret, |mut acc, x| {\n            array_prop_append_vec(&x.ids, &mut acc.ids);\n            array_prop_append_vec(&x.authors, &mut acc.authors);\n            array_prop_append_vec(&x.kinds, &mut acc.kinds);\n            array_prop_append_vec(&x.relays, &mut acc.relays);\n            array_prop_append_vec(&x.e_tag, &mut acc.e_tag);\n            array_prop_append_vec(&x.p_tag, &mut acc.p_tag);\n            array_prop_append_vec(&x.t_tag, &mut acc.t_tag);\n            array_prop_append_vec(&x.d_tag, &mut acc.d_tag);\n            array_prop_append_vec(&x.r_tag, &mut acc.r_tag);\n            array_prop_append_vec(&x.a_tag, &mut acc.a_tag);\n            array_prop_append_vec(&x.g_tag, &mut acc.g_tag);\n            array_prop_append_vec(&x.k_tag, &mut acc.k_tag);\n            array_prop_append_vec(&x.i_tag, &mut acc.i_tag);\n            acc.search = x.search.to_owned();\n            acc.since = x.since;\n            acc.until = x.until;\n            acc.limit = x.limit;\n\n            acc\n        })\n    }\n}\n\n/// Expand a `ReqFilter` into a flat list of `FlatReqFilter` via cartesian product.\n///\n/// Instead of boxing field values through an enum + string tag (old approach), we\n/// collect typed slices per field and index them directly via the product indices,\n/// eliminating both heap allocation and string-equality dispatch inside the loop.\npub fn expand(f: &ReqFilter) -> Vec<FlatReqFilter> {\n    // Collect optional slices for each multi-valued field.\n    // HashSet does not implement Deref, so we use as_ref() + collect().\n    let ids_v: Vec<&String> = f.ids.as_ref().map_or_else(Vec::new, |s| s.iter().collect());\n    let authors_v: Vec<&String> = f\n        .authors\n        .as_ref()\n        .map_or_else(Vec::new, |s| s.iter().collect());\n    let kinds_v: Vec<i32> = f\n        .kinds\n        .as_ref()\n        .map_or_else(Vec::new, |s| s.iter().copied().collect());\n    let relays_v: Vec<&String> = f\n        .relays\n        .as_ref()\n        .map_or_else(Vec::new, |s| s.iter().collect());\n    let e_tags_v: Vec<&String> = f\n        .e_tag\n        .as_ref()\n        .map_or_else(Vec::new, |s| s.iter().collect());\n    let p_tags_v: Vec<&String> = f\n        .p_tag\n        .as_ref()\n        .map_or_else(Vec::new, |s| s.iter().collect());\n    let d_tags_v: Vec<&String> = f\n        .d_tag\n        .as_ref()\n        .map_or_else(Vec::new, |s| s.iter().collect());\n    let t_tags_v: Vec<&String> = f\n        .t_tag\n        .as_ref()\n        .map_or_else(Vec::new, |s| s.iter().collect());\n    let r_tags_v: Vec<&String> = f\n        .r_tag\n        .as_ref()\n        .map_or_else(Vec::new, |s| s.iter().collect());\n    let a_tags_v: Vec<&String> = f\n        .a_tag\n        .as_ref()\n        .map_or_else(Vec::new, |s| s.iter().collect());\n    let g_tags_v: Vec<&String> = f\n        .g_tag\n        .as_ref()\n        .map_or_else(Vec::new, |s| s.iter().collect());\n    let k_tags_v: Vec<&String> = f\n        .k_tag\n        .as_ref()\n        .map_or_else(Vec::new, |s| s.iter().collect());\n    let i_tags_v: Vec<&String> = f\n        .i_tag\n        .as_ref()\n        .map_or_else(Vec::new, |s| s.iter().collect());\n\n    // Build lengths for non-empty dimensions only.\n    let mut dim_lengths: Vec<usize> = Vec::with_capacity(13);\n    if !ids_v.is_empty() {\n        dim_lengths.push(ids_v.len());\n    }\n    if !authors_v.is_empty() {\n        dim_lengths.push(authors_v.len());\n    }\n    if !kinds_v.is_empty() {\n        dim_lengths.push(kinds_v.len());\n    }\n    if !relays_v.is_empty() {\n        dim_lengths.push(relays_v.len());\n    }\n    if !e_tags_v.is_empty() {\n        dim_lengths.push(e_tags_v.len());\n    }\n    if !p_tags_v.is_empty() {\n        dim_lengths.push(p_tags_v.len());\n    }\n    if !d_tags_v.is_empty() {\n        dim_lengths.push(d_tags_v.len());\n    }\n    if !t_tags_v.is_empty() {\n        dim_lengths.push(t_tags_v.len());\n    }\n    if !r_tags_v.is_empty() {\n        dim_lengths.push(r_tags_v.len());\n    }\n    if !a_tags_v.is_empty() {\n        dim_lengths.push(a_tags_v.len());\n    }\n    if !g_tags_v.is_empty() {\n        dim_lengths.push(g_tags_v.len());\n    }\n    if !k_tags_v.is_empty() {\n        dim_lengths.push(k_tags_v.len());\n    }\n    if !i_tags_v.is_empty() {\n        dim_lengths.push(i_tags_v.len());\n    }\n\n    if dim_lengths.is_empty() {\n        return vec![FlatReqFilter {\n            search: f.search.clone(),\n            since: f.since,\n            until: f.until,\n            limit: f.limit,\n            ..Default::default()\n        }];\n    }\n\n    let capacity: usize = dim_lengths.iter().product();\n    let mut ret: Vec<FlatReqFilter> = Vec::with_capacity(capacity);\n\n    let ranges: Vec<Vec<usize>> = dim_lengths.iter().map(|&n| (0..n).collect()).collect();\n\n    for combo in ranges.into_iter().multi_cartesian_product() {\n        // ci tracks which dimension of the combo corresponds to each field.\n        #[allow(unused_assignments)]\n        let mut ci = 0usize;\n\n        macro_rules! take_str {\n            ($v:expr) => {{\n                if $v.is_empty() {\n                    None\n                } else {\n                    let idx = combo[ci];\n                    ci += 1;\n                    Some((*$v[idx]).clone())\n                }\n            }};\n        }\n        macro_rules! take_i32 {\n            ($v:expr) => {{\n                if $v.is_empty() {\n                    None\n                } else {\n                    let idx = combo[ci];\n                    ci += 1;\n                    Some($v[idx])\n                }\n            }};\n        }\n\n        let flat = FlatReqFilter {\n            id: take_str!(ids_v),\n            author: take_str!(authors_v),\n            kind: take_i32!(kinds_v),\n            relay: take_str!(relays_v),\n            e_tag: take_str!(e_tags_v),\n            p_tag: take_str!(p_tags_v),\n            d_tag: take_str!(d_tags_v),\n            t_tag: take_str!(t_tags_v),\n            r_tag: take_str!(r_tags_v),\n            a_tag: take_str!(a_tags_v),\n            g_tag: take_str!(g_tags_v),\n            k_tag: take_str!(k_tags_v),\n            i_tag: take_str!(i_tags_v),\n            search: f.search.clone(),\n            since: f.since,\n            until: f.until,\n            limit: f.limit,\n        };\n        let _ = ci; // suppress dead-assignment warning on final macro invocation\n        ret.push(flat);\n    }\n\n    ret\n}\n\n/// Convenience `Into` impl so existing call sites using `(&filter).into()` continue to work.\nimpl From<&ReqFilter> for Vec<FlatReqFilter> {\n    fn from(f: &ReqFilter) -> Vec<FlatReqFilter> {\n        expand(f)\n    }\n}\n\nimpl Distance for ReqFilter {\n    fn distance(&self, b: &Self) -> u32 {\n        let mut ret = 0u32;\n\n        ret += prop_dist_vec(&self.ids, &b.ids);\n        ret += prop_dist_vec(&self.kinds, &b.kinds);\n        ret += prop_dist_vec(&self.authors, &b.authors);\n        ret += prop_dist_vec(&self.relays, &b.relays);\n        ret += prop_dist_vec(&self.e_tag, &b.e_tag);\n        ret += prop_dist_vec(&self.p_tag, &b.p_tag);\n        ret += prop_dist_vec(&self.d_tag, &b.d_tag);\n        ret += prop_dist_vec(&self.r_tag, &b.r_tag);\n        ret += prop_dist_vec(&self.t_tag, &b.t_tag);\n        ret += prop_dist_vec(&self.a_tag, &b.a_tag);\n        ret += prop_dist_vec(&self.g_tag, &b.g_tag);\n        ret += prop_dist_vec(&self.k_tag, &b.k_tag);\n        ret += prop_dist_vec(&self.i_tag, &b.i_tag);\n\n        ret\n    }\n}\n\nimpl CanMerge for ReqFilter {\n    fn can_merge(&self, other: &Self) -> bool {\n        if self.since != other.since\n            || self.until != other.until\n            || self.limit != other.limit\n            || self.search != other.search\n        {\n            return false;\n        }\n\n        self.distance(other) <= 1\n    }\n}\n\n#[inline(always)]\nfn prop_dist<T: Eq>(a: &Option<T>, b: &Option<T>) -> u32 {\n    if (a.is_some() && b.is_none()) || (a.is_none() && b.is_some()) {\n        return 10;\n    } else if a.is_some() && a != b {\n        return 1;\n    }\n    0\n}\n\n#[inline(always)]\nfn prop_dist_vec<T: Eq + Hash>(a: &Option<HashSet<T>>, b: &Option<HashSet<T>>) -> u32 {\n    if (a.is_some() && b.is_none()) || (a.is_none() && b.is_some()) {\n        return 10;\n    }\n    match (a, b) {\n        (Some(aa), Some(bb)) => {\n            if aa.len() != bb.len() {\n                1\n            } else if aa == bb {\n                0\n            } else {\n                1\n            }\n        }\n        (None, None) => 0,\n        _ => panic!(\"Should not reach here!\"),\n    }\n}\n\n#[inline(always)]\nfn array_prop_append<T: Clone + Eq + Hash>(val: &Option<T>, arr: &mut Option<HashSet<T>>) {\n    if let Some(ap) = val {\n        match arr {\n            Some(set) => {\n                set.insert(ap.clone());\n            }\n            None => {\n                *arr = Some(HashSet::from([ap.clone()]));\n            }\n        }\n    }\n}\n\n#[inline(always)]\nfn array_prop_append_vec<T: Clone + Eq + Hash>(\n    val: &Option<HashSet<T>>,\n    arr: &mut Option<HashSet<T>>,\n) {\n    if let Some(ap) = val {\n        match arr {\n            Some(set) => {\n                set.extend(ap.iter().cloned());\n            }\n            None => {\n                *arr = Some(ap.clone());\n            }\n        }\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use std::collections::HashSet;\n\n    use crate::filter::FlatReqFilter;\n    use crate::ReqFilter;\n\n    #[test]\n    fn test_expand_filter() {\n        let input = ReqFilter {\n            authors: Some(HashSet::from([\n                \"a\".to_owned(),\n                \"b\".to_owned(),\n                \"c\".to_owned(),\n            ])),\n            kinds: Some(HashSet::from([1, 2, 3])),\n            ids: Some(HashSet::from([\"x\".to_owned(), \"y\".to_owned()])),\n            p_tag: Some(HashSet::from([\"a\".to_owned()])),\n            since: Some(99),\n            limit: Some(10),\n            ..Default::default()\n        };\n\n        let output: Vec<FlatReqFilter> = (&input).into();\n        // 3 authors × 3 kinds × 2 ids × 1 p_tag = 18\n        assert_eq!(output.len(), 18);\n\n        // Spot-check a few expected entries exist\n        assert!(output.iter().any(|f| f.author.as_deref() == Some(\"a\")\n            && f.kind == Some(1)\n            && f.id.as_deref() == Some(\"x\")\n            && f.p_tag.as_deref() == Some(\"a\")\n            && f.since == Some(99)\n            && f.limit == Some(10)));\n    }\n}\n"
  },
  {
    "path": "packages/system-wasm/src/lib.rs",
    "content": "extern crate console_error_panic_hook;\n\nuse crate::filter::{FlatReqFilter, ReqFilter};\nuse secp256k1::{XOnlyPublicKey, SECP256K1};\nuse serde::{Deserialize, Serialize};\nuse wasm_bindgen::prelude::*;\n\npub mod diff;\npub mod filter;\npub mod merge;\npub mod pow;\npub mod verify;\n\n#[derive(PartialEq, Clone, Serialize, Deserialize)]\npub struct Event {\n    #[serde(rename = \"id\", skip_serializing_if = \"Option::is_none\")]\n    pub id: Option<String>,\n    pub kind: i32,\n    pub created_at: u64,\n    pub pubkey: String,\n    pub content: String,\n    #[serde(rename = \"sig\", skip_serializing_if = \"Option::is_none\")]\n    pub sig: Option<String>,\n    pub tags: Vec<Vec<String>>,\n}\n\n#[wasm_bindgen]\npub fn diff_filters(prev: JsValue, next: JsValue) -> Result<JsValue, JsValue> {\n    console_error_panic_hook::set_once();\n    let prev_parsed: Vec<FlatReqFilter> = serde_wasm_bindgen::from_value(prev)?;\n    let next_parsed: Vec<FlatReqFilter> = serde_wasm_bindgen::from_value(next)?;\n    let result = diff::diff_filter(&prev_parsed, &next_parsed);\n    Ok(serde_wasm_bindgen::to_value(&result)?)\n}\n\n#[wasm_bindgen]\npub fn expand_filter(val: JsValue) -> Result<JsValue, JsValue> {\n    console_error_panic_hook::set_once();\n    let parsed: ReqFilter = serde_wasm_bindgen::from_value(val)?;\n    let result: Vec<FlatReqFilter> = (&parsed).into();\n    Ok(serde_wasm_bindgen::to_value(&result)?)\n}\n\n#[wasm_bindgen]\npub fn get_diff(prev: JsValue, next: JsValue) -> Result<JsValue, JsValue> {\n    console_error_panic_hook::set_once();\n    let prev_parsed: Vec<ReqFilter> = serde_wasm_bindgen::from_value(prev)?;\n    let next_parsed: Vec<ReqFilter> = serde_wasm_bindgen::from_value(next)?;\n    let expanded_prev: Vec<FlatReqFilter> =\n        prev_parsed.iter().flat_map(|v| filter::expand(v)).collect();\n    let expanded_next: Vec<FlatReqFilter> =\n        next_parsed.iter().flat_map(|v| filter::expand(v)).collect();\n    let result = diff::diff_filter(&expanded_prev, &expanded_next);\n    Ok(serde_wasm_bindgen::to_value(&result)?)\n}\n\n#[wasm_bindgen]\npub fn flat_merge(val: JsValue) -> Result<JsValue, JsValue> {\n    console_error_panic_hook::set_once();\n    let val_parsed: Vec<FlatReqFilter> = serde_wasm_bindgen::from_value(val)?;\n    let result = merge::merge::<FlatReqFilter, ReqFilter>(val_parsed.iter().collect());\n    Ok(serde_wasm_bindgen::to_value(&result)?)\n}\n\n#[wasm_bindgen]\npub fn compress(val: JsValue) -> Result<JsValue, JsValue> {\n    console_error_panic_hook::set_once();\n    let val_parsed: Vec<ReqFilter> = serde_wasm_bindgen::from_value(val)?;\n    let result = merge::merge::<ReqFilter, ReqFilter>(val_parsed.iter().collect());\n    Ok(serde_wasm_bindgen::to_value(&result)?)\n}\n\n#[wasm_bindgen]\npub fn pow(val: JsValue, target: JsValue) -> Result<JsValue, JsValue> {\n    console_error_panic_hook::set_once();\n    let mut val_parsed: Event = serde_wasm_bindgen::from_value(val)?;\n    let target_parsed: u8 = serde_wasm_bindgen::from_value(target)?;\n    pow::pow(&mut val_parsed, target_parsed);\n    Ok(serde_wasm_bindgen::to_value(&val_parsed)?)\n}\n\n/// Verify a raw Schnorr signature given the message hash, signature, and\n/// x-only public key — all as hex strings.\n///\n/// Returns a `JsValue` error (rather than panicking) if any hex value is\n/// malformed or the wrong length.\n#[wasm_bindgen]\npub fn schnorr_verify(hash: JsValue, sig: JsValue, pub_key: JsValue) -> Result<bool, JsValue> {\n    console_error_panic_hook::set_once();\n    let msg_hex: String = serde_wasm_bindgen::from_value(hash)?;\n    let sig_hex: String = serde_wasm_bindgen::from_value(sig)?;\n    let pub_key_hex: String = serde_wasm_bindgen::from_value(pub_key)?;\n\n    let key_bytes = hex::decode(&pub_key_hex).map_err(|e| JsValue::from_str(&e.to_string()))?;\n    let sig_bytes = hex::decode(&sig_hex).map_err(|e| JsValue::from_str(&e.to_string()))?;\n    let msg_bytes = hex::decode(&msg_hex).map_err(|e| JsValue::from_str(&e.to_string()))?;\n\n    let key =\n        XOnlyPublicKey::from_slice(&key_bytes).map_err(|e| JsValue::from_str(&e.to_string()))?;\n    let sig = secp256k1::schnorr::Signature::from_slice(&sig_bytes)\n        .map_err(|e| JsValue::from_str(&e.to_string()))?;\n\n    Ok(SECP256K1.verify_schnorr(&sig, &msg_bytes, &key).is_ok())\n}\n\nfn log_error(msg: &str, err: &str) {\n    web_sys::console::error_2(&JsValue::from_str(msg), &JsValue::from_str(err));\n}\n\n/// Verify a single Nostr event.\n///\n/// Computes the canonical event ID from scratch (does not trust `event.id`)\n/// then checks the Schnorr signature.  Returns `false` for any malformed\n/// field rather than throwing — preserving existing call-site behaviour.\n#[wasm_bindgen]\npub fn schnorr_verify_event(event: JsValue) -> Result<bool, JsValue> {\n    console_error_panic_hook::set_once();\n    let event_obj: Event = serde_wasm_bindgen::from_value(event)?;\n    match verify::verify_event(&event_obj, false) {\n        Ok(result) => Ok(result),\n        Err(e) => {\n            log_error(\"schnorr_verify_event failed\", &format!(\"{:?}\", e));\n            Ok(false)\n        }\n    }\n}\n\n#[wasm_bindgen]\npub fn schnorr_verify_batch(events: JsValue) -> Result<Box<[u8]>, JsValue> {\n    console_error_panic_hook::set_once();\n    let events_parsed: Vec<Event> = serde_wasm_bindgen::from_value(events)?;\n    let results: Vec<bool> = verify::verify_batch_with_errors(&events_parsed);\n    Ok(results\n        .into_iter()\n        .map(|b| b as u8)\n        .collect::<Vec<_>>()\n        .into_boxed_slice())\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use itertools::Itertools;\n    use std::cmp::Ordering;\n    use std::collections::HashSet;\n\n    #[test]\n    fn flat_merge_expanded() {\n        let input = vec![\n            ReqFilter {\n                kinds: Some(HashSet::from([1, 6969, 6])),\n                authors: Some(HashSet::from([\n                    \"kieran\".to_string(),\n                    \"snort\".to_string(),\n                    \"c\".to_string(),\n                    \"d\".to_string(),\n                    \"e\".to_string(),\n                ])),\n                since: Some(1),\n                until: Some(100),\n                ..Default::default()\n            },\n            ReqFilter {\n                kinds: Some(HashSet::from([4])),\n                authors: Some(HashSet::from([\"kieran\".to_string()])),\n                ..Default::default()\n            },\n            ReqFilter {\n                kinds: Some(HashSet::from([4])),\n                p_tag: Some(HashSet::from([\"kieran\".to_string()])),\n                ..Default::default()\n            },\n            ReqFilter {\n                kinds: Some(HashSet::from([1000])),\n                authors: Some(HashSet::from([\"snort\".to_string()])),\n                p_tag: Some(HashSet::from([\"kieran\".to_string()])),\n                ..Default::default()\n            },\n        ];\n\n        let expanded: Vec<FlatReqFilter> = input\n            .iter()\n            .flat_map(|v| filter::expand(v))\n            .sorted_by(|_, _| {\n                if rand::random() {\n                    Ordering::Less\n                } else {\n                    Ordering::Greater\n                }\n            })\n            .collect();\n        let merged_expanded: Vec<ReqFilter> = merge::merge(expanded.iter().collect());\n        assert_eq!(merged_expanded.len(), input.len());\n        assert!(merged_expanded.iter().all(|v| input.contains(v)));\n    }\n}\n"
  },
  {
    "path": "packages/system-wasm/src/merge.rs",
    "content": "use crate::filter::CanMerge;\n\npub fn merge<'a, T, Z>(all: Vec<&'a T>) -> Vec<Z>\nwhere\n    T: CanMerge,\n    for<'b> Z: CanMerge + From<Vec<&'a T>> + From<Vec<&'b Z>>,\n{\n    let mut ret: Vec<Z> = merge_once(all);\n    loop {\n        let last_len = ret.len();\n        ret = merge_once(ret.iter().collect());\n        if last_len == ret.len() {\n            break;\n        }\n    }\n    ret\n}\n\nfn merge_once<'a, T, Z>(all: Vec<&'a T>) -> Vec<Z>\nwhere\n    T: CanMerge,\n    Z: From<Vec<&'a T>>,\n{\n    let mut ret: Vec<Z> = vec![];\n    if all.is_empty() {\n        return ret;\n    }\n\n    let merge_sets: Vec<Vec<&T>> = vec![vec![all.first().unwrap()]];\n    let merge_sets = all.iter().skip(1).fold(merge_sets, |mut acc, x| {\n        let mut did_match = false;\n        for y in acc.iter_mut() {\n            if y.iter().all(|z| z.can_merge(x)) {\n                y.push(x);\n                did_match = true;\n                break;\n            }\n        }\n        if !did_match {\n            acc.push(vec![x]);\n        }\n        acc\n    });\n\n    for s in merge_sets {\n        ret.push(Z::from(s));\n    }\n\n    ret\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::filter::{Distance, FlatReqFilter, ReqFilter};\n    use std::collections::HashSet;\n\n    #[test]\n    fn distance() {\n        let a = FlatReqFilter {\n            id: Some(\"a\".to_owned()),\n            ..Default::default()\n        };\n        let b = FlatReqFilter {\n            id: Some(\"a\".to_owned()),\n            ..Default::default()\n        };\n        let c = FlatReqFilter {\n            id: Some(\"c\".to_owned()),\n            ..Default::default()\n        };\n        let d = FlatReqFilter {\n            id: Some(\"a\".to_owned()),\n            kind: Some(1),\n            ..Default::default()\n        };\n        let e = FlatReqFilter {\n            id: Some(\"e\".to_owned()),\n            kind: Some(1),\n            ..Default::default()\n        };\n        assert_eq!(a.distance(&b), 0);\n        assert_eq!(a.distance(&c), 1);\n        assert_eq!(a.distance(&d), 10);\n        assert_eq!(a.distance(&e), 11);\n    }\n\n    #[test]\n    fn merge_set() {\n        let a = FlatReqFilter {\n            id: Some(\"0\".to_owned()),\n            author: Some(\"a\".to_owned()),\n            limit: Some(10),\n            ..Default::default()\n        };\n        let b = FlatReqFilter {\n            id: Some(\"0\".to_owned()),\n            author: Some(\"b\".to_owned()),\n            limit: Some(10),\n            ..Default::default()\n        };\n\n        let output = ReqFilter {\n            ids: Some(HashSet::from([\"0\".to_owned()])),\n            authors: Some(HashSet::from([\"a\".to_owned(), \"b\".to_owned()])),\n            limit: Some(10),\n            ..Default::default()\n        };\n        assert_eq!(ReqFilter::from(vec![&a, &b]), output);\n    }\n\n    #[test]\n    fn can_merge_filters() {\n        let a = FlatReqFilter {\n            id: Some(\"0\".to_owned()),\n            author: Some(\"a\".to_owned()),\n            limit: Some(10),\n            ..Default::default()\n        };\n        let b = FlatReqFilter {\n            id: Some(\"0\".to_owned()),\n            author: Some(\"b\".to_owned()),\n            limit: Some(10),\n            ..Default::default()\n        };\n        let c = FlatReqFilter {\n            id: Some(\"0\".to_owned()),\n            author: Some(\"b\".to_owned()),\n            limit: Some(100),\n            ..Default::default()\n        };\n        assert!(&a.can_merge(&b));\n        assert!(!&b.can_merge(&c));\n    }\n\n    #[test]\n    fn flat_merge() {\n        let input = vec![\n            FlatReqFilter {\n                id: Some(\"0\".to_owned()),\n                author: Some(\"a\".to_owned()),\n                ..Default::default()\n            },\n            FlatReqFilter {\n                id: Some(\"0\".to_owned()),\n                author: Some(\"b\".to_owned()),\n                ..Default::default()\n            },\n            FlatReqFilter {\n                kind: Some(1),\n                ..Default::default()\n            },\n            FlatReqFilter {\n                kind: Some(2),\n                ..Default::default()\n            },\n            FlatReqFilter {\n                kind: Some(2),\n                ..Default::default()\n            },\n            FlatReqFilter {\n                id: Some(\"0\".to_owned()),\n                author: Some(\"c\".to_owned()),\n                ..Default::default()\n            },\n            FlatReqFilter {\n                author: Some(\"c\".to_owned()),\n                kind: Some(1),\n                ..Default::default()\n            },\n            FlatReqFilter {\n                author: Some(\"c\".to_owned()),\n                limit: Some(100),\n                ..Default::default()\n            },\n            FlatReqFilter {\n                id: Some(\"1\".to_owned()),\n                author: Some(\"c\".to_owned()),\n                ..Default::default()\n            },\n        ];\n        let output = vec![\n            ReqFilter {\n                ids: Some(HashSet::from([\"0\".to_owned()])),\n                authors: Some(HashSet::from([\n                    \"a\".to_owned(),\n                    \"b\".to_owned(),\n                    \"c\".to_owned(),\n                ])),\n                ..Default::default()\n            },\n            ReqFilter {\n                kinds: Some(HashSet::from([1, 2])),\n                ..Default::default()\n            },\n            ReqFilter {\n                authors: Some(HashSet::from([\"c\".to_owned()])),\n                kinds: Some(HashSet::from([1])),\n                ..Default::default()\n            },\n            ReqFilter {\n                authors: Some(HashSet::from([\"c\".to_owned()])),\n                limit: Some(100),\n                ..Default::default()\n            },\n            ReqFilter {\n                ids: Some(HashSet::from([\"1\".to_owned()])),\n                authors: Some(HashSet::from([\"c\".to_owned()])),\n                ..Default::default()\n            },\n        ];\n\n        assert_eq!(\n            merge::<FlatReqFilter, ReqFilter>(input.iter().collect()),\n            output\n        )\n    }\n}\n"
  },
  {
    "path": "packages/system-wasm/src/pow.rs",
    "content": "use crate::Event;\n\npub fn pow(ev: &mut Event, target: u8) {\n    let mut ctr = 0u32;\n    let nonce_tag_idx = match ev.tags.iter().position(|x| x[0] == \"nonce\") {\n        Some(i) => i,\n        None => {\n            let idx = ev.tags.len();\n            ev.tags.push(vec![\n                \"nonce\".to_owned(),\n                ctr.to_string(),\n                target.to_string(),\n            ]);\n            idx\n        }\n    };\n\n    loop {\n        ev.tags[nonce_tag_idx][1] = ctr.to_string();\n\n        let id_hex = make_id(ev);\n        let digest = sha256::digest(id_hex.as_bytes());\n        if count_leading_zeros(&digest) >= target {\n            ev.id = Some(digest);\n            break;\n        }\n\n        ctr += 1;\n    }\n}\n\n/// Count the number of leading zero bits in a hex-encoded SHA-256 digest.\n/// Decodes nibble-by-nibble from the `&str` without allocating a `Vec<u8>`.\nfn count_leading_zeros(hex_str: &str) -> u8 {\n    let mut count = 0u8;\n    let bytes = hex_str.as_bytes();\n    let mut i = 0;\n    while i + 1 < bytes.len() {\n        let byte = (hex_nibble(bytes[i]) << 4) | hex_nibble(bytes[i + 1]);\n        if byte == 0 {\n            count += 8;\n        } else {\n            count += byte.leading_zeros() as u8;\n            break;\n        }\n        i += 2;\n    }\n    count\n}\n\n#[inline(always)]\nfn hex_nibble(c: u8) -> u8 {\n    match c {\n        b'0'..=b'9' => c - b'0',\n        b'a'..=b'f' => c - b'a' + 10,\n        b'A'..=b'F' => c - b'A' + 10,\n        _ => 0,\n    }\n}\n\n/// Write the canonical Nostr event serialisation using serde_json for correct escaping.\npub fn make_id(ev: &Event) -> String {\n    let payload = serde_json::json!([0, ev.pubkey, ev.created_at, ev.kind, ev.tags, ev.content]);\n    sha256::digest(payload.to_string().as_bytes())\n}\n\n#[cfg(test)]\nmod tests {\n    use crate::Event;\n    use serde::Deserialize;\n    use serde_json::json;\n\n    #[test]\n    fn make_id() {\n        let ev = Event::deserialize(json!({\n          \"content\": \"Oh i think it doesnt work until you reload\",\n          \"created_at\": 1695568849,\n          \"id\": \"0000051bca8ee62220b34827358dca69284734a2e7420f3c4b814901a531c767\",\n          \"kind\": 1,\n          \"pubkey\": \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\",\n          \"sig\": \"0c18bfcde49fd42c7faf93b3ecd7caf10f0414c9ee3234fca96ea0bbb1a805cb2767fc067dc1a743420c499b34c232e19b73beb2f1fe47c18a2856c67bdef983\",\n          \"tags\": [\n            [\"e\",\"ad17146f086345a12583b537daabdf49ccc5cd09e2c0b4816c835f397b693e6b\",\"wss://nos.lol/\",\"root\"],\n            [\"e\",\"72759bf1f525e9715f4e6d22381f53dc4d2ab47d7aaac11340e7fced13e10b11\",\"wss://nos.lol/\",\"reply\"],\n            [\"p\",\"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\"],\n            [\"p\",\"1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411\"],\n            [\"nonce\",\"7403\",\"18\"]\n          ]\n        })).ok().unwrap();\n\n        assert_eq!(super::make_id(&ev), ev.id.unwrap())\n    }\n\n    #[test]\n    fn make_id_with_special_chars_in_content() {\n        let ev = Event::deserialize(json!({\n          \"content\": \"{\\\"about\\\":\\\"mar - the main character, might be a girl\\\\n\\\\ncatoshi - the black cat, definitely a cat\\\",\\\"banner\\\":\\\"https://mar101xy.com/images/mar101xy-profile-cover.jpg\\\",\\\"bot\\\":false,\\\"display_name\\\":\\\"mar\\\",\\\"lud16\\\":\\\"mar101xy@walletofsatoshi.com\\\",\\\"nip05\\\":\\\"mar@mar101xy.com\\\",\\\"picture\\\":\\\"https://mar101xy.com/images/avatar.jpg\\\",\\\"displayName\\\":\\\"mar\\\",\\\"fields\\\":[[\\\"test\\\",\\\"testing ditto\\\"],[\\\"gender\\\",\\\"testing gender\\\"]],\\\"name\\\":\\\"mar\\\"}\",\n          \"created_at\": 1775155758,\n          \"id\": \"053516868fe8f94fa180835d3b0be4042aaaddc514c6e6d6d8e0fa9694d3442d\",\n          \"kind\": 0,\n          \"pubkey\": \"c7acabf1fed201a53185e4dc5e0c6bae2bc5db19d73abf840535f305d8f05180\",\n          \"sig\": \"c8de210d80a2ad92e1145e9c52177ab077f862acd9857f7e8b6ae24645893b0d81bf585814ececb17b0ecd17529135b39cdd9aaf2a84626509c11c6f0c6ed62f\",\n          \"tags\": [[\"client\",\"Ditto\"]]\n        })).ok().unwrap();\n\n        assert_eq!(super::make_id(&ev), ev.id.unwrap())\n    }\n\n    #[test]\n    fn make_id_with_escaped_backslash_in_content() {\n        let ev = Event::deserialize(json!({\n          \"content\": \"{\\\"name\\\":\\\"TheGrinder\\\",\\\"about\\\":\\\"Sovereign, creator of bitcoins, future owner of Mars and grinder of many things...\\\\n0863F34D0311FC550226F06A376B54D5650980FB\\\",\\\"picture\\\":\\\"https://i.nostr.build/TghNVYXqMe7knx7P.jpg\\\",\\\"banner\\\":\\\"https://nostr.build/i/094828ef504cb05424a9680db23d37db3cf02f05ede1d33528c5c5f9872db66e.jpg\\\",\\\"displayName\\\":\\\"TheGrinder\\\",\\\"lud16\\\":\\\"thegrinder@rizful.com\\\",\\\"display_name\\\":\\\"TheGrinder\\\",\\\"website\\\":\\\"https://zap.stream/thegrinder\\\",\\\"nip05\\\":\\\"thegrinder@nostrplebs.com\\\"}\",\n          \"created_at\": 1774868231,\n          \"id\": \"2dc93fea65b858e864520687927bb8e83374fff8eeb592c9cfaa8b470fc7b2db\",\n          \"kind\": 0,\n          \"pubkey\": \"6e75f7972397ca3295e0f4ca0fbc6eb9cc79be85bafdd56bd378220ca8eee74e\",\n          \"sig\": \"4b2c21ff288b2e4e900f88429a0b4a8c3d6c248cab175b8e984d3251cf67578626583379cef99c73e85df3fc35407f292499df7124c3d854bfbf6ac0421a03ee\",\n          \"tags\": [[\"client\",\"noStrudel\",\"31990:266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5:1686066542546\"]]\n        })).ok().unwrap();\n\n        assert_eq!(super::make_id(&ev), ev.id.unwrap())\n    }\n\n    #[test]\n    fn count_zeros() {\n        assert_eq!(10u8.leading_zeros(), 4);\n        assert_eq!(super::count_leading_zeros(\"00\"), 8);\n        assert_eq!(\n            super::count_leading_zeros(\n                \"0000051bca8ee62220b34827358dca69284734a2e7420f3c4b814901a531c767\"\n            ),\n            21\n        )\n    }\n}\n"
  },
  {
    "path": "packages/system-wasm/src/verify.rs",
    "content": "//! Schnorr signature verification for Nostr events.\n//!\n//! Centralises the logic used by both `schnorr_verify_event` (single) and\n//! `schnorr_verify_batch` (N events in one call) so the two code paths share\n//! the same parsing and error handling.\n\nuse secp256k1::{schnorr::Signature, XOnlyPublicKey, SECP256K1};\n\nuse crate::{pow, Event};\n\n/// Errors that can occur during event verification.\n#[derive(Debug)]\npub enum VerifyError {\n    /// `sig` field is missing from the event.\n    MissingSig,\n    /// A hex field has the wrong byte length.\n    BadLength {\n        field: &'static str,\n        got: usize,\n        expected: usize,\n    },\n    /// Hex decoding failed.\n    HexDecode(&'static str),\n    /// secp256k1 rejected the public key bytes.\n    BadPubkey,\n    /// secp256k1 rejected the signature bytes.\n    BadSig,\n}\n\nimpl From<VerifyError> for wasm_bindgen::JsValue {\n    fn from(e: VerifyError) -> Self {\n        wasm_bindgen::JsValue::from_str(&format!(\"{:?}\", e))\n    }\n}\n\n/// Decode a fixed-length hex string into a byte array without allocating a Vec.\n#[inline]\nfn decode_hex_fixed<const N: usize>(s: &str, field: &'static str) -> Result<[u8; N], VerifyError> {\n    // A hex string for N bytes must be exactly 2*N characters.\n    if s.len() != N * 2 {\n        return Err(VerifyError::BadLength {\n            field,\n            got: s.len(),\n            expected: N * 2,\n        });\n    }\n    let mut out = [0u8; N];\n    hex::decode_to_slice(s, &mut out).map_err(|_| VerifyError::HexDecode(field))?;\n    Ok(out)\n}\n\n/// Verify a single Nostr event.\n///\n/// If `trust_id` is true and `event.id` is `Some`, the provided ID is decoded\n/// and used directly as the message hash rather than recomputing it.  This\n/// saves a full SHA-256 + JSON serialisation when the caller has already\n/// validated the ID separately (e.g. events retrieved from a local DB that\n/// stores only verified events).\n///\n/// Returns `Ok(true)` if valid, `Ok(false)` if the signature is wrong,\n/// `Err(...)` if the event is malformed.\npub fn verify_event(event: &Event, trust_id: bool) -> Result<bool, VerifyError> {\n    // --- fast pre-validation: check hex lengths before touching secp256k1 ---\n    let pubkey_bytes: [u8; 32] = decode_hex_fixed(&event.pubkey, \"pubkey\")?;\n\n    let sig_str = event.sig.as_deref().ok_or(VerifyError::MissingSig)?;\n    let sig_bytes: [u8; 64] = decode_hex_fixed(sig_str, \"sig\")?;\n\n    // Compute (or reuse) the event ID.\n    let id_bytes: [u8; 32] = if trust_id {\n        if let Some(id) = event.id.as_deref() {\n            decode_hex_fixed(id, \"id\")?\n        } else {\n            // No ID provided — must compute it.\n            let id_hex = pow::make_id(event);\n            decode_hex_fixed(&id_hex, \"id\")?\n        }\n    } else {\n        // Always recompute — canonical verification.\n        let id_hex = pow::make_id(event);\n        decode_hex_fixed(&id_hex, \"id\")?\n    };\n\n    // --- secp256k1 ---\n    let key = XOnlyPublicKey::from_slice(&pubkey_bytes).map_err(|_| VerifyError::BadPubkey)?;\n    let sig = Signature::from_slice(&sig_bytes).map_err(|_| VerifyError::BadSig)?;\n\n    Ok(SECP256K1.verify_schnorr(&sig, &id_bytes, &key).is_ok())\n}\n\n/// Result of a batch verification: one entry per input event.\n///\n/// `true`  — valid signature and ID.\n/// `false` — invalid signature / malformed event.\npub fn verify_batch(events: &[Event]) -> Vec<bool> {\n    events\n        .iter()\n        .map(|ev| verify_event(ev, false).unwrap_or(false))\n        .collect()\n}\n\n/// Verify a batch of events, logging detailed errors for each failure.\n/// Returns a Vec<bool> where true means valid, false means invalid/error.\npub fn verify_batch_with_errors(events: &[Event]) -> Vec<bool> {\n    events\n        .iter()\n        .enumerate()\n        .map(|(idx, ev)| match verify_event(ev, false) {\n            Ok(true) => true,\n            Ok(false) => {\n                eprintln!(\"batch[{}]: signature verification failed\", idx);\n                false\n            }\n            Err(e) => {\n                eprintln!(\"batch[{}]: verification error: {:?}\", idx, e);\n                false\n            }\n        })\n        .collect()\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use serde::Deserialize;\n    use serde_json::json;\n\n    fn make_valid_event() -> Event {\n        Event::deserialize(json!({\n          \"content\": \"Oh i think it doesnt work until you reload\",\n          \"created_at\": 1695568849,\n          \"id\": \"0000051bca8ee62220b34827358dca69284734a2e7420f3c4b814901a531c767\",\n          \"kind\": 1,\n          \"pubkey\": \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\",\n          \"sig\": \"0c18bfcde49fd42c7faf93b3ecd7caf10f0414c9ee3234fca96ea0bbb1a805cb2767fc067dc1a743420c499b34c232e19b73beb2f1fe47c18a2856c67bdef983\",\n          \"tags\": [\n            [\"e\",\"ad17146f086345a12583b537daabdf49ccc5cd09e2c0b4816c835f397b693e6b\",\"wss://nos.lol/\",\"root\"],\n            [\"e\",\"72759bf1f525e9715f4e6d22381f53dc4d2ab47d7aaac11340e7fced13e10b11\",\"wss://nos.lol/\",\"reply\"],\n            [\"p\",\"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\"],\n            [\"p\",\"1bc70a0148b3f316da33fe3c89f23e3e71ac4ff998027ec712b905cd24f6a411\"],\n            [\"nonce\",\"7403\",\"18\"]\n          ]\n        })).unwrap()\n    }\n\n    #[test]\n    fn verify_valid_event() {\n        let ev = make_valid_event();\n        assert_eq!(verify_event(&ev, false).unwrap(), true);\n    }\n\n    #[test]\n    fn verify_valid_event_trust_id() {\n        let ev = make_valid_event();\n        // With trust_id=true the ID is decoded directly — should still verify.\n        assert_eq!(verify_event(&ev, true).unwrap(), true);\n    }\n\n    #[test]\n    fn verify_bad_sig() {\n        let mut ev = make_valid_event();\n        // Flip the last byte of the signature.\n        let mut sig = ev.sig.clone().unwrap();\n        let last = sig.pop().unwrap();\n        sig.push(if last == 'a' { 'b' } else { 'a' });\n        ev.sig = Some(sig);\n        // secp256k1 may reject the bytes entirely (BadSig) or return false.\n        let result = verify_event(&ev, false);\n        assert!(matches!(result, Ok(false) | Err(VerifyError::BadSig)));\n    }\n\n    #[test]\n    fn verify_bad_pubkey_length() {\n        let mut ev = make_valid_event();\n        ev.pubkey = \"deadbeef\".to_string(); // too short\n        assert!(matches!(\n            verify_event(&ev, false),\n            Err(VerifyError::BadLength {\n                field: \"pubkey\",\n                ..\n            })\n        ));\n    }\n\n    #[test]\n    fn verify_missing_sig() {\n        let mut ev = make_valid_event();\n        ev.sig = None;\n        assert!(matches!(\n            verify_event(&ev, false),\n            Err(VerifyError::MissingSig)\n        ));\n    }\n\n    #[test]\n    fn batch_verify_mixed() {\n        let valid = make_valid_event();\n        let mut invalid = make_valid_event();\n        invalid.sig = None;\n\n        let results = verify_batch(&[valid.clone(), invalid, valid]);\n        assert_eq!(results, vec![true, false, true]);\n    }\n\n    #[test]\n    fn batch_verify_empty() {\n        assert_eq!(verify_batch(&[]), Vec::<bool>::new());\n    }\n\n    #[test]\n    fn batch_verify_events_with_special_content() {\n        let profile_with_newlines = Event::deserialize(json!({\n          \"content\": \"{\\\"about\\\":\\\"mar - the main character, might be a girl\\\\n\\\\ncatoshi - the black cat, definitely a cat\\\",\\\"banner\\\":\\\"https://mar101xy.com/images/mar101xy-profile-cover.jpg\\\",\\\"bot\\\":false,\\\"display_name\\\":\\\"mar\\\",\\\"lud16\\\":\\\"mar101xy@walletofsatoshi.com\\\",\\\"nip05\\\":\\\"mar@mar101xy.com\\\",\\\"picture\\\":\\\"https://mar101xy.com/images/avatar.jpg\\\",\\\"displayName\\\":\\\"mar\\\",\\\"fields\\\":[[\\\"test\\\",\\\"testing ditto\\\"],[\\\"gender\\\",\\\"testing gender\\\"]],\\\"name\\\":\\\"mar\\\"}\",\n          \"created_at\": 1775155758,\n          \"id\": \"053516868fe8f94fa180835d3b0be4042aaaddc514c6e6d6d8e0fa9694d3442d\",\n          \"kind\": 0,\n          \"pubkey\": \"c7acabf1fed201a53185e4dc5e0c6bae2bc5db19d73abf840535f305d8f05180\",\n          \"sig\": \"c8de210d80a2ad92e1145e9c52177ab077f862acd9857f7e8b6ae24645893b0d81bf585814ececb17b0ecd17529135b39cdd9aaf2a84626509c11c6f0c6ed62f\",\n          \"tags\": [[\"client\",\"Ditto\"]]\n        })).unwrap();\n\n        let profile_with_escaped_backslash = Event::deserialize(json!({\n          \"content\": \"{\\\"name\\\":\\\"TheGrinder\\\",\\\"about\\\":\\\"Sovereign, creator of bitcoins, future owner of Mars and grinder of many things...\\\\n0863F34D0311FC550226F06A376B54D5650980FB\\\",\\\"picture\\\":\\\"https://i.nostr.build/TghNVYXqMe7knx7P.jpg\\\",\\\"banner\\\":\\\"https://nostr.build/i/094828ef504cb05424a9680db23d37db3cf02f05ede1d33528c5c5f9872db66e.jpg\\\",\\\"displayName\\\":\\\"TheGrinder\\\",\\\"lud16\\\":\\\"thegrinder@rizful.com\\\",\\\"display_name\\\":\\\"TheGrinder\\\",\\\"website\\\":\\\"https://zap.stream/thegrinder\\\",\\\"nip05\\\":\\\"thegrinder@nostrplebs.com\\\"}\",\n          \"created_at\": 1774868231,\n          \"id\": \"2dc93fea65b858e864520687927bb8e83374fff8eeb592c9cfaa8b470fc7b2db\",\n          \"kind\": 0,\n          \"pubkey\": \"6e75f7972397ca3295e0f4ca0fbc6eb9cc79be85bafdd56bd378220ca8eee74e\",\n          \"sig\": \"4b2c21ff288b2e4e900f88429a0b4a8c3d6c248cab175b8e984d3251cf67578626583379cef99c73e85df3fc35407f292499df7124c3d854bfbf6ac0421a03ee\",\n          \"tags\": [[\"client\",\"noStrudel\",\"31990:266815e0c9210dfa324c6cba3573b14bee49da4209a9456f9484e5106cd408a5:1686066542546\"]]\n        })).unwrap();\n\n        let plain = make_valid_event();\n\n        let results = verify_batch(&[profile_with_newlines, profile_with_escaped_backslash, plain]);\n        assert_eq!(results, vec![true, true, true]);\n    }\n\n    #[test]\n    fn batch_verify_user_event() {\n        let ev = Event::deserialize(json!({\n          \"kind\": 1,\n          \"id\": \"c55e31fe1c93705558d58c8ad309b0b27c2f21dae92f72bfbc8869de872a2616\",\n          \"pubkey\": \"06639a386c9c1014217622ccbcf40908c4f1a0c33e23f8d6d68f4abf655f8f71\",\n          \"created_at\": 1774961298,\n          \"tags\": [\n            [\"e\", \"507c11d1cdb2130c751ff05e7afa0a47079025ba39ef099ae1a25c53c03ae99e\", \"wss://pyramid.fiatjaf.com/\", \"root\", \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\"],\n            [\"e\", \"0468572f697fa7e399f7a99b0d7f1d640a10ceeab17d31e68e11af37be444b26\", \"wss://nos.lol/\", \"reply\", \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\"],\n            [\"p\", \"63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed\"]\n          ],\n          \"content\": \"I'm interested to try it.\\nLocally I have qwen3.5 8B running with ollama on a RK1 32GB compute module.\",\n          \"sig\": \"c07c9757ebb3e0808077d5876d5c670c0e788d9f92326ff21aae4766e026e722d017c2e9c1229eece8861c308732d920f1bdbb30ceddd4342d2c4c95f4c5fa05\"\n        })).unwrap();\n\n        let computed_id = crate::pow::make_id(&ev);\n        println!(\"computed_id: {}\", computed_id);\n        println!(\"event id: {:?}\", ev.id);\n\n        let results = verify_batch(&[ev]);\n        println!(\"verify result: {:?}\", results);\n        assert_eq!(results, vec![true]);\n    }\n}\n"
  },
  {
    "path": "packages/system-wasm/system-query.iml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"RUST_MODULE\" version=\"4\">\n  <component name=\"NewModuleRootManager\" inherit-compiler-output=\"true\">\n    <exclude-output />\n    <content url=\"file://$MODULE_DIR$\">\n      <sourceFolder url=\"file://$MODULE_DIR$/benches\" isTestSource=\"true\" />\n      <sourceFolder url=\"file://$MODULE_DIR$/src\" isTestSource=\"false\" />\n      <excludeFolder url=\"file://$MODULE_DIR$/target\" />\n    </content>\n    <orderEntry type=\"inheritedJdk\" />\n    <orderEntry type=\"sourceFolder\" forTests=\"false\" />\n  </component>\n</module>"
  },
  {
    "path": "packages/system-wasm/typedoc.json",
    "content": "{\n  \"entryPoints\": [\"pkg/system_wasm.d.ts\"]\n}\n"
  },
  {
    "path": "packages/wallet/README.md",
    "content": "# wallet\n"
  },
  {
    "path": "packages/wallet/package.json",
    "content": "{\n  \"name\": \"@snort/wallet\",\n  \"version\": \"2.0.0-pre.9\",\n  \"description\": \"Snort wallet system package\",\n  \"type\": \"module\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"module\": \"src/index.ts\",\n  \"repository\": \"https://git.v0l.io/Kieran/snort\",\n  \"author\": \"v0l\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"build\": \"rm -rf dist && bunx --bun tsc\"\n  },\n  \"files\": [\"src\", \"dist\"],\n  \"dependencies\": {\n    \"@scure/base\": \"^2.0.0\",\n    \"@snort/shared\": \"^2.0.0-pre.4\",\n    \"@snort/system\": \"^2.0.0-pre.11\",\n    \"debug\": \"^4.4.3\",\n    \"eventemitter3\": \"^5.0.1\"\n  },\n  \"devDependencies\": {\n    \"@types/debug\": \"^4.1.12\",\n    \"@webbtc/webln-types\": \"^3.0.0\",\n    \"typescript\": \"^5.9.3\"\n  }\n}\n"
  },
  {
    "path": "packages/wallet/src/AlbyWallet.ts",
    "content": "import { base64 } from \"@scure/base\"\nimport { unixNow, unwrap } from \"@snort/shared\"\n\nimport {\n  type InvoiceRequest,\n  type LNWallet,\n  prToWalletInvoice,\n  WalletError,\n  WalletErrorCode,\n  type WalletEvents,\n  type WalletInfo,\n  type WalletInvoice,\n  WalletInvoiceState,\n} from \".\"\nimport EventEmitter from \"eventemitter3\"\n\nexport interface OAuthToken {\n  access_token: string\n  created_at: number\n  expires_in: number\n  refresh_token: string\n  scope: string\n  token_type: string\n  clientId: string\n  clientSecret: string\n}\n\nexport default class AlbyWallet extends EventEmitter<WalletEvents> implements LNWallet {\n  #token: OAuthToken\n  constructor(token: OAuthToken) {\n    super()\n    this.#token = token\n  }\n\n  isReady() {\n    return true\n  }\n\n  canAutoLogin() {\n    return true\n  }\n\n  canGetInvoices() {\n    return this.#token.scope.includes(\"invoices:read\")\n  }\n\n  canGetBalance() {\n    return this.#token.scope.includes(\"balance:read\")\n  }\n\n  canCreateInvoice() {\n    return true\n  }\n\n  canPayInvoice() {\n    return true\n  }\n\n  async getInfo() {\n    const me = await this.#fetch<GetUserResponse>(\"/user/me\")\n    return { alias: me.lightning_address } as WalletInfo\n  }\n\n  async login() {\n    return true\n  }\n\n  close() {\n    return Promise.resolve(true)\n  }\n\n  async getBalance() {\n    await this.#refreshToken()\n    const bal = await this.#fetch<GetBalanceResponse>(\"/balance\")\n    return bal.balance\n  }\n\n  async createInvoice(req: InvoiceRequest) {\n    const inv = await this.#fetch<CreateInvoiceResponse>(\"/invoices\", \"POST\", {\n      amount: req.amount,\n      memo: req.memo,\n    })\n\n    return unwrap(prToWalletInvoice(inv.payment_request))\n  }\n\n  async payInvoice(pr: string) {\n    const pay = await this.#fetch<PayInvoiceResponse>(\"/payments/bolt11\", \"POST\", {\n      invoice: pr,\n    })\n\n    return {\n      ...prToWalletInvoice(pay.payment_request),\n      fees: pay.fee,\n      preimage: pay.payment_preimage,\n      state: WalletInvoiceState.Paid,\n      direction: \"out\",\n    } as WalletInvoice\n  }\n\n  async getInvoices() {\n    const invoices = await this.#fetch<Array<GetInvoiceResponse>>(\"/invoices?page=1&items=20\")\n    return invoices.map(a => {\n      return {\n        ...prToWalletInvoice(a.payment_request),\n        memo: a.comment,\n        preimage: a.preimage,\n        state: a.settled ? WalletInvoiceState.Paid : WalletInvoiceState.Pending,\n        direction: a.type === \"incoming\" ? \"in\" : \"out\",\n      } as WalletInvoice\n    })\n  }\n\n  async #fetch<T>(path: string, method: \"GET\" | \"POST\" = \"GET\", body?: object) {\n    const req = await fetch(`https://api.getalby.com${path}`, {\n      method: method,\n      body: body ? JSON.stringify(body) : undefined,\n      headers: {\n        accept: \"application/json\",\n        authorization: `Bearer ${this.#token.access_token}`,\n        ...(body ? { \"content-type\": \"application/json\" } : {}),\n      },\n    })\n    const json = await req.text()\n    if (req.ok) {\n      return JSON.parse(json) as T\n    } else {\n      if (json.length > 0) {\n        throw new WalletError(WalletErrorCode.GeneralError, JSON.parse(json).message as string)\n      } else {\n        throw new WalletError(WalletErrorCode.GeneralError, `Error: ${json} (${req.status})`)\n      }\n    }\n  }\n  async #refreshToken() {\n    if (this.#token.created_at + this.#token.expires_in < unixNow()) {\n      const params = new URLSearchParams()\n      params.set(\"refresh_token\", this.#token.refresh_token)\n      params.set(\"grant_type\", \"refresh_token\")\n\n      const req = await fetch(\"https://api.getalby.com/oauth/token\", {\n        method: \"POST\",\n        body: params,\n        headers: {\n          accept: \"application/json\",\n          \"content-type\": \"application/x-www-form-urlencoded\",\n          authorization: `Basic ${base64.encode(\n            new TextEncoder().encode(`${this.#token.clientId}:${this.#token.clientSecret}`),\n          )}`,\n        },\n      })\n      const json = await req.json()\n      if (req.ok) {\n        this.#token = {\n          ...(json as OAuthToken),\n          created_at: unixNow(),\n        }\n        this.emit(\"change\", JSON.stringify(this.#token))\n      }\n    }\n  }\n}\n\ninterface GetBalanceResponse {\n  balance: number\n  currency: string\n  unit: string\n}\n\ninterface CreateInvoiceResponse {\n  expires_at: string\n  payment_hash: string\n  payment_request: string\n}\n\ninterface PayInvoiceResponse {\n  amount: number\n  description?: string\n  destination: string\n  fee: number\n  payment_hash: string\n  payment_preimage: string\n  payment_request: string\n}\n\ninterface GetInvoiceResponse {\n  amount: number\n  comment?: string\n  created_at: string\n  creation_date: number\n  currency: string\n  expires_at: string\n  preimage: string\n  payment_request: string\n  settled: boolean\n  settled_at: string\n  type: \"incoming\" | \"outgoing\"\n}\n\ninterface GetUserResponse {\n  lightning_address: string\n}\n"
  },
  {
    "path": "packages/wallet/src/LNDHub.ts",
    "content": "import { throwIfOffline } from \"@snort/shared\"\n\nimport {\n  type InvoiceRequest,\n  type LNWallet,\n  prToWalletInvoice,\n  type Sats,\n  WalletError,\n  WalletErrorCode,\n  type WalletEvents,\n  type WalletInfo,\n  type WalletInvoice,\n  WalletInvoiceState,\n} from \".\"\nimport EventEmitter from \"eventemitter3\"\n\nconst defaultHeaders = {\n  Accept: \"application/json\",\n  \"Content-Type\": \"application/json\",\n}\n\nexport default class LNDHubWallet extends EventEmitter<WalletEvents> implements LNWallet {\n  type: \"lndhub\"\n  url: URL\n  user: string\n  password: string\n  auth?: AuthResponse\n\n  constructor(url: string) {\n    super()\n    if (url.startsWith(\"lndhub://\")) {\n      const regex = /^lndhub:\\/\\/([\\S-]+):([\\S-]+)@(.*)$/i\n      const parsedUrl = url.match(regex)\n      if (!parsedUrl || parsedUrl.length !== 4) {\n        throw new Error(\"Invalid LNDHUB config\")\n      }\n      this.url = new URL(parsedUrl[3])\n      this.user = parsedUrl[1]\n      this.password = parsedUrl[2]\n      this.type = \"lndhub\"\n    } else {\n      throw new Error(\"Invalid config\")\n    }\n  }\n\n  isReady(): boolean {\n    return this.auth !== undefined\n  }\n\n  canAutoLogin() {\n    return true\n  }\n\n  canGetInvoices() {\n    return true\n  }\n\n  canGetBalance() {\n    return true\n  }\n\n  canCreateInvoice() {\n    return true\n  }\n\n  canPayInvoice() {\n    return true\n  }\n\n  close(): Promise<boolean> {\n    return Promise.resolve(true)\n  }\n\n  async getInfo() {\n    await this.login()\n    return await this.getJson<WalletInfo>(\"GET\", \"/getinfo\")\n  }\n\n  async login() {\n    if (this.auth) return true\n\n    const rsp = await this.getJson<AuthResponse>(\"POST\", \"/auth?type=auth\", {\n      login: this.user,\n      password: this.password,\n    })\n    this.auth = rsp as AuthResponse\n    this.emit(\"change\")\n    return true\n  }\n\n  async getBalance(): Promise<Sats> {\n    await this.login()\n    const rsp = await this.getJson<GetBalanceResponse>(\"GET\", \"/balance\")\n    const bal = Math.floor((rsp as GetBalanceResponse).BTC.AvailableBalance)\n    return bal as Sats\n  }\n\n  async createInvoice(req: InvoiceRequest) {\n    await this.login()\n    const rsp = await this.getJson<UserInvoicesResponse>(\"POST\", \"/addinvoice\", {\n      amt: req.amount,\n      memo: req.memo,\n    })\n\n    const pRsp = rsp as UserInvoicesResponse\n    return {\n      pr: pRsp.payment_request,\n      memo: req.memo,\n      amount: req.amount,\n      paymentHash: pRsp.payment_hash,\n      timestamp: pRsp.timestamp,\n    } as WalletInvoice\n  }\n\n  async payInvoice(pr: string) {\n    await this.login()\n    const rsp = await this.getJson<PayInvoiceResponse>(\"POST\", \"/payinvoice\", {\n      invoice: pr,\n    })\n\n    const pRsp = rsp as PayInvoiceResponse\n    return {\n      pr: pr,\n      paymentHash: pRsp.payment_hash,\n      preimage: pRsp.payment_preimage,\n      state: pRsp.payment_error\n        ? WalletInvoiceState.Failed\n        : pRsp.payment_preimage\n          ? WalletInvoiceState.Paid\n          : WalletInvoiceState.Pending,\n    } as WalletInvoice\n  }\n\n  async getInvoices(): Promise<WalletInvoice[]> {\n    await this.login()\n    const rsp = await this.getJson<UserInvoicesResponse[]>(\"GET\", \"/getuserinvoices\")\n    return (rsp as UserInvoicesResponse[])\n      .sort((a, b) => (a.timestamp > b.timestamp ? -1 : 1))\n      .slice(0, 50)\n      .map(a => {\n        const decodedInvoice = prToWalletInvoice(a.payment_request)\n        if (!decodedInvoice) {\n          throw new WalletError(WalletErrorCode.InvalidInvoice, \"Failed to parse invoice\")\n        }\n        return {\n          ...decodedInvoice,\n          state: a.ispaid ? WalletInvoiceState.Paid : decodedInvoice.state,\n          paymentHash: a.payment_hash,\n          memo: a.description,\n        } as WalletInvoice\n      })\n  }\n\n  private async getJson<T>(method: \"GET\" | \"POST\", path: string, body?: unknown): Promise<T> {\n    throwIfOffline()\n    const auth = `Bearer ${this.auth?.access_token}`\n    const url = `${this.url.pathname === \"/\" ? this.url.toString().slice(0, -1) : this.url.toString()}${path}`\n    const rsp = await fetch(url, {\n      method: method,\n      body: body ? JSON.stringify(body) : undefined,\n      headers: {\n        ...defaultHeaders,\n        Authorization: auth,\n      },\n    })\n    const json = await rsp.json()\n    if (\"code\" in json && !rsp.ok) {\n      const err = json as ErrorResponse\n      throw new WalletError(err.code, err.message)\n    }\n    return json as T\n  }\n}\n\ninterface AuthResponse {\n  refresh_token?: string\n  access_token?: string\n  token_type?: string\n}\n\ninterface GetBalanceResponse {\n  BTC: {\n    AvailableBalance: number\n  }\n}\n\ninterface UserInvoicesResponse {\n  amt: number\n  description: string\n  ispaid: boolean\n  type: string\n  timestamp: number\n  pay_req: string\n  payment_hash: string\n  payment_request: string\n  r_hash: string\n}\n\ninterface PayInvoiceResponse {\n  payment_error?: string\n  payment_hash: string\n  payment_preimage: string\n  payment_route?: { total_amt: number; total_fees: number }\n}\n\ninterface ErrorResponse {\n  code: number\n  message: string\n}\n"
  },
  {
    "path": "packages/wallet/src/NostrWalletConnect.ts",
    "content": "/* eslint-disable max-lines */\nimport { dedupe } from \"@snort/shared\"\nimport { Connection, EventBuilder, EventKind, type NostrEvent, PrivateKeySigner, decryptSigner } from \"@snort/system\"\nimport debug from \"debug\"\n\nimport {\n  type InvoiceRequest,\n  type LNWallet,\n  WalletError,\n  WalletErrorCode,\n  type WalletEvents,\n  type WalletInfo,\n  type WalletInvoice,\n  WalletInvoiceState,\n} from \".\"\nimport EventEmitter from \"eventemitter3\"\n\ninterface WalletConnectConfig {\n  relayUrl: string\n  walletPubkey: string\n  secret: string\n}\n\ninterface QueueObj {\n  resolve: (o: string) => void\n  reject: (e: Error) => void\n}\n\ninterface WalletConnectResponse<T> {\n  result_type?: string\n  result?: T\n  error?: {\n    code:\n      | \"RATE_LIMITED\"\n      | \"NOT_IMPLEMENTED\"\n      | \"INSUFFICIENT_BALANCE\"\n      | \"QUOTA_EXCEEDED\"\n      | \"RESTRICTED\"\n      | \"UNAUTHORIZED\"\n      | \"INTERNAL\"\n      | \"OTHER\"\n    message: string\n  }\n}\n\ninterface GetInfoResponse {\n  alias?: string\n  color?: string\n  pubkey?: string\n  network?: string\n  block_height?: number\n  block_hash?: string\n  methods?: Array<string>\n}\n\ninterface ListTransactionsResponse {\n  transactions: Array<{\n    type: \"incoming\" | \"outgoing\"\n    invoice: string\n    description?: string\n    description_hash?: string\n    preimage?: string\n    payment_hash?: string\n    amount: number\n    feed_paid: number\n    settled_at?: number\n    created_at: number\n    expires_at: number\n    metadata?: object\n  }>\n}\n\ninterface MakeInvoiceResponse {\n  invoice: string\n  payment_hash: string\n}\n\nconst DefaultSupported = [\"get_info\", \"pay_invoice\"]\n\nexport class NostrConnectWallet extends EventEmitter<WalletEvents> implements LNWallet {\n  #log = debug(\"NWC\")\n  #config: WalletConnectConfig\n  #conn?: Connection\n  #commandQueue: Map<string, QueueObj>\n  #info?: WalletInfo\n  #supported_methods: Array<string> = DefaultSupported\n\n  constructor(cfg: string) {\n    super()\n    this.#config = NostrConnectWallet.parseConfigUrl(cfg)\n    this.#commandQueue = new Map()\n  }\n\n  static parseConfigUrl(url: string) {\n    const uri = new URL(url.replace(\"nostrwalletconnect://\", \"http://\").replace(\"nostr+walletconnect://\", \"http://\"))\n    return {\n      relayUrl: uri.searchParams.get(\"relay\"),\n      walletPubkey: uri.host,\n      secret: uri.searchParams.get(\"secret\"),\n    } as WalletConnectConfig\n  }\n\n  canAutoLogin(): boolean {\n    return true\n  }\n\n  isReady(): boolean {\n    return this.#conn !== undefined\n  }\n\n  canGetInvoices() {\n    return this.#supported_methods.includes(\"list_transactions\")\n  }\n\n  canGetBalance() {\n    return this.#supported_methods.includes(\"get_balance\")\n  }\n\n  canCreateInvoice() {\n    return this.#supported_methods.includes(\"make_invoice\")\n  }\n\n  canPayInvoice() {\n    return this.#supported_methods.includes(\"pay_invoice\")\n  }\n\n  async getInfo() {\n    await this.login()\n    if (this.#info) return this.#info\n\n    const rsp = await this.#rpc<WalletConnectResponse<GetInfoResponse>>(\"get_info\", {})\n    if (!rsp.error) {\n      this.#supported_methods = dedupe([\"get_info\", ...(rsp.result?.methods ?? DefaultSupported)])\n      this.#log(\"Supported methods: %o\", this.#supported_methods)\n      const info = {\n        nodePubKey: rsp.result?.pubkey,\n        alias: rsp.result?.alias,\n        blockHeight: rsp.result?.block_height,\n        blockHash: rsp.result?.block_hash,\n        chains: rsp.result?.network ? [rsp.result.network] : undefined,\n      } as WalletInfo\n      this.#info = info\n      return info\n    } else if (rsp.error.code === \"NOT_IMPLEMENTED\") {\n      // legacy get_info uses event kind 13_194\n      return await new Promise<WalletInfo>((resolve, reject) => {\n        this.#commandQueue.set(\"info\", {\n          resolve: (o: string) => {\n            this.#supported_methods = dedupe([\"get_info\", ...o.split(\",\")])\n            this.#log(\"Supported methods: %o\", this.#supported_methods)\n            const info = {\n              alias: \"NWC\",\n            } as WalletInfo\n            this.#info = info\n            resolve(info)\n          },\n          reject,\n        })\n        this.#conn?.request([\"REQ\", \"info\", { kinds: [13194], limit: 1 }])\n      })\n    } else {\n      throw new WalletError(WalletErrorCode.GeneralError, rsp.error.message)\n    }\n  }\n\n  async login() {\n    if (this.#conn) return true\n\n    await new Promise<void>(resolve => {\n      this.#conn = new Connection(this.#config.relayUrl, { read: true, write: true })\n      this.#conn.on(\"connected\", () => resolve())\n      this.#conn.on(\"auth\", async (c, r, cb) => {\n        const eb = new EventBuilder()\n        eb.kind(EventKind.Auth).tag([\"relay\", r]).tag([\"challenge\", c])\n        const ev = await eb.buildAndSign(this.#config.secret)\n        cb(ev)\n      })\n      this.#conn.on(\"unverifiedEvent\", (s, e) => {\n        this.#onReply(s, e)\n      })\n      this.#conn.connect()\n    })\n    await this.getInfo()\n    this.emit(\"change\")\n    return true\n  }\n\n  async close() {\n    this.#conn?.close()\n    return true\n  }\n\n  async getBalance() {\n    await this.login()\n    const rsp = await this.#rpc<WalletConnectResponse<{ balance: number }>>(\"get_balance\", {})\n    if (!rsp.error) {\n      return (rsp.result?.balance ?? 0) / 1000\n    } else {\n      throw new WalletError(WalletErrorCode.GeneralError, rsp.error.message)\n    }\n  }\n\n  async createInvoice(req: InvoiceRequest) {\n    await this.login()\n    const rsp = await this.#rpc<WalletConnectResponse<MakeInvoiceResponse>>(\"make_invoice\", {\n      amount: req.amount * 1000,\n      description: req.memo,\n      expiry: req.expiry,\n    })\n    if (!rsp.error) {\n      return {\n        pr: rsp.result?.invoice,\n        paymentHash: rsp.result?.payment_hash,\n        memo: req.memo,\n        amount: req.amount * 1000,\n        state: WalletInvoiceState.Pending,\n      } as WalletInvoice\n    } else {\n      throw new WalletError(WalletErrorCode.GeneralError, rsp.error.message)\n    }\n  }\n\n  async payInvoice(pr: string) {\n    await this.login()\n    const rsp = await this.#rpc<WalletConnectResponse<WalletInvoice>>(\"pay_invoice\", {\n      invoice: pr,\n    })\n    if (!rsp.error) {\n      return {\n        ...rsp.result,\n        pr,\n        state: WalletInvoiceState.Paid,\n      } as WalletInvoice\n    } else {\n      throw new WalletError(WalletErrorCode.GeneralError, rsp.error.message)\n    }\n  }\n\n  async getInvoices() {\n    await this.login()\n    const rsp = await this.#rpc<WalletConnectResponse<ListTransactionsResponse>>(\"list_transactions\", {\n      limit: 50,\n    })\n    if (!rsp.error) {\n      return (\n        rsp.result?.transactions.map(\n          a =>\n            ({\n              pr: a.invoice,\n              paymentHash: a.payment_hash,\n              memo: a.description,\n              amount: a.amount,\n              fees: a.feed_paid,\n              timestamp: typeof a.created_at === \"string\" ? new Date(a.created_at).getTime() / 1000 : a.created_at,\n              preimage: a.preimage,\n              state: WalletInvoiceState.Paid,\n              direction: a.type === \"incoming\" ? \"in\" : \"out\",\n            }) as WalletInvoice,\n        ) ?? []\n      )\n    } else {\n      throw new WalletError(WalletErrorCode.GeneralError, rsp.error.message)\n    }\n  }\n\n  async #onReply(sub: string, e: NostrEvent) {\n    if (sub === \"info\") {\n      const pending = this.#commandQueue.get(\"info\")\n      if (!pending) {\n        throw new WalletError(WalletErrorCode.GeneralError, \"No pending info command found\")\n      }\n      pending.resolve(e.content)\n      this.#commandQueue.delete(\"info\")\n      return\n    }\n\n    if (e.kind !== 23195) {\n      throw new WalletError(WalletErrorCode.GeneralError, \"Unknown event kind\")\n    }\n\n    const replyTo = e.tags.find(a => a[0] === \"e\")\n    if (!replyTo) {\n      throw new WalletError(WalletErrorCode.GeneralError, \"Missing e-tag in command response\")\n    }\n\n    const pending = this.#commandQueue.get(replyTo[1])\n    if (!pending) {\n      throw new WalletError(WalletErrorCode.GeneralError, \"No pending command found\")\n    }\n\n    pending.resolve(e.content)\n    this.#commandQueue.delete(replyTo[1])\n    this.#conn?.closeRequest(sub)\n  }\n\n  async #rpc<T>(method: string, params: Record<string, string | number | undefined>) {\n    if (!this.#conn) throw new WalletError(WalletErrorCode.GeneralError, \"Not implemented\")\n    this.#log(\"> %o\", { method, params })\n    if (!this.#supported_methods.includes(method)) {\n      const ret = {\n        error: {\n          code: \"NOT_IMPLEMENTED\",\n          message: `get_info claims the method \"${method}\" is not supported`,\n        },\n      } as T\n      this.#log(\"< %o\", ret)\n      return ret\n    }\n\n    const payload = JSON.stringify({\n      method,\n      params,\n    })\n    const signer = new PrivateKeySigner(this.#config.secret)\n    const eb = new EventBuilder()\n    eb.kind(23194 as EventKind)\n      .content(await signer.nip44Encrypt(payload, this.#config.walletPubkey))\n      .tag([\"p\", this.#config.walletPubkey])\n\n    const evCommand = await eb.buildAndSign(this.#config.secret)\n    this.#conn.request([\n      \"REQ\",\n      evCommand.id.slice(0, 12),\n      {\n        kinds: [23195 as EventKind],\n        authors: [this.#config.walletPubkey],\n        [\"#e\"]: [evCommand.id],\n      },\n    ])\n    await this.#conn.publish(evCommand)\n    return await new Promise<T>((resolve, reject) => {\n      this.#commandQueue.set(evCommand.id, {\n        resolve: async (o: string) => {\n          const reply = JSON.parse(await decryptSigner(o, signer, this.#config.walletPubkey))\n          this.#log(\"< %o\", reply)\n          resolve(reply)\n        },\n        reject,\n      })\n    })\n  }\n}\n"
  },
  {
    "path": "packages/wallet/src/WebLN.ts",
    "content": "import { barrierQueue, processWorkQueue, unwrap, type WorkQueueItem } from \"@snort/shared\"\n\nimport {\n  type InvoiceRequest,\n  type LNWallet,\n  prToWalletInvoice,\n  type Sats,\n  WalletError,\n  WalletErrorCode,\n  type WalletEvents,\n  type WalletInfo,\n  type WalletInvoice,\n  WalletInvoiceState,\n} from \".\"\nimport EventEmitter from \"eventemitter3\"\n\nconst WebLNQueue: Array<WorkQueueItem> = []\nprocessWorkQueue(WebLNQueue)\n\nexport class WebLNWallet extends EventEmitter<WalletEvents> implements LNWallet {\n  isReady(): boolean {\n    return window.webln !== undefined && window.webln !== null\n  }\n\n  canCreateInvoice() {\n    return true\n  }\n\n  canPayInvoice() {\n    return true\n  }\n\n  canGetInvoices() {\n    return false\n  }\n\n  canGetBalance() {\n    return window.webln?.getBalance !== undefined\n  }\n\n  canAutoLogin(): boolean {\n    return true\n  }\n\n  async getInfo(): Promise<WalletInfo> {\n    await this.login()\n    if (this.isReady()) {\n      const rsp = await barrierQueue(WebLNQueue, async () => await window.webln?.getInfo())\n      if (rsp) {\n        return {\n          nodePubKey: rsp.node.pubkey,\n          alias: rsp.node.alias,\n        } as WalletInfo\n      } else {\n        throw new WalletError(WalletErrorCode.GeneralError, \"Could not load wallet info\")\n      }\n    }\n    throw new WalletError(WalletErrorCode.GeneralError, \"WebLN not available\")\n  }\n\n  async login(): Promise<boolean> {\n    if (window.webln) {\n      await window.webln.enable()\n    }\n    return true\n  }\n\n  close(): Promise<boolean> {\n    return Promise.resolve(true)\n  }\n\n  async getBalance(): Promise<Sats> {\n    await this.login()\n    if (window.webln?.getBalance) {\n      const rsp = await barrierQueue(WebLNQueue, async () => await unwrap(window.webln?.getBalance).call(window.webln))\n      return rsp.balance\n    }\n    return 0\n  }\n\n  async createInvoice(req: InvoiceRequest): Promise<WalletInvoice> {\n    await this.login()\n    if (this.isReady()) {\n      const rsp = await barrierQueue(\n        WebLNQueue,\n        async () =>\n          await window.webln?.makeInvoice({\n            amount: req.amount,\n            defaultMemo: req.memo,\n          }),\n      )\n      if (rsp) {\n        const invoice = prToWalletInvoice(rsp.paymentRequest)\n        if (!invoice) {\n          throw new WalletError(WalletErrorCode.InvalidInvoice, \"Could not parse invoice\")\n        }\n        return invoice\n      }\n    }\n    throw new WalletError(WalletErrorCode.GeneralError, \"WebLN not available\")\n  }\n\n  async payInvoice(pr: string): Promise<WalletInvoice> {\n    await this.login()\n    if (this.isReady()) {\n      const invoice = prToWalletInvoice(pr)\n      if (!invoice) {\n        throw new WalletError(WalletErrorCode.InvalidInvoice, \"Could not parse invoice\")\n      }\n      const rsp = await barrierQueue(WebLNQueue, async () => await window.webln?.sendPayment(pr))\n      if (rsp) {\n        invoice.state = WalletInvoiceState.Paid\n        invoice.preimage = rsp.preimage\n        invoice.fees = \"route\" in rsp ? (rsp.route as { total_fees: number }).total_fees : 0\n        return invoice\n      } else {\n        invoice.state = WalletInvoiceState.Failed\n        return invoice\n      }\n    }\n    throw new WalletError(WalletErrorCode.GeneralError, \"WebLN not available\")\n  }\n\n  getInvoices(): Promise<WalletInvoice[]> {\n    return Promise.resolve([])\n  }\n}\n"
  },
  {
    "path": "packages/wallet/src/custom.d.ts",
    "content": "/// <reference types=\"@webbtc/webln-types\" />\n"
  },
  {
    "path": "packages/wallet/src/index.ts",
    "content": "import { decodeInvoice, unwrap } from \"@snort/shared\"\nimport AlbyWallet from \"./AlbyWallet\"\nimport LNDHubWallet from \"./LNDHub\"\nimport { NostrConnectWallet } from \"./NostrWalletConnect\"\nimport { WebLNWallet } from \"./WebLN\"\nimport type EventEmitter from \"eventemitter3\"\n\nexport * from \"./zapper\"\n\nexport enum WalletKind {\n  LNDHub = 1,\n  //LNC = 2,\n  WebLN = 3,\n  NWC = 4,\n  //Cashu = 5,\n  Alby = 6,\n}\n\nexport enum WalletErrorCode {\n  BadAuth = 1,\n  NotEnoughBalance = 2,\n  BadPartner = 3,\n  InvalidInvoice = 4,\n  RouteNotFound = 5,\n  GeneralError = 6,\n  NodeFailure = 7,\n}\n\nexport class WalletError extends Error {\n  code: WalletErrorCode\n\n  constructor(c: WalletErrorCode, msg: string) {\n    super(msg)\n    this.code = c\n  }\n}\n\nexport const UnknownWalletError = {\n  code: WalletErrorCode.GeneralError,\n  message: \"Unknown error\",\n} as WalletError\n\nexport interface WalletInfo {\n  fee: number\n  nodePubKey: string\n  alias: string\n  pendingChannels: number\n  activeChannels: number\n  peers: number\n  blockHeight: number\n  blockHash: string\n  synced: boolean\n  chains: string[]\n  version: string\n}\n\nexport interface Login {\n  service: string\n  save: () => Promise<void>\n  load: () => Promise<void>\n}\n\nexport interface InvoiceRequest {\n  amount: Sats\n  memo?: string\n  expiry?: number\n}\n\nexport enum WalletInvoiceState {\n  Pending = 0,\n  Paid = 1,\n  Expired = 2,\n  Failed = 3,\n}\n\nexport interface WalletInvoice {\n  pr: string\n  paymentHash: string\n  memo: string\n  amount: MilliSats\n  fees: number\n  timestamp: number\n  preimage?: string\n  state: WalletInvoiceState\n  direction: \"in\" | \"out\"\n}\n\nexport function prToWalletInvoice(pr: string) {\n  const parsedInvoice = decodeInvoice(pr)\n  if (parsedInvoice) {\n    return {\n      amount: parsedInvoice.amount ?? 0,\n      memo: parsedInvoice.description,\n      paymentHash: parsedInvoice.paymentHash ?? \"\",\n      timestamp: parsedInvoice.timestamp ?? 0,\n      state: parsedInvoice.expired ? WalletInvoiceState.Expired : WalletInvoiceState.Pending,\n      pr,\n      direction: \"in\",\n    } as WalletInvoice\n  }\n}\n\nexport type Sats = number\nexport type MilliSats = number\n\nexport interface WalletEvents {\n  change: (data?: string) => void\n}\n\nexport type LNWallet = EventEmitter<WalletEvents> & {\n  isReady(): boolean\n  getInfo: () => Promise<WalletInfo>\n  login: (password?: string) => Promise<boolean>\n  close: () => Promise<boolean>\n  getBalance: () => Promise<Sats>\n  createInvoice: (req: InvoiceRequest) => Promise<WalletInvoice>\n  payInvoice: (pr: string) => Promise<WalletInvoice>\n  getInvoices: () => Promise<WalletInvoice[]>\n\n  canAutoLogin: () => boolean\n  canGetInvoices: () => boolean\n  canGetBalance: () => boolean\n  canCreateInvoice: () => boolean\n  canPayInvoice: () => boolean\n}\n\n/**\n * Load wallet by kind\n *\n * Some wallets are loaded using `async import` to avoid large dependency costs in bundle\n * @param kind The wallet kind to create\n * @param data Opaque data\n */\nexport async function loadWallet(kind: WalletKind, data: string | undefined) {\n  switch (kind) {\n    case WalletKind.WebLN: {\n      return new WebLNWallet()\n    }\n    case WalletKind.LNDHub: {\n      return new LNDHubWallet(unwrap(data))\n    }\n    case WalletKind.NWC: {\n      return new NostrConnectWallet(unwrap(data))\n    }\n    case WalletKind.Alby: {\n      return new AlbyWallet(JSON.parse(unwrap(data)))\n    }\n  }\n}\n\nexport { WebLNWallet, LNDHubWallet, NostrConnectWallet, AlbyWallet }\n"
  },
  {
    "path": "packages/wallet/src/zapper.ts",
    "content": "import { isHex, LNURL } from \"@snort/shared\"\nimport { EventPublisher, type NostrEvent, NostrLink, type SystemInterface } from \"@snort/system\"\nimport { type LNWallet, WalletInvoiceState } from \".\"\n\nexport interface ZapTarget {\n  type: \"lnurl\" | \"pubkey\"\n  value: string\n  weight: number\n  memo?: string\n  name?: string\n  zap?: {\n    pubkey: string\n    anon: boolean\n    event?: NostrLink\n  }\n}\n\nexport interface ZapTargetResult {\n  target: ZapTarget\n  paid: boolean\n  sent: number\n  fee: number\n  pr: string\n  error?: Error\n}\n\ninterface ZapTargetLoaded {\n  target: ZapTarget\n  svc?: LNURL\n}\n\nexport class Zapper {\n  #inProgress = false\n  #loadedTargets?: Array<ZapTargetLoaded>\n\n  constructor(\n    readonly system: SystemInterface,\n    readonly publisher?: EventPublisher,\n    readonly onResult?: (r: ZapTargetResult) => void,\n  ) {}\n\n  /**\n   * Create targets from Event\n   */\n  static fromEvent(ev: NostrEvent) {\n    if (ev.tags.some(a => a[0] === \"zap\")) {\n      return ev.tags\n        .filter(a => a[0] === \"zap\")\n        .map(v => {\n          if (v[1].length === 64 && isHex(v[1]) && v.length === 4) {\n            // NIP-57.G\n            return {\n              type: \"pubkey\",\n              value: v[1],\n              weight: Number(v[3] ?? 0),\n              zap: {\n                pubkey: v[1],\n                event: NostrLink.fromEvent(ev),\n              },\n            } as ZapTarget\n          } else {\n            // assume event specific zap target\n            return {\n              type: \"lnurl\",\n              value: v[1],\n              weight: 1,\n              zap: {\n                pubkey: ev.pubkey,\n                event: NostrLink.fromEvent(ev),\n              },\n            } as ZapTarget\n          }\n        })\n    } else {\n      return [\n        {\n          type: \"pubkey\",\n          value: ev.pubkey,\n          weight: 1,\n          zap: {\n            pubkey: ev.pubkey,\n            event: NostrLink.fromEvent(ev),\n          },\n        } as ZapTarget,\n      ]\n    }\n  }\n\n  async send(wallet: LNWallet | undefined, targets: Array<ZapTarget>, amount: number) {\n    if (this.#inProgress) {\n      throw new Error(\"Payout already in progress\")\n    }\n    this.#inProgress = true\n\n    const total = targets.reduce((acc, v) => (acc += v.weight), 0)\n    const ret = [] as Array<ZapTargetResult>\n\n    for (const t of targets) {\n      const toSend = Math.floor(amount * (t.weight / total))\n      try {\n        const svc = await this.#getService(t)\n        if (!svc) {\n          throw new Error(`Failed to get invoice from ${t.value}`)\n        }\n        const relays = [...this.system.pool].filter(([, v]) => !v.ephemeral).map(([k]) => k)\n        let pub = this.publisher\n        if (t.zap?.anon ?? false) {\n          const newKey = new Uint8Array(32)\n          crypto.getRandomValues(newKey)\n          pub = EventPublisher.privateKey(newKey)\n        }\n        const zap =\n          t.zap && svc.canZap\n            ? await pub?.zap(toSend * 1000, t.zap.pubkey, relays, t.zap?.event, t.memo, eb => {\n                if (t.zap?.anon) {\n                  eb.tag([\"anon\", \"\"])\n                }\n                return eb\n              })\n            : undefined\n        const invoice = await svc.getInvoice(toSend, t.memo, zap)\n        if (invoice?.pr) {\n          const res = await wallet?.payInvoice(invoice.pr)\n          ret.push({\n            target: t,\n            paid: res?.state === WalletInvoiceState.Paid,\n            sent: toSend,\n            pr: invoice.pr,\n            fee: res?.fees ?? 0,\n          })\n          this.onResult?.(ret[ret.length - 1])\n        } else {\n          throw new Error(`Failed to get invoice from ${t.value}`)\n        }\n      } catch (e) {\n        ret.push({\n          target: t,\n          paid: false,\n          sent: 0,\n          fee: 0,\n          pr: \"\",\n          error: e as Error,\n        })\n        this.onResult?.(ret[ret.length - 1])\n      }\n    }\n\n    this.#inProgress = false\n    return ret\n  }\n\n  async load(targets: Array<ZapTarget>) {\n    const svcs = targets.map(async a => {\n      return {\n        target: a,\n        loading: await this.#getService(a),\n      }\n    })\n    const loaded = await Promise.all(svcs)\n    this.#loadedTargets = loaded.map(a => ({\n      target: a.target,\n      svc: a.loading,\n    }))\n  }\n\n  /**\n   * Any target supports zaps\n   */\n  canZap() {\n    return this.#loadedTargets?.some(a => a.svc?.canZap ?? false)\n  }\n\n  /**\n   * Max comment length which can be sent to all (smallest comment length)\n   */\n  maxComment() {\n    return (\n      this.#loadedTargets\n        ?.map(a => (a.svc?.canZap ? 255 : (a.svc?.maxCommentLength ?? 0)))\n        .reduce((acc, v) => (acc > v ? v : acc), 255) ?? 0\n    )\n  }\n\n  /**\n   * Max of the min amounts\n   */\n  minAmount() {\n    return this.#loadedTargets?.map(a => a.svc?.min ?? 0).reduce((acc, v) => (acc < v ? v : acc), 1000) ?? 0\n  }\n\n  /**\n   * Min of the max amounts\n   */\n  maxAmount() {\n    return this.#loadedTargets?.map(a => a.svc?.max ?? 100e9).reduce((acc, v) => (acc > v ? v : acc), 100e9) ?? 0\n  }\n\n  async #getService(t: ZapTarget) {\n    try {\n      if (t.type === \"lnurl\") {\n        const svc = new LNURL(t.value)\n        await svc.load()\n        return svc\n      } else if (t.type === \"pubkey\") {\n        const profile = await this.system.config.profiles.get(t.value)\n        if (profile) {\n          const svc = new LNURL(profile.lud16 ?? profile.lud06 ?? \"\")\n          await svc.load()\n          return svc\n        }\n      }\n    } catch {\n      // nothing\n    }\n  }\n}\n"
  },
  {
    "path": "packages/wallet/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \"src\",\n    \"target\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"esModuleInterop\": true,\n    \"noImplicitOverride\": true,\n    \"module\": \"ESNext\",\n    \"strict\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"inlineSourceMap\": true,\n    \"outDir\": \"dist\",\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"./src/**/*.ts\"],\n  \"exclude\": [\"**/*.test.ts\", \"./src/Cashu.ts\"]\n}\n"
  },
  {
    "path": "packages/wallet/typedoc.json",
    "content": "{\n  \"entryPoints\": [\"src/index.ts\"]\n}\n"
  },
  {
    "path": "packages/worker-relay/README.md",
    "content": "## Worker Relay\n\nWorker relay is a Nostr relay built on `sqlite-wasm`\n\n`WorkerRelayInterface` is the class which accepts the URL of the worker script\n\n`sqlite-wasm` uses OFPS in order to persist the database.\n\n### Example\n\n```typescript\nimport { WorkerRelayInterface } from \"@snort/worker-relay\";\n\n// when using Vite import the worker script directly (for production)\nimport WorkerVite from \"@snort/worker-relay/src/worker?worker\";\n\n// in dev mode import esm module, i have no idea why it has to work like this\nconst workerScript = import.meta.env.DEV\n  ? new URL(\"@snort/worker-relay/dist/esm/worker.mjs\", import.meta.url)\n  : new WorkerVite();\n\nconst workerRelay = new WorkerRelayInterface(workerScript);\n\n// load sqlite database and run migrations\nawait workerRelay.init({\n  databasePath: \"relay.db\",\n  insertBatchSize: 100,\n});\n\n// Query worker relay with regular nostr REQ command\nconst results = await workerRelay.query([\"REQ\", \"1\", { kinds: [1], limit: 10 }]);\n\n// publish a new event to the relay\nconst myEvent = {\n  kind: 1,\n  created_at: Math.floor(new Date().getTime() / 1000),\n  content: \"test\",\n  tags: [],\n};\nif (await workerRelay.event(myEvent)) {\n  console.log(\"Success\");\n}\n```\n"
  },
  {
    "path": "packages/worker-relay/example/basic.ts",
    "content": "import { WorkerRelayInterface } from \"@snort/worker-relay\"\n\n// when using Vite import the worker script directly (for production)\nimport WorkerVite from \"@snort/worker-relay/src/worker?worker\"\n\n// in dev mode import esm module, i have no idea why it has to work like this\nconst workerScript = import.meta.env.DEV\n  ? new URL(\"@snort/worker-relay/dist/esm/worker.mjs\", import.meta.url)\n  : new WorkerVite()\n\nconst workerRelay = new WorkerRelayInterface(workerScript)\n\n// load sqlite database and run migrations\nawait workerRelay.init({\n  databasePath: \"relay.db\",\n  insertBatchSize: 100,\n})\n\n// Query worker relay with regular nostr REQ command\nconst results = await workerRelay.query([\"REQ\", \"1\", { kinds: [1], limit: 10 }])\n\n// publish a new event to the relay\nconst myEvent = {\n  kind: 1,\n  created_at: Math.floor(new Date().getTime() / 1000),\n  content: \"test\",\n  tags: [],\n}\nif (await workerRelay.event(myEvent)) {\n  console.log(\"Success\")\n}\n"
  },
  {
    "path": "packages/worker-relay/package.json",
    "content": "{\n  \"name\": \"@snort/worker-relay\",\n  \"version\": \"2.0.0-pre.4\",\n  \"description\": \"A nostr relay in a service worker\",\n  \"main\": \"dist/index.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"type\": \"module\",\n  \"module\": \"src/index.ts\",\n  \"repository\": \"https://git.v0l.io/Kieran/snort\",\n  \"author\": \"Kieran\",\n  \"license\": \"MIT\",\n  \"scripts\": {\n    \"build\": \"rm -rf dist && bunx --bun tsc && bun run build:esm\",\n    \"build:esm\": \"bunx --bun esbuild src/worker.ts --bundle --minify --sourcemap --outdir=dist/esm --format=esm --out-extension:.js=.mjs --loader:.wasm=copy --asset-names=\\\"[name]\\\"\"\n  },\n  \"files\": [\"src\", \"dist\"],\n  \"dependencies\": {\n    \"@sqlite.org/sqlite-wasm\": \"^3.50.4-build1\",\n    \"eventemitter3\": \"^5.0.1\",\n    \"uuid\": \"^13.0.0\"\n  },\n  \"devDependencies\": {\n    \"@types/debug\": \"^4.1.12\",\n    \"@types/sharedworker\": \"^0.0.188\",\n    \"@types/uuid\": \"^11.0.0\",\n    \"esbuild\": \"^0.25.11\",\n    \"typescript\": \"^5.9.3\"\n  }\n}\n"
  },
  {
    "path": "packages/worker-relay/src/custom.d.ts",
    "content": "declare module \"*.wasm\" {\n  const value: string\n  export default value\n}\ndeclare module \"*.wasm?url\" {\n  const value: string\n  export default value\n}\n"
  },
  {
    "path": "packages/worker-relay/src/debug.ts",
    "content": "let debug = false\nexport function debugLog(scope: string, msg: string, ...args: Array<any>) {\n  if (!debug) return\n  console.log(scope, msg, ...args)\n}\n\nexport function setLogging(v: boolean) {\n  debug = v\n}\n"
  },
  {
    "path": "packages/worker-relay/src/forYouFeed.ts",
    "content": "import { debugLog } from \"./debug\"\nimport type { NostrEvent, RelayHandler } from \"./types\"\n\n// import { parseZap } from \"../../system/src/zaps\";\n// placeholder:\nconst parseZap = (_zap: NostrEvent) => {\n  return { event: null } as { event: null | NostrEvent }\n}\n\nconst log = (msg: string, ...args: Array<any>) => debugLog(\"getForYouFeed\", msg, ...args)\n\nexport async function getForYouFeed(relay: RelayHandler, pubkey: string): Promise<NostrEvent[]> {\n  console.time(\"For You feed generation time\")\n\n  log(\"pubkey\", pubkey)\n\n  // Get events reacted to by me\n  const myReactedEventIds = await getMyReactedEvents(relay, pubkey)\n  log(\"my reacted events\", myReactedEventIds)\n\n  // Single query covers both getMyReactedAuthors and getOthersWhoReacted —\n  // both needed the same \"#e\" lookup so we do it once and split in one pass.\n  const { myReactedAuthors, othersWhoReacted } = await getReactionMaps(relay, myReactedEventIds, pubkey)\n  log(\"my reacted authors\", myReactedAuthors)\n  // this tends to be small when the user has just logged in, we should maybe subscribe for more from relays\n  log(\"others who reacted\", othersWhoReacted)\n\n  // Get event ids reacted to by those others\n  const reactedByOthers = await getEventIdsReactedByOthers(relay, othersWhoReacted, myReactedEventIds, pubkey)\n  log(\"reacted by others\", reactedByOthers)\n\n  // Get full events in sorted order\n  const feed = await getFeedEvents(relay, reactedByOthers, myReactedAuthors)\n  log(\"feed.length\", feed.length)\n\n  console.timeEnd(\"For You feed generation time\")\n  return feed\n}\n\n/**\n * Single-query replacement for the former getMyReactedAuthors + getOthersWhoReacted pair.\n * Both functions issued the identical `{\"#e\": ids}` query; merging them halves the SQL work.\n */\nasync function getReactionMaps(relay: RelayHandler, myReactedEventIds: Set<string>, myPubkey: string) {\n  const myReactedAuthors = new Map<string, number>()\n  const othersWhoReacted = new Map<string, number>()\n\n  const reactions = relay.req(\"getReactionMaps\", {\n    \"#e\": Array.from(myReactedEventIds),\n  }) as NostrEvent[]\n\n  reactions.forEach(reaction => {\n    if (reaction.pubkey !== myPubkey) {\n      myReactedAuthors.set(reaction.pubkey, (myReactedAuthors.get(reaction.pubkey) || 0) + 1)\n      othersWhoReacted.set(reaction.pubkey, (othersWhoReacted.get(reaction.pubkey) || 0) + 1)\n    }\n  })\n\n  return { myReactedAuthors, othersWhoReacted }\n}\n\nasync function getMyReactedEvents(relay: RelayHandler, pubkey: string) {\n  const myReactedEventIds = new Set<string>()\n\n  const myEvents = relay.req(\"getMyReactedEventIds\", {\n    authors: [pubkey],\n    kinds: [1, 6, 7, 9735],\n  }) as NostrEvent[]\n  myEvents.forEach(ev => {\n    const targetEventId =\n      ev.kind === 9735 ? parseZap(ev).event?.id : ev.tags.find((tag: string[]) => tag[0] === \"e\")?.[1]\n    if (targetEventId) {\n      myReactedEventIds.add(targetEventId)\n    }\n  })\n\n  return myReactedEventIds\n}\n\nasync function getEventIdsReactedByOthers(\n  relay: RelayHandler,\n  othersWhoReacted: Map<string, number>,\n  myReactedEvents: Set<string>,\n  myPub: string,\n) {\n  const eventIdsReactedByOthers = new Map<string, number>()\n\n  const events = relay.req(\"getEventIdsReactedByOthers\", {\n    authors: [...othersWhoReacted.keys()],\n    kinds: [1, 6, 7, 9735],\n  }) as NostrEvent[]\n\n  events.forEach(event => {\n    if (event.pubkey === myPub || myReactedEvents.has(event.id)) {\n      // NIP-113 NOT filter could improve performance by not selecting these events in the first place\n      return\n    }\n    event.tags.forEach((tag: string[]) => {\n      if (tag[0] === \"e\") {\n        const score = Math.ceil(Math.sqrt(othersWhoReacted.get(event.pubkey) || 0))\n        eventIdsReactedByOthers.set(tag[1], (eventIdsReactedByOthers.get(tag[1]) || 0) + score)\n      }\n    })\n  })\n\n  return eventIdsReactedByOthers\n}\n\nasync function getFeedEvents(\n  relay: RelayHandler,\n  reactedToIds: Map<string, number>,\n  reactedToAuthors: Map<string, number>,\n) {\n  const events = relay\n    .sql(\n      `select json from events where id in (${Array.from(reactedToIds.keys())\n        .map(() => \"?\")\n        .join(\", \")}) and kind = 1 order by seen_at ASC, created DESC limit 1000`,\n      Array.from(reactedToIds.keys()),\n    )\n    .map(row => JSON.parse(row[0] as string) as NostrEvent)\n\n  const seen = new Set<string>(events.map(ev => ev.id))\n\n  log(\"reactedToAuthors\", reactedToAuthors)\n\n  const favoriteAuthors = Array.from(reactedToAuthors.keys())\n    .sort((a, b) => reactedToAuthors.get(b)! - reactedToAuthors.get(a)!)\n    .slice(20)\n\n  const eventsByFavoriteAuthors = relay\n    .sql(\n      `select json from events where pubkey in (${favoriteAuthors\n        .map(() => \"?\")\n        .join(\", \")}) and kind = 1 order by seen_at ASC, created DESC limit 100`,\n      favoriteAuthors,\n    )\n    .map(row => JSON.parse(row[0] as string) as NostrEvent)\n\n  eventsByFavoriteAuthors.forEach(ev => {\n    if (!seen.has(ev.id)) {\n      events.push(ev)\n    }\n  })\n\n  // Filter out replies\n  const filteredEvents = events.filter(ev => !ev.tags.some((tag: string[]) => tag[0] === \"e\"))\n\n  // Define constants for normalization\n  // const recentnessWeight = -1;\n  const currentTime = Date.now()\n\n  // Calculate min and max for normalization\n  let minReactions = Infinity,\n    maxReactions = -Infinity\n  let minAge = Infinity,\n    maxAge = -Infinity\n\n  filteredEvents.forEach(event => {\n    const reactions = reactedToIds.get(event.id) || 0\n    minReactions = Math.min(minReactions, reactions)\n    maxReactions = Math.max(maxReactions, reactions)\n\n    const age = currentTime - new Date(event.created_at).getTime()\n    minAge = Math.min(minAge, age)\n    maxAge = Math.max(maxAge, age)\n  })\n\n  const normalize = (value: number, min: number, max: number) => (value - min) / (max - min)\n\n  const maxFavoriteness = Math.max(...Array.from(reactedToAuthors.values()))\n  const favoritenessWeight = 0.5\n\n  // Normalize and sort events by calculated score\n  filteredEvents.sort((a, b) => {\n    const aReactions = normalize(reactedToIds.get(a.id) || 0, minReactions, maxReactions)\n    const bReactions = normalize(reactedToIds.get(b.id) || 0, minReactions, maxReactions)\n\n    const aAge = normalize(currentTime - new Date(a.created_at).getTime(), minAge, maxAge)\n    const bAge = normalize(currentTime - new Date(b.created_at).getTime(), minAge, maxAge)\n\n    const aFavoriteness = normalize(reactedToAuthors.get(a.pubkey) || 0, 0, maxFavoriteness)\n    const bFavoriteness = normalize(reactedToAuthors.get(b.pubkey) || 0, 0, maxFavoriteness)\n\n    // randomly big or small weight for recentness\n    const recentnessWeight = Math.random() > 0.75 ? -0.1 : -10\n    const aScore = aReactions + recentnessWeight * aAge + aFavoriteness * favoritenessWeight\n    const bScore = bReactions + recentnessWeight * bAge + bFavoriteness * favoritenessWeight\n\n    // Sort by descending score\n    return bScore - aScore\n  })\n\n  return filteredEvents\n}\n"
  },
  {
    "path": "packages/worker-relay/src/index.ts",
    "content": "export * from \"./interface\"\n"
  },
  {
    "path": "packages/worker-relay/src/interface.ts",
    "content": "import { v4 as uuid } from \"uuid\"\nimport { setLogging } from \"./debug\"\nimport type { EventMetadata, NostrEvent, OkResponse, ReqCommand, WorkerMessage, WorkerMessageCommand } from \"./types\"\n\nexport interface InitAargs {\n  /**\n   * OPFS file path for the database\n   */\n  databasePath: string\n}\n\nexport class WorkerRelayInterface {\n  #worker: Worker\n  #commandQueue: Map<string, (v: unknown, ports: ReadonlyArray<MessagePort>) => void> = new Map()\n\n  // Command timeout\n  timeout: number = 30_000\n\n  /**\n   * Interface wrapper for worker relay\n   * @param scriptPath Path to worker script or Worker script object\n   */\n  constructor(scriptPath?: string | URL | Worker) {\n    if (scriptPath instanceof Worker) {\n      this.#worker = scriptPath\n    } else {\n      const sp = scriptPath ? scriptPath : new URL(\"@snort/worker-relay/dist/esm/worker.mjs\", import.meta.url)\n      this.#worker = new Worker(sp, { type: \"module\" })\n    }\n    this.#worker.onerror = e => {\n      console.error(\"Worker Error:\", e)\n    }\n    this.#worker.onmessageerror = e => {\n      console.error(e)\n    }\n    this.#worker.onmessage = e => {\n      const cmd = e.data as WorkerMessage<any>\n      if (cmd.cmd === \"reply\") {\n        const q = this.#commandQueue.get(cmd.id)\n        q?.(cmd, e.ports)\n        this.#commandQueue.delete(cmd.id)\n      }\n    }\n  }\n\n  async init(args: InitAargs) {\n    return await this.#workerRpc<InitAargs, boolean>(\"init\", args)\n  }\n\n  async event(ev: NostrEvent) {\n    return await this.#workerRpc<NostrEvent, OkResponse>(\"event\", ev)\n  }\n\n  async query(req: ReqCommand) {\n    return await this.#workerRpc<ReqCommand, Array<NostrEvent>>(\"req\", req)\n  }\n\n  async count(req: ReqCommand) {\n    return await this.#workerRpc<ReqCommand, number>(\"count\", req)\n  }\n\n  async delete(req: ReqCommand) {\n    return await this.#workerRpc<ReqCommand, Array<string>>(\"delete\", req)\n  }\n\n  async summary() {\n    return await this.#workerRpc<void, Record<string, number>>(\"summary\")\n  }\n\n  async close(id: string) {\n    return await this.#workerRpc<string, boolean>(\"close\", id)\n  }\n\n  async dump() {\n    return await this.#workerRpc<void, Uint8Array>(\"dumpDb\")\n  }\n\n  async wipe() {\n    return await this.#workerRpc<void, boolean>(\"wipe\")\n  }\n\n  async forYouFeed(pubkey: string) {\n    return await this.#workerRpc<string, Array<NostrEvent>>(\"forYouFeed\", pubkey)\n  }\n\n  setEventMetadata(id: string, _meta: EventMetadata) {\n    // Fire-and-forget: post directly without UUID/promise/reply to avoid the\n    // per-note RPC round-trip cost. The worker batches these via microtask.\n    this.#worker.postMessage({ id: \"\", cmd: \"setSeenAt\", args: id } as WorkerMessage<string>)\n  }\n\n  async debug(v: string) {\n    setLogging(true)\n    return await this.#workerRpc<string, boolean>(\"debug\", v)\n  }\n\n  configureSearchIndex(config: Record<number, Array<string>>) {\n    return this.#workerRpc<Record<number, Array<string>>, void>(\"configureSearchIndex\", config)\n  }\n\n  async #workerRpc<T, R>(cmd: WorkerMessageCommand, args?: T) {\n    const id = uuid()\n    const msg = {\n      id,\n      cmd,\n      args,\n    } as WorkerMessage<T>\n    //const start = unixNowMs();\n    return await new Promise<R>((resolve, reject) => {\n      this.#worker.postMessage(msg)\n      const t = setTimeout(() => {\n        this.#commandQueue.delete(id)\n        reject(\n          new Error(`Timeout executing ${cmd} ${JSON.stringify(args)}`, {\n            cause: msg,\n          }),\n        )\n      }, this.timeout)\n      this.#commandQueue.set(id, (v, port) => {\n        clearTimeout(t)\n        const cmdReply = v as WorkerMessage<R & { error?: any }>\n        if (cmdReply.args.error) {\n          reject(cmdReply.args.error)\n          return\n        }\n        //debugLog(\"interface\", `${cmd} took ${(unixNowMs() - start).toFixed(1)}ms`, args);\n        resolve(cmdReply.args)\n      })\n    })\n  }\n}\n"
  },
  {
    "path": "packages/worker-relay/src/memory-relay.ts",
    "content": "import { EventEmitter } from \"eventemitter3\"\nimport { debugLog } from \"./debug\"\nimport {\n  type EventMetadata,\n  eventMatchesFilter,\n  type NostrEvent,\n  type RelayHandler,\n  type RelayHandlerEvents,\n  type ReqFilter,\n} from \"./types\"\n\n/**\n * A very simple dumb fallback relay using a flat table\n */\nexport class InMemoryRelay extends EventEmitter<RelayHandlerEvents> implements RelayHandler {\n  #events: Map<string, NostrEvent> = new Map()\n  #log = (msg: string, ...args: Array<any>) => debugLog(\"InMemoryRelay\", msg, ...args)\n\n  init() {\n    this.#log(\"Using in-memory relay\")\n    return Promise.resolve()\n  }\n\n  count(req: ReqFilter): number {\n    let ret = 0\n    for (const [, e] of this.#events) {\n      if (eventMatchesFilter(e, req)) {\n        ret++\n      }\n    }\n    return ret\n  }\n\n  summary(): Record<string, number> {\n    const ret = {} as Record<string, number>\n    for (const [k, v] of this.#events) {\n      ret[v.kind.toString()] ??= 0\n      ret[v.kind.toString()]++\n    }\n    return ret\n  }\n\n  dump(): Promise<Uint8Array> {\n    const enc = new TextEncoder()\n    return Promise.resolve(enc.encode(JSON.stringify(this.#events.values())))\n  }\n\n  close(): void {\n    // nothing\n  }\n\n  wipe() {\n    this.#events = new Map()\n    return Promise.resolve()\n  }\n\n  event(ev: NostrEvent) {\n    if (this.#events.has(ev.id)) return false\n    this.#events.set(ev.id, ev)\n    this.emit(\"event\", [ev])\n    return true\n  }\n\n  eventBatch(evs: NostrEvent[]) {\n    const inserted = []\n    for (const ev of evs) {\n      if (this.#events.has(ev.id)) continue\n      this.#events.set(ev.id, ev)\n      inserted.push(ev)\n    }\n    if (inserted.length > 0) {\n      this.emit(\"event\", inserted)\n      return true\n    }\n    return false\n  }\n\n  sql(sql: string, params: (string | number)[]): (string | number)[][] {\n    return []\n  }\n\n  req(id: string, filter: ReqFilter) {\n    const ret = []\n    for (const [, e] of this.#events) {\n      if (eventMatchesFilter(e, filter)) {\n        if (filter.ids_only === true) {\n          ret.push(e.id)\n        } else {\n          ret.push(e)\n        }\n      }\n    }\n    return ret\n  }\n\n  delete(filter: ReqFilter) {\n    const forDelete = this.req(\"ids-for-delete\", { ...filter, ids_only: true }) as Array<string>\n    forDelete.forEach(a => this.#events.delete(a))\n\n    return forDelete\n  }\n\n  setEventMetadata(_id: string, _meta: EventMetadata) {\n    return\n  }\n\n  batchSetSeenAt(_ids: Array<string>, _seen_at: number) {\n    return\n  }\n\n  configureSearchIndex(_kindTagsMapping: Record<number, string[]>) {\n    this.#log(\"configureSearchableTags not supported in InMemoryRelay\")\n  }\n}\n"
  },
  {
    "path": "packages/worker-relay/src/queue.ts",
    "content": "export interface WorkQueueItem {\n  next: () => Promise<unknown>\n  resolve(v: unknown): void\n  reject(e: unknown): void\n}\n\nexport async function processWorkQueue(queue?: Array<WorkQueueItem>) {\n  while (queue && queue.length > 0) {\n    const v = queue.shift()\n    if (v) {\n      try {\n        const ret = await v.next()\n        v.resolve(ret)\n      } catch (e) {\n        v.reject(e)\n      }\n    }\n  }\n}\n\nexport const barrierQueue = async <T>(queue: Array<WorkQueueItem>, then: () => Promise<T>): Promise<T> => {\n  return new Promise<T>((resolve, reject) => {\n    queue.push({\n      next: then,\n      resolve,\n      reject,\n    })\n  })\n}\n"
  },
  {
    "path": "packages/worker-relay/src/sqlite/fixers.ts",
    "content": "import type { SqliteRelay } from \"./sqlite-relay\"\n\nexport async function runFixers(relay: SqliteRelay) {}\n"
  },
  {
    "path": "packages/worker-relay/src/sqlite/migrations.ts",
    "content": "import { debugLog } from \"../debug\"\nimport type { NostrEvent } from \"../types\"\nimport type { SqliteRelay } from \"./sqlite-relay\"\n\nconst log = (msg: string, ...args: Array<any>) => debugLog(\"SqliteRelay:migrations\", msg, ...args)\n\nconst migrations = [\n  { version: 1, script: migrate_v1 },\n  { version: 2, script: migrate_v2 },\n  { version: 3, script: migrate_v3 },\n  { version: 4, script: migrate_v4 },\n  { version: 5, script: migrate_v5 },\n  { version: 6, script: migrate_v6 },\n  { version: 7, script: migrate_v7 },\n]\n\nasync function migrate(relay: SqliteRelay) {\n  if (!relay.db) throw new Error(\"DB must be open\")\n\n  relay.db.exec(\n    \"CREATE TABLE IF NOT EXISTS __migration (\\\n    version INTEGER PRIMARY KEY, \\\n    migrated_at INTEGER \\\n  )\",\n  )\n  const res = relay.db.exec(\"SELECT MAX(version) FROM __migration\", { returnValue: \"resultRows\" })\n  let currentVersion = (res[0][0] as number | undefined) ?? 0\n\n  for (const { version, script } of migrations) {\n    if (currentVersion < version) {\n      log(`Migrating to v${version}`)\n      await script(relay)\n      currentVersion = version\n    }\n  }\n}\n\nfunction migrate_v1(relay: SqliteRelay) {\n  return relay.db?.transaction(db => {\n    db.exec(\n      \"CREATE TABLE events (\\\n      id TEXT(64) PRIMARY KEY, \\\n      pubkey TEXT(64), \\\n      created INTEGER, \\\n      kind INTEGER, \\\n      json TEXT \\\n    )\",\n    )\n    db.exec(\n      \"CREATE TABLE tags (\\\n      event_id TEXT(64), \\\n      key TEXT, \\\n      value TEXT, \\\n      CONSTRAINT tags_FK FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE \\\n      )\",\n    )\n    db.exec(\"CREATE INDEX tags_key_IDX ON tags (key,value)\")\n    db.exec(\"insert into __migration values(1, ?)\", {\n      bind: [Date.now() / 1000],\n    })\n  })\n}\n\nfunction migrate_v2(relay: SqliteRelay) {\n  relay.db?.transaction(db => {\n    db.exec(\"CREATE INDEX pubkey_kind_IDX ON events (pubkey,kind)\")\n    db.exec(\"CREATE INDEX pubkey_created_IDX ON events (pubkey,created)\")\n    db.exec(\"insert into __migration values(2, ?)\", {\n      bind: [Date.now() / 1000],\n    })\n  })\n}\n\nfunction migrate_v3(relay: SqliteRelay) {\n  relay.db?.transaction(db => {\n    db.exec(\"CREATE VIRTUAL TABLE search_content using fts5(id UNINDEXED, content)\")\n    const events = db.selectArrays(\"select json from events where kind in (?,?)\", [0, 1])\n    for (const json of events) {\n      const ev = JSON.parse(json[0] as string) as NostrEvent\n      if (ev) {\n        relay.insertIntoSearchIndex(db, ev)\n      }\n    }\n    db.exec(\"insert into __migration values(3, ?)\", {\n      bind: [Date.now() / 1000],\n    })\n  })\n}\n\nasync function migrate_v4(relay: SqliteRelay) {\n  relay.db?.transaction(db => {\n    db.exec(\"ALTER TABLE events ADD COLUMN seen_at INTEGER\")\n    db.exec(\"insert into __migration values(4, ?)\", {\n      bind: [Date.now() / 1000],\n    })\n  })\n}\n\nasync function migrate_v5(relay: SqliteRelay) {\n  relay.db?.transaction(db => {\n    db.exec(\"CREATE INDEX seen_at_IDX ON events (seen_at)\")\n    db.exec(\"insert into __migration values(5, ?)\", {\n      bind: [Date.now() / 1000],\n    })\n  })\n}\n\nasync function migrate_v6(relay: SqliteRelay) {\n  relay.db?.transaction(db => {\n    db.exec(\"ALTER TABLE events ADD COLUMN relays TEXT\")\n    db.exec(\"insert into __migration values(6, ?)\", {\n      bind: [Date.now() / 1000],\n    })\n  })\n}\n\nasync function migrate_v7(relay: SqliteRelay) {\n  relay.db?.transaction(db => {\n    // Composite (kind, created) index: covers kind-only filters with ORDER BY created DESC\n    db.exec(\"CREATE INDEX kind_created_IDX ON events (kind, created DESC)\")\n    // Composite (pubkey, kind, created) covering index replaces the two narrower indexes\n    db.exec(\"DROP INDEX IF EXISTS pubkey_kind_IDX\")\n    db.exec(\"DROP INDEX IF EXISTS pubkey_created_IDX\")\n    db.exec(\"CREATE INDEX pubkey_kind_created_IDX ON events (pubkey, kind, created DESC)\")\n    // Index on tags.event_id: fixes O(n) full-table scans on FK cascade deletes and parameterized-replaceable JOINs\n    db.exec(\"CREATE INDEX tags_event_id_IDX ON tags (event_id)\")\n    db.exec(\"insert into __migration values(7, ?)\", {\n      bind: [Date.now() / 1000],\n    })\n  })\n}\n\nexport default migrate\n"
  },
  {
    "path": "packages/worker-relay/src/sqlite/sqlite-relay.ts",
    "content": "import sqlite3InitModule, { type Database, type SAHPoolUtil, type Sqlite3Static } from \"@sqlite.org/sqlite-wasm\"\n// import wasm file directly, this needs to be copied from https://sqlite.org/download.html\nimport SqlitePath from \"@sqlite.org/sqlite-wasm/sqlite3.wasm?url\"\nimport { EventEmitter } from \"eventemitter3\"\nimport { debugLog } from \"../debug\"\nimport {\n  type EventMetadata,\n  type NostrEvent,\n  type RelayHandler,\n  type RelayHandlerEvents,\n  type ReqFilter,\n  unixNowMs,\n} from \"../types\"\nimport { runFixers } from \"./fixers\"\nimport migrate from \"./migrations\"\n\n// Maximum number of event IDs to keep in the in-memory dedup cache.\n// Each entry is a 64-char hex string (~64 bytes); 50k entries ≈ 3 MB.\n// When the cap is hit the entire set is cleared — correctness is preserved\n// because INSERT OR IGNORE provides the definitive dedup at the DB layer.\nconst MAX_SEEN_INSERTS = 50_000\n\nexport class SqliteRelay extends EventEmitter<RelayHandlerEvents> implements RelayHandler {\n  #sqlite?: Sqlite3Static\n  #log = (msg: string, ...args: Array<any>) => debugLog(\"SqliteRelay\", msg, ...args)\n  db?: Database\n  #pool?: SAHPoolUtil\n  #seenInserts = new Set<string>()\n  #searchableTagsByKind = new Map<number, Set<string>>()\n  /** True while dump() is exporting the DB file; used to guard concurrent DB access. */\n  #isDumping = false\n\n  /**\n   * Configure which event tags should be indexed for full-text search by kind\n   */\n  configureSearchIndex(kindTagsMapping: Record<number, string[]>) {\n    this.#searchableTagsByKind.clear()\n    for (const [kind, tags] of Object.entries(kindTagsMapping)) {\n      this.#searchableTagsByKind.set(parseInt(kind, 10), new Set(tags))\n    }\n    this.#log(`Updated searchable tags by kind:`, kindTagsMapping)\n  }\n\n  /**\n   * Initialize the SQLite driver\n   */\n  async init(path: string) {\n    if (this.#sqlite) return\n    this.#sqlite = await sqlite3InitModule({\n      locateFile: (path, prefix) => {\n        if (path === \"sqlite3.wasm\") {\n          return SqlitePath\n        }\n        return prefix + path\n      },\n      print: msg => this.#log(msg),\n      printErr: msg => this.#log(msg),\n    })\n    this.#log(`Got SQLite version: ${this.#sqlite.version.libVersion}`)\n    await this.#open(path)\n    if (this.db) {\n      await migrate(this)\n      // don't await to avoid timeout\n      runFixers(this)\n    }\n  }\n\n  /**\n   * Open the database from its path\n   */\n  async #open(path: string) {\n    if (!this.#sqlite) throw new Error(\"Must call init first\")\n    if (this.db) return\n\n    this.#pool = await this.#sqlite.installOpfsSAHPoolVfs({})\n    this.db = new this.#pool.OpfsSAHPoolDb(path)\n    this.#log(`Opened ${this.db.filename}`)\n  }\n\n  /**\n   * Delete all data\n   */\n  async wipe() {\n    if (this.#pool && this.db) {\n      const dbName = this.db.filename\n      this.close()\n      await this.#pool.wipeFiles()\n      await this.#open(dbName)\n      await migrate(this)\n    }\n  }\n\n  close() {\n    this.db?.close()\n    this.db = undefined\n  }\n\n  /**\n   * Insert an event to the database\n   */\n  event(ev: NostrEvent) {\n    if (this.#isDumping || !this.db) return false\n    if (this.#insertEvent(this.db, ev)) {\n      this.#log(`Inserted: kind=${ev.kind},authors=${ev.pubkey},id=${ev.id}`)\n      this.emit(\"event\", [ev])\n      return true\n    }\n    return false\n  }\n\n  sql(sql: string, params: Array<any>) {\n    return this.db?.selectArrays(sql, params) as Array<Array<string | number>>\n  }\n\n  /**\n   * Write multiple events\n   */\n  eventBatch(evs: Array<NostrEvent>) {\n    if (this.#isDumping || !this.db) return false\n    const start = unixNowMs()\n    const eventsInserted: Array<NostrEvent> = []\n    this.db?.transaction(db => {\n      for (const ev of evs) {\n        if (this.#insertEvent(db, ev)) {\n          eventsInserted.push(ev)\n        }\n      }\n    })\n    if (eventsInserted.length > 0) {\n      this.#log(`Inserted Batch: ${eventsInserted.length}/${evs.length}, ${(unixNowMs() - start).toLocaleString()}ms`)\n      this.emit(\"event\", eventsInserted)\n    }\n    return eventsInserted.length > 0\n  }\n\n  setEventMetadata(id: string, meta: EventMetadata) {\n    if (meta.seen_at) {\n      this.db?.exec(\"update events set seen_at = ? where id = ?\", {\n        bind: [meta.seen_at, id],\n      })\n    }\n  }\n\n  /**\n   * Set seen_at for a batch of events in a single UPDATE statement.\n   * All ids receive the same seen_at timestamp.\n   */\n  batchSetSeenAt(ids: Array<string>, seen_at: number) {\n    if (ids.length === 0 || !this.db) return\n    this.db.exec(`update events set seen_at = ? where id in (${this.#repeatParams(ids.length)})`, {\n      bind: [seen_at, ...ids],\n    })\n  }\n\n  #deleteById(db: Database, ids: Array<string>) {\n    if (ids.length === 0) return\n    db.exec(`delete from events where id in (${this.#repeatParams(ids.length)})`, {\n      bind: ids,\n    })\n    const deleted = db.changes()\n    db.exec(`delete from search_content where id in (${this.#repeatParams(ids.length)})`, {\n      bind: ids,\n    })\n    this.#log(\"Deleted\", ids, deleted)\n  }\n\n  #insertEvent(db: Database, ev: NostrEvent) {\n    if (this.#seenInserts.has(ev.id)) return false\n\n    const legacyReplaceableKinds = [0, 3, 41]\n\n    // handle deletes\n    if (ev.kind === 5) {\n      // delete using a request filter, take e/a tags for making a filter\n      const eTags = ev.tags.filter(a => a[0] === \"e\").map(a => a[1])\n      const deletedE = this.delete({\n        ids: eTags,\n        authors: [ev.pubkey],\n      })\n\n      // a tags are harder to delete, just delete one-by-one to avoid multiple authors/kinds\n      let aDeleted = 0\n      const aTags = ev.tags.filter(a => a[0] === \"a\").map(a => a[1])\n      for (const t of aTags) {\n        const aSplit = t.split(\":\")\n        // check if the event author is the author of the a tag\n        if (aSplit[1] !== ev.pubkey) {\n          this.#log(\"Skipping delete request for %s from %s, pubkey doesnt match\", t, ev.pubkey)\n          continue\n        }\n        const k = Number(aSplit[0])\n        if (Number.isNaN(k)) {\n          continue\n        }\n        aDeleted += this.delete({\n          authors: [ev.pubkey],\n          kinds: [k],\n          \"#d\": [aSplit[2]],\n        }).length\n      }\n      return deletedE.length > 0 || aDeleted > 0\n    }\n\n    // Handle legacy and standard replaceable events (kinds 0, 3, 41, 10000-19999)\n    if (legacyReplaceableKinds.includes(ev.kind) || (ev.kind >= 10_000 && ev.kind < 20_000)) {\n      const oldEvents = db.selectValues(`SELECT id FROM events WHERE kind = ? AND pubkey = ? AND created <= ?`, [\n        ev.kind,\n        ev.pubkey,\n        ev.created_at,\n      ]) as Array<string>\n\n      if (oldEvents.includes(ev.id)) {\n        // Already have this event\n        this.#markSeen(ev.id)\n        return false\n      } else {\n        // Delete older events of the same kind and pubkey\n        this.#deleteById(db, oldEvents)\n      }\n    }\n\n    // Handle parameterized replaceable events (kinds 30000-39999)\n    if (ev.kind >= 30_000 && ev.kind < 40_000) {\n      const dTag = ev.tags.find(a => a[0] === \"d\")?.[1] ?? \"\"\n\n      const oldEvents = db.selectValues(\n        `SELECT e.id\n         FROM events e\n         JOIN tags t ON e.id = t.event_id\n         WHERE e.kind = ? AND e.pubkey = ? AND t.key = ? AND t.value = ? AND created <= ?`,\n        [ev.kind, ev.pubkey, \"d\", dTag, ev.created_at],\n      ) as Array<string>\n\n      if (oldEvents.includes(ev.id)) {\n        // Already have this event\n        this.#markSeen(ev.id)\n        return false\n      } else {\n        // Delete older events with the same kind, pubkey, and d tag\n        this.#deleteById(db, oldEvents)\n      }\n    }\n\n    // Proceed to insert the new event\n    const evInsert = { ...ev }\n    delete evInsert.relays // Remove non-DB fields\n\n    db.exec(\n      `INSERT OR IGNORE INTO events(id, pubkey, created, kind, json, relays) \n       VALUES(?,?,?,?,?,?)`,\n      {\n        bind: [ev.id, ev.pubkey, ev.created_at, ev.kind, JSON.stringify(evInsert), (ev.relays ?? []).join(\",\")],\n      },\n    )\n\n    const insertedEvents = db.changes()\n    if (insertedEvents > 0) {\n      // Insert all tags in a single multi-row INSERT to avoid per-tag SQL roundtrips\n      const tagRows = ev.tags.filter(a => a[0].length === 1)\n      if (tagRows.length > 0) {\n        const placeholders = tagRows.map(() => \"(?, ?, ?)\").join(\", \")\n        const tagParams: Array<string> = []\n        for (const t of tagRows) {\n          tagParams.push(ev.id, t[0], t[1] ?? \"\")\n        }\n        db.exec(`INSERT INTO tags(event_id, key, value) VALUES ${placeholders}`, {\n          bind: tagParams,\n        })\n      }\n      this.insertIntoSearchIndex(db, ev)\n    } else {\n      this.#updateRelays(db, ev)\n      return false\n    }\n\n    this.#markSeen(ev.id)\n    return true\n  }\n\n  /**\n   * Append relays\n   */\n  #updateRelays(db: Database, ev: NostrEvent) {\n    const relays = db.selectArrays(\"select relays from events where id = ?\", [ev.id])\n    const oldRelays = new Set((relays?.at(0)?.at(0) as string | null)?.split(\",\") ?? [])\n    let hasNew = false\n    for (const r of ev.relays ?? []) {\n      if (!oldRelays.has(r)) {\n        oldRelays.add(r)\n        hasNew = true\n      }\n    }\n    if (hasNew) {\n      db.exec(\"update events set relays = ? where id = ?\", {\n        bind: [[...oldRelays].join(\",\"), ev.id],\n      })\n    }\n  }\n\n  /**\n   * Query relay by nostr filter\n   */\n  req(id: string, req: ReqFilter) {\n    const start = unixNowMs()\n\n    const [sql, params] = this.#buildQuery(req)\n    const res = this.db?.selectArrays(sql, params)\n    const results =\n      res?.map(a => {\n        if (req.ids_only === true) {\n          return a[0] as string\n        }\n        const ev = JSON.parse(a[0] as string) as NostrEvent\n        return {\n          ...ev,\n          relays: (a[1] as string | null)?.split(\",\"),\n        }\n      }) ?? []\n    const time = unixNowMs() - start\n    this.#log(`Query ${id} results took ${time.toLocaleString()}ms`, req)\n    return results\n  }\n\n  /**\n   * Count results by nostr filter\n   */\n  count(req: ReqFilter) {\n    const start = unixNowMs()\n    const [sql, params] = this.#buildQuery(req, true)\n    const rows = this.db?.exec(sql, {\n      bind: params,\n      returnValue: \"resultRows\",\n    })\n    const results = (rows?.at(0)?.at(0) as number | undefined) ?? 0\n    const time = unixNowMs() - start\n    this.#log(`Query count results took ${time.toLocaleString()}ms`)\n    return results\n  }\n\n  /**\n   * Delete events by nostr filter\n   */\n  delete(req: ReqFilter) {\n    this.#log(`Starting delete of ${JSON.stringify(req)}`)\n    const start = unixNowMs()\n    const for_delete = this.req(\"ids-for-delete\", { ...req, ids_only: true }) as Array<string>\n\n    const grouped = for_delete.reduce(\n      (acc, v, i) => {\n        const batch = (i / 1000).toFixed(0)\n        acc[batch] ??= []\n        acc[batch].push(v)\n        return acc\n      },\n      {} as Record<string, Array<string>>,\n    )\n    this.#log(`Starting delete of ${Object.keys(grouped).length} batches`)\n    Object.entries(grouped).forEach(([_batch, ids]) => {\n      this.#deleteById(this.db!, ids)\n    })\n    const time = unixNowMs() - start\n    this.#log(`Delete ${for_delete.length} events took ${time.toLocaleString()}ms`)\n    return for_delete\n  }\n\n  /**\n   * Get a summary about events table\n   */\n  summary() {\n    const res = this.db?.exec(\"select kind, count(*) from events group by kind\", {\n      returnValue: \"resultRows\",\n    })\n    return Object.fromEntries(res?.map(a => [String(a[0]), a[1] as number]) ?? [])\n  }\n\n  /**\n   * Dump the database file.\n   * Sets #isDumping for the duration so that concurrent DB calls (event, req, etc.)\n   * can detect the export window and avoid operating on a closed/undefined db.\n   */\n  async dump() {\n    if (this.#isDumping) {\n      this.#log(\"dump() called while already dumping, skipping\")\n      return new Uint8Array()\n    }\n    const filePath = String(this.db?.filename ?? \"\")\n    if (this.db && this.#pool) {\n      this.#isDumping = true\n      try {\n        return await this.#pool.exportFile(`/${filePath}`)\n      } catch (e) {\n        console.error(e)\n      } finally {\n        this.#isDumping = false\n        await this.#open(filePath)\n      }\n    }\n    return new Uint8Array()\n  }\n\n  #buildQuery(req: ReqFilter, count = false, remove = false): [string, Array<any>] {\n    const conditions: Array<string> = []\n    const params: Array<any> = []\n\n    let resultType = \"json,relays\"\n    if (count) {\n      resultType = \"count(json)\"\n    } else if (req.ids_only === true) {\n      resultType = \"id\"\n    }\n    let operation = `select ${resultType}`\n    if (remove) {\n      operation = \"delete\"\n    }\n    let sql = `${operation} from events`\n    const orTags = Object.entries(req).filter(([k]) => k.startsWith(\"#\"))\n    let tx = 0\n    for (const [key, values] of orTags) {\n      const vArray = values as Array<string>\n      sql += ` inner join tags t_${tx} on events.id = t_${tx}.event_id and t_${tx}.key = ? and t_${tx}.value in (${this.#repeatParams(\n        vArray.length,\n      )})`\n      params.push(key.slice(1))\n      params.push(...vArray)\n      tx++\n    }\n    if (req.search) {\n      sql += \" inner join search_content on search_content.id = events.id\"\n      conditions.push(\"search_content match ?\")\n      params.push(req.search.replaceAll(\".\", \"+\").replaceAll(\"@\", \"+\"))\n    }\n    if (req.ids) {\n      conditions.push(`id in (${this.#repeatParams(req.ids.length)})`)\n      params.push(...req.ids)\n    }\n    if (req.authors) {\n      conditions.push(`pubkey in (${this.#repeatParams(req.authors.length)})`)\n      params.push(...req.authors)\n    }\n    if (req.kinds) {\n      conditions.push(`kind in (${this.#repeatParams(req.kinds.length)})`)\n      params.push(...req.kinds)\n    }\n    if (req.since) {\n      conditions.push(\"created >= ?\")\n      params.push(req.since)\n    }\n    if (req.until) {\n      conditions.push(\"created < ?\")\n      params.push(req.until)\n    }\n    if (conditions.length > 0) {\n      sql += ` where ${conditions.join(\" and \")}`\n    }\n    // Always order by created DESC so queries are deterministic and indexes can be used.\n    // Append LIMIT only when requested.\n    sql += \" order by created desc\"\n    if (req.limit) {\n      sql += ` limit ${req.limit}`\n    }\n    return [sql, params]\n  }\n\n  #repeatParams(n: number) {\n    const ret: Array<string> = []\n    for (let x = 0; x < n; x++) {\n      ret.push(\"?\")\n    }\n    return ret.join(\", \")\n  }\n\n  insertIntoSearchIndex(db: Database, ev: NostrEvent) {\n    let indexContent = \"\"\n    let shouldIndex = false\n\n    // always index profiles\n    if (ev.kind === 0) {\n      shouldIndex = true\n      const profile = JSON.parse(ev.content) as {\n        name?: string\n        display_name?: string\n        lud16?: string\n        nip05?: string\n        website?: string\n        about?: string\n      }\n      if (profile) {\n        indexContent = [\n          profile.name,\n          profile.display_name,\n          profile.about,\n          profile.website,\n          profile.lud16,\n          profile.nip05,\n        ].join(\" \")\n      }\n    }\n\n    // Check if this event kind has configured searchable tags\n    const searchableTags = this.#searchableTagsByKind.get(ev.kind)\n    let searchableTagContent = \"\"\n\n    if (searchableTags) {\n      shouldIndex = true\n      searchableTagContent = ev.tags\n        .filter(tag => tag.length >= 2 && searchableTags.has(tag[0]))\n        .map(tag => tag[1])\n        .filter(value => value && value.trim().length > 0)\n        .join(\" \")\n    }\n\n    if (shouldIndex) {\n      // Always include content + any searchable tag content\n      const fullContent = [ev.content, indexContent, searchableTagContent]\n        .filter(content => content && content.trim().length > 0)\n        .join(\" \")\n\n      if (fullContent.trim().length > 0) {\n        db.exec(\"insert into search_content values(?,?)\", {\n          bind: [ev.id, fullContent],\n        })\n      }\n    }\n  }\n\n  /**\n   * Add an event ID to the dedup cache, evicting the entire cache when the\n   * cap is reached. Correctness is preserved by INSERT OR IGNORE at the DB layer.\n   */\n  #markSeen(id: string) {\n    if (this.#seenInserts.size >= MAX_SEEN_INSERTS) {\n      this.#log(`#seenInserts cap reached (${MAX_SEEN_INSERTS}), clearing dedup cache`)\n      this.#seenInserts.clear()\n    }\n    this.#seenInserts.add(id)\n  }\n}\n"
  },
  {
    "path": "packages/worker-relay/src/types.ts",
    "content": "import type { EventEmitter } from \"eventemitter3\"\n\nexport type WorkerMessageCommand =\n  | \"reply\"\n  | \"init\"\n  | \"event\"\n  | \"req\"\n  | \"count\"\n  | \"summary\"\n  | \"close\"\n  | \"dumpDb\"\n  | \"emit-event\"\n  | \"forYouFeed\"\n  | \"setEventMetadata\"\n  | \"setSeenAt\"\n  | \"debug\"\n  | \"delete\"\n  | \"wipe\"\n  | \"configureSearchIndex\"\n\nexport interface WorkerMessage<T> {\n  id: string\n  cmd: WorkerMessageCommand\n  args: T\n}\n\nexport interface NostrEvent {\n  id: string\n  pubkey: string\n  created_at: number\n  kind: number\n  tags: Array<Array<string>>\n  content: string\n  sig: string\n  relays?: Array<string>\n}\n\nexport interface EventMetadata {\n  seen_at?: number\n}\n\nexport type ReqCommand = [\"REQ\", id: string, ...filters: Array<ReqFilter>]\n\nexport interface ReqFilter {\n  ids?: string[]\n  authors?: string[]\n  kinds?: number[]\n  search?: string\n  since?: number\n  until?: number\n  limit?: number\n  [key: string]: Array<string> | Array<number> | string | number | undefined | boolean\n}\n\nexport interface OkResponse {\n  ok: boolean\n  id: string\n  relay: string\n  message?: string\n  event: NostrEvent\n}\n\nexport interface RelayHandler extends EventEmitter<RelayHandlerEvents> {\n  init(path: string, path2Wasm?: string): Promise<void>\n  close(): void\n  event(ev: NostrEvent): boolean\n  eventBatch(evs: Array<NostrEvent>): boolean\n\n  /**\n   * Run any SQL command\n   */\n  sql(sql: string, params: Array<string | number>): Array<Array<string | number>>\n  req(id: string, req: ReqFilter): Array<NostrEvent | string>\n  count(req: ReqFilter): number\n  summary(): Record<string, number>\n  dump(): Promise<Uint8Array>\n  delete(req: ReqFilter): Array<string>\n  setEventMetadata(id: string, meta: EventMetadata): void\n  batchSetSeenAt(ids: Array<string>, seen_at: number): void\n  wipe(): Promise<void>\n  configureSearchIndex(kindTagsMapping: Record<number, string[]>): void\n}\n\nexport interface RelayHandlerEvents {\n  event: (evs: Array<NostrEvent>) => void\n}\n\nexport function unixNowMs() {\n  return new Date().getTime()\n}\n\nexport function eventMatchesFilter(ev: NostrEvent, filter: ReqFilter) {\n  if (filter.since && ev.created_at < filter.since) {\n    return false\n  }\n  if (filter.until && ev.created_at > filter.until) {\n    return false\n  }\n  if (!(filter.ids?.includes(ev.id) ?? true)) {\n    return false\n  }\n  if (!(filter.authors?.includes(ev.pubkey) ?? true)) {\n    return false\n  }\n  if (!(filter.kinds?.includes(ev.kind) ?? true)) {\n    return false\n  }\n  const orTags = Object.entries(filter).filter(([k]) => k.startsWith(\"#\"))\n  for (const [k, v] of orTags) {\n    const vargs = v as Array<string>\n    for (const x of vargs) {\n      if (!ev.tags.find(a => a[0] === k.slice(1) && a[1] === x)) {\n        return false\n      }\n    }\n  }\n  const andTags = Object.entries(filter).filter(([k]) => k.startsWith(\"&\"))\n  for (const [k, v] of andTags) {\n    const vargs = v as Array<string>\n    const allMatch = vargs.every(x => ev.tags.some(tag => tag[0] === k.slice(1) && tag[1] === x))\n    if (!allMatch) {\n      return false\n    }\n  }\n\n  return true\n}\n"
  },
  {
    "path": "packages/worker-relay/src/worker.ts",
    "content": "/// <reference lib=\"webworker\" />\n\nimport { setLogging } from \"./debug\"\nimport { getForYouFeed } from \"./forYouFeed\"\nimport { InMemoryRelay } from \"./memory-relay\"\nimport { SqliteRelay } from \"./sqlite/sqlite-relay\"\nimport type { EventMetadata, NostrEvent, OkResponse, RelayHandler, ReqCommand, ReqFilter, WorkerMessage } from \"./types\"\n\nlet relay: RelayHandler | undefined\n\n// Timer-windowed event batch.\n// Events are accumulated for up to BATCH_WINDOW_MS before being flushed\n// together in a single DB transaction, reducing the number of SQLite writes\n// when many events arrive in quick succession (e.g. initial relay sync).\n// Callers receive an optimistic ok reply immediately; the actual write is\n// fire-and-forget from the caller's perspective.\nconst BATCH_WINDOW_MS = 50\nconst pendingEvents: Array<NostrEvent> = []\nlet flushScheduled = false\n\nfunction flushPendingEvents() {\n  flushScheduled = false\n  if (!relay || pendingEvents.length === 0) return\n  const evs = pendingEvents.splice(0)\n  relay.eventBatch(evs)\n}\n\n// Timer-windowed seen_at batch.\n// setSeenAt messages are fire-and-forget: no reply is sent, and all IDs that\n// arrive within BATCH_WINDOW_MS are flushed as a single UPDATE in one DB roundtrip.\nconst pendingSeenAt: Array<string> = []\nlet seenAtFlushScheduled = false\n\nfunction flushPendingSeenAt() {\n  seenAtFlushScheduled = false\n  if (!relay || pendingSeenAt.length === 0) return\n  const ids = pendingSeenAt.splice(0)\n  const seen_at = Math.round(Date.now() / 1000)\n  relay.batchSetSeenAt(ids, seen_at)\n}\n\ninterface InitAargs {\n  databasePath: string\n}\n\nconst handleMsg = async (port: MessagePort | DedicatedWorkerGlobalScope, ev: MessageEvent) => {\n  async function reply<T>(id: string, obj?: T) {\n    port.postMessage({\n      id,\n      cmd: \"reply\",\n      args: obj,\n    } as WorkerMessage<T>)\n  }\n\n  const msg = ev.data as WorkerMessage<any>\n  try {\n    switch (msg.cmd) {\n      case \"debug\": {\n        setLogging(true)\n        reply(msg.id, true)\n        break\n      }\n      case \"init\": {\n        const args = msg.args as InitAargs\n        try {\n          if (\"WebAssembly\" in self) {\n            relay = new SqliteRelay()\n          } else {\n            relay = new InMemoryRelay()\n          }\n          await relay.init(args.databasePath)\n        } catch (e) {\n          console.error(\"Fallback to InMemoryRelay\", e)\n          relay = new InMemoryRelay()\n          await relay.init(args.databasePath)\n        }\n        reply(msg.id, true)\n        break\n      }\n      case \"event\": {\n        const ev = msg.args as NostrEvent\n        // Reply immediately (optimistic ok) so the caller is not blocked waiting\n        // for the DB flush. Events are accumulated and written in a single\n        // SQLite transaction once the BATCH_WINDOW_MS timer fires.\n        pendingEvents.push(ev)\n        if (!flushScheduled) {\n          flushScheduled = true\n          setTimeout(flushPendingEvents, BATCH_WINDOW_MS)\n        }\n        reply(msg.id, { ok: true, id: ev.id, relay: \"\", event: ev } as OkResponse)\n        break\n      }\n      case \"close\": {\n        const res = relay?.close()\n        reply(msg.id, res)\n        break\n      }\n      case \"req\": {\n        const req = msg.args as ReqCommand\n        const filters = req.slice(2) as Array<ReqFilter>\n        const results: Array<string | NostrEvent> = []\n        const ids = new Set<string>()\n        for (const r of filters) {\n          const rx = relay?.req(req[1], r) ?? []\n          for (const x of rx) {\n            if ((typeof x === \"string\" && ids.has(x)) || ids.has((x as NostrEvent).id)) {\n              continue\n            }\n            ids.add(typeof x === \"string\" ? x : (x as NostrEvent).id)\n            results.push(x)\n          }\n        }\n        reply(msg.id, results)\n        break\n      }\n      case \"count\": {\n        const req = msg.args as ReqCommand\n        let results = 0\n        const filters = req.slice(2) as Array<ReqFilter>\n        for (const r of filters) {\n          const c = relay?.count(r) ?? 0\n          results += c\n        }\n        reply(msg.id, results)\n        break\n      }\n      case \"delete\": {\n        const req = msg.args as ReqCommand\n        const results = []\n        const filters = req.slice(2) as Array<ReqFilter>\n        for (const r of filters) {\n          const c = relay?.delete(r) ?? []\n          results.push(...c)\n        }\n        reply(msg.id, results)\n        break\n      }\n      case \"summary\": {\n        const res = relay?.summary()\n        reply(msg.id, res)\n        break\n      }\n      case \"dumpDb\": {\n        const res = await relay?.dump()\n        reply(msg.id, res)\n        break\n      }\n      case \"wipe\": {\n        await relay?.wipe()\n        reply(msg.id, true)\n        break\n      }\n      case \"forYouFeed\": {\n        const res = await getForYouFeed(relay!, msg.args as string)\n        reply(msg.id, res)\n        break\n      }\n      case \"setSeenAt\": {\n        // Fire-and-forget: no reply. Accumulate IDs and flush as one UPDATE per tick.\n        const id = msg.args as string\n        pendingSeenAt.push(id)\n        if (!seenAtFlushScheduled) {\n          seenAtFlushScheduled = true\n          setTimeout(flushPendingSeenAt, BATCH_WINDOW_MS)\n        }\n        break\n      }\n      case \"setEventMetadata\": {\n        // Legacy path kept for backward compat; new callers should use setSeenAt.\n        const [id, metadata] = msg.args as [string, EventMetadata]\n        relay?.setEventMetadata(id, metadata)\n        reply(msg.id, true)\n        break\n      }\n      case \"configureSearchIndex\": {\n        const kindTagsMapping = msg.args as Record<number, string[]>\n        relay?.configureSearchIndex(kindTagsMapping)\n        reply(msg.id, true)\n        break\n      }\n      default: {\n        reply(msg.id, { error: \"Unknown command\" })\n        break\n      }\n    }\n  } catch (e) {\n    if (e instanceof Error) {\n      reply(msg.id, { error: e.message })\n    } else if (typeof e === \"string\") {\n      reply(msg.id, { error: e })\n    } else {\n      reply(msg.id, \"Unknown error\")\n    }\n  }\n}\n\nif (\"SharedWorkerGlobalScope\" in globalThis) {\n  onconnect = e => {\n    const port = e.ports[0]\n    port.onmessage = msg => handleMsg(port, msg)\n    port.start()\n  }\n}\nif (\"DedicatedWorkerGlobalScope\" in globalThis) {\n  onmessage = e => {\n    handleMsg(self as DedicatedWorkerGlobalScope, e)\n  }\n}\n"
  },
  {
    "path": "packages/worker-relay/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \"src\",\n    \"target\": \"ESNext\",\n    \"moduleResolution\": \"Bundler\",\n    \"esModuleInterop\": true,\n    \"noImplicitOverride\": true,\n    \"module\": \"ESNext\",\n    \"strict\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"inlineSourceMap\": true,\n    \"outDir\": \"dist\",\n    \"skipLibCheck\": true\n  },\n  \"include\": [\"./src/**/*.ts\"],\n  \"files\": [\"./src/index.ts\"]\n}\n"
  },
  {
    "path": "packages/worker-relay/typedoc.json",
    "content": "{\n  \"entryPoints\": [\"src/index.ts\"]\n}\n"
  },
  {
    "path": "src-tauri/.gitignore",
    "content": "# Generated by Cargo\n# will have compiled files and executables\n/target/\n"
  },
  {
    "path": "src-tauri/Cargo.toml",
    "content": "[package]\nname = \"app\"\nversion = \"0.1.0\"\ndescription = \"A Tauri App\"\nauthors = [\"you\"]\nlicense = \"\"\nrepository = \"\"\ndefault-run = \"app\"\nedition = \"2021\"\nrust-version = \"1.60\"\n\n# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html\n\n[build-dependencies]\ntauri-build = { version = \"2.0.0-rc\", features = [] }\n\n[dependencies]\nserde_json = \"1.0\"\nserde = { version = \"1.0\", features = [\"derive\"] }\ntauri = { version = \"2.0.0-rc\", features = [] }\n\n[features]\n# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.\n# If you use cargo directly instead of tauri's cli you can use this feature flag to switch between tauri's `dev` and `build` modes.\n# DO NOT REMOVE!!\ncustom-protocol = [ \"tauri/custom-protocol\" ]\n"
  },
  {
    "path": "src-tauri/build.rs",
    "content": "fn main() {\n  tauri_build::build()\n}\n"
  },
  {
    "path": "src-tauri/capabilities/migrated.json",
    "content": "{\n  \"identifier\": \"migrated\",\n  \"description\": \"permissions that were migrated from v1\",\n  \"local\": true,\n  \"windows\": [\n    \"main\"\n  ],\n  \"permissions\": [\n    \"core:default\"\n  ]\n}"
  },
  {
    "path": "src-tauri/gen/schemas/acl-manifests.json",
    "content": "{\"core\":{\"default_permission\":{\"identifier\":\"default\",\"description\":\"Default core plugins set which includes:\\n- 'core:path:default'\\n- 'core:event:default'\\n- 'core:window:default'\\n- 'core:webview:default'\\n- 'core:app:default'\\n- 'core:image:default'\\n- 'core:resources:default'\\n- 'core:menu:default'\\n- 'core:tray:default'\\n\",\"permissions\":[\"core:path:default\",\"core:event:default\",\"core:window:default\",\"core:webview:default\",\"core:app:default\",\"core:image:default\",\"core:resources:default\",\"core:menu:default\",\"core:tray:default\"]},\"permissions\":{},\"permission_sets\":{},\"global_scope_schema\":null},\"core:app\":{\"default_permission\":{\"identifier\":\"default\",\"description\":\"Default permissions for the plugin.\",\"permissions\":[\"allow-version\",\"allow-name\",\"allow-tauri-version\"]},\"permissions\":{\"allow-app-hide\":{\"identifier\":\"allow-app-hide\",\"description\":\"Enables the app_hide command without any pre-configured scope.\",\"commands\":{\"allow\":[\"app_hide\"],\"deny\":[]}},\"allow-app-show\":{\"identifier\":\"allow-app-show\",\"description\":\"Enables the app_show command without any pre-configured scope.\",\"commands\":{\"allow\":[\"app_show\"],\"deny\":[]}},\"allow-default-window-icon\":{\"identifier\":\"allow-default-window-icon\",\"description\":\"Enables the default_window_icon command without any pre-configured scope.\",\"commands\":{\"allow\":[\"default_window_icon\"],\"deny\":[]}},\"allow-name\":{\"identifier\":\"allow-name\",\"description\":\"Enables the name command without any pre-configured scope.\",\"commands\":{\"allow\":[\"name\"],\"deny\":[]}},\"allow-tauri-version\":{\"identifier\":\"allow-tauri-version\",\"description\":\"Enables the tauri_version command without any pre-configured scope.\",\"commands\":{\"allow\":[\"tauri_version\"],\"deny\":[]}},\"allow-version\":{\"identifier\":\"allow-version\",\"description\":\"Enables the version command without any pre-configured scope.\",\"commands\":{\"allow\":[\"version\"],\"deny\":[]}},\"deny-app-hide\":{\"identifier\":\"deny-app-hide\",\"description\":\"Denies the app_hide command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"app_hide\"]}},\"deny-app-show\":{\"identifier\":\"deny-app-show\",\"description\":\"Denies the app_show command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"app_show\"]}},\"deny-default-window-icon\":{\"identifier\":\"deny-default-window-icon\",\"description\":\"Denies the default_window_icon command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"default_window_icon\"]}},\"deny-name\":{\"identifier\":\"deny-name\",\"description\":\"Denies the name command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"name\"]}},\"deny-tauri-version\":{\"identifier\":\"deny-tauri-version\",\"description\":\"Denies the tauri_version command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"tauri_version\"]}},\"deny-version\":{\"identifier\":\"deny-version\",\"description\":\"Denies the version command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"version\"]}}},\"permission_sets\":{},\"global_scope_schema\":null},\"core:event\":{\"default_permission\":{\"identifier\":\"default\",\"description\":\"Default permissions for the plugin.\",\"permissions\":[\"allow-listen\",\"allow-unlisten\",\"allow-emit\",\"allow-emit-to\"]},\"permissions\":{\"allow-emit\":{\"identifier\":\"allow-emit\",\"description\":\"Enables the emit command without any pre-configured scope.\",\"commands\":{\"allow\":[\"emit\"],\"deny\":[]}},\"allow-emit-to\":{\"identifier\":\"allow-emit-to\",\"description\":\"Enables the emit_to command without any pre-configured scope.\",\"commands\":{\"allow\":[\"emit_to\"],\"deny\":[]}},\"allow-listen\":{\"identifier\":\"allow-listen\",\"description\":\"Enables the listen command without any pre-configured scope.\",\"commands\":{\"allow\":[\"listen\"],\"deny\":[]}},\"allow-unlisten\":{\"identifier\":\"allow-unlisten\",\"description\":\"Enables the unlisten command without any pre-configured scope.\",\"commands\":{\"allow\":[\"unlisten\"],\"deny\":[]}},\"deny-emit\":{\"identifier\":\"deny-emit\",\"description\":\"Denies the emit command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"emit\"]}},\"deny-emit-to\":{\"identifier\":\"deny-emit-to\",\"description\":\"Denies the emit_to command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"emit_to\"]}},\"deny-listen\":{\"identifier\":\"deny-listen\",\"description\":\"Denies the listen command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"listen\"]}},\"deny-unlisten\":{\"identifier\":\"deny-unlisten\",\"description\":\"Denies the unlisten command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"unlisten\"]}}},\"permission_sets\":{},\"global_scope_schema\":null},\"core:image\":{\"default_permission\":{\"identifier\":\"default\",\"description\":\"Default permissions for the plugin.\",\"permissions\":[\"allow-new\",\"allow-from-bytes\",\"allow-from-path\",\"allow-rgba\",\"allow-size\"]},\"permissions\":{\"allow-from-bytes\":{\"identifier\":\"allow-from-bytes\",\"description\":\"Enables the from_bytes command without any pre-configured scope.\",\"commands\":{\"allow\":[\"from_bytes\"],\"deny\":[]}},\"allow-from-path\":{\"identifier\":\"allow-from-path\",\"description\":\"Enables the from_path command without any pre-configured scope.\",\"commands\":{\"allow\":[\"from_path\"],\"deny\":[]}},\"allow-new\":{\"identifier\":\"allow-new\",\"description\":\"Enables the new command without any pre-configured scope.\",\"commands\":{\"allow\":[\"new\"],\"deny\":[]}},\"allow-rgba\":{\"identifier\":\"allow-rgba\",\"description\":\"Enables the rgba command without any pre-configured scope.\",\"commands\":{\"allow\":[\"rgba\"],\"deny\":[]}},\"allow-size\":{\"identifier\":\"allow-size\",\"description\":\"Enables the size command without any pre-configured scope.\",\"commands\":{\"allow\":[\"size\"],\"deny\":[]}},\"deny-from-bytes\":{\"identifier\":\"deny-from-bytes\",\"description\":\"Denies the from_bytes command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"from_bytes\"]}},\"deny-from-path\":{\"identifier\":\"deny-from-path\",\"description\":\"Denies the from_path command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"from_path\"]}},\"deny-new\":{\"identifier\":\"deny-new\",\"description\":\"Denies the new command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"new\"]}},\"deny-rgba\":{\"identifier\":\"deny-rgba\",\"description\":\"Denies the rgba command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"rgba\"]}},\"deny-size\":{\"identifier\":\"deny-size\",\"description\":\"Denies the size command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"size\"]}}},\"permission_sets\":{},\"global_scope_schema\":null},\"core:menu\":{\"default_permission\":{\"identifier\":\"default\",\"description\":\"Default permissions for the plugin.\",\"permissions\":[\"allow-new\",\"allow-append\",\"allow-prepend\",\"allow-insert\",\"allow-remove\",\"allow-remove-at\",\"allow-items\",\"allow-get\",\"allow-popup\",\"allow-create-default\",\"allow-set-as-app-menu\",\"allow-set-as-window-menu\",\"allow-text\",\"allow-set-text\",\"allow-is-enabled\",\"allow-set-enabled\",\"allow-set-accelerator\",\"allow-set-as-windows-menu-for-nsapp\",\"allow-set-as-help-menu-for-nsapp\",\"allow-is-checked\",\"allow-set-checked\",\"allow-set-icon\"]},\"permissions\":{\"allow-append\":{\"identifier\":\"allow-append\",\"description\":\"Enables the append command without any pre-configured scope.\",\"commands\":{\"allow\":[\"append\"],\"deny\":[]}},\"allow-create-default\":{\"identifier\":\"allow-create-default\",\"description\":\"Enables the create_default command without any pre-configured scope.\",\"commands\":{\"allow\":[\"create_default\"],\"deny\":[]}},\"allow-get\":{\"identifier\":\"allow-get\",\"description\":\"Enables the get command without any pre-configured scope.\",\"commands\":{\"allow\":[\"get\"],\"deny\":[]}},\"allow-insert\":{\"identifier\":\"allow-insert\",\"description\":\"Enables the insert command without any pre-configured scope.\",\"commands\":{\"allow\":[\"insert\"],\"deny\":[]}},\"allow-is-checked\":{\"identifier\":\"allow-is-checked\",\"description\":\"Enables the is_checked command without any pre-configured scope.\",\"commands\":{\"allow\":[\"is_checked\"],\"deny\":[]}},\"allow-is-enabled\":{\"identifier\":\"allow-is-enabled\",\"description\":\"Enables the is_enabled command without any pre-configured scope.\",\"commands\":{\"allow\":[\"is_enabled\"],\"deny\":[]}},\"allow-items\":{\"identifier\":\"allow-items\",\"description\":\"Enables the items command without any pre-configured scope.\",\"commands\":{\"allow\":[\"items\"],\"deny\":[]}},\"allow-new\":{\"identifier\":\"allow-new\",\"description\":\"Enables the new command without any pre-configured scope.\",\"commands\":{\"allow\":[\"new\"],\"deny\":[]}},\"allow-popup\":{\"identifier\":\"allow-popup\",\"description\":\"Enables the popup command without any pre-configured scope.\",\"commands\":{\"allow\":[\"popup\"],\"deny\":[]}},\"allow-prepend\":{\"identifier\":\"allow-prepend\",\"description\":\"Enables the prepend command without any pre-configured scope.\",\"commands\":{\"allow\":[\"prepend\"],\"deny\":[]}},\"allow-remove\":{\"identifier\":\"allow-remove\",\"description\":\"Enables the remove command without any pre-configured scope.\",\"commands\":{\"allow\":[\"remove\"],\"deny\":[]}},\"allow-remove-at\":{\"identifier\":\"allow-remove-at\",\"description\":\"Enables the remove_at command without any pre-configured scope.\",\"commands\":{\"allow\":[\"remove_at\"],\"deny\":[]}},\"allow-set-accelerator\":{\"identifier\":\"allow-set-accelerator\",\"description\":\"Enables the set_accelerator command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_accelerator\"],\"deny\":[]}},\"allow-set-as-app-menu\":{\"identifier\":\"allow-set-as-app-menu\",\"description\":\"Enables the set_as_app_menu command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_as_app_menu\"],\"deny\":[]}},\"allow-set-as-help-menu-for-nsapp\":{\"identifier\":\"allow-set-as-help-menu-for-nsapp\",\"description\":\"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_as_help_menu_for_nsapp\"],\"deny\":[]}},\"allow-set-as-window-menu\":{\"identifier\":\"allow-set-as-window-menu\",\"description\":\"Enables the set_as_window_menu command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_as_window_menu\"],\"deny\":[]}},\"allow-set-as-windows-menu-for-nsapp\":{\"identifier\":\"allow-set-as-windows-menu-for-nsapp\",\"description\":\"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_as_windows_menu_for_nsapp\"],\"deny\":[]}},\"allow-set-checked\":{\"identifier\":\"allow-set-checked\",\"description\":\"Enables the set_checked command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_checked\"],\"deny\":[]}},\"allow-set-enabled\":{\"identifier\":\"allow-set-enabled\",\"description\":\"Enables the set_enabled command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_enabled\"],\"deny\":[]}},\"allow-set-icon\":{\"identifier\":\"allow-set-icon\",\"description\":\"Enables the set_icon command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_icon\"],\"deny\":[]}},\"allow-set-text\":{\"identifier\":\"allow-set-text\",\"description\":\"Enables the set_text command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_text\"],\"deny\":[]}},\"allow-text\":{\"identifier\":\"allow-text\",\"description\":\"Enables the text command without any pre-configured scope.\",\"commands\":{\"allow\":[\"text\"],\"deny\":[]}},\"deny-append\":{\"identifier\":\"deny-append\",\"description\":\"Denies the append command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"append\"]}},\"deny-create-default\":{\"identifier\":\"deny-create-default\",\"description\":\"Denies the create_default command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"create_default\"]}},\"deny-get\":{\"identifier\":\"deny-get\",\"description\":\"Denies the get command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"get\"]}},\"deny-insert\":{\"identifier\":\"deny-insert\",\"description\":\"Denies the insert command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"insert\"]}},\"deny-is-checked\":{\"identifier\":\"deny-is-checked\",\"description\":\"Denies the is_checked command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"is_checked\"]}},\"deny-is-enabled\":{\"identifier\":\"deny-is-enabled\",\"description\":\"Denies the is_enabled command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"is_enabled\"]}},\"deny-items\":{\"identifier\":\"deny-items\",\"description\":\"Denies the items command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"items\"]}},\"deny-new\":{\"identifier\":\"deny-new\",\"description\":\"Denies the new command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"new\"]}},\"deny-popup\":{\"identifier\":\"deny-popup\",\"description\":\"Denies the popup command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"popup\"]}},\"deny-prepend\":{\"identifier\":\"deny-prepend\",\"description\":\"Denies the prepend command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"prepend\"]}},\"deny-remove\":{\"identifier\":\"deny-remove\",\"description\":\"Denies the remove command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"remove\"]}},\"deny-remove-at\":{\"identifier\":\"deny-remove-at\",\"description\":\"Denies the remove_at command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"remove_at\"]}},\"deny-set-accelerator\":{\"identifier\":\"deny-set-accelerator\",\"description\":\"Denies the set_accelerator command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_accelerator\"]}},\"deny-set-as-app-menu\":{\"identifier\":\"deny-set-as-app-menu\",\"description\":\"Denies the set_as_app_menu command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_as_app_menu\"]}},\"deny-set-as-help-menu-for-nsapp\":{\"identifier\":\"deny-set-as-help-menu-for-nsapp\",\"description\":\"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_as_help_menu_for_nsapp\"]}},\"deny-set-as-window-menu\":{\"identifier\":\"deny-set-as-window-menu\",\"description\":\"Denies the set_as_window_menu command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_as_window_menu\"]}},\"deny-set-as-windows-menu-for-nsapp\":{\"identifier\":\"deny-set-as-windows-menu-for-nsapp\",\"description\":\"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_as_windows_menu_for_nsapp\"]}},\"deny-set-checked\":{\"identifier\":\"deny-set-checked\",\"description\":\"Denies the set_checked command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_checked\"]}},\"deny-set-enabled\":{\"identifier\":\"deny-set-enabled\",\"description\":\"Denies the set_enabled command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_enabled\"]}},\"deny-set-icon\":{\"identifier\":\"deny-set-icon\",\"description\":\"Denies the set_icon command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_icon\"]}},\"deny-set-text\":{\"identifier\":\"deny-set-text\",\"description\":\"Denies the set_text command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_text\"]}},\"deny-text\":{\"identifier\":\"deny-text\",\"description\":\"Denies the text command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"text\"]}}},\"permission_sets\":{},\"global_scope_schema\":null},\"core:path\":{\"default_permission\":{\"identifier\":\"default\",\"description\":\"Default permissions for the plugin.\",\"permissions\":[\"allow-resolve-directory\",\"allow-resolve\",\"allow-normalize\",\"allow-join\",\"allow-dirname\",\"allow-extname\",\"allow-basename\",\"allow-is-absolute\"]},\"permissions\":{\"allow-basename\":{\"identifier\":\"allow-basename\",\"description\":\"Enables the basename command without any pre-configured scope.\",\"commands\":{\"allow\":[\"basename\"],\"deny\":[]}},\"allow-dirname\":{\"identifier\":\"allow-dirname\",\"description\":\"Enables the dirname command without any pre-configured scope.\",\"commands\":{\"allow\":[\"dirname\"],\"deny\":[]}},\"allow-extname\":{\"identifier\":\"allow-extname\",\"description\":\"Enables the extname command without any pre-configured scope.\",\"commands\":{\"allow\":[\"extname\"],\"deny\":[]}},\"allow-is-absolute\":{\"identifier\":\"allow-is-absolute\",\"description\":\"Enables the is_absolute command without any pre-configured scope.\",\"commands\":{\"allow\":[\"is_absolute\"],\"deny\":[]}},\"allow-join\":{\"identifier\":\"allow-join\",\"description\":\"Enables the join command without any pre-configured scope.\",\"commands\":{\"allow\":[\"join\"],\"deny\":[]}},\"allow-normalize\":{\"identifier\":\"allow-normalize\",\"description\":\"Enables the normalize command without any pre-configured scope.\",\"commands\":{\"allow\":[\"normalize\"],\"deny\":[]}},\"allow-resolve\":{\"identifier\":\"allow-resolve\",\"description\":\"Enables the resolve command without any pre-configured scope.\",\"commands\":{\"allow\":[\"resolve\"],\"deny\":[]}},\"allow-resolve-directory\":{\"identifier\":\"allow-resolve-directory\",\"description\":\"Enables the resolve_directory command without any pre-configured scope.\",\"commands\":{\"allow\":[\"resolve_directory\"],\"deny\":[]}},\"deny-basename\":{\"identifier\":\"deny-basename\",\"description\":\"Denies the basename command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"basename\"]}},\"deny-dirname\":{\"identifier\":\"deny-dirname\",\"description\":\"Denies the dirname command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"dirname\"]}},\"deny-extname\":{\"identifier\":\"deny-extname\",\"description\":\"Denies the extname command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"extname\"]}},\"deny-is-absolute\":{\"identifier\":\"deny-is-absolute\",\"description\":\"Denies the is_absolute command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"is_absolute\"]}},\"deny-join\":{\"identifier\":\"deny-join\",\"description\":\"Denies the join command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"join\"]}},\"deny-normalize\":{\"identifier\":\"deny-normalize\",\"description\":\"Denies the normalize command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"normalize\"]}},\"deny-resolve\":{\"identifier\":\"deny-resolve\",\"description\":\"Denies the resolve command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"resolve\"]}},\"deny-resolve-directory\":{\"identifier\":\"deny-resolve-directory\",\"description\":\"Denies the resolve_directory command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"resolve_directory\"]}}},\"permission_sets\":{},\"global_scope_schema\":null},\"core:resources\":{\"default_permission\":{\"identifier\":\"default\",\"description\":\"Default permissions for the plugin.\",\"permissions\":[\"allow-close\"]},\"permissions\":{\"allow-close\":{\"identifier\":\"allow-close\",\"description\":\"Enables the close command without any pre-configured scope.\",\"commands\":{\"allow\":[\"close\"],\"deny\":[]}},\"deny-close\":{\"identifier\":\"deny-close\",\"description\":\"Denies the close command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"close\"]}}},\"permission_sets\":{},\"global_scope_schema\":null},\"core:tray\":{\"default_permission\":{\"identifier\":\"default\",\"description\":\"Default permissions for the plugin.\",\"permissions\":[\"allow-new\",\"allow-get-by-id\",\"allow-remove-by-id\",\"allow-set-icon\",\"allow-set-menu\",\"allow-set-tooltip\",\"allow-set-title\",\"allow-set-visible\",\"allow-set-temp-dir-path\",\"allow-set-icon-as-template\",\"allow-set-show-menu-on-left-click\"]},\"permissions\":{\"allow-get-by-id\":{\"identifier\":\"allow-get-by-id\",\"description\":\"Enables the get_by_id command without any pre-configured scope.\",\"commands\":{\"allow\":[\"get_by_id\"],\"deny\":[]}},\"allow-new\":{\"identifier\":\"allow-new\",\"description\":\"Enables the new command without any pre-configured scope.\",\"commands\":{\"allow\":[\"new\"],\"deny\":[]}},\"allow-remove-by-id\":{\"identifier\":\"allow-remove-by-id\",\"description\":\"Enables the remove_by_id command without any pre-configured scope.\",\"commands\":{\"allow\":[\"remove_by_id\"],\"deny\":[]}},\"allow-set-icon\":{\"identifier\":\"allow-set-icon\",\"description\":\"Enables the set_icon command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_icon\"],\"deny\":[]}},\"allow-set-icon-as-template\":{\"identifier\":\"allow-set-icon-as-template\",\"description\":\"Enables the set_icon_as_template command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_icon_as_template\"],\"deny\":[]}},\"allow-set-menu\":{\"identifier\":\"allow-set-menu\",\"description\":\"Enables the set_menu command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_menu\"],\"deny\":[]}},\"allow-set-show-menu-on-left-click\":{\"identifier\":\"allow-set-show-menu-on-left-click\",\"description\":\"Enables the set_show_menu_on_left_click command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_show_menu_on_left_click\"],\"deny\":[]}},\"allow-set-temp-dir-path\":{\"identifier\":\"allow-set-temp-dir-path\",\"description\":\"Enables the set_temp_dir_path command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_temp_dir_path\"],\"deny\":[]}},\"allow-set-title\":{\"identifier\":\"allow-set-title\",\"description\":\"Enables the set_title command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_title\"],\"deny\":[]}},\"allow-set-tooltip\":{\"identifier\":\"allow-set-tooltip\",\"description\":\"Enables the set_tooltip command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_tooltip\"],\"deny\":[]}},\"allow-set-visible\":{\"identifier\":\"allow-set-visible\",\"description\":\"Enables the set_visible command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_visible\"],\"deny\":[]}},\"deny-get-by-id\":{\"identifier\":\"deny-get-by-id\",\"description\":\"Denies the get_by_id command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"get_by_id\"]}},\"deny-new\":{\"identifier\":\"deny-new\",\"description\":\"Denies the new command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"new\"]}},\"deny-remove-by-id\":{\"identifier\":\"deny-remove-by-id\",\"description\":\"Denies the remove_by_id command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"remove_by_id\"]}},\"deny-set-icon\":{\"identifier\":\"deny-set-icon\",\"description\":\"Denies the set_icon command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_icon\"]}},\"deny-set-icon-as-template\":{\"identifier\":\"deny-set-icon-as-template\",\"description\":\"Denies the set_icon_as_template command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_icon_as_template\"]}},\"deny-set-menu\":{\"identifier\":\"deny-set-menu\",\"description\":\"Denies the set_menu command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_menu\"]}},\"deny-set-show-menu-on-left-click\":{\"identifier\":\"deny-set-show-menu-on-left-click\",\"description\":\"Denies the set_show_menu_on_left_click command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_show_menu_on_left_click\"]}},\"deny-set-temp-dir-path\":{\"identifier\":\"deny-set-temp-dir-path\",\"description\":\"Denies the set_temp_dir_path command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_temp_dir_path\"]}},\"deny-set-title\":{\"identifier\":\"deny-set-title\",\"description\":\"Denies the set_title command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_title\"]}},\"deny-set-tooltip\":{\"identifier\":\"deny-set-tooltip\",\"description\":\"Denies the set_tooltip command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_tooltip\"]}},\"deny-set-visible\":{\"identifier\":\"deny-set-visible\",\"description\":\"Denies the set_visible command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_visible\"]}}},\"permission_sets\":{},\"global_scope_schema\":null},\"core:webview\":{\"default_permission\":{\"identifier\":\"default\",\"description\":\"Default permissions for the plugin.\",\"permissions\":[\"allow-get-all-webviews\",\"allow-webview-position\",\"allow-webview-size\",\"allow-internal-toggle-devtools\"]},\"permissions\":{\"allow-create-webview\":{\"identifier\":\"allow-create-webview\",\"description\":\"Enables the create_webview command without any pre-configured scope.\",\"commands\":{\"allow\":[\"create_webview\"],\"deny\":[]}},\"allow-create-webview-window\":{\"identifier\":\"allow-create-webview-window\",\"description\":\"Enables the create_webview_window command without any pre-configured scope.\",\"commands\":{\"allow\":[\"create_webview_window\"],\"deny\":[]}},\"allow-get-all-webviews\":{\"identifier\":\"allow-get-all-webviews\",\"description\":\"Enables the get_all_webviews command without any pre-configured scope.\",\"commands\":{\"allow\":[\"get_all_webviews\"],\"deny\":[]}},\"allow-internal-toggle-devtools\":{\"identifier\":\"allow-internal-toggle-devtools\",\"description\":\"Enables the internal_toggle_devtools command without any pre-configured scope.\",\"commands\":{\"allow\":[\"internal_toggle_devtools\"],\"deny\":[]}},\"allow-print\":{\"identifier\":\"allow-print\",\"description\":\"Enables the print command without any pre-configured scope.\",\"commands\":{\"allow\":[\"print\"],\"deny\":[]}},\"allow-reparent\":{\"identifier\":\"allow-reparent\",\"description\":\"Enables the reparent command without any pre-configured scope.\",\"commands\":{\"allow\":[\"reparent\"],\"deny\":[]}},\"allow-set-webview-focus\":{\"identifier\":\"allow-set-webview-focus\",\"description\":\"Enables the set_webview_focus command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_webview_focus\"],\"deny\":[]}},\"allow-set-webview-position\":{\"identifier\":\"allow-set-webview-position\",\"description\":\"Enables the set_webview_position command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_webview_position\"],\"deny\":[]}},\"allow-set-webview-size\":{\"identifier\":\"allow-set-webview-size\",\"description\":\"Enables the set_webview_size command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_webview_size\"],\"deny\":[]}},\"allow-set-webview-zoom\":{\"identifier\":\"allow-set-webview-zoom\",\"description\":\"Enables the set_webview_zoom command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_webview_zoom\"],\"deny\":[]}},\"allow-webview-close\":{\"identifier\":\"allow-webview-close\",\"description\":\"Enables the webview_close command without any pre-configured scope.\",\"commands\":{\"allow\":[\"webview_close\"],\"deny\":[]}},\"allow-webview-position\":{\"identifier\":\"allow-webview-position\",\"description\":\"Enables the webview_position command without any pre-configured scope.\",\"commands\":{\"allow\":[\"webview_position\"],\"deny\":[]}},\"allow-webview-size\":{\"identifier\":\"allow-webview-size\",\"description\":\"Enables the webview_size command without any pre-configured scope.\",\"commands\":{\"allow\":[\"webview_size\"],\"deny\":[]}},\"deny-create-webview\":{\"identifier\":\"deny-create-webview\",\"description\":\"Denies the create_webview command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"create_webview\"]}},\"deny-create-webview-window\":{\"identifier\":\"deny-create-webview-window\",\"description\":\"Denies the create_webview_window command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"create_webview_window\"]}},\"deny-get-all-webviews\":{\"identifier\":\"deny-get-all-webviews\",\"description\":\"Denies the get_all_webviews command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"get_all_webviews\"]}},\"deny-internal-toggle-devtools\":{\"identifier\":\"deny-internal-toggle-devtools\",\"description\":\"Denies the internal_toggle_devtools command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"internal_toggle_devtools\"]}},\"deny-print\":{\"identifier\":\"deny-print\",\"description\":\"Denies the print command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"print\"]}},\"deny-reparent\":{\"identifier\":\"deny-reparent\",\"description\":\"Denies the reparent command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"reparent\"]}},\"deny-set-webview-focus\":{\"identifier\":\"deny-set-webview-focus\",\"description\":\"Denies the set_webview_focus command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_webview_focus\"]}},\"deny-set-webview-position\":{\"identifier\":\"deny-set-webview-position\",\"description\":\"Denies the set_webview_position command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_webview_position\"]}},\"deny-set-webview-size\":{\"identifier\":\"deny-set-webview-size\",\"description\":\"Denies the set_webview_size command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_webview_size\"]}},\"deny-set-webview-zoom\":{\"identifier\":\"deny-set-webview-zoom\",\"description\":\"Denies the set_webview_zoom command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_webview_zoom\"]}},\"deny-webview-close\":{\"identifier\":\"deny-webview-close\",\"description\":\"Denies the webview_close command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"webview_close\"]}},\"deny-webview-position\":{\"identifier\":\"deny-webview-position\",\"description\":\"Denies the webview_position command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"webview_position\"]}},\"deny-webview-size\":{\"identifier\":\"deny-webview-size\",\"description\":\"Denies the webview_size command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"webview_size\"]}}},\"permission_sets\":{},\"global_scope_schema\":null},\"core:window\":{\"default_permission\":{\"identifier\":\"default\",\"description\":\"Default permissions for the plugin.\",\"permissions\":[\"allow-get-all-windows\",\"allow-scale-factor\",\"allow-inner-position\",\"allow-outer-position\",\"allow-inner-size\",\"allow-outer-size\",\"allow-is-fullscreen\",\"allow-is-minimized\",\"allow-is-maximized\",\"allow-is-focused\",\"allow-is-decorated\",\"allow-is-resizable\",\"allow-is-maximizable\",\"allow-is-minimizable\",\"allow-is-closable\",\"allow-is-visible\",\"allow-title\",\"allow-current-monitor\",\"allow-primary-monitor\",\"allow-monitor-from-point\",\"allow-available-monitors\",\"allow-cursor-position\",\"allow-theme\",\"allow-internal-toggle-maximize\"]},\"permissions\":{\"allow-available-monitors\":{\"identifier\":\"allow-available-monitors\",\"description\":\"Enables the available_monitors command without any pre-configured scope.\",\"commands\":{\"allow\":[\"available_monitors\"],\"deny\":[]}},\"allow-center\":{\"identifier\":\"allow-center\",\"description\":\"Enables the center command without any pre-configured scope.\",\"commands\":{\"allow\":[\"center\"],\"deny\":[]}},\"allow-close\":{\"identifier\":\"allow-close\",\"description\":\"Enables the close command without any pre-configured scope.\",\"commands\":{\"allow\":[\"close\"],\"deny\":[]}},\"allow-create\":{\"identifier\":\"allow-create\",\"description\":\"Enables the create command without any pre-configured scope.\",\"commands\":{\"allow\":[\"create\"],\"deny\":[]}},\"allow-current-monitor\":{\"identifier\":\"allow-current-monitor\",\"description\":\"Enables the current_monitor command without any pre-configured scope.\",\"commands\":{\"allow\":[\"current_monitor\"],\"deny\":[]}},\"allow-cursor-position\":{\"identifier\":\"allow-cursor-position\",\"description\":\"Enables the cursor_position command without any pre-configured scope.\",\"commands\":{\"allow\":[\"cursor_position\"],\"deny\":[]}},\"allow-destroy\":{\"identifier\":\"allow-destroy\",\"description\":\"Enables the destroy command without any pre-configured scope.\",\"commands\":{\"allow\":[\"destroy\"],\"deny\":[]}},\"allow-get-all-windows\":{\"identifier\":\"allow-get-all-windows\",\"description\":\"Enables the get_all_windows command without any pre-configured scope.\",\"commands\":{\"allow\":[\"get_all_windows\"],\"deny\":[]}},\"allow-hide\":{\"identifier\":\"allow-hide\",\"description\":\"Enables the hide command without any pre-configured scope.\",\"commands\":{\"allow\":[\"hide\"],\"deny\":[]}},\"allow-inner-position\":{\"identifier\":\"allow-inner-position\",\"description\":\"Enables the inner_position command without any pre-configured scope.\",\"commands\":{\"allow\":[\"inner_position\"],\"deny\":[]}},\"allow-inner-size\":{\"identifier\":\"allow-inner-size\",\"description\":\"Enables the inner_size command without any pre-configured scope.\",\"commands\":{\"allow\":[\"inner_size\"],\"deny\":[]}},\"allow-internal-toggle-maximize\":{\"identifier\":\"allow-internal-toggle-maximize\",\"description\":\"Enables the internal_toggle_maximize command without any pre-configured scope.\",\"commands\":{\"allow\":[\"internal_toggle_maximize\"],\"deny\":[]}},\"allow-is-closable\":{\"identifier\":\"allow-is-closable\",\"description\":\"Enables the is_closable command without any pre-configured scope.\",\"commands\":{\"allow\":[\"is_closable\"],\"deny\":[]}},\"allow-is-decorated\":{\"identifier\":\"allow-is-decorated\",\"description\":\"Enables the is_decorated command without any pre-configured scope.\",\"commands\":{\"allow\":[\"is_decorated\"],\"deny\":[]}},\"allow-is-focused\":{\"identifier\":\"allow-is-focused\",\"description\":\"Enables the is_focused command without any pre-configured scope.\",\"commands\":{\"allow\":[\"is_focused\"],\"deny\":[]}},\"allow-is-fullscreen\":{\"identifier\":\"allow-is-fullscreen\",\"description\":\"Enables the is_fullscreen command without any pre-configured scope.\",\"commands\":{\"allow\":[\"is_fullscreen\"],\"deny\":[]}},\"allow-is-maximizable\":{\"identifier\":\"allow-is-maximizable\",\"description\":\"Enables the is_maximizable command without any pre-configured scope.\",\"commands\":{\"allow\":[\"is_maximizable\"],\"deny\":[]}},\"allow-is-maximized\":{\"identifier\":\"allow-is-maximized\",\"description\":\"Enables the is_maximized command without any pre-configured scope.\",\"commands\":{\"allow\":[\"is_maximized\"],\"deny\":[]}},\"allow-is-minimizable\":{\"identifier\":\"allow-is-minimizable\",\"description\":\"Enables the is_minimizable command without any pre-configured scope.\",\"commands\":{\"allow\":[\"is_minimizable\"],\"deny\":[]}},\"allow-is-minimized\":{\"identifier\":\"allow-is-minimized\",\"description\":\"Enables the is_minimized command without any pre-configured scope.\",\"commands\":{\"allow\":[\"is_minimized\"],\"deny\":[]}},\"allow-is-resizable\":{\"identifier\":\"allow-is-resizable\",\"description\":\"Enables the is_resizable command without any pre-configured scope.\",\"commands\":{\"allow\":[\"is_resizable\"],\"deny\":[]}},\"allow-is-visible\":{\"identifier\":\"allow-is-visible\",\"description\":\"Enables the is_visible command without any pre-configured scope.\",\"commands\":{\"allow\":[\"is_visible\"],\"deny\":[]}},\"allow-maximize\":{\"identifier\":\"allow-maximize\",\"description\":\"Enables the maximize command without any pre-configured scope.\",\"commands\":{\"allow\":[\"maximize\"],\"deny\":[]}},\"allow-minimize\":{\"identifier\":\"allow-minimize\",\"description\":\"Enables the minimize command without any pre-configured scope.\",\"commands\":{\"allow\":[\"minimize\"],\"deny\":[]}},\"allow-monitor-from-point\":{\"identifier\":\"allow-monitor-from-point\",\"description\":\"Enables the monitor_from_point command without any pre-configured scope.\",\"commands\":{\"allow\":[\"monitor_from_point\"],\"deny\":[]}},\"allow-outer-position\":{\"identifier\":\"allow-outer-position\",\"description\":\"Enables the outer_position command without any pre-configured scope.\",\"commands\":{\"allow\":[\"outer_position\"],\"deny\":[]}},\"allow-outer-size\":{\"identifier\":\"allow-outer-size\",\"description\":\"Enables the outer_size command without any pre-configured scope.\",\"commands\":{\"allow\":[\"outer_size\"],\"deny\":[]}},\"allow-primary-monitor\":{\"identifier\":\"allow-primary-monitor\",\"description\":\"Enables the primary_monitor command without any pre-configured scope.\",\"commands\":{\"allow\":[\"primary_monitor\"],\"deny\":[]}},\"allow-request-user-attention\":{\"identifier\":\"allow-request-user-attention\",\"description\":\"Enables the request_user_attention command without any pre-configured scope.\",\"commands\":{\"allow\":[\"request_user_attention\"],\"deny\":[]}},\"allow-scale-factor\":{\"identifier\":\"allow-scale-factor\",\"description\":\"Enables the scale_factor command without any pre-configured scope.\",\"commands\":{\"allow\":[\"scale_factor\"],\"deny\":[]}},\"allow-set-always-on-bottom\":{\"identifier\":\"allow-set-always-on-bottom\",\"description\":\"Enables the set_always_on_bottom command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_always_on_bottom\"],\"deny\":[]}},\"allow-set-always-on-top\":{\"identifier\":\"allow-set-always-on-top\",\"description\":\"Enables the set_always_on_top command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_always_on_top\"],\"deny\":[]}},\"allow-set-closable\":{\"identifier\":\"allow-set-closable\",\"description\":\"Enables the set_closable command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_closable\"],\"deny\":[]}},\"allow-set-content-protected\":{\"identifier\":\"allow-set-content-protected\",\"description\":\"Enables the set_content_protected command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_content_protected\"],\"deny\":[]}},\"allow-set-cursor-grab\":{\"identifier\":\"allow-set-cursor-grab\",\"description\":\"Enables the set_cursor_grab command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_cursor_grab\"],\"deny\":[]}},\"allow-set-cursor-icon\":{\"identifier\":\"allow-set-cursor-icon\",\"description\":\"Enables the set_cursor_icon command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_cursor_icon\"],\"deny\":[]}},\"allow-set-cursor-position\":{\"identifier\":\"allow-set-cursor-position\",\"description\":\"Enables the set_cursor_position command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_cursor_position\"],\"deny\":[]}},\"allow-set-cursor-visible\":{\"identifier\":\"allow-set-cursor-visible\",\"description\":\"Enables the set_cursor_visible command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_cursor_visible\"],\"deny\":[]}},\"allow-set-decorations\":{\"identifier\":\"allow-set-decorations\",\"description\":\"Enables the set_decorations command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_decorations\"],\"deny\":[]}},\"allow-set-effects\":{\"identifier\":\"allow-set-effects\",\"description\":\"Enables the set_effects command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_effects\"],\"deny\":[]}},\"allow-set-focus\":{\"identifier\":\"allow-set-focus\",\"description\":\"Enables the set_focus command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_focus\"],\"deny\":[]}},\"allow-set-fullscreen\":{\"identifier\":\"allow-set-fullscreen\",\"description\":\"Enables the set_fullscreen command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_fullscreen\"],\"deny\":[]}},\"allow-set-icon\":{\"identifier\":\"allow-set-icon\",\"description\":\"Enables the set_icon command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_icon\"],\"deny\":[]}},\"allow-set-ignore-cursor-events\":{\"identifier\":\"allow-set-ignore-cursor-events\",\"description\":\"Enables the set_ignore_cursor_events command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_ignore_cursor_events\"],\"deny\":[]}},\"allow-set-max-size\":{\"identifier\":\"allow-set-max-size\",\"description\":\"Enables the set_max_size command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_max_size\"],\"deny\":[]}},\"allow-set-maximizable\":{\"identifier\":\"allow-set-maximizable\",\"description\":\"Enables the set_maximizable command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_maximizable\"],\"deny\":[]}},\"allow-set-min-size\":{\"identifier\":\"allow-set-min-size\",\"description\":\"Enables the set_min_size command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_min_size\"],\"deny\":[]}},\"allow-set-minimizable\":{\"identifier\":\"allow-set-minimizable\",\"description\":\"Enables the set_minimizable command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_minimizable\"],\"deny\":[]}},\"allow-set-position\":{\"identifier\":\"allow-set-position\",\"description\":\"Enables the set_position command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_position\"],\"deny\":[]}},\"allow-set-progress-bar\":{\"identifier\":\"allow-set-progress-bar\",\"description\":\"Enables the set_progress_bar command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_progress_bar\"],\"deny\":[]}},\"allow-set-resizable\":{\"identifier\":\"allow-set-resizable\",\"description\":\"Enables the set_resizable command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_resizable\"],\"deny\":[]}},\"allow-set-shadow\":{\"identifier\":\"allow-set-shadow\",\"description\":\"Enables the set_shadow command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_shadow\"],\"deny\":[]}},\"allow-set-size\":{\"identifier\":\"allow-set-size\",\"description\":\"Enables the set_size command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_size\"],\"deny\":[]}},\"allow-set-size-constraints\":{\"identifier\":\"allow-set-size-constraints\",\"description\":\"Enables the set_size_constraints command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_size_constraints\"],\"deny\":[]}},\"allow-set-skip-taskbar\":{\"identifier\":\"allow-set-skip-taskbar\",\"description\":\"Enables the set_skip_taskbar command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_skip_taskbar\"],\"deny\":[]}},\"allow-set-title\":{\"identifier\":\"allow-set-title\",\"description\":\"Enables the set_title command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_title\"],\"deny\":[]}},\"allow-set-title-bar-style\":{\"identifier\":\"allow-set-title-bar-style\",\"description\":\"Enables the set_title_bar_style command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_title_bar_style\"],\"deny\":[]}},\"allow-set-visible-on-all-workspaces\":{\"identifier\":\"allow-set-visible-on-all-workspaces\",\"description\":\"Enables the set_visible_on_all_workspaces command without any pre-configured scope.\",\"commands\":{\"allow\":[\"set_visible_on_all_workspaces\"],\"deny\":[]}},\"allow-show\":{\"identifier\":\"allow-show\",\"description\":\"Enables the show command without any pre-configured scope.\",\"commands\":{\"allow\":[\"show\"],\"deny\":[]}},\"allow-start-dragging\":{\"identifier\":\"allow-start-dragging\",\"description\":\"Enables the start_dragging command without any pre-configured scope.\",\"commands\":{\"allow\":[\"start_dragging\"],\"deny\":[]}},\"allow-start-resize-dragging\":{\"identifier\":\"allow-start-resize-dragging\",\"description\":\"Enables the start_resize_dragging command without any pre-configured scope.\",\"commands\":{\"allow\":[\"start_resize_dragging\"],\"deny\":[]}},\"allow-theme\":{\"identifier\":\"allow-theme\",\"description\":\"Enables the theme command without any pre-configured scope.\",\"commands\":{\"allow\":[\"theme\"],\"deny\":[]}},\"allow-title\":{\"identifier\":\"allow-title\",\"description\":\"Enables the title command without any pre-configured scope.\",\"commands\":{\"allow\":[\"title\"],\"deny\":[]}},\"allow-toggle-maximize\":{\"identifier\":\"allow-toggle-maximize\",\"description\":\"Enables the toggle_maximize command without any pre-configured scope.\",\"commands\":{\"allow\":[\"toggle_maximize\"],\"deny\":[]}},\"allow-unmaximize\":{\"identifier\":\"allow-unmaximize\",\"description\":\"Enables the unmaximize command without any pre-configured scope.\",\"commands\":{\"allow\":[\"unmaximize\"],\"deny\":[]}},\"allow-unminimize\":{\"identifier\":\"allow-unminimize\",\"description\":\"Enables the unminimize command without any pre-configured scope.\",\"commands\":{\"allow\":[\"unminimize\"],\"deny\":[]}},\"deny-available-monitors\":{\"identifier\":\"deny-available-monitors\",\"description\":\"Denies the available_monitors command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"available_monitors\"]}},\"deny-center\":{\"identifier\":\"deny-center\",\"description\":\"Denies the center command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"center\"]}},\"deny-close\":{\"identifier\":\"deny-close\",\"description\":\"Denies the close command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"close\"]}},\"deny-create\":{\"identifier\":\"deny-create\",\"description\":\"Denies the create command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"create\"]}},\"deny-current-monitor\":{\"identifier\":\"deny-current-monitor\",\"description\":\"Denies the current_monitor command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"current_monitor\"]}},\"deny-cursor-position\":{\"identifier\":\"deny-cursor-position\",\"description\":\"Denies the cursor_position command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"cursor_position\"]}},\"deny-destroy\":{\"identifier\":\"deny-destroy\",\"description\":\"Denies the destroy command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"destroy\"]}},\"deny-get-all-windows\":{\"identifier\":\"deny-get-all-windows\",\"description\":\"Denies the get_all_windows command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"get_all_windows\"]}},\"deny-hide\":{\"identifier\":\"deny-hide\",\"description\":\"Denies the hide command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"hide\"]}},\"deny-inner-position\":{\"identifier\":\"deny-inner-position\",\"description\":\"Denies the inner_position command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"inner_position\"]}},\"deny-inner-size\":{\"identifier\":\"deny-inner-size\",\"description\":\"Denies the inner_size command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"inner_size\"]}},\"deny-internal-toggle-maximize\":{\"identifier\":\"deny-internal-toggle-maximize\",\"description\":\"Denies the internal_toggle_maximize command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"internal_toggle_maximize\"]}},\"deny-is-closable\":{\"identifier\":\"deny-is-closable\",\"description\":\"Denies the is_closable command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"is_closable\"]}},\"deny-is-decorated\":{\"identifier\":\"deny-is-decorated\",\"description\":\"Denies the is_decorated command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"is_decorated\"]}},\"deny-is-focused\":{\"identifier\":\"deny-is-focused\",\"description\":\"Denies the is_focused command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"is_focused\"]}},\"deny-is-fullscreen\":{\"identifier\":\"deny-is-fullscreen\",\"description\":\"Denies the is_fullscreen command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"is_fullscreen\"]}},\"deny-is-maximizable\":{\"identifier\":\"deny-is-maximizable\",\"description\":\"Denies the is_maximizable command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"is_maximizable\"]}},\"deny-is-maximized\":{\"identifier\":\"deny-is-maximized\",\"description\":\"Denies the is_maximized command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"is_maximized\"]}},\"deny-is-minimizable\":{\"identifier\":\"deny-is-minimizable\",\"description\":\"Denies the is_minimizable command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"is_minimizable\"]}},\"deny-is-minimized\":{\"identifier\":\"deny-is-minimized\",\"description\":\"Denies the is_minimized command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"is_minimized\"]}},\"deny-is-resizable\":{\"identifier\":\"deny-is-resizable\",\"description\":\"Denies the is_resizable command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"is_resizable\"]}},\"deny-is-visible\":{\"identifier\":\"deny-is-visible\",\"description\":\"Denies the is_visible command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"is_visible\"]}},\"deny-maximize\":{\"identifier\":\"deny-maximize\",\"description\":\"Denies the maximize command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"maximize\"]}},\"deny-minimize\":{\"identifier\":\"deny-minimize\",\"description\":\"Denies the minimize command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"minimize\"]}},\"deny-monitor-from-point\":{\"identifier\":\"deny-monitor-from-point\",\"description\":\"Denies the monitor_from_point command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"monitor_from_point\"]}},\"deny-outer-position\":{\"identifier\":\"deny-outer-position\",\"description\":\"Denies the outer_position command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"outer_position\"]}},\"deny-outer-size\":{\"identifier\":\"deny-outer-size\",\"description\":\"Denies the outer_size command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"outer_size\"]}},\"deny-primary-monitor\":{\"identifier\":\"deny-primary-monitor\",\"description\":\"Denies the primary_monitor command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"primary_monitor\"]}},\"deny-request-user-attention\":{\"identifier\":\"deny-request-user-attention\",\"description\":\"Denies the request_user_attention command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"request_user_attention\"]}},\"deny-scale-factor\":{\"identifier\":\"deny-scale-factor\",\"description\":\"Denies the scale_factor command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"scale_factor\"]}},\"deny-set-always-on-bottom\":{\"identifier\":\"deny-set-always-on-bottom\",\"description\":\"Denies the set_always_on_bottom command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_always_on_bottom\"]}},\"deny-set-always-on-top\":{\"identifier\":\"deny-set-always-on-top\",\"description\":\"Denies the set_always_on_top command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_always_on_top\"]}},\"deny-set-closable\":{\"identifier\":\"deny-set-closable\",\"description\":\"Denies the set_closable command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_closable\"]}},\"deny-set-content-protected\":{\"identifier\":\"deny-set-content-protected\",\"description\":\"Denies the set_content_protected command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_content_protected\"]}},\"deny-set-cursor-grab\":{\"identifier\":\"deny-set-cursor-grab\",\"description\":\"Denies the set_cursor_grab command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_cursor_grab\"]}},\"deny-set-cursor-icon\":{\"identifier\":\"deny-set-cursor-icon\",\"description\":\"Denies the set_cursor_icon command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_cursor_icon\"]}},\"deny-set-cursor-position\":{\"identifier\":\"deny-set-cursor-position\",\"description\":\"Denies the set_cursor_position command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_cursor_position\"]}},\"deny-set-cursor-visible\":{\"identifier\":\"deny-set-cursor-visible\",\"description\":\"Denies the set_cursor_visible command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_cursor_visible\"]}},\"deny-set-decorations\":{\"identifier\":\"deny-set-decorations\",\"description\":\"Denies the set_decorations command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_decorations\"]}},\"deny-set-effects\":{\"identifier\":\"deny-set-effects\",\"description\":\"Denies the set_effects command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_effects\"]}},\"deny-set-focus\":{\"identifier\":\"deny-set-focus\",\"description\":\"Denies the set_focus command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_focus\"]}},\"deny-set-fullscreen\":{\"identifier\":\"deny-set-fullscreen\",\"description\":\"Denies the set_fullscreen command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_fullscreen\"]}},\"deny-set-icon\":{\"identifier\":\"deny-set-icon\",\"description\":\"Denies the set_icon command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_icon\"]}},\"deny-set-ignore-cursor-events\":{\"identifier\":\"deny-set-ignore-cursor-events\",\"description\":\"Denies the set_ignore_cursor_events command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_ignore_cursor_events\"]}},\"deny-set-max-size\":{\"identifier\":\"deny-set-max-size\",\"description\":\"Denies the set_max_size command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_max_size\"]}},\"deny-set-maximizable\":{\"identifier\":\"deny-set-maximizable\",\"description\":\"Denies the set_maximizable command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_maximizable\"]}},\"deny-set-min-size\":{\"identifier\":\"deny-set-min-size\",\"description\":\"Denies the set_min_size command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_min_size\"]}},\"deny-set-minimizable\":{\"identifier\":\"deny-set-minimizable\",\"description\":\"Denies the set_minimizable command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_minimizable\"]}},\"deny-set-position\":{\"identifier\":\"deny-set-position\",\"description\":\"Denies the set_position command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_position\"]}},\"deny-set-progress-bar\":{\"identifier\":\"deny-set-progress-bar\",\"description\":\"Denies the set_progress_bar command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_progress_bar\"]}},\"deny-set-resizable\":{\"identifier\":\"deny-set-resizable\",\"description\":\"Denies the set_resizable command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_resizable\"]}},\"deny-set-shadow\":{\"identifier\":\"deny-set-shadow\",\"description\":\"Denies the set_shadow command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_shadow\"]}},\"deny-set-size\":{\"identifier\":\"deny-set-size\",\"description\":\"Denies the set_size command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_size\"]}},\"deny-set-size-constraints\":{\"identifier\":\"deny-set-size-constraints\",\"description\":\"Denies the set_size_constraints command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_size_constraints\"]}},\"deny-set-skip-taskbar\":{\"identifier\":\"deny-set-skip-taskbar\",\"description\":\"Denies the set_skip_taskbar command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_skip_taskbar\"]}},\"deny-set-title\":{\"identifier\":\"deny-set-title\",\"description\":\"Denies the set_title command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_title\"]}},\"deny-set-title-bar-style\":{\"identifier\":\"deny-set-title-bar-style\",\"description\":\"Denies the set_title_bar_style command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_title_bar_style\"]}},\"deny-set-visible-on-all-workspaces\":{\"identifier\":\"deny-set-visible-on-all-workspaces\",\"description\":\"Denies the set_visible_on_all_workspaces command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"set_visible_on_all_workspaces\"]}},\"deny-show\":{\"identifier\":\"deny-show\",\"description\":\"Denies the show command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"show\"]}},\"deny-start-dragging\":{\"identifier\":\"deny-start-dragging\",\"description\":\"Denies the start_dragging command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"start_dragging\"]}},\"deny-start-resize-dragging\":{\"identifier\":\"deny-start-resize-dragging\",\"description\":\"Denies the start_resize_dragging command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"start_resize_dragging\"]}},\"deny-theme\":{\"identifier\":\"deny-theme\",\"description\":\"Denies the theme command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"theme\"]}},\"deny-title\":{\"identifier\":\"deny-title\",\"description\":\"Denies the title command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"title\"]}},\"deny-toggle-maximize\":{\"identifier\":\"deny-toggle-maximize\",\"description\":\"Denies the toggle_maximize command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"toggle_maximize\"]}},\"deny-unmaximize\":{\"identifier\":\"deny-unmaximize\",\"description\":\"Denies the unmaximize command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"unmaximize\"]}},\"deny-unminimize\":{\"identifier\":\"deny-unminimize\",\"description\":\"Denies the unminimize command without any pre-configured scope.\",\"commands\":{\"allow\":[],\"deny\":[\"unminimize\"]}}},\"permission_sets\":{},\"global_scope_schema\":null}}"
  },
  {
    "path": "src-tauri/gen/schemas/capabilities.json",
    "content": "{\"migrated\":{\"identifier\":\"migrated\",\"description\":\"permissions that were migrated from v1\",\"local\":true,\"windows\":[\"main\"],\"permissions\":[\"core:default\"]}}"
  },
  {
    "path": "src-tauri/gen/schemas/desktop-schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"title\": \"CapabilityFile\",\n  \"description\": \"Capability formats accepted in a capability file.\",\n  \"anyOf\": [\n    {\n      \"description\": \"A single capability.\",\n      \"allOf\": [\n        {\n          \"$ref\": \"#/definitions/Capability\"\n        }\n      ]\n    },\n    {\n      \"description\": \"A list of capabilities.\",\n      \"type\": \"array\",\n      \"items\": {\n        \"$ref\": \"#/definitions/Capability\"\n      }\n    },\n    {\n      \"description\": \"A list of capabilities.\",\n      \"type\": \"object\",\n      \"required\": [\n        \"capabilities\"\n      ],\n      \"properties\": {\n        \"capabilities\": {\n          \"description\": \"The list of capabilities.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"#/definitions/Capability\"\n          }\n        }\n      }\n    }\n  ],\n  \"definitions\": {\n    \"Capability\": {\n      \"description\": \"A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\\n\\nIt controls application windows fine grained access to the Tauri core, application, or plugin commands. If a window is not matching any capability then it has no access to the IPC layer at all.\\n\\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\\n\\n## Example\\n\\n```json { \\\"identifier\\\": \\\"main-user-files-write\\\", \\\"description\\\": \\\"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\\\", \\\"windows\\\": [ \\\"main\\\" ], \\\"permissions\\\": [ \\\"core:default\\\", \\\"dialog:open\\\", { \\\"identifier\\\": \\\"fs:allow-write-text-file\\\", \\\"allow\\\": [{ \\\"path\\\": \\\"$HOME/test.txt\\\" }] }, \\\"platforms\\\": [\\\"macOS\\\",\\\"windows\\\"] } ```\",\n      \"type\": \"object\",\n      \"required\": [\n        \"identifier\",\n        \"permissions\"\n      ],\n      \"properties\": {\n        \"identifier\": {\n          \"description\": \"Identifier of the capability.\\n\\n## Example\\n\\n`main-user-files-write`\",\n          \"type\": \"string\"\n        },\n        \"description\": {\n          \"description\": \"Description of what the capability is intended to allow on associated windows.\\n\\nIt should contain a description of what the grouped permissions should allow.\\n\\n## Example\\n\\nThis capability allows the `main` window access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n          \"default\": \"\",\n          \"type\": \"string\"\n        },\n        \"remote\": {\n          \"description\": \"Configure remote URLs that can use the capability permissions.\\n\\nThis setting is optional and defaults to not being set, as our default use case is that the content is served from our local application.\\n\\n:::caution Make sure you understand the security implications of providing remote sources with local system access. :::\\n\\n## Example\\n\\n```json { \\\"urls\\\": [\\\"https://*.mydomain.dev\\\"] } ```\",\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/definitions/CapabilityRemote\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"local\": {\n          \"description\": \"Whether this capability is enabled for local app URLs or not. Defaults to `true`.\",\n          \"default\": true,\n          \"type\": \"boolean\"\n        },\n        \"windows\": {\n          \"description\": \"List of windows that are affected by this capability. Can be a glob pattern.\\n\\nOn multiwebview windows, prefer [`Self::webviews`] for a fine grained access control.\\n\\n## Example\\n\\n`[\\\"main\\\"]`\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"webviews\": {\n          \"description\": \"List of webviews that are affected by this capability. Can be a glob pattern.\\n\\nThis is only required when using on multiwebview contexts, by default all child webviews of a window that matches [`Self::windows`] are linked.\\n\\n## Example\\n\\n`[\\\"sub-webview-one\\\", \\\"sub-webview-two\\\"]`\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"permissions\": {\n          \"description\": \"List of permissions attached to this capability.\\n\\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\\n\\n## Example\\n\\n```json [ \\\"core:default\\\", \\\"shell:allow-open\\\", \\\"dialog:open\\\", { \\\"identifier\\\": \\\"fs:allow-write-text-file\\\", \\\"allow\\\": [{ \\\"path\\\": \\\"$HOME/test.txt\\\" }] } ```\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"#/definitions/PermissionEntry\"\n          },\n          \"uniqueItems\": true\n        },\n        \"platforms\": {\n          \"description\": \"Limit which target platforms this capability applies to.\\n\\nBy default all platforms are targeted.\\n\\n## Example\\n\\n`[\\\"macOS\\\",\\\"windows\\\"]`\",\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"$ref\": \"#/definitions/Target\"\n          }\n        }\n      }\n    },\n    \"CapabilityRemote\": {\n      \"description\": \"Configuration for remote URLs that are associated with the capability.\",\n      \"type\": \"object\",\n      \"required\": [\n        \"urls\"\n      ],\n      \"properties\": {\n        \"urls\": {\n          \"description\": \"Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\\n\\n## Examples\\n\\n- \\\"https://*.mydomain.dev\\\": allows subdomains of mydomain.dev - \\\"https://mydomain.dev/api/*\\\": allows any subpath of mydomain.dev/api\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        }\n      }\n    },\n    \"PermissionEntry\": {\n      \"description\": \"An entry for a permission value in a [`Capability`] can be either a raw permission [`Identifier`] or an object that references a permission and extends its scope.\",\n      \"anyOf\": [\n        {\n          \"description\": \"Reference a permission or permission set by identifier.\",\n          \"allOf\": [\n            {\n              \"$ref\": \"#/definitions/Identifier\"\n            }\n          ]\n        },\n        {\n          \"description\": \"Reference a permission or permission set by identifier and extends its scope.\",\n          \"type\": \"object\",\n          \"allOf\": [\n            {\n              \"properties\": {\n                \"identifier\": {\n                  \"description\": \"Identifier of the permission or permission set.\",\n                  \"allOf\": [\n                    {\n                      \"$ref\": \"#/definitions/Identifier\"\n                    }\n                  ]\n                },\n                \"allow\": {\n                  \"description\": \"Data that defines what is allowed by the scope.\",\n                  \"type\": [\n                    \"array\",\n                    \"null\"\n                  ],\n                  \"items\": {\n                    \"$ref\": \"#/definitions/Value\"\n                  }\n                },\n                \"deny\": {\n                  \"description\": \"Data that defines what is denied by the scope. This should be prioritized by validation logic.\",\n                  \"type\": [\n                    \"array\",\n                    \"null\"\n                  ],\n                  \"items\": {\n                    \"$ref\": \"#/definitions/Value\"\n                  }\n                }\n              }\n            }\n          ],\n          \"required\": [\n            \"identifier\"\n          ]\n        }\n      ]\n    },\n    \"Identifier\": {\n      \"description\": \"Permission identifier\",\n      \"oneOf\": [\n        {\n          \"description\": \"Default core plugins set which includes:\\n- 'core:path:default'\\n- 'core:event:default'\\n- 'core:window:default'\\n- 'core:webview:default'\\n- 'core:app:default'\\n- 'core:image:default'\\n- 'core:resources:default'\\n- 'core:menu:default'\\n- 'core:tray:default'\\n\",\n          \"type\": \"string\",\n          \"const\": \"core:default\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:default\"\n        },\n        {\n          \"description\": \"Enables the app_hide command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:allow-app-hide\"\n        },\n        {\n          \"description\": \"Enables the app_show command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:allow-app-show\"\n        },\n        {\n          \"description\": \"Enables the default_window_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:allow-default-window-icon\"\n        },\n        {\n          \"description\": \"Enables the name command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:allow-name\"\n        },\n        {\n          \"description\": \"Enables the tauri_version command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:allow-tauri-version\"\n        },\n        {\n          \"description\": \"Enables the version command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:allow-version\"\n        },\n        {\n          \"description\": \"Denies the app_hide command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:deny-app-hide\"\n        },\n        {\n          \"description\": \"Denies the app_show command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:deny-app-show\"\n        },\n        {\n          \"description\": \"Denies the default_window_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:deny-default-window-icon\"\n        },\n        {\n          \"description\": \"Denies the name command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:deny-name\"\n        },\n        {\n          \"description\": \"Denies the tauri_version command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:deny-tauri-version\"\n        },\n        {\n          \"description\": \"Denies the version command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:deny-version\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:default\"\n        },\n        {\n          \"description\": \"Enables the emit command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:allow-emit\"\n        },\n        {\n          \"description\": \"Enables the emit_to command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:allow-emit-to\"\n        },\n        {\n          \"description\": \"Enables the listen command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:allow-listen\"\n        },\n        {\n          \"description\": \"Enables the unlisten command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:allow-unlisten\"\n        },\n        {\n          \"description\": \"Denies the emit command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:deny-emit\"\n        },\n        {\n          \"description\": \"Denies the emit_to command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:deny-emit-to\"\n        },\n        {\n          \"description\": \"Denies the listen command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:deny-listen\"\n        },\n        {\n          \"description\": \"Denies the unlisten command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:deny-unlisten\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:default\"\n        },\n        {\n          \"description\": \"Enables the from_bytes command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:allow-from-bytes\"\n        },\n        {\n          \"description\": \"Enables the from_path command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:allow-from-path\"\n        },\n        {\n          \"description\": \"Enables the new command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:allow-new\"\n        },\n        {\n          \"description\": \"Enables the rgba command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:allow-rgba\"\n        },\n        {\n          \"description\": \"Enables the size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:allow-size\"\n        },\n        {\n          \"description\": \"Denies the from_bytes command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:deny-from-bytes\"\n        },\n        {\n          \"description\": \"Denies the from_path command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:deny-from-path\"\n        },\n        {\n          \"description\": \"Denies the new command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:deny-new\"\n        },\n        {\n          \"description\": \"Denies the rgba command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:deny-rgba\"\n        },\n        {\n          \"description\": \"Denies the size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:deny-size\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:default\"\n        },\n        {\n          \"description\": \"Enables the append command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-append\"\n        },\n        {\n          \"description\": \"Enables the create_default command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-create-default\"\n        },\n        {\n          \"description\": \"Enables the get command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-get\"\n        },\n        {\n          \"description\": \"Enables the insert command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-insert\"\n        },\n        {\n          \"description\": \"Enables the is_checked command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-is-checked\"\n        },\n        {\n          \"description\": \"Enables the is_enabled command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-is-enabled\"\n        },\n        {\n          \"description\": \"Enables the items command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-items\"\n        },\n        {\n          \"description\": \"Enables the new command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-new\"\n        },\n        {\n          \"description\": \"Enables the popup command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-popup\"\n        },\n        {\n          \"description\": \"Enables the prepend command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-prepend\"\n        },\n        {\n          \"description\": \"Enables the remove command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-remove\"\n        },\n        {\n          \"description\": \"Enables the remove_at command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-remove-at\"\n        },\n        {\n          \"description\": \"Enables the set_accelerator command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-accelerator\"\n        },\n        {\n          \"description\": \"Enables the set_as_app_menu command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-as-app-menu\"\n        },\n        {\n          \"description\": \"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-as-help-menu-for-nsapp\"\n        },\n        {\n          \"description\": \"Enables the set_as_window_menu command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-as-window-menu\"\n        },\n        {\n          \"description\": \"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-as-windows-menu-for-nsapp\"\n        },\n        {\n          \"description\": \"Enables the set_checked command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-checked\"\n        },\n        {\n          \"description\": \"Enables the set_enabled command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-enabled\"\n        },\n        {\n          \"description\": \"Enables the set_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-icon\"\n        },\n        {\n          \"description\": \"Enables the set_text command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-text\"\n        },\n        {\n          \"description\": \"Enables the text command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-text\"\n        },\n        {\n          \"description\": \"Denies the append command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-append\"\n        },\n        {\n          \"description\": \"Denies the create_default command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-create-default\"\n        },\n        {\n          \"description\": \"Denies the get command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-get\"\n        },\n        {\n          \"description\": \"Denies the insert command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-insert\"\n        },\n        {\n          \"description\": \"Denies the is_checked command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-is-checked\"\n        },\n        {\n          \"description\": \"Denies the is_enabled command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-is-enabled\"\n        },\n        {\n          \"description\": \"Denies the items command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-items\"\n        },\n        {\n          \"description\": \"Denies the new command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-new\"\n        },\n        {\n          \"description\": \"Denies the popup command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-popup\"\n        },\n        {\n          \"description\": \"Denies the prepend command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-prepend\"\n        },\n        {\n          \"description\": \"Denies the remove command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-remove\"\n        },\n        {\n          \"description\": \"Denies the remove_at command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-remove-at\"\n        },\n        {\n          \"description\": \"Denies the set_accelerator command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-accelerator\"\n        },\n        {\n          \"description\": \"Denies the set_as_app_menu command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-as-app-menu\"\n        },\n        {\n          \"description\": \"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-as-help-menu-for-nsapp\"\n        },\n        {\n          \"description\": \"Denies the set_as_window_menu command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-as-window-menu\"\n        },\n        {\n          \"description\": \"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-as-windows-menu-for-nsapp\"\n        },\n        {\n          \"description\": \"Denies the set_checked command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-checked\"\n        },\n        {\n          \"description\": \"Denies the set_enabled command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-enabled\"\n        },\n        {\n          \"description\": \"Denies the set_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-icon\"\n        },\n        {\n          \"description\": \"Denies the set_text command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-text\"\n        },\n        {\n          \"description\": \"Denies the text command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-text\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:default\"\n        },\n        {\n          \"description\": \"Enables the basename command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-basename\"\n        },\n        {\n          \"description\": \"Enables the dirname command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-dirname\"\n        },\n        {\n          \"description\": \"Enables the extname command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-extname\"\n        },\n        {\n          \"description\": \"Enables the is_absolute command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-is-absolute\"\n        },\n        {\n          \"description\": \"Enables the join command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-join\"\n        },\n        {\n          \"description\": \"Enables the normalize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-normalize\"\n        },\n        {\n          \"description\": \"Enables the resolve command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-resolve\"\n        },\n        {\n          \"description\": \"Enables the resolve_directory command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-resolve-directory\"\n        },\n        {\n          \"description\": \"Denies the basename command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-basename\"\n        },\n        {\n          \"description\": \"Denies the dirname command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-dirname\"\n        },\n        {\n          \"description\": \"Denies the extname command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-extname\"\n        },\n        {\n          \"description\": \"Denies the is_absolute command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-is-absolute\"\n        },\n        {\n          \"description\": \"Denies the join command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-join\"\n        },\n        {\n          \"description\": \"Denies the normalize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-normalize\"\n        },\n        {\n          \"description\": \"Denies the resolve command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-resolve\"\n        },\n        {\n          \"description\": \"Denies the resolve_directory command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-resolve-directory\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:resources:default\"\n        },\n        {\n          \"description\": \"Enables the close command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:resources:allow-close\"\n        },\n        {\n          \"description\": \"Denies the close command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:resources:deny-close\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:default\"\n        },\n        {\n          \"description\": \"Enables the get_by_id command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-get-by-id\"\n        },\n        {\n          \"description\": \"Enables the new command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-new\"\n        },\n        {\n          \"description\": \"Enables the remove_by_id command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-remove-by-id\"\n        },\n        {\n          \"description\": \"Enables the set_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-icon\"\n        },\n        {\n          \"description\": \"Enables the set_icon_as_template command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-icon-as-template\"\n        },\n        {\n          \"description\": \"Enables the set_menu command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-menu\"\n        },\n        {\n          \"description\": \"Enables the set_show_menu_on_left_click command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-show-menu-on-left-click\"\n        },\n        {\n          \"description\": \"Enables the set_temp_dir_path command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-temp-dir-path\"\n        },\n        {\n          \"description\": \"Enables the set_title command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-title\"\n        },\n        {\n          \"description\": \"Enables the set_tooltip command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-tooltip\"\n        },\n        {\n          \"description\": \"Enables the set_visible command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-visible\"\n        },\n        {\n          \"description\": \"Denies the get_by_id command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-get-by-id\"\n        },\n        {\n          \"description\": \"Denies the new command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-new\"\n        },\n        {\n          \"description\": \"Denies the remove_by_id command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-remove-by-id\"\n        },\n        {\n          \"description\": \"Denies the set_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-icon\"\n        },\n        {\n          \"description\": \"Denies the set_icon_as_template command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-icon-as-template\"\n        },\n        {\n          \"description\": \"Denies the set_menu command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-menu\"\n        },\n        {\n          \"description\": \"Denies the set_show_menu_on_left_click command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-show-menu-on-left-click\"\n        },\n        {\n          \"description\": \"Denies the set_temp_dir_path command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-temp-dir-path\"\n        },\n        {\n          \"description\": \"Denies the set_title command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-title\"\n        },\n        {\n          \"description\": \"Denies the set_tooltip command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-tooltip\"\n        },\n        {\n          \"description\": \"Denies the set_visible command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-visible\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:default\"\n        },\n        {\n          \"description\": \"Enables the create_webview command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-create-webview\"\n        },\n        {\n          \"description\": \"Enables the create_webview_window command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-create-webview-window\"\n        },\n        {\n          \"description\": \"Enables the get_all_webviews command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-get-all-webviews\"\n        },\n        {\n          \"description\": \"Enables the internal_toggle_devtools command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-internal-toggle-devtools\"\n        },\n        {\n          \"description\": \"Enables the print command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-print\"\n        },\n        {\n          \"description\": \"Enables the reparent command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-reparent\"\n        },\n        {\n          \"description\": \"Enables the set_webview_focus command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-set-webview-focus\"\n        },\n        {\n          \"description\": \"Enables the set_webview_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-set-webview-position\"\n        },\n        {\n          \"description\": \"Enables the set_webview_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-set-webview-size\"\n        },\n        {\n          \"description\": \"Enables the set_webview_zoom command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-set-webview-zoom\"\n        },\n        {\n          \"description\": \"Enables the webview_close command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-webview-close\"\n        },\n        {\n          \"description\": \"Enables the webview_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-webview-position\"\n        },\n        {\n          \"description\": \"Enables the webview_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-webview-size\"\n        },\n        {\n          \"description\": \"Denies the create_webview command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-create-webview\"\n        },\n        {\n          \"description\": \"Denies the create_webview_window command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-create-webview-window\"\n        },\n        {\n          \"description\": \"Denies the get_all_webviews command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-get-all-webviews\"\n        },\n        {\n          \"description\": \"Denies the internal_toggle_devtools command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-internal-toggle-devtools\"\n        },\n        {\n          \"description\": \"Denies the print command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-print\"\n        },\n        {\n          \"description\": \"Denies the reparent command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-reparent\"\n        },\n        {\n          \"description\": \"Denies the set_webview_focus command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-set-webview-focus\"\n        },\n        {\n          \"description\": \"Denies the set_webview_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-set-webview-position\"\n        },\n        {\n          \"description\": \"Denies the set_webview_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-set-webview-size\"\n        },\n        {\n          \"description\": \"Denies the set_webview_zoom command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-set-webview-zoom\"\n        },\n        {\n          \"description\": \"Denies the webview_close command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-webview-close\"\n        },\n        {\n          \"description\": \"Denies the webview_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-webview-position\"\n        },\n        {\n          \"description\": \"Denies the webview_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-webview-size\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:default\"\n        },\n        {\n          \"description\": \"Enables the available_monitors command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-available-monitors\"\n        },\n        {\n          \"description\": \"Enables the center command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-center\"\n        },\n        {\n          \"description\": \"Enables the close command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-close\"\n        },\n        {\n          \"description\": \"Enables the create command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-create\"\n        },\n        {\n          \"description\": \"Enables the current_monitor command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-current-monitor\"\n        },\n        {\n          \"description\": \"Enables the cursor_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-cursor-position\"\n        },\n        {\n          \"description\": \"Enables the destroy command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-destroy\"\n        },\n        {\n          \"description\": \"Enables the get_all_windows command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-get-all-windows\"\n        },\n        {\n          \"description\": \"Enables the hide command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-hide\"\n        },\n        {\n          \"description\": \"Enables the inner_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-inner-position\"\n        },\n        {\n          \"description\": \"Enables the inner_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-inner-size\"\n        },\n        {\n          \"description\": \"Enables the internal_toggle_maximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-internal-toggle-maximize\"\n        },\n        {\n          \"description\": \"Enables the is_closable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-closable\"\n        },\n        {\n          \"description\": \"Enables the is_decorated command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-decorated\"\n        },\n        {\n          \"description\": \"Enables the is_focused command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-focused\"\n        },\n        {\n          \"description\": \"Enables the is_fullscreen command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-fullscreen\"\n        },\n        {\n          \"description\": \"Enables the is_maximizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-maximizable\"\n        },\n        {\n          \"description\": \"Enables the is_maximized command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-maximized\"\n        },\n        {\n          \"description\": \"Enables the is_minimizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-minimizable\"\n        },\n        {\n          \"description\": \"Enables the is_minimized command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-minimized\"\n        },\n        {\n          \"description\": \"Enables the is_resizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-resizable\"\n        },\n        {\n          \"description\": \"Enables the is_visible command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-visible\"\n        },\n        {\n          \"description\": \"Enables the maximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-maximize\"\n        },\n        {\n          \"description\": \"Enables the minimize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-minimize\"\n        },\n        {\n          \"description\": \"Enables the monitor_from_point command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-monitor-from-point\"\n        },\n        {\n          \"description\": \"Enables the outer_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-outer-position\"\n        },\n        {\n          \"description\": \"Enables the outer_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-outer-size\"\n        },\n        {\n          \"description\": \"Enables the primary_monitor command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-primary-monitor\"\n        },\n        {\n          \"description\": \"Enables the request_user_attention command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-request-user-attention\"\n        },\n        {\n          \"description\": \"Enables the scale_factor command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-scale-factor\"\n        },\n        {\n          \"description\": \"Enables the set_always_on_bottom command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-always-on-bottom\"\n        },\n        {\n          \"description\": \"Enables the set_always_on_top command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-always-on-top\"\n        },\n        {\n          \"description\": \"Enables the set_closable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-closable\"\n        },\n        {\n          \"description\": \"Enables the set_content_protected command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-content-protected\"\n        },\n        {\n          \"description\": \"Enables the set_cursor_grab command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-cursor-grab\"\n        },\n        {\n          \"description\": \"Enables the set_cursor_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-cursor-icon\"\n        },\n        {\n          \"description\": \"Enables the set_cursor_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-cursor-position\"\n        },\n        {\n          \"description\": \"Enables the set_cursor_visible command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-cursor-visible\"\n        },\n        {\n          \"description\": \"Enables the set_decorations command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-decorations\"\n        },\n        {\n          \"description\": \"Enables the set_effects command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-effects\"\n        },\n        {\n          \"description\": \"Enables the set_focus command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-focus\"\n        },\n        {\n          \"description\": \"Enables the set_fullscreen command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-fullscreen\"\n        },\n        {\n          \"description\": \"Enables the set_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-icon\"\n        },\n        {\n          \"description\": \"Enables the set_ignore_cursor_events command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-ignore-cursor-events\"\n        },\n        {\n          \"description\": \"Enables the set_max_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-max-size\"\n        },\n        {\n          \"description\": \"Enables the set_maximizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-maximizable\"\n        },\n        {\n          \"description\": \"Enables the set_min_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-min-size\"\n        },\n        {\n          \"description\": \"Enables the set_minimizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-minimizable\"\n        },\n        {\n          \"description\": \"Enables the set_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-position\"\n        },\n        {\n          \"description\": \"Enables the set_progress_bar command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-progress-bar\"\n        },\n        {\n          \"description\": \"Enables the set_resizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-resizable\"\n        },\n        {\n          \"description\": \"Enables the set_shadow command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-shadow\"\n        },\n        {\n          \"description\": \"Enables the set_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-size\"\n        },\n        {\n          \"description\": \"Enables the set_size_constraints command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-size-constraints\"\n        },\n        {\n          \"description\": \"Enables the set_skip_taskbar command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-skip-taskbar\"\n        },\n        {\n          \"description\": \"Enables the set_title command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-title\"\n        },\n        {\n          \"description\": \"Enables the set_title_bar_style command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-title-bar-style\"\n        },\n        {\n          \"description\": \"Enables the set_visible_on_all_workspaces command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-visible-on-all-workspaces\"\n        },\n        {\n          \"description\": \"Enables the show command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-show\"\n        },\n        {\n          \"description\": \"Enables the start_dragging command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-start-dragging\"\n        },\n        {\n          \"description\": \"Enables the start_resize_dragging command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-start-resize-dragging\"\n        },\n        {\n          \"description\": \"Enables the theme command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-theme\"\n        },\n        {\n          \"description\": \"Enables the title command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-title\"\n        },\n        {\n          \"description\": \"Enables the toggle_maximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-toggle-maximize\"\n        },\n        {\n          \"description\": \"Enables the unmaximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-unmaximize\"\n        },\n        {\n          \"description\": \"Enables the unminimize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-unminimize\"\n        },\n        {\n          \"description\": \"Denies the available_monitors command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-available-monitors\"\n        },\n        {\n          \"description\": \"Denies the center command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-center\"\n        },\n        {\n          \"description\": \"Denies the close command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-close\"\n        },\n        {\n          \"description\": \"Denies the create command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-create\"\n        },\n        {\n          \"description\": \"Denies the current_monitor command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-current-monitor\"\n        },\n        {\n          \"description\": \"Denies the cursor_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-cursor-position\"\n        },\n        {\n          \"description\": \"Denies the destroy command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-destroy\"\n        },\n        {\n          \"description\": \"Denies the get_all_windows command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-get-all-windows\"\n        },\n        {\n          \"description\": \"Denies the hide command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-hide\"\n        },\n        {\n          \"description\": \"Denies the inner_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-inner-position\"\n        },\n        {\n          \"description\": \"Denies the inner_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-inner-size\"\n        },\n        {\n          \"description\": \"Denies the internal_toggle_maximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-internal-toggle-maximize\"\n        },\n        {\n          \"description\": \"Denies the is_closable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-closable\"\n        },\n        {\n          \"description\": \"Denies the is_decorated command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-decorated\"\n        },\n        {\n          \"description\": \"Denies the is_focused command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-focused\"\n        },\n        {\n          \"description\": \"Denies the is_fullscreen command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-fullscreen\"\n        },\n        {\n          \"description\": \"Denies the is_maximizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-maximizable\"\n        },\n        {\n          \"description\": \"Denies the is_maximized command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-maximized\"\n        },\n        {\n          \"description\": \"Denies the is_minimizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-minimizable\"\n        },\n        {\n          \"description\": \"Denies the is_minimized command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-minimized\"\n        },\n        {\n          \"description\": \"Denies the is_resizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-resizable\"\n        },\n        {\n          \"description\": \"Denies the is_visible command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-visible\"\n        },\n        {\n          \"description\": \"Denies the maximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-maximize\"\n        },\n        {\n          \"description\": \"Denies the minimize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-minimize\"\n        },\n        {\n          \"description\": \"Denies the monitor_from_point command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-monitor-from-point\"\n        },\n        {\n          \"description\": \"Denies the outer_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-outer-position\"\n        },\n        {\n          \"description\": \"Denies the outer_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-outer-size\"\n        },\n        {\n          \"description\": \"Denies the primary_monitor command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-primary-monitor\"\n        },\n        {\n          \"description\": \"Denies the request_user_attention command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-request-user-attention\"\n        },\n        {\n          \"description\": \"Denies the scale_factor command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-scale-factor\"\n        },\n        {\n          \"description\": \"Denies the set_always_on_bottom command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-always-on-bottom\"\n        },\n        {\n          \"description\": \"Denies the set_always_on_top command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-always-on-top\"\n        },\n        {\n          \"description\": \"Denies the set_closable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-closable\"\n        },\n        {\n          \"description\": \"Denies the set_content_protected command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-content-protected\"\n        },\n        {\n          \"description\": \"Denies the set_cursor_grab command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-cursor-grab\"\n        },\n        {\n          \"description\": \"Denies the set_cursor_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-cursor-icon\"\n        },\n        {\n          \"description\": \"Denies the set_cursor_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-cursor-position\"\n        },\n        {\n          \"description\": \"Denies the set_cursor_visible command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-cursor-visible\"\n        },\n        {\n          \"description\": \"Denies the set_decorations command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-decorations\"\n        },\n        {\n          \"description\": \"Denies the set_effects command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-effects\"\n        },\n        {\n          \"description\": \"Denies the set_focus command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-focus\"\n        },\n        {\n          \"description\": \"Denies the set_fullscreen command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-fullscreen\"\n        },\n        {\n          \"description\": \"Denies the set_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-icon\"\n        },\n        {\n          \"description\": \"Denies the set_ignore_cursor_events command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-ignore-cursor-events\"\n        },\n        {\n          \"description\": \"Denies the set_max_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-max-size\"\n        },\n        {\n          \"description\": \"Denies the set_maximizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-maximizable\"\n        },\n        {\n          \"description\": \"Denies the set_min_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-min-size\"\n        },\n        {\n          \"description\": \"Denies the set_minimizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-minimizable\"\n        },\n        {\n          \"description\": \"Denies the set_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-position\"\n        },\n        {\n          \"description\": \"Denies the set_progress_bar command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-progress-bar\"\n        },\n        {\n          \"description\": \"Denies the set_resizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-resizable\"\n        },\n        {\n          \"description\": \"Denies the set_shadow command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-shadow\"\n        },\n        {\n          \"description\": \"Denies the set_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-size\"\n        },\n        {\n          \"description\": \"Denies the set_size_constraints command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-size-constraints\"\n        },\n        {\n          \"description\": \"Denies the set_skip_taskbar command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-skip-taskbar\"\n        },\n        {\n          \"description\": \"Denies the set_title command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-title\"\n        },\n        {\n          \"description\": \"Denies the set_title_bar_style command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-title-bar-style\"\n        },\n        {\n          \"description\": \"Denies the set_visible_on_all_workspaces command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-visible-on-all-workspaces\"\n        },\n        {\n          \"description\": \"Denies the show command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-show\"\n        },\n        {\n          \"description\": \"Denies the start_dragging command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-start-dragging\"\n        },\n        {\n          \"description\": \"Denies the start_resize_dragging command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-start-resize-dragging\"\n        },\n        {\n          \"description\": \"Denies the theme command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-theme\"\n        },\n        {\n          \"description\": \"Denies the title command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-title\"\n        },\n        {\n          \"description\": \"Denies the toggle_maximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-toggle-maximize\"\n        },\n        {\n          \"description\": \"Denies the unmaximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-unmaximize\"\n        },\n        {\n          \"description\": \"Denies the unminimize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-unminimize\"\n        }\n      ]\n    },\n    \"Value\": {\n      \"description\": \"All supported ACL values.\",\n      \"anyOf\": [\n        {\n          \"description\": \"Represents a null JSON value.\",\n          \"type\": \"null\"\n        },\n        {\n          \"description\": \"Represents a [`bool`].\",\n          \"type\": \"boolean\"\n        },\n        {\n          \"description\": \"Represents a valid ACL [`Number`].\",\n          \"allOf\": [\n            {\n              \"$ref\": \"#/definitions/Number\"\n            }\n          ]\n        },\n        {\n          \"description\": \"Represents a [`String`].\",\n          \"type\": \"string\"\n        },\n        {\n          \"description\": \"Represents a list of other [`Value`]s.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"#/definitions/Value\"\n          }\n        },\n        {\n          \"description\": \"Represents a map of [`String`] keys to [`Value`]s.\",\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"$ref\": \"#/definitions/Value\"\n          }\n        }\n      ]\n    },\n    \"Number\": {\n      \"description\": \"A valid ACL number.\",\n      \"anyOf\": [\n        {\n          \"description\": \"Represents an [`i64`].\",\n          \"type\": \"integer\",\n          \"format\": \"int64\"\n        },\n        {\n          \"description\": \"Represents a [`f64`].\",\n          \"type\": \"number\",\n          \"format\": \"double\"\n        }\n      ]\n    },\n    \"Target\": {\n      \"description\": \"Platform target.\",\n      \"oneOf\": [\n        {\n          \"description\": \"MacOS.\",\n          \"type\": \"string\",\n          \"enum\": [\n            \"macOS\"\n          ]\n        },\n        {\n          \"description\": \"Windows.\",\n          \"type\": \"string\",\n          \"enum\": [\n            \"windows\"\n          ]\n        },\n        {\n          \"description\": \"Linux.\",\n          \"type\": \"string\",\n          \"enum\": [\n            \"linux\"\n          ]\n        },\n        {\n          \"description\": \"Android.\",\n          \"type\": \"string\",\n          \"enum\": [\n            \"android\"\n          ]\n        },\n        {\n          \"description\": \"iOS.\",\n          \"type\": \"string\",\n          \"enum\": [\n            \"iOS\"\n          ]\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "src-tauri/gen/schemas/linux-schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"title\": \"CapabilityFile\",\n  \"description\": \"Capability formats accepted in a capability file.\",\n  \"anyOf\": [\n    {\n      \"description\": \"A single capability.\",\n      \"allOf\": [\n        {\n          \"$ref\": \"#/definitions/Capability\"\n        }\n      ]\n    },\n    {\n      \"description\": \"A list of capabilities.\",\n      \"type\": \"array\",\n      \"items\": {\n        \"$ref\": \"#/definitions/Capability\"\n      }\n    },\n    {\n      \"description\": \"A list of capabilities.\",\n      \"type\": \"object\",\n      \"required\": [\n        \"capabilities\"\n      ],\n      \"properties\": {\n        \"capabilities\": {\n          \"description\": \"The list of capabilities.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"#/definitions/Capability\"\n          }\n        }\n      }\n    }\n  ],\n  \"definitions\": {\n    \"Capability\": {\n      \"description\": \"A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\\n\\nIt controls application windows fine grained access to the Tauri core, application, or plugin commands. If a window is not matching any capability then it has no access to the IPC layer at all.\\n\\nThis can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`. A Window can have none, one, or multiple associated capabilities.\\n\\n## Example\\n\\n```json { \\\"identifier\\\": \\\"main-user-files-write\\\", \\\"description\\\": \\\"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\\\", \\\"windows\\\": [ \\\"main\\\" ], \\\"permissions\\\": [ \\\"core:default\\\", \\\"dialog:open\\\", { \\\"identifier\\\": \\\"fs:allow-write-text-file\\\", \\\"allow\\\": [{ \\\"path\\\": \\\"$HOME/test.txt\\\" }] }, \\\"platforms\\\": [\\\"macOS\\\",\\\"windows\\\"] } ```\",\n      \"type\": \"object\",\n      \"required\": [\n        \"identifier\",\n        \"permissions\"\n      ],\n      \"properties\": {\n        \"identifier\": {\n          \"description\": \"Identifier of the capability.\\n\\n## Example\\n\\n`main-user-files-write`\",\n          \"type\": \"string\"\n        },\n        \"description\": {\n          \"description\": \"Description of what the capability is intended to allow on associated windows.\\n\\nIt should contain a description of what the grouped permissions should allow.\\n\\n## Example\\n\\nThis capability allows the `main` window access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n          \"default\": \"\",\n          \"type\": \"string\"\n        },\n        \"remote\": {\n          \"description\": \"Configure remote URLs that can use the capability permissions.\\n\\nThis setting is optional and defaults to not being set, as our default use case is that the content is served from our local application.\\n\\n:::caution Make sure you understand the security implications of providing remote sources with local system access. :::\\n\\n## Example\\n\\n```json { \\\"urls\\\": [\\\"https://*.mydomain.dev\\\"] } ```\",\n          \"anyOf\": [\n            {\n              \"$ref\": \"#/definitions/CapabilityRemote\"\n            },\n            {\n              \"type\": \"null\"\n            }\n          ]\n        },\n        \"local\": {\n          \"description\": \"Whether this capability is enabled for local app URLs or not. Defaults to `true`.\",\n          \"default\": true,\n          \"type\": \"boolean\"\n        },\n        \"windows\": {\n          \"description\": \"List of windows that are affected by this capability. Can be a glob pattern.\\n\\nOn multiwebview windows, prefer [`Self::webviews`] for a fine grained access control.\\n\\n## Example\\n\\n`[\\\"main\\\"]`\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"webviews\": {\n          \"description\": \"List of webviews that are affected by this capability. Can be a glob pattern.\\n\\nThis is only required when using on multiwebview contexts, by default all child webviews of a window that matches [`Self::windows`] are linked.\\n\\n## Example\\n\\n`[\\\"sub-webview-one\\\", \\\"sub-webview-two\\\"]`\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        },\n        \"permissions\": {\n          \"description\": \"List of permissions attached to this capability.\\n\\nMust include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`. For commands directly implemented in the application itself only `${permission-name}` is required.\\n\\n## Example\\n\\n```json [ \\\"core:default\\\", \\\"shell:allow-open\\\", \\\"dialog:open\\\", { \\\"identifier\\\": \\\"fs:allow-write-text-file\\\", \\\"allow\\\": [{ \\\"path\\\": \\\"$HOME/test.txt\\\" }] } ```\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"#/definitions/PermissionEntry\"\n          },\n          \"uniqueItems\": true\n        },\n        \"platforms\": {\n          \"description\": \"Limit which target platforms this capability applies to.\\n\\nBy default all platforms are targeted.\\n\\n## Example\\n\\n`[\\\"macOS\\\",\\\"windows\\\"]`\",\n          \"type\": [\n            \"array\",\n            \"null\"\n          ],\n          \"items\": {\n            \"$ref\": \"#/definitions/Target\"\n          }\n        }\n      }\n    },\n    \"CapabilityRemote\": {\n      \"description\": \"Configuration for remote URLs that are associated with the capability.\",\n      \"type\": \"object\",\n      \"required\": [\n        \"urls\"\n      ],\n      \"properties\": {\n        \"urls\": {\n          \"description\": \"Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\\n\\n## Examples\\n\\n- \\\"https://*.mydomain.dev\\\": allows subdomains of mydomain.dev - \\\"https://mydomain.dev/api/*\\\": allows any subpath of mydomain.dev/api\",\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"string\"\n          }\n        }\n      }\n    },\n    \"PermissionEntry\": {\n      \"description\": \"An entry for a permission value in a [`Capability`] can be either a raw permission [`Identifier`] or an object that references a permission and extends its scope.\",\n      \"anyOf\": [\n        {\n          \"description\": \"Reference a permission or permission set by identifier.\",\n          \"allOf\": [\n            {\n              \"$ref\": \"#/definitions/Identifier\"\n            }\n          ]\n        },\n        {\n          \"description\": \"Reference a permission or permission set by identifier and extends its scope.\",\n          \"type\": \"object\",\n          \"allOf\": [\n            {\n              \"properties\": {\n                \"identifier\": {\n                  \"description\": \"Identifier of the permission or permission set.\",\n                  \"allOf\": [\n                    {\n                      \"$ref\": \"#/definitions/Identifier\"\n                    }\n                  ]\n                },\n                \"allow\": {\n                  \"description\": \"Data that defines what is allowed by the scope.\",\n                  \"type\": [\n                    \"array\",\n                    \"null\"\n                  ],\n                  \"items\": {\n                    \"$ref\": \"#/definitions/Value\"\n                  }\n                },\n                \"deny\": {\n                  \"description\": \"Data that defines what is denied by the scope. This should be prioritized by validation logic.\",\n                  \"type\": [\n                    \"array\",\n                    \"null\"\n                  ],\n                  \"items\": {\n                    \"$ref\": \"#/definitions/Value\"\n                  }\n                }\n              }\n            }\n          ],\n          \"required\": [\n            \"identifier\"\n          ]\n        }\n      ]\n    },\n    \"Identifier\": {\n      \"description\": \"Permission identifier\",\n      \"oneOf\": [\n        {\n          \"description\": \"Default core plugins set which includes:\\n- 'core:path:default'\\n- 'core:event:default'\\n- 'core:window:default'\\n- 'core:webview:default'\\n- 'core:app:default'\\n- 'core:image:default'\\n- 'core:resources:default'\\n- 'core:menu:default'\\n- 'core:tray:default'\\n\",\n          \"type\": \"string\",\n          \"const\": \"core:default\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:default\"\n        },\n        {\n          \"description\": \"Enables the app_hide command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:allow-app-hide\"\n        },\n        {\n          \"description\": \"Enables the app_show command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:allow-app-show\"\n        },\n        {\n          \"description\": \"Enables the default_window_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:allow-default-window-icon\"\n        },\n        {\n          \"description\": \"Enables the name command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:allow-name\"\n        },\n        {\n          \"description\": \"Enables the tauri_version command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:allow-tauri-version\"\n        },\n        {\n          \"description\": \"Enables the version command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:allow-version\"\n        },\n        {\n          \"description\": \"Denies the app_hide command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:deny-app-hide\"\n        },\n        {\n          \"description\": \"Denies the app_show command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:deny-app-show\"\n        },\n        {\n          \"description\": \"Denies the default_window_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:deny-default-window-icon\"\n        },\n        {\n          \"description\": \"Denies the name command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:deny-name\"\n        },\n        {\n          \"description\": \"Denies the tauri_version command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:deny-tauri-version\"\n        },\n        {\n          \"description\": \"Denies the version command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:app:deny-version\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:default\"\n        },\n        {\n          \"description\": \"Enables the emit command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:allow-emit\"\n        },\n        {\n          \"description\": \"Enables the emit_to command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:allow-emit-to\"\n        },\n        {\n          \"description\": \"Enables the listen command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:allow-listen\"\n        },\n        {\n          \"description\": \"Enables the unlisten command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:allow-unlisten\"\n        },\n        {\n          \"description\": \"Denies the emit command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:deny-emit\"\n        },\n        {\n          \"description\": \"Denies the emit_to command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:deny-emit-to\"\n        },\n        {\n          \"description\": \"Denies the listen command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:deny-listen\"\n        },\n        {\n          \"description\": \"Denies the unlisten command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:event:deny-unlisten\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:default\"\n        },\n        {\n          \"description\": \"Enables the from_bytes command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:allow-from-bytes\"\n        },\n        {\n          \"description\": \"Enables the from_path command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:allow-from-path\"\n        },\n        {\n          \"description\": \"Enables the new command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:allow-new\"\n        },\n        {\n          \"description\": \"Enables the rgba command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:allow-rgba\"\n        },\n        {\n          \"description\": \"Enables the size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:allow-size\"\n        },\n        {\n          \"description\": \"Denies the from_bytes command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:deny-from-bytes\"\n        },\n        {\n          \"description\": \"Denies the from_path command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:deny-from-path\"\n        },\n        {\n          \"description\": \"Denies the new command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:deny-new\"\n        },\n        {\n          \"description\": \"Denies the rgba command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:deny-rgba\"\n        },\n        {\n          \"description\": \"Denies the size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:image:deny-size\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:default\"\n        },\n        {\n          \"description\": \"Enables the append command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-append\"\n        },\n        {\n          \"description\": \"Enables the create_default command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-create-default\"\n        },\n        {\n          \"description\": \"Enables the get command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-get\"\n        },\n        {\n          \"description\": \"Enables the insert command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-insert\"\n        },\n        {\n          \"description\": \"Enables the is_checked command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-is-checked\"\n        },\n        {\n          \"description\": \"Enables the is_enabled command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-is-enabled\"\n        },\n        {\n          \"description\": \"Enables the items command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-items\"\n        },\n        {\n          \"description\": \"Enables the new command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-new\"\n        },\n        {\n          \"description\": \"Enables the popup command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-popup\"\n        },\n        {\n          \"description\": \"Enables the prepend command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-prepend\"\n        },\n        {\n          \"description\": \"Enables the remove command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-remove\"\n        },\n        {\n          \"description\": \"Enables the remove_at command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-remove-at\"\n        },\n        {\n          \"description\": \"Enables the set_accelerator command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-accelerator\"\n        },\n        {\n          \"description\": \"Enables the set_as_app_menu command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-as-app-menu\"\n        },\n        {\n          \"description\": \"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-as-help-menu-for-nsapp\"\n        },\n        {\n          \"description\": \"Enables the set_as_window_menu command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-as-window-menu\"\n        },\n        {\n          \"description\": \"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-as-windows-menu-for-nsapp\"\n        },\n        {\n          \"description\": \"Enables the set_checked command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-checked\"\n        },\n        {\n          \"description\": \"Enables the set_enabled command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-enabled\"\n        },\n        {\n          \"description\": \"Enables the set_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-icon\"\n        },\n        {\n          \"description\": \"Enables the set_text command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-set-text\"\n        },\n        {\n          \"description\": \"Enables the text command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:allow-text\"\n        },\n        {\n          \"description\": \"Denies the append command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-append\"\n        },\n        {\n          \"description\": \"Denies the create_default command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-create-default\"\n        },\n        {\n          \"description\": \"Denies the get command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-get\"\n        },\n        {\n          \"description\": \"Denies the insert command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-insert\"\n        },\n        {\n          \"description\": \"Denies the is_checked command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-is-checked\"\n        },\n        {\n          \"description\": \"Denies the is_enabled command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-is-enabled\"\n        },\n        {\n          \"description\": \"Denies the items command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-items\"\n        },\n        {\n          \"description\": \"Denies the new command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-new\"\n        },\n        {\n          \"description\": \"Denies the popup command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-popup\"\n        },\n        {\n          \"description\": \"Denies the prepend command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-prepend\"\n        },\n        {\n          \"description\": \"Denies the remove command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-remove\"\n        },\n        {\n          \"description\": \"Denies the remove_at command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-remove-at\"\n        },\n        {\n          \"description\": \"Denies the set_accelerator command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-accelerator\"\n        },\n        {\n          \"description\": \"Denies the set_as_app_menu command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-as-app-menu\"\n        },\n        {\n          \"description\": \"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-as-help-menu-for-nsapp\"\n        },\n        {\n          \"description\": \"Denies the set_as_window_menu command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-as-window-menu\"\n        },\n        {\n          \"description\": \"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-as-windows-menu-for-nsapp\"\n        },\n        {\n          \"description\": \"Denies the set_checked command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-checked\"\n        },\n        {\n          \"description\": \"Denies the set_enabled command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-enabled\"\n        },\n        {\n          \"description\": \"Denies the set_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-icon\"\n        },\n        {\n          \"description\": \"Denies the set_text command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-set-text\"\n        },\n        {\n          \"description\": \"Denies the text command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:menu:deny-text\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:default\"\n        },\n        {\n          \"description\": \"Enables the basename command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-basename\"\n        },\n        {\n          \"description\": \"Enables the dirname command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-dirname\"\n        },\n        {\n          \"description\": \"Enables the extname command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-extname\"\n        },\n        {\n          \"description\": \"Enables the is_absolute command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-is-absolute\"\n        },\n        {\n          \"description\": \"Enables the join command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-join\"\n        },\n        {\n          \"description\": \"Enables the normalize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-normalize\"\n        },\n        {\n          \"description\": \"Enables the resolve command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-resolve\"\n        },\n        {\n          \"description\": \"Enables the resolve_directory command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:allow-resolve-directory\"\n        },\n        {\n          \"description\": \"Denies the basename command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-basename\"\n        },\n        {\n          \"description\": \"Denies the dirname command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-dirname\"\n        },\n        {\n          \"description\": \"Denies the extname command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-extname\"\n        },\n        {\n          \"description\": \"Denies the is_absolute command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-is-absolute\"\n        },\n        {\n          \"description\": \"Denies the join command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-join\"\n        },\n        {\n          \"description\": \"Denies the normalize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-normalize\"\n        },\n        {\n          \"description\": \"Denies the resolve command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-resolve\"\n        },\n        {\n          \"description\": \"Denies the resolve_directory command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:path:deny-resolve-directory\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:resources:default\"\n        },\n        {\n          \"description\": \"Enables the close command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:resources:allow-close\"\n        },\n        {\n          \"description\": \"Denies the close command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:resources:deny-close\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:default\"\n        },\n        {\n          \"description\": \"Enables the get_by_id command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-get-by-id\"\n        },\n        {\n          \"description\": \"Enables the new command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-new\"\n        },\n        {\n          \"description\": \"Enables the remove_by_id command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-remove-by-id\"\n        },\n        {\n          \"description\": \"Enables the set_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-icon\"\n        },\n        {\n          \"description\": \"Enables the set_icon_as_template command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-icon-as-template\"\n        },\n        {\n          \"description\": \"Enables the set_menu command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-menu\"\n        },\n        {\n          \"description\": \"Enables the set_show_menu_on_left_click command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-show-menu-on-left-click\"\n        },\n        {\n          \"description\": \"Enables the set_temp_dir_path command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-temp-dir-path\"\n        },\n        {\n          \"description\": \"Enables the set_title command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-title\"\n        },\n        {\n          \"description\": \"Enables the set_tooltip command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-tooltip\"\n        },\n        {\n          \"description\": \"Enables the set_visible command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:allow-set-visible\"\n        },\n        {\n          \"description\": \"Denies the get_by_id command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-get-by-id\"\n        },\n        {\n          \"description\": \"Denies the new command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-new\"\n        },\n        {\n          \"description\": \"Denies the remove_by_id command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-remove-by-id\"\n        },\n        {\n          \"description\": \"Denies the set_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-icon\"\n        },\n        {\n          \"description\": \"Denies the set_icon_as_template command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-icon-as-template\"\n        },\n        {\n          \"description\": \"Denies the set_menu command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-menu\"\n        },\n        {\n          \"description\": \"Denies the set_show_menu_on_left_click command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-show-menu-on-left-click\"\n        },\n        {\n          \"description\": \"Denies the set_temp_dir_path command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-temp-dir-path\"\n        },\n        {\n          \"description\": \"Denies the set_title command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-title\"\n        },\n        {\n          \"description\": \"Denies the set_tooltip command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-tooltip\"\n        },\n        {\n          \"description\": \"Denies the set_visible command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:tray:deny-set-visible\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:default\"\n        },\n        {\n          \"description\": \"Enables the create_webview command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-create-webview\"\n        },\n        {\n          \"description\": \"Enables the create_webview_window command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-create-webview-window\"\n        },\n        {\n          \"description\": \"Enables the get_all_webviews command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-get-all-webviews\"\n        },\n        {\n          \"description\": \"Enables the internal_toggle_devtools command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-internal-toggle-devtools\"\n        },\n        {\n          \"description\": \"Enables the print command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-print\"\n        },\n        {\n          \"description\": \"Enables the reparent command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-reparent\"\n        },\n        {\n          \"description\": \"Enables the set_webview_focus command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-set-webview-focus\"\n        },\n        {\n          \"description\": \"Enables the set_webview_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-set-webview-position\"\n        },\n        {\n          \"description\": \"Enables the set_webview_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-set-webview-size\"\n        },\n        {\n          \"description\": \"Enables the set_webview_zoom command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-set-webview-zoom\"\n        },\n        {\n          \"description\": \"Enables the webview_close command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-webview-close\"\n        },\n        {\n          \"description\": \"Enables the webview_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-webview-position\"\n        },\n        {\n          \"description\": \"Enables the webview_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:allow-webview-size\"\n        },\n        {\n          \"description\": \"Denies the create_webview command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-create-webview\"\n        },\n        {\n          \"description\": \"Denies the create_webview_window command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-create-webview-window\"\n        },\n        {\n          \"description\": \"Denies the get_all_webviews command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-get-all-webviews\"\n        },\n        {\n          \"description\": \"Denies the internal_toggle_devtools command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-internal-toggle-devtools\"\n        },\n        {\n          \"description\": \"Denies the print command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-print\"\n        },\n        {\n          \"description\": \"Denies the reparent command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-reparent\"\n        },\n        {\n          \"description\": \"Denies the set_webview_focus command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-set-webview-focus\"\n        },\n        {\n          \"description\": \"Denies the set_webview_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-set-webview-position\"\n        },\n        {\n          \"description\": \"Denies the set_webview_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-set-webview-size\"\n        },\n        {\n          \"description\": \"Denies the set_webview_zoom command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-set-webview-zoom\"\n        },\n        {\n          \"description\": \"Denies the webview_close command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-webview-close\"\n        },\n        {\n          \"description\": \"Denies the webview_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-webview-position\"\n        },\n        {\n          \"description\": \"Denies the webview_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:webview:deny-webview-size\"\n        },\n        {\n          \"description\": \"Default permissions for the plugin.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:default\"\n        },\n        {\n          \"description\": \"Enables the available_monitors command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-available-monitors\"\n        },\n        {\n          \"description\": \"Enables the center command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-center\"\n        },\n        {\n          \"description\": \"Enables the close command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-close\"\n        },\n        {\n          \"description\": \"Enables the create command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-create\"\n        },\n        {\n          \"description\": \"Enables the current_monitor command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-current-monitor\"\n        },\n        {\n          \"description\": \"Enables the cursor_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-cursor-position\"\n        },\n        {\n          \"description\": \"Enables the destroy command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-destroy\"\n        },\n        {\n          \"description\": \"Enables the get_all_windows command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-get-all-windows\"\n        },\n        {\n          \"description\": \"Enables the hide command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-hide\"\n        },\n        {\n          \"description\": \"Enables the inner_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-inner-position\"\n        },\n        {\n          \"description\": \"Enables the inner_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-inner-size\"\n        },\n        {\n          \"description\": \"Enables the internal_toggle_maximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-internal-toggle-maximize\"\n        },\n        {\n          \"description\": \"Enables the is_closable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-closable\"\n        },\n        {\n          \"description\": \"Enables the is_decorated command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-decorated\"\n        },\n        {\n          \"description\": \"Enables the is_focused command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-focused\"\n        },\n        {\n          \"description\": \"Enables the is_fullscreen command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-fullscreen\"\n        },\n        {\n          \"description\": \"Enables the is_maximizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-maximizable\"\n        },\n        {\n          \"description\": \"Enables the is_maximized command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-maximized\"\n        },\n        {\n          \"description\": \"Enables the is_minimizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-minimizable\"\n        },\n        {\n          \"description\": \"Enables the is_minimized command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-minimized\"\n        },\n        {\n          \"description\": \"Enables the is_resizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-resizable\"\n        },\n        {\n          \"description\": \"Enables the is_visible command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-is-visible\"\n        },\n        {\n          \"description\": \"Enables the maximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-maximize\"\n        },\n        {\n          \"description\": \"Enables the minimize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-minimize\"\n        },\n        {\n          \"description\": \"Enables the monitor_from_point command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-monitor-from-point\"\n        },\n        {\n          \"description\": \"Enables the outer_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-outer-position\"\n        },\n        {\n          \"description\": \"Enables the outer_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-outer-size\"\n        },\n        {\n          \"description\": \"Enables the primary_monitor command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-primary-monitor\"\n        },\n        {\n          \"description\": \"Enables the request_user_attention command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-request-user-attention\"\n        },\n        {\n          \"description\": \"Enables the scale_factor command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-scale-factor\"\n        },\n        {\n          \"description\": \"Enables the set_always_on_bottom command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-always-on-bottom\"\n        },\n        {\n          \"description\": \"Enables the set_always_on_top command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-always-on-top\"\n        },\n        {\n          \"description\": \"Enables the set_closable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-closable\"\n        },\n        {\n          \"description\": \"Enables the set_content_protected command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-content-protected\"\n        },\n        {\n          \"description\": \"Enables the set_cursor_grab command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-cursor-grab\"\n        },\n        {\n          \"description\": \"Enables the set_cursor_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-cursor-icon\"\n        },\n        {\n          \"description\": \"Enables the set_cursor_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-cursor-position\"\n        },\n        {\n          \"description\": \"Enables the set_cursor_visible command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-cursor-visible\"\n        },\n        {\n          \"description\": \"Enables the set_decorations command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-decorations\"\n        },\n        {\n          \"description\": \"Enables the set_effects command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-effects\"\n        },\n        {\n          \"description\": \"Enables the set_focus command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-focus\"\n        },\n        {\n          \"description\": \"Enables the set_fullscreen command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-fullscreen\"\n        },\n        {\n          \"description\": \"Enables the set_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-icon\"\n        },\n        {\n          \"description\": \"Enables the set_ignore_cursor_events command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-ignore-cursor-events\"\n        },\n        {\n          \"description\": \"Enables the set_max_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-max-size\"\n        },\n        {\n          \"description\": \"Enables the set_maximizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-maximizable\"\n        },\n        {\n          \"description\": \"Enables the set_min_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-min-size\"\n        },\n        {\n          \"description\": \"Enables the set_minimizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-minimizable\"\n        },\n        {\n          \"description\": \"Enables the set_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-position\"\n        },\n        {\n          \"description\": \"Enables the set_progress_bar command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-progress-bar\"\n        },\n        {\n          \"description\": \"Enables the set_resizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-resizable\"\n        },\n        {\n          \"description\": \"Enables the set_shadow command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-shadow\"\n        },\n        {\n          \"description\": \"Enables the set_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-size\"\n        },\n        {\n          \"description\": \"Enables the set_size_constraints command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-size-constraints\"\n        },\n        {\n          \"description\": \"Enables the set_skip_taskbar command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-skip-taskbar\"\n        },\n        {\n          \"description\": \"Enables the set_title command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-title\"\n        },\n        {\n          \"description\": \"Enables the set_title_bar_style command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-title-bar-style\"\n        },\n        {\n          \"description\": \"Enables the set_visible_on_all_workspaces command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-set-visible-on-all-workspaces\"\n        },\n        {\n          \"description\": \"Enables the show command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-show\"\n        },\n        {\n          \"description\": \"Enables the start_dragging command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-start-dragging\"\n        },\n        {\n          \"description\": \"Enables the start_resize_dragging command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-start-resize-dragging\"\n        },\n        {\n          \"description\": \"Enables the theme command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-theme\"\n        },\n        {\n          \"description\": \"Enables the title command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-title\"\n        },\n        {\n          \"description\": \"Enables the toggle_maximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-toggle-maximize\"\n        },\n        {\n          \"description\": \"Enables the unmaximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-unmaximize\"\n        },\n        {\n          \"description\": \"Enables the unminimize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:allow-unminimize\"\n        },\n        {\n          \"description\": \"Denies the available_monitors command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-available-monitors\"\n        },\n        {\n          \"description\": \"Denies the center command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-center\"\n        },\n        {\n          \"description\": \"Denies the close command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-close\"\n        },\n        {\n          \"description\": \"Denies the create command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-create\"\n        },\n        {\n          \"description\": \"Denies the current_monitor command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-current-monitor\"\n        },\n        {\n          \"description\": \"Denies the cursor_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-cursor-position\"\n        },\n        {\n          \"description\": \"Denies the destroy command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-destroy\"\n        },\n        {\n          \"description\": \"Denies the get_all_windows command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-get-all-windows\"\n        },\n        {\n          \"description\": \"Denies the hide command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-hide\"\n        },\n        {\n          \"description\": \"Denies the inner_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-inner-position\"\n        },\n        {\n          \"description\": \"Denies the inner_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-inner-size\"\n        },\n        {\n          \"description\": \"Denies the internal_toggle_maximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-internal-toggle-maximize\"\n        },\n        {\n          \"description\": \"Denies the is_closable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-closable\"\n        },\n        {\n          \"description\": \"Denies the is_decorated command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-decorated\"\n        },\n        {\n          \"description\": \"Denies the is_focused command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-focused\"\n        },\n        {\n          \"description\": \"Denies the is_fullscreen command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-fullscreen\"\n        },\n        {\n          \"description\": \"Denies the is_maximizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-maximizable\"\n        },\n        {\n          \"description\": \"Denies the is_maximized command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-maximized\"\n        },\n        {\n          \"description\": \"Denies the is_minimizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-minimizable\"\n        },\n        {\n          \"description\": \"Denies the is_minimized command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-minimized\"\n        },\n        {\n          \"description\": \"Denies the is_resizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-resizable\"\n        },\n        {\n          \"description\": \"Denies the is_visible command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-is-visible\"\n        },\n        {\n          \"description\": \"Denies the maximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-maximize\"\n        },\n        {\n          \"description\": \"Denies the minimize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-minimize\"\n        },\n        {\n          \"description\": \"Denies the monitor_from_point command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-monitor-from-point\"\n        },\n        {\n          \"description\": \"Denies the outer_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-outer-position\"\n        },\n        {\n          \"description\": \"Denies the outer_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-outer-size\"\n        },\n        {\n          \"description\": \"Denies the primary_monitor command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-primary-monitor\"\n        },\n        {\n          \"description\": \"Denies the request_user_attention command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-request-user-attention\"\n        },\n        {\n          \"description\": \"Denies the scale_factor command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-scale-factor\"\n        },\n        {\n          \"description\": \"Denies the set_always_on_bottom command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-always-on-bottom\"\n        },\n        {\n          \"description\": \"Denies the set_always_on_top command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-always-on-top\"\n        },\n        {\n          \"description\": \"Denies the set_closable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-closable\"\n        },\n        {\n          \"description\": \"Denies the set_content_protected command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-content-protected\"\n        },\n        {\n          \"description\": \"Denies the set_cursor_grab command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-cursor-grab\"\n        },\n        {\n          \"description\": \"Denies the set_cursor_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-cursor-icon\"\n        },\n        {\n          \"description\": \"Denies the set_cursor_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-cursor-position\"\n        },\n        {\n          \"description\": \"Denies the set_cursor_visible command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-cursor-visible\"\n        },\n        {\n          \"description\": \"Denies the set_decorations command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-decorations\"\n        },\n        {\n          \"description\": \"Denies the set_effects command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-effects\"\n        },\n        {\n          \"description\": \"Denies the set_focus command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-focus\"\n        },\n        {\n          \"description\": \"Denies the set_fullscreen command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-fullscreen\"\n        },\n        {\n          \"description\": \"Denies the set_icon command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-icon\"\n        },\n        {\n          \"description\": \"Denies the set_ignore_cursor_events command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-ignore-cursor-events\"\n        },\n        {\n          \"description\": \"Denies the set_max_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-max-size\"\n        },\n        {\n          \"description\": \"Denies the set_maximizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-maximizable\"\n        },\n        {\n          \"description\": \"Denies the set_min_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-min-size\"\n        },\n        {\n          \"description\": \"Denies the set_minimizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-minimizable\"\n        },\n        {\n          \"description\": \"Denies the set_position command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-position\"\n        },\n        {\n          \"description\": \"Denies the set_progress_bar command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-progress-bar\"\n        },\n        {\n          \"description\": \"Denies the set_resizable command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-resizable\"\n        },\n        {\n          \"description\": \"Denies the set_shadow command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-shadow\"\n        },\n        {\n          \"description\": \"Denies the set_size command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-size\"\n        },\n        {\n          \"description\": \"Denies the set_size_constraints command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-size-constraints\"\n        },\n        {\n          \"description\": \"Denies the set_skip_taskbar command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-skip-taskbar\"\n        },\n        {\n          \"description\": \"Denies the set_title command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-title\"\n        },\n        {\n          \"description\": \"Denies the set_title_bar_style command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-title-bar-style\"\n        },\n        {\n          \"description\": \"Denies the set_visible_on_all_workspaces command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-set-visible-on-all-workspaces\"\n        },\n        {\n          \"description\": \"Denies the show command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-show\"\n        },\n        {\n          \"description\": \"Denies the start_dragging command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-start-dragging\"\n        },\n        {\n          \"description\": \"Denies the start_resize_dragging command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-start-resize-dragging\"\n        },\n        {\n          \"description\": \"Denies the theme command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-theme\"\n        },\n        {\n          \"description\": \"Denies the title command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-title\"\n        },\n        {\n          \"description\": \"Denies the toggle_maximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-toggle-maximize\"\n        },\n        {\n          \"description\": \"Denies the unmaximize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-unmaximize\"\n        },\n        {\n          \"description\": \"Denies the unminimize command without any pre-configured scope.\",\n          \"type\": \"string\",\n          \"const\": \"core:window:deny-unminimize\"\n        }\n      ]\n    },\n    \"Value\": {\n      \"description\": \"All supported ACL values.\",\n      \"anyOf\": [\n        {\n          \"description\": \"Represents a null JSON value.\",\n          \"type\": \"null\"\n        },\n        {\n          \"description\": \"Represents a [`bool`].\",\n          \"type\": \"boolean\"\n        },\n        {\n          \"description\": \"Represents a valid ACL [`Number`].\",\n          \"allOf\": [\n            {\n              \"$ref\": \"#/definitions/Number\"\n            }\n          ]\n        },\n        {\n          \"description\": \"Represents a [`String`].\",\n          \"type\": \"string\"\n        },\n        {\n          \"description\": \"Represents a list of other [`Value`]s.\",\n          \"type\": \"array\",\n          \"items\": {\n            \"$ref\": \"#/definitions/Value\"\n          }\n        },\n        {\n          \"description\": \"Represents a map of [`String`] keys to [`Value`]s.\",\n          \"type\": \"object\",\n          \"additionalProperties\": {\n            \"$ref\": \"#/definitions/Value\"\n          }\n        }\n      ]\n    },\n    \"Number\": {\n      \"description\": \"A valid ACL number.\",\n      \"anyOf\": [\n        {\n          \"description\": \"Represents an [`i64`].\",\n          \"type\": \"integer\",\n          \"format\": \"int64\"\n        },\n        {\n          \"description\": \"Represents a [`f64`].\",\n          \"type\": \"number\",\n          \"format\": \"double\"\n        }\n      ]\n    },\n    \"Target\": {\n      \"description\": \"Platform target.\",\n      \"oneOf\": [\n        {\n          \"description\": \"MacOS.\",\n          \"type\": \"string\",\n          \"enum\": [\n            \"macOS\"\n          ]\n        },\n        {\n          \"description\": \"Windows.\",\n          \"type\": \"string\",\n          \"enum\": [\n            \"windows\"\n          ]\n        },\n        {\n          \"description\": \"Linux.\",\n          \"type\": \"string\",\n          \"enum\": [\n            \"linux\"\n          ]\n        },\n        {\n          \"description\": \"Android.\",\n          \"type\": \"string\",\n          \"enum\": [\n            \"android\"\n          ]\n        },\n        {\n          \"description\": \"iOS.\",\n          \"type\": \"string\",\n          \"enum\": [\n            \"iOS\"\n          ]\n        }\n      ]\n    }\n  }\n}"
  },
  {
    "path": "src-tauri/src/main.rs",
    "content": "// Prevents additional console window on Windows in release, DO NOT REMOVE!!\n#![cfg_attr(not(debug_assertions), windows_subsystem = \"windows\")]\n\nuse tauri::Manager;\n\nfn main() {\n  tauri::Builder::default()\n    .setup(|app| {\n      #[cfg(debug_assertions)] // only include this code on debug builds\n      {\n        let window = app.get_webview_window(\"main\").unwrap();\n        window.open_devtools();\n        window.close_devtools();\n      }\n      Ok(())\n    })\n    .run(tauri::generate_context!())\n    .expect(\"error while running tauri application\");\n}\n"
  },
  {
    "path": "src-tauri/tauri.conf.json",
    "content": "{\n  \"build\": {\n    \"beforeBuildCommand\": \"bun run build\",\n    \"beforeDevCommand\": \"bun run --filter @snort/app start\",\n    \"frontendDist\": \"../packages/app/build\",\n    \"devUrl\": \"http://localhost:5173\"\n  },\n  \"bundle\": {\n    \"active\": true,\n    \"category\": \"DeveloperTool\",\n    \"copyright\": \"\",\n    \"targets\": \"all\",\n    \"externalBin\": [],\n    \"icon\": [\n      \"icons/128x128.png\",\n      \"icons/128x128@2x.png\"\n    ],\n    \"windows\": {\n      \"certificateThumbprint\": null,\n      \"digestAlgorithm\": \"sha256\",\n      \"timestampUrl\": \"\"\n    },\n    \"longDescription\": \"\",\n    \"macOS\": {\n      \"entitlements\": null,\n      \"exceptionDomain\": \"\",\n      \"frameworks\": [],\n      \"providerShortName\": null,\n      \"signingIdentity\": null\n    },\n    \"resources\": [],\n    \"shortDescription\": \"\",\n    \"linux\": {\n      \"deb\": {\n        \"depends\": []\n      }\n    }\n  },\n  \"productName\": \"snort\",\n  \"mainBinaryName\": \"snort\",\n  \"version\": \"0.2.0\",\n  \"identifier\": \"social.snort.app\",\n  \"plugins\": {},\n  \"app\": {\n    \"windows\": [\n      {\n        \"fullscreen\": false,\n        \"height\": 600,\n        \"resizable\": true,\n        \"title\": \"snort.social\",\n        \"width\": 800\n      }\n    ],\n    \"security\": {\n      \"csp\": \"script-src 'wasm-unsafe-eval'; connect-src ipc: http://ipc.localhost\"\n    }\n  }\n}"
  },
  {
    "path": "zapstore.yaml",
    "content": "# Source code repository\nrepository: https://github.com/v0l/snort\n\n# Match all APK artifacts (universal, arm64, armeabi-v7a, x86_64)\nmatch: \".*snort-.*\\\\.apk$\"\n\n# App metadata (from nap.yaml)\nname: Snort\nid: social.snort.app\ndescription: Nostr social client\nicon: https://snort.social/nostrich_256.png\nimages:\n  - https://snort.social/nostrich_512.png\n\n# License\nlicense: MIT\n\n# Tags\ntags:\n  - social\n  - twitter\n"
  }
]