This commit adds comprehensive mobile app support to enable a native Android app that won't timeout or sleep when the screen goes dark.
New Features:
- JWT-based authentication system (no WordPress session dependency)
- REST API endpoints for mobile app (agent status, queue management, call control)
- Server-Sent Events (SSE) for real-time updates to mobile app
- Firebase Cloud Messaging (FCM) integration for push notifications
- Gitea-based automatic plugin updates
- Mobile app admin settings page
New Files:
- includes/class-twp-mobile-auth.php - JWT authentication with login/refresh/logout
- includes/class-twp-mobile-api.php - REST API endpoints under /twilio-mobile/v1
- includes/class-twp-mobile-sse.php - Real-time event streaming
- includes/class-twp-fcm.php - Push notification handling
- includes/class-twp-auto-updater.php - Gitea-based auto-updates
- admin/mobile-app-settings.php - Admin configuration page
Modified Files:
- includes/class-twp-activator.php - Added twp_mobile_sessions table
- includes/class-twp-core.php - Load and initialize mobile classes
- admin/class-twp-admin.php - Added Mobile App menu item and settings page
Database Changes:
- New table: twp_mobile_sessions (stores JWT refresh tokens and FCM tokens)
API Endpoints:
- POST /twilio-mobile/v1/auth/login
- POST /twilio-mobile/v1/auth/refresh
- POST /twilio-mobile/v1/auth/logout
- GET/POST /twilio-mobile/v1/agent/status
- GET /twilio-mobile/v1/queues/state
- POST /twilio-mobile/v1/calls/{call_sid}/accept
- GET /twilio-mobile/v1/stream/events (SSE)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
292 lines
10 KiB
PHP
292 lines
10 KiB
PHP
<?php
|
|
/**
|
|
* Automatic Plugin Updater
|
|
*
|
|
* Checks for updates from Gitea repository and installs them automatically
|
|
*/
|
|
class TWP_Auto_Updater {
|
|
|
|
private $plugin_slug = 'twilio-wp-plugin';
|
|
private $plugin_basename;
|
|
private $gitea_repo = 'wp-plugins/twilio-wp-plugin';
|
|
private $gitea_api_url;
|
|
private $current_version;
|
|
private $gitea_base_url = 'https://repo.anhonesthost.net';
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
public function __construct() {
|
|
$this->plugin_basename = plugin_basename(dirname(dirname(__FILE__)) . '/twilio-wp-plugin.php');
|
|
$this->current_version = defined('TWP_VERSION') ? TWP_VERSION : '0.0.0';
|
|
$this->gitea_api_url = $this->gitea_base_url . '/api/v1/repos/' . $this->gitea_repo . '/releases/latest';
|
|
}
|
|
|
|
/**
|
|
* Initialize updater hooks
|
|
*/
|
|
public function init() {
|
|
// Hook into WordPress update checks
|
|
add_filter('pre_set_site_transient_update_plugins', array($this, 'check_for_update'));
|
|
add_filter('plugins_api', array($this, 'plugin_info'), 10, 3);
|
|
|
|
// Add settings page for manual check
|
|
add_action('admin_init', array($this, 'register_settings'));
|
|
|
|
// Add update check to admin notices
|
|
if (get_option('twp_auto_update_enabled', '1') === '1') {
|
|
add_action('admin_init', array($this, 'maybe_auto_check_updates'));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Register auto-update settings
|
|
*/
|
|
public function register_settings() {
|
|
register_setting('twp_settings', 'twp_auto_update_enabled');
|
|
register_setting('twp_settings', 'twp_gitea_repo');
|
|
register_setting('twp_settings', 'twp_gitea_token'); // Optional for private repos
|
|
}
|
|
|
|
/**
|
|
* Check for updates periodically
|
|
*/
|
|
public function maybe_auto_check_updates() {
|
|
$last_check = get_option('twp_last_update_check', 0);
|
|
$check_interval = 12 * HOUR_IN_SECONDS; // Check every 12 hours
|
|
|
|
if (time() - $last_check > $check_interval) {
|
|
update_option('twp_last_update_check', time());
|
|
// Force WordPress to check for updates
|
|
wp_clean_plugins_cache();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check for plugin updates
|
|
*/
|
|
public function check_for_update($transient) {
|
|
if (empty($transient->checked)) {
|
|
return $transient;
|
|
}
|
|
|
|
// Get Gitea repo from settings if available
|
|
$custom_repo = get_option('twp_gitea_repo', '');
|
|
if (!empty($custom_repo)) {
|
|
$this->gitea_repo = $custom_repo;
|
|
$this->gitea_api_url = $this->gitea_base_url . '/api/v1/repos/' . $this->gitea_repo . '/releases/latest';
|
|
}
|
|
|
|
$update_info = $this->get_latest_release();
|
|
|
|
if ($update_info && version_compare($this->current_version, $update_info->version, '<')) {
|
|
$plugin_data = array(
|
|
'id' => 'twilio-wp-plugin',
|
|
'slug' => $this->plugin_slug,
|
|
'plugin' => $this->plugin_basename,
|
|
'new_version' => $update_info->version,
|
|
'url' => $update_info->homepage,
|
|
'package' => $update_info->download_url,
|
|
'tested' => '6.8',
|
|
'requires' => '5.8',
|
|
'requires_php' => '7.4',
|
|
'icons' => array(),
|
|
'banners' => array(),
|
|
'compatibility' => new stdClass(),
|
|
);
|
|
|
|
$transient->response[$this->plugin_basename] = (object) $plugin_data;
|
|
|
|
error_log("TWP Auto-Updater: New version {$update_info->version} available (current: {$this->current_version})");
|
|
} else {
|
|
error_log("TWP Auto-Updater: No updates available (current: {$this->current_version})");
|
|
}
|
|
|
|
return $transient;
|
|
}
|
|
|
|
/**
|
|
* Get plugin information for update screen
|
|
*/
|
|
public function plugin_info($false, $action, $args) {
|
|
if ($action !== 'plugin_information') {
|
|
return $false;
|
|
}
|
|
|
|
if (!isset($args->slug) || $args->slug !== $this->plugin_slug) {
|
|
return $false;
|
|
}
|
|
|
|
$update_info = $this->get_latest_release();
|
|
|
|
if (!$update_info) {
|
|
return $false;
|
|
}
|
|
|
|
$plugin_info = new stdClass();
|
|
$plugin_info->name = 'Twilio WP Plugin';
|
|
$plugin_info->slug = $this->plugin_slug;
|
|
$plugin_info->version = $update_info->version;
|
|
$plugin_info->author = '<a href="https://cybercove.io/">Joshua Knapp</a>';
|
|
$plugin_info->homepage = $update_info->homepage;
|
|
$plugin_info->download_link = $update_info->download_url;
|
|
$plugin_info->requires = '5.8';
|
|
$plugin_info->tested = '6.8';
|
|
$plugin_info->requires_php = '7.4';
|
|
$plugin_info->last_updated = $update_info->release_date;
|
|
$plugin_info->downloaded = 10;
|
|
|
|
$plugin_info->sections = array(
|
|
'description' => '<p>Twilio WordPress Plugin for call management and mobile app support.</p>',
|
|
'changelog' => '<pre>' . esc_html($update_info->changelog) . '</pre>',
|
|
'installation' => '<p>Upload the plugin to your WordPress site and activate it.</p>'
|
|
);
|
|
|
|
return $plugin_info;
|
|
}
|
|
|
|
/**
|
|
* Get latest release information from Gitea
|
|
*/
|
|
private function get_latest_release() {
|
|
// Check cache first (1 hour)
|
|
$cache_key = 'twp_latest_release';
|
|
$cached = get_transient($cache_key);
|
|
|
|
if ($cached !== false) {
|
|
return $cached;
|
|
}
|
|
|
|
// Use cURL for Gitea API
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $this->gitea_api_url);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: application/json'));
|
|
curl_setopt($ch, CURLOPT_USERAGENT, 'WordPress/Twilio-WP-Plugin-Updater');
|
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
|
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
|
|
|
|
// Add Gitea token if configured (for private repos)
|
|
$gitea_token = get_option('twp_gitea_token', '');
|
|
if (!empty($gitea_token)) {
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
|
|
'Accept: application/json',
|
|
'Authorization: token ' . $gitea_token
|
|
));
|
|
}
|
|
|
|
$response = curl_exec($ch);
|
|
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if (!$response || $http_code !== 200) {
|
|
error_log("TWP Auto-Updater: Gitea API returned status $http_code");
|
|
return false;
|
|
}
|
|
|
|
$release = json_decode($response);
|
|
|
|
if (!$release || !isset($release->tag_name)) {
|
|
error_log('TWP Auto-Updater: Invalid release data from Gitea');
|
|
return false;
|
|
}
|
|
|
|
// Parse release information
|
|
$version = ltrim($release->tag_name, 'v'); // Remove 'v' prefix if present
|
|
$download_url = null;
|
|
|
|
// Find the zip asset
|
|
if (isset($release->assets) && is_array($release->assets)) {
|
|
foreach ($release->assets as $asset) {
|
|
if (strpos($asset->name, '.zip') !== false) {
|
|
$download_url = $asset->browser_download_url;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fallback to zipball if no asset found
|
|
if (!$download_url) {
|
|
$download_url = $release->zipball_url;
|
|
}
|
|
|
|
// Format changelog
|
|
$changelog = !empty($release->body) ? $release->body : 'No changelog provided for this release.';
|
|
|
|
// Handle empty changelog
|
|
if (empty(trim($changelog))) {
|
|
$changelog = "Version " . $version . "\n\n" .
|
|
"Released on " . date('F j, Y', strtotime($release->published_at)) . "\n\n" .
|
|
"* Updated plugin files";
|
|
}
|
|
|
|
$update_info = (object) array(
|
|
'version' => $version,
|
|
'download_url' => $download_url,
|
|
'homepage' => $this->gitea_base_url . '/' . $this->gitea_repo,
|
|
'release_date' => $release->published_at,
|
|
'description' => $changelog,
|
|
'changelog' => $changelog
|
|
);
|
|
|
|
// Cache for 1 hour
|
|
set_transient($cache_key, $update_info, HOUR_IN_SECONDS);
|
|
|
|
return $update_info;
|
|
}
|
|
|
|
/**
|
|
* Manual update check (for admin page)
|
|
*/
|
|
public function manual_check_for_updates() {
|
|
// Clear cache
|
|
delete_transient('twp_latest_release');
|
|
update_option('twp_last_update_check', 0);
|
|
|
|
// Force WordPress to check
|
|
wp_clean_plugins_cache();
|
|
delete_site_transient('update_plugins');
|
|
|
|
$update_info = $this->get_latest_release();
|
|
|
|
if (!$update_info) {
|
|
return array(
|
|
'success' => false,
|
|
'message' => 'Failed to check for updates. Please check your internet connection and Gitea repository settings.'
|
|
);
|
|
}
|
|
|
|
if (version_compare($this->current_version, $update_info->version, '<')) {
|
|
return array(
|
|
'success' => true,
|
|
'update_available' => true,
|
|
'current_version' => $this->current_version,
|
|
'latest_version' => $update_info->version,
|
|
'message' => "Update available: Version {$update_info->version}. Go to Plugins page to update."
|
|
);
|
|
} else {
|
|
return array(
|
|
'success' => true,
|
|
'update_available' => false,
|
|
'current_version' => $this->current_version,
|
|
'message' => 'You are running the latest version.'
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get current update status
|
|
*/
|
|
public function get_update_status() {
|
|
$update_info = $this->get_latest_release();
|
|
|
|
return array(
|
|
'current_version' => $this->current_version,
|
|
'latest_version' => $update_info ? $update_info->version : 'Unknown',
|
|
'update_available' => $update_info && version_compare($this->current_version, $update_info->version, '<'),
|
|
'last_check' => get_option('twp_last_update_check', 0),
|
|
'auto_update_enabled' => get_option('twp_auto_update_enabled', '1') === '1'
|
|
);
|
|
}
|
|
}
|