- Voice enhancements, user management, payment method
This commit is contained in:
@@ -1,143 +1,179 @@
|
||||
# CYBERCHAT v2.0
|
||||
# CyberChat
|
||||
|
||||
A self-contained, embed-ready real-time web chat built with **PHP, JavaScript, HTML5, and SQLite**. No external dependencies beyond PHP 8.0+.
|
||||
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
|
||||
|
||||
## Features
|
||||
|
||||
- **Register on the fly** — pick a callsign (username) and passphrase, start chatting instantly
|
||||
- **Session-locked** — one login per user enforced by IP + cookie; no multi-location sessions
|
||||
- **Daily chat rooms** — each day starts fresh; yesterday's messages are automatically archived
|
||||
- **SQLite archives** — stored per `archive/{year}/{month}/{day}.sqlite`; browseable via `archive-viewer.php`
|
||||
- **Neon cyberpunk UI** — dark by default, light mode toggle per user (saved to localStorage)
|
||||
- **Embed-ready** — drop into any `<div>` container; auto-adapts to any size
|
||||
- **Fully configurable** — `config.json` controls all limits, intervals, and theming
|
||||
- **Voice clips** — record, review, send, and queue WAV/WebM clips one at a time using normal PHP polling
|
||||
- **No Node.js or WebSockets** — voice uses browser recording, HTTP uploads, and the existing poll loop
|
||||
|
||||
---
|
||||
- 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
|
||||
- Private groups with plan-based member limits, including the owner
|
||||
- Premium-configurable recording presence for both sending and viewing
|
||||
- Premium-configurable automatic voice sending
|
||||
- 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.0+ with **PDO SQLite** extension enabled
|
||||
- Any web server (Apache, Nginx, Caddy, PHP built-in)
|
||||
- Write permissions on `db/`, `archive/`, and `uploads/voice/` directories
|
||||
- PHP/web-server upload limits at or above `voice.max_upload_bytes`
|
||||
- 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
|
||||
|
||||
## Quick Start
|
||||
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
|
||||
# 1. Copy files to your web root (or a subdirectory)
|
||||
cp -r cyberchat/ /var/www/html/chat/
|
||||
|
||||
# 2. Make sure database, archive, and voice storage are writable
|
||||
chmod 755 /var/www/html/chat/db/
|
||||
chmod 755 /var/www/html/chat/archive/
|
||||
chmod 755 /var/www/html/chat/uploads/voice/
|
||||
|
||||
# 3. Visit in browser
|
||||
# http://yourdomain.com/chat/
|
||||
chmod 0777 db archive uploads/voice
|
||||
```
|
||||
|
||||
The SQLite database is created automatically on first visit.
|
||||
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
|
||||
```
|
||||
|
||||
## Embed in Your Own Page
|
||||
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 |
|
||||
|---|---:|---:|---:|
|
||||
| Group members, including owner | 2 | 4 | 8 |
|
||||
| Recording status send/view | No | Yes | Yes |
|
||||
| Automatic voice send | 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 can independently configure its price, currency, billing interval, Stripe Price ID, active status, sort order, archive retention, group limit, and every feature entitlement.
|
||||
|
||||
## 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
|
||||
<!-- Fonts -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=Rajdhani:wght@400;600;700&family=Orbitron:wght@700;900&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Stylesheet -->
|
||||
<link rel="stylesheet" href="/chat/assets/css/cyberchat.css">
|
||||
|
||||
<!-- Container — set any size -->
|
||||
<div id="my-chat" style="width:100%; height:600px;"></div>
|
||||
|
||||
<!-- Script -->
|
||||
<script src="/chat/assets/js/cyberchat.js"></script>
|
||||
<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>
|
||||
window.CYBERCHAT_BASE = '/chat'; // path to your cyberchat install
|
||||
CyberChat.init('#my-chat');
|
||||
</script>
|
||||
```
|
||||
|
||||
See `embed-example.html` for a live demo.
|
||||
See `embed-example.html` for a complete example.
|
||||
|
||||
---
|
||||
## Main Files
|
||||
|
||||
## Configuration — `config.json`
|
||||
|
||||
| Key | Default | Description |
|
||||
|-----|---------|-------------|
|
||||
| `chat.max_message_length` | 500 | Max characters per message |
|
||||
| `chat.max_username_length` | 12 | Max callsign length |
|
||||
| `chat.poll_interval_ms` | 2000 | How often client polls for new messages (ms) |
|
||||
| `chat.messages_per_page` | 100 | Messages loaded on initial connect |
|
||||
| `chat.session_lock_ip` | true | Enforce single login per IP |
|
||||
| `chat.session_lock_cookie` | true | Enforce single login per cookie |
|
||||
| `voice.enabled` | true | Enable voice clip controls and uploads |
|
||||
| `voice.max_duration_seconds` | 60 | Maximum voice clip duration |
|
||||
| `voice.max_upload_bytes` | 12582912 | Maximum voice upload size |
|
||||
| `voice.auto_play_default` | true | Queue and play new incoming clips one at a time by default |
|
||||
| `voice.upload_dir` | "uploads/voice" | Voice recording storage path |
|
||||
| `security.min_password_length` | 4 | Minimum passphrase length |
|
||||
| `security.session_timeout_hours` | 24 | Session expiry |
|
||||
| `security.bcrypt_cost` | 10 | bcrypt work factor for passwords |
|
||||
| `ui.default_theme` | "dark" | Default theme (`dark` or `light`) |
|
||||
| `ui.app_title` | "CYBERCHAT" | Title shown in header |
|
||||
| `ui.app_subtitle` | "v3.0 // SECURE CHANNEL" | Subtitle shown in header |
|
||||
| `colors.user_palette` | [...] | Array of hex colors assigned randomly to users |
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
cyberchat/
|
||||
├── index.html ← Main chat page
|
||||
├── embed-example.html ← Embed usage example
|
||||
├── archive-viewer.php ← Browse archived days
|
||||
├── bootstrap.php ← DB init, helpers, session auth
|
||||
├── config.json ← All configuration
|
||||
├── api/
|
||||
│ ├── auth.php ← Register / Login / Logout / Check
|
||||
│ ├── messages.php ← Send / Poll / History
|
||||
│ └── config.php ← Serves safe config to frontend
|
||||
├── assets/
|
||||
│ ├── css/cyberchat.css ← Full cyberpunk stylesheet
|
||||
│ └── js/cyberchat.js ← Chat client (no framework)
|
||||
├── db/
|
||||
│ └── chat.sqlite ← Created automatically; today's messages
|
||||
├── uploads/
|
||||
│ └── voice/ ← WAV/WebM voice recordings
|
||||
└── archive/
|
||||
└── {year}/{month}/ ← Auto-archived per day as .sqlite files
|
||||
└── {day}.sqlite
|
||||
```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/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
|
||||
|
||||
## Archive Viewer
|
||||
|
||||
Visit `archive-viewer.php` to browse historical chat logs. Select a day from the sidebar to read its messages.
|
||||
|
||||
---
|
||||
|
||||
## Nginx Config Example
|
||||
|
||||
See `nginx-example.conf` for a ready-to-use virtual host config.
|
||||
|
||||
---
|
||||
|
||||
## Security Notes
|
||||
|
||||
- Passwords are hashed with **bcrypt** (configurable cost factor)
|
||||
- Session tokens are 64-char cryptographically random hex strings
|
||||
- Session cookies are `HttpOnly`, `SameSite=Strict`, and `Secure` when served over HTTPS
|
||||
- All user input is escaped on output; no raw HTML accepted
|
||||
- Single-login enforcement via IP + cookie prevents session sharing
|
||||
- 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.
|
||||
|
||||
Reference in New Issue
Block a user