195f3fa56d
One ID-keyed message ledger now handles sends and polls. Messages are always sorted by server ID, latest at bottom. Duplicate DOM rows and voice players are removed. Poll cursors advance only from validated received messages. Voice autoplay queues each received clip once. Added exact user_id ownership tracking. Cache-busted client to 20260609.4.
181 lines
7.4 KiB
Markdown
181 lines
7.4 KiB
Markdown
# CyberChat
|
|
|
|
CyberChat is a framework-free PHP, SQLite, JavaScript, and HTML5 chat application with configurable paid tiers, Stripe subscriptions, Mailgun email verification, 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
|
|
- 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
|
|
- Single-worker queued polling with cursor catch-up, request timeouts, deduplication, bounded retry backoff, and a capped browser message buffer
|
|
- 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:
|
|
|
|
```bash
|
|
chmod 0777 db archive uploads/voice
|
|
```
|
|
|
|
For a managed server, ownership is preferable:
|
|
|
|
```bash
|
|
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 |
|
|
|---|---:|---:|---:|
|
|
| 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 |
|
|
|
|
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**.
|
|
|
|
## 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:
|
|
|
|
- <https://docs.stripe.com/api/checkout/sessions/create>
|
|
- <https://docs.stripe.com/webhooks>
|
|
|
|
## 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
|
|
|
|
```html
|
|
<link rel="stylesheet" href="/chat/assets/css/cyberchat.css?v=20260609.3">
|
|
<div id="my-chat" style="width:100%;height:600px"></div>
|
|
<script>
|
|
window.CYBERCHAT_BASE = '/chat';
|
|
</script>
|
|
<script src="/chat/assets/js/cyberchat-app.js?v=20260609.4"></script>
|
|
<script>
|
|
CyberChat.init('#my-chat');
|
|
</script>
|
|
```
|
|
|
|
See `embed-example.html` for a complete example.
|
|
|
|
## Main Files
|
|
|
|
```text
|
|
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/messages.php Text, voice, polling, and recording presence
|
|
api/stripe-webhook.php Stripe event synchronization
|
|
assets/js/cyberchat-app.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.
|