feat: round 3 helpers — 1 new files
Universal: Auto Version Bump / Version Bump (push) Successful in 10s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 15s

This commit is contained in:
Jonathan Miller
2026-06-21 17:43:50 -05:00
parent 53d55dadea
commit 154fc1714e
@@ -0,0 +1,110 @@
<?php
namespace Moko\Plugin\System\MokoSuiteSupport\Helper;
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\Database\DatabaseInterface;
/**
* Webhook channel handler — Facebook, Instagram, WhatsApp inbound message processing.
*/
class WebhookChannelHelper
{
/**
* Process an inbound Facebook Messenger webhook.
*/
public static function handleFacebook(array $payload, string $appSecret): object
{
// Verify signature is done at controller level
$results = ['processed' => 0, 'errors' => 0];
foreach ($payload['entry'] ?? [] as $entry) {
foreach ($entry['messaging'] ?? [] as $event) {
if (!isset($event['message'])) {
continue;
}
$senderId = $event['sender']['id'] ?? '';
$messageText = $event['message']['text'] ?? '';
if (empty($senderId) || empty($messageText)) {
continue;
}
$conversationId = self::findOrCreateConversation($senderId, 'facebook');
ConversationHelper::sendMessage($conversationId, $messageText, 'visitor');
AgentHelper::autoAssign($conversationId);
$results['processed']++;
}
}
return (object) $results;
}
/**
* Process an inbound WhatsApp Cloud API webhook.
*/
public static function handleWhatsApp(array $payload): object
{
$results = ['processed' => 0, 'errors' => 0];
foreach ($payload['entry'] ?? [] as $entry) {
foreach ($entry['changes'] ?? [] as $change) {
$messages = $change['value']['messages'] ?? [];
foreach ($messages as $msg) {
$phone = $msg['from'] ?? '';
$text = $msg['text']['body'] ?? '';
if (empty($phone) || empty($text)) {
continue;
}
$conversationId = self::findOrCreateConversation($phone, 'whatsapp');
ConversationHelper::sendMessage($conversationId, $text, 'visitor');
AgentHelper::autoAssign($conversationId);
$results['processed']++;
}
}
}
return (object) $results;
}
/**
* Find existing open conversation for a channel ID, or create a new one.
*/
private static function findOrCreateConversation(string $channelUserId, string $channel): int
{
$db = Factory::getContainer()->get(DatabaseInterface::class);
$db->setQuery($db->getQuery(true)
->select('id')
->from('#__mokosuitesupport_conversations')
->where('channel_user_id = ' . $db->quote($channelUserId))
->where($db->quoteName('channel') . ' = ' . $db->quote($channel))
->where($db->quoteName('status') . ' IN (' . $db->quote('open') . ',' . $db->quote('assigned') . ')')
->order('started_at DESC'), 0, 1);
$existingId = (int) $db->loadResult();
if ($existingId) {
return $existingId;
}
$result = ConversationHelper::create($channel, null, $channelUserId);
$convId = $result->conversation_id;
// Store channel user ID
$db->setQuery($db->getQuery(true)
->update('#__mokosuitesupport_conversations')
->set('channel_user_id = ' . $db->quote($channelUserId))
->where('id = ' . (int) $convId));
$db->execute();
return $convId;
}
}