Files
chat/README.md
T
Ty Clifford ef7a9a330f -
Fixed polling after voice/text sends.

Changes include:

Stalled polls abort and retry automatically.
Polling now schedules after each completed request.
Local sends no longer advance the server cursor and skip interleaved 
messages.
Sends trigger immediate reconciliation.
API requests bypass browser caches.
2026-06-08 17:25:49 -04:00

8.1 KiB

CyberChat

CyberChat is a framework-free PHP, SQLite, JavaScript, and HTML5 chat application with configurable paid tiers, Stripe subscriptions, Mailgun email verification, private groups, voice messages, personal archives, an administrator dashboard, and an optional MySQL/MariaDB mirror.

Included Features

  • Registration without an email address
  • Verified email required before premium checkout
  • Mailgun email verification and email two-factor login codes
  • Stripe Checkout, Billing Portal, webhook synchronization, and cancellation
  • Configurable plans, prices, Stripe Price IDs, limits, and feature assignments
  • Subscription display switch that hides new sales while preserving billing management for existing customers
  • Globally configurable private groups with plan-based member limits, including the owner
  • Premium-configurable recording presence for both sending and viewing
  • Premium-configurable automatic voice sending
  • Tier-configurable automatic playback of newly received voice clips
  • Administrator tier overrides that grant plan features without payment
  • Resilient polling with stalled-request timeouts and post-send reconciliation
  • Plan-based custom username colors
  • Personal text archives retained for at least 30 days
  • Plan-based voice archive access and JSON/CSV exports
  • Visitor and feature usage statistics
  • SQLite by default, with optional automatic MySQL/MariaDB mirroring
  • Dark neon interface with a saved light-mode toggle

Requirements

  • PHP 8.1 or newer
  • PHP extensions: pdo_sqlite, curl, and fileinfo
  • A web server with HTTPS for production
  • Write access to db/, archive/, uploads/voice/, and config.json
  • A modern browser with MediaRecorder for voice recording
  • Optional: PDO MySQL for the MySQL/MariaDB mirror

Installation

  1. Place the application in the web root.
  2. Make the runtime directories and configuration writable by the web-server user.
  3. Configure Apache with the included .htaccess, or adapt nginx-example.conf.
  4. Open admin.php and sign in with the initial password changeme123.
  5. Immediately change admin.password in the Configuration tab.
  6. Open Plans & Platform to configure tiers, Mailgun, Stripe, and optional MySQL mirroring.

The SQLite schema and default Free, Plus, and Pro tiers are created automatically on first use.

For a simple shared-hosting deployment:

chmod 0777 db archive uploads/voice

For a managed server, ownership is preferable:

chown -R www-data:www-data db archive uploads/voice
chmod -R 0770 db archive uploads/voice

Replace www-data with the PHP-FPM or web-server account. SQLite must be able to create the database plus -wal and -shm sidecar files. When the application directory itself is restricted, database.main_db may be an absolute path to a writable persistent directory.

Default Tiers

The defaults are starting points and are fully editable in the dashboard.

Feature Free Plus Pro
Groups available Yes Yes Yes
Group members, including owner 2 4 8
Recording status send/view No Yes Yes
Automatic voice send No Yes Yes
Automatic voice play No Yes Yes
Custom username color No Yes Yes
Text archive 30 days 90 days 365 days
Text export Yes Yes Yes
Voice archive/export No Yes Yes
Email 2FA No Yes Yes

Each tier has an explicit Enable groups for this tier toggle and a separate Maximum People Per Group value. The minimum is two people, including the group owner; disabling groups uses the toggle rather than a numeric value of zero.

Administrators can assign a tier directly from Admin > Users > Edit > Tier Override. The override grants that tier's features without changing Stripe billing data and remains in effect until it is changed back to Follow Stripe / billing status.

Private groups can be enabled or disabled globally under Admin > Plans & Platform > Group Availability or Admin > Config > Feature Availability. Each tier also has a Groups Available entitlement. Disabling either control hides group navigation and channels and blocks group API access without deleting existing groups or messages.

Mailgun

Configure these fields under Admin > Plans & Platform:

  • API key
  • Sending domain
  • From address
  • API base, normally https://api.mailgun.net/v3
  • EU API base, when applicable: https://api.eu.mailgun.net/v3

The reusable mailer is in lib/mailer.php. It sends verification links and codes, limits verification attempts, and sends 2FA codes with a direct link to the authentication screen.

Mailgun API reference: https://documentation.mailgun.com/docs/mailgun/api-reference/send/mailgun/messages/post-v3--domain-name--messages

Stripe

  1. Create recurring Stripe Prices for the paid tiers.

  2. Enter each price_... ID in the matching dashboard plan.

  3. Enter the Stripe secret key and webhook signing secret.

  4. Add this webhook endpoint:

    https://YOUR-DOMAIN/YOUR-PATH/api/stripe-webhook.php

  5. Subscribe the endpoint to:

    • checkout.session.completed
    • customer.subscription.created
    • customer.subscription.updated
    • customer.subscription.deleted
    • invoice.paid
    • invoice.payment_failed

Checkout is rejected until the account has a verified email. Stripe customer and subscription IDs, status, current period end, cancellation state, and selected plan are synchronized into SQLite.

When subscriptions.enabled is off, plans and checkout are hidden from non-subscribers. Existing Stripe customers retain Billing Portal and cancellation access.

Stripe references:

Archives

The application archives daily messages into:

archive/{year}/{month}/{day}.sqlite

The public legacy archive browser now redirects to the authenticated My Archive view. Users can only query their own sent messages within their plan retention window. Free users receive text history only; voice history and voice export require the corresponding plan entitlements.

MySQL/MariaDB Mirror

SQLite remains the required primary database. The optional mirror imports the main database and all archive databases into sqlite_mirror_rows using:

  • source database path
  • source table
  • row key
  • JSON row data
  • synchronization time

Set a PDO MySQL DSN in the dashboard, enable the mirror, and optionally enable automatic import. A manual Run MySQL Mirror Now action is also available.

Embedding

<link rel="stylesheet" href="/chat/assets/css/cyberchat.css">
<div id="my-chat" style="width:100%;height:600px"></div>
<script>
  window.CYBERCHAT_BASE = '/chat';
</script>
<script src="/chat/assets/js/cyberchat-v4.js"></script>
<script>
  CyberChat.init('#my-chat');
</script>

See embed-example.html for a complete example.

Main Files

admin.php                    Administrator dashboard
bootstrap.php                Configuration, schema, auth, plans, archives, stats
config.json                  Runtime settings and service credentials
api/account.php              Email, color, and 2FA settings
api/archive.php              Private personal archive and export
api/auth.php                 Registration, login, 2FA, sessions
api/billing.php              Stripe checkout, portal, and cancellation
api/groups.php               Private group management
api/messages.php             Text, voice, polling, and recording presence
api/stripe-webhook.php       Stripe event synchronization
assets/js/cyberchat-v4.js    Browser application
lib/mailer.php               Reusable Mailgun sender
lib/stripe.php               Stripe REST client and subscription sync
lib/mysql_mirror.php         Optional SQLite-to-MySQL mirror

Production Security

  • Change the default administrator password and statistics salt.
  • Serve the application only over HTTPS.
  • Keep .htaccess rules enabled or reproduce all deny rules in the web-server configuration.
  • Never expose config.json, db/, archive/, or lib/.
  • Use separate Stripe test and live webhook secrets.
  • Restrict admin.php by IP or additional HTTP authentication where practical.
  • Back up SQLite databases and voice files together.