Compare commits

...

2 Commits

Author SHA1 Message Date
gitea-actions[bot] 2080375343 chore(version): auto-bump patch 01.08.18-dev [skip ci] 2026-06-28 01:49:49 +00:00
jmiller 8e748c2072 feat: add Twitter thread support and cost warning (#163)
Universal: Auto Version Bump / Version Bump (push) Successful in 9s
Universal: PR Check / Branch Policy (pull_request) Successful in 2s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Universal: PR Check / Secret Scan (pull_request) Successful in 8s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 30s
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Authored-by: Moko Consulting
2026-06-27 20:48:22 -05:00
52 changed files with 258 additions and 85 deletions
+1 -1
View File
@@ -5,7 +5,7 @@
# FILE INFORMATION
# DEFGROUP: Gitea.Workflow
# INGROUP: mokocli.Automation
# VERSION: 01.08.17
# VERSION: 01.08.18
# BRIEF: Auto-create feature branch when an issue is opened
name: "Universal: Issue Branch"
+4 -1
View File
@@ -2,6 +2,9 @@
## [Unreleased]
### Added
- **X/Twitter threads**: Auto-split messages exceeding 280 chars into reply chains at sentence boundaries
- **X/Twitter cost-optimized posting**: Optional mode to post text-only tweet first ($0.015) with URL as separate reply ($0.20)
- **X/Twitter cost warning**: Language string documenting X API pricing for text vs URL posts
- **Instagram carousel**: Multi-image/video posts via Meta carousel container flow (up to 10 items)
- **Instagram Reels**: Short-form video publishing via REELS media type
- **Instagram Stories**: Image and video story publishing via STORIES media type
@@ -82,7 +85,7 @@
## [01.03.00] --- 2026-06-21
<!-- VERSION: 01.08.17 -->
<!-- VERSION: 01.08.18 -->
All notable changes to MokoSuiteCross will be documented in this file.
+1 -1
View File
@@ -1,6 +1,6 @@
# MokoSuiteCross
<!-- VERSION: 01.08.17 -->
<!-- VERSION: 01.08.18 -->
Cross-posting Joomla content to social media, email marketing, and chat platforms for Joomla 5/6.
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="component" method="upgrade">
<name>com_mokosuitecross</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -0,0 +1 @@
/* 01.08.18 — no schema changes */
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="content" method="upgrade">
<name>Content - MokoSuiteCross</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - ActivityPub (Fediverse)</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Google Blogger</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Bluesky</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Brevo (Sendinblue)</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Constant Contact</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - ConvertKit</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Dev.to</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Discord</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Facebook / Meta</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Ghost</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Google Business Profile</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Google Chat</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Hashnode</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Instagram</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-06-23</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - LinkedIn</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Mailchimp</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Mastodon</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Matrix / Element</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Medium</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - MokoSuiteCalendar Events</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - MokoSuiteGallery</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Nostr</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Ntfy Push Notifications</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Pinterest</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Reddit</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - RSS Feed</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - SendGrid</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Slack</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Microsoft Teams</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Telegram</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Threads (Meta)</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - TikTok</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Tumblr</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,2 +1,3 @@
PLG_MOKOSUITECROSS_TWITTER="MokoSuiteCross - X / Twitter"
PLG_MOKOSUITECROSS_TWITTER_DESCRIPTION="Cross-post Joomla articles to X / Twitter."
PLG_MOKOSUITECROSS_TWITTER_COST_WARNING="X API Pricing: Text-only posts cost $0.015 each. Posts containing URLs cost $0.20 each. Cross-posting articles with links will incur URL post charges."
@@ -51,9 +51,6 @@ class TwitterService extends CMSPlugin implements SubscriberInterface, MokoSuite
public function publish(string $message, array $media, array $credentials, array $params): array
{
$apiUrl = 'https://api.twitter.com/2/tweets';
$postData = json_encode(['text' => mb_substr($message, 0, 280)]);
$consumerKey = $credentials['api_key'] ?? '';
$consumerSecret = $credentials['api_secret'] ?? '';
$accessToken = $credentials['access_token'] ?? '';
@@ -67,41 +64,17 @@ class TwitterService extends CMSPlugin implements SubscriberInterface, MokoSuite
];
}
$authHeader = $this->buildOAuth1Header('POST', $apiUrl, $consumerKey, $consumerSecret, $accessToken, $tokenSecret);
$ch = curl_init($apiUrl);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postData,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: ' . $authHeader,
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($ch);
if ($response === false) {
$curlError = curl_error($ch);
curl_close($ch);
return ['success' => false, 'platform_post_id' => '', 'response' => ['error' => 'Connection error: ' . $curlError]];
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true) ?: [];
if ($httpCode === 201 && !empty($data['data']['id'])) {
return ['success' => true, 'platform_post_id' => $data['data']['id'], 'response' => $data];
if (!empty($params['cost_optimize'])) {
return $this->publishCostOptimized($message, $credentials, $consumerKey, $consumerSecret, $accessToken, $tokenSecret);
}
return ['success' => false, 'platform_post_id' => '', 'response' => $data];
$chunks = $this->splitIntoThread($message);
if (\count($chunks) === 1) {
return $this->postTweet($chunks[0], null, $consumerKey, $consumerSecret, $accessToken, $tokenSecret);
}
return $this->postThread($chunks, $consumerKey, $consumerSecret, $accessToken, $tokenSecret);
}
public function validateCredentials(array $credentials): array
@@ -158,6 +131,201 @@ class TwitterService extends CMSPlugin implements SubscriberInterface, MokoSuite
return true;
}
private function splitIntoThread(string $message, int $maxLen = 280): array
{
if (mb_strlen($message) <= $maxLen) {
return [$message];
}
$chunks = [];
while (mb_strlen($message) > $maxLen) {
$segment = mb_substr($message, 0, $maxLen);
$splitPos = false;
foreach (['. ', '! ', '? '] as $delimiter) {
$pos = mb_strrpos($segment, $delimiter);
if ($pos !== false && ($splitPos === false || $pos > $splitPos)) {
$splitPos = $pos + mb_strlen($delimiter) - 1;
}
}
if ($splitPos === false || $splitPos < 1) {
$splitPos = mb_strrpos($segment, ' ');
}
if ($splitPos === false || $splitPos < 1) {
$splitPos = $maxLen;
}
$chunks[] = trim(mb_substr($message, 0, $splitPos));
$message = trim(mb_substr($message, $splitPos));
}
if ($message !== '') {
$chunks[] = $message;
}
return $chunks;
}
private function postTweet(
string $text,
?string $replyToId,
string $consumerKey,
string $consumerSecret,
string $accessToken,
string $tokenSecret
): array {
$apiUrl = 'https://api.twitter.com/2/tweets';
$body = ['text' => $text];
if ($replyToId !== null) {
$body['reply'] = ['in_reply_to_tweet_id' => $replyToId];
}
$postData = json_encode($body);
$authHeader = $this->buildOAuth1Header('POST', $apiUrl, $consumerKey, $consumerSecret, $accessToken, $tokenSecret);
$ch = curl_init($apiUrl);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $postData,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: ' . $authHeader,
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($ch);
if ($response === false) {
$curlError = curl_error($ch);
curl_close($ch);
return ['success' => false, 'platform_post_id' => '', 'response' => ['error' => 'Connection error: ' . $curlError]];
}
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true) ?: [];
if ($httpCode === 201 && !empty($data['data']['id'])) {
return ['success' => true, 'platform_post_id' => $data['data']['id'], 'response' => $data];
}
return ['success' => false, 'platform_post_id' => '', 'response' => $data];
}
private function postThread(
array $chunks,
string $consumerKey,
string $consumerSecret,
string $accessToken,
string $tokenSecret
): array {
$firstResult = $this->postTweet($chunks[0], null, $consumerKey, $consumerSecret, $accessToken, $tokenSecret);
if (!$firstResult['success']) {
return $firstResult;
}
$rootId = $firstResult['platform_post_id'];
$previousId = $rootId;
for ($i = 1, $count = \count($chunks); $i < $count; $i++) {
$result = $this->postTweet($chunks[$i], $previousId, $consumerKey, $consumerSecret, $accessToken, $tokenSecret);
if (!$result['success']) {
return [
'success' => false,
'platform_post_id' => $rootId,
'response' => [
'error' => 'Thread failed at tweet ' . ($i + 1) . ' of ' . $count,
'root_tweet' => $rootId,
'failed_tweet' => $result['response'],
],
];
}
$previousId = $result['platform_post_id'];
}
return ['success' => true, 'platform_post_id' => $rootId, 'response' => $firstResult['response']];
}
private function publishCostOptimized(
string $message,
array $credentials,
string $consumerKey,
string $consumerSecret,
string $accessToken,
string $tokenSecret
): array {
$urlPattern = '/https?:\/\/\S+/';
$urls = [];
preg_match_all($urlPattern, $message, $urls);
$urls = $urls[0] ?? [];
$textOnly = trim(preg_replace($urlPattern, '', $message));
$textOnly = preg_replace('/\s{2,}/', ' ', $textOnly);
if ($textOnly === '' && $urls === []) {
return ['success' => false, 'platform_post_id' => '', 'response' => ['error' => 'Empty message after URL extraction.']];
}
$textChunks = $textOnly !== '' ? $this->splitIntoThread($textOnly) : [];
if ($textChunks === [] && $urls !== []) {
$textChunks = [implode(' ', $urls)];
$urls = [];
}
$firstResult = $this->postTweet($textChunks[0], null, $consumerKey, $consumerSecret, $accessToken, $tokenSecret);
if (!$firstResult['success']) {
return $firstResult;
}
$rootId = $firstResult['platform_post_id'];
$previousId = $rootId;
for ($i = 1, $count = \count($textChunks); $i < $count; $i++) {
$result = $this->postTweet($textChunks[$i], $previousId, $consumerKey, $consumerSecret, $accessToken, $tokenSecret);
if (!$result['success']) {
return [
'success' => false,
'platform_post_id' => $rootId,
'response' => ['error' => 'Cost-optimized thread failed at tweet ' . ($i + 1), 'root_tweet' => $rootId],
];
}
$previousId = $result['platform_post_id'];
}
if ($urls !== []) {
$urlText = implode(' ', $urls);
$result = $this->postTweet($urlText, $previousId, $consumerKey, $consumerSecret, $accessToken, $tokenSecret);
if (!$result['success']) {
return [
'success' => false,
'platform_post_id' => $rootId,
'response' => ['error' => 'Cost-optimized URL reply failed.', 'root_tweet' => $rootId],
];
}
}
return ['success' => true, 'platform_post_id' => $rootId, 'response' => $firstResult['response']];
}
/**
* Build an OAuth 1.0a Authorization header with HMAC-SHA1 signature.
*/
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - X / Twitter</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Generic Webhook</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - WhatsApp Business</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - WordPress</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="mokosuitecross" method="upgrade">
<name>MokoSuiteCross - Youtube</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-06-23</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="system" method="upgrade">
<name>System - MokoSuiteCross</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="system" method="upgrade">
<name>System - MokoSuiteCross Events</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="system" method="upgrade">
<name>System - MokoSuiteCross Gallery</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="task" method="upgrade">
<name>Task - MokoSuiteCross Queue Processor</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" group="webservices" method="upgrade">
<name>Web Services - MokoSuiteCross</name>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>
+1 -1
View File
@@ -2,7 +2,7 @@
<extension type="package" method="upgrade">
<name>MokoSuiteCross</name>
<packagename>mokosuitecross</packagename>
<version>01.08.17</version>
<version>01.08.18</version>
<creationDate>2026-05-28</creationDate>
<author>Moko Consulting</author>
<authorEmail>hello@mokoconsulting.tech</authorEmail>