diff --git a/htdocs/admin/fediverse.php b/htdocs/admin/fediverse.php index e69b5833f23..bf19d655f2d 100644 --- a/htdocs/admin/fediverse.php +++ b/htdocs/admin/fediverse.php @@ -68,6 +68,19 @@ if ($action == 'add') { $socialNetworkName = GETPOST('socialnetwork_name', 'alpha'); $socialNetworkUrl = GETPOST('socialnetwork_url', 'alpha'); + + // other params if exist + $paramNames = GETPOST('param_name', 'array'); + $paramValues = GETPOST('param_value', 'array'); + + $additionalParams = []; + if (!empty($paramNames) && is_array($paramNames)) { + foreach ($paramNames as $index => $paramName) { + if (!empty($paramName) && isset($paramValues[$index])) { + $additionalParams[$paramName] = $paramValues[$index]; + } + } + } if (!$error) { $db->begin(); @@ -76,6 +89,8 @@ if ($action == 'add') { 'url' => $socialNetworkUrl ); + $socialNetworkData = array_merge($socialNetworkData, $additionalParams); + $boxlabel = '(SocialNetwoksInformations)'; $sql = "INSERT INTO ".MAIN_DB_PREFIX."boxes_def (file, note)"; @@ -175,13 +190,37 @@ print ''.$langs->trans('SocialNetworkUrl').''; print ''; print 'https://mastodon.social/api/v1/accounts/id_user'; print ''; + +print ''; +print $form->textwithpicto($langs->trans("Others"), $langs->trans("AddMoreParams")); +print ''; +print 'Token : ****
Cookie : ****'; +print ''; + +print ''; +print ''; +print '
'; +print ''; +print ''; +print ''; + + print ''; print ''; print $form->buttonsSaveCancel("Add", ''); print ''; - +print ''; print ''; print '

'; @@ -222,12 +261,20 @@ if ($resql) { $socialNetworkTitle = $socialNetworkData['title']; $socialNetworkUrl = $socialNetworkData['url']; - $key = $obj->rowid; + $socialNetworkId = $obj->rowid; $fediverseparser = new SocialNetworkManager($socialNetworkTitle); $path_fediverse = DOL_DATA_ROOT.'/fediverse/temp/'.$socialNetworkTitle; - $result = $fediverseparser->fetchPosts($socialNetworkUrl, 5, 300, $path_fediverse); + //check if other params exist + $authParams = []; + foreach ($socialNetworkData as $key => $value) { + if ($key !== 'title' && $key !== 'url') { + $authParams[$key] = $value; + } + } + + $result = $fediverseparser->fetchPosts($socialNetworkUrl, 5, 300, $path_fediverse, $authParams); print "
"; print '
'."\n"; @@ -238,9 +285,9 @@ if ($resql) { print ''; print "".$langs->trans("SocialNetworks")." ".($i+1).""; print ''; - print ''.img_edit().''; - print ''.img_delete().''; - print ''; + print ''.img_edit().''; + print ''.img_delete().''; + print ''; print ''; print ''."\n"; @@ -271,7 +318,7 @@ if ($resql) { print ''."\n"; // Active - $active = _isInBoxListFediverse((int) $key, $boxlist) ? 'yes' : 'no'; + $active = _isInBoxListFediverse((int) $socialNetworkId, $boxlist) ? 'yes' : 'no'; print ''; print ''.$langs->trans('WidgetAvailable').''; diff --git a/htdocs/core/boxes/box_fediverse.php b/htdocs/core/boxes/box_fediverse.php index 34e45139229..485b8e6ec27 100644 --- a/htdocs/core/boxes/box_fediverse.php +++ b/htdocs/core/boxes/box_fediverse.php @@ -76,11 +76,18 @@ class box_fediverse extends ModeleBoxes $socialNetworkTitle = ''; $socialNetworkUrl = ''; + $authParams = []; if ($num > 0) { $obj = $this->db->fetch_row($resql); $socialNetworkData = json_decode($obj[0], true); $socialNetworkTitle = $socialNetworkData['title']; $socialNetworkUrl = $socialNetworkData['url']; + + foreach ($socialNetworkData as $key => $value) { + if ($key !== 'title' && $key !== 'url') { + $authParams[$key] = $value; + } + } } $fediverseParser = new SocialNetworkManager($socialNetworkTitle); diff --git a/htdocs/core/class/mastodonhandler.class.php b/htdocs/core/class/mastodonhandler.class.php index 06e5b8625ba..2ca873b1184 100644 --- a/htdocs/core/class/mastodonhandler.class.php +++ b/htdocs/core/class/mastodonhandler.class.php @@ -40,33 +40,111 @@ class MastodonHandler */ public $error = ''; + /** + * @var string Access token for authenticated requests + */ + private $accessToken; /** - * fetch Social Network API to retrieve posts. - * - * @param string $urlAPI URL of the Fediverse API. - * @param int $maxNb Maximum number of posts to retrieve (default is 5). - * @param int $cacheDelay Number of seconds to use cached data (0 to disable caching). - * @param string $cacheDir Directory to store cached data. - * @return bool Status code: False if error, true if success. + * @var string The client ID for the Mastodon app */ - public function fetch($urlAPI, $maxNb = 5, $cacheDelay = 60, $cacheDir = '') + private $clientId; + + /** + * @var string The client secret for the Mastodon app + */ + private $clientSecret; + + /** + * @var string The redirect URI for the Mastodon app + */ + private $redirectUri; + + + /** + * Constructor to set the necessary credentials. + * + * @param array $authParams parameters for authentication + */ + public function __construct($authParams) { - $result = getURLContent($urlAPI, 'GET', '', 1, array(), array('http', 'https'), 0); - if (empty($result['content'])) { - $this->error = 'Error retrieving URL '.$urlAPI; + $this->clientId = $authParams['client_id'] ?? ''; + $this->clientSecret = $authParams['client_secret'] ?? ''; + $this->redirectUri = $authParams['redirect_uri'] ?? ''; + $this->accessToken = $authParams['access_token'] ?? ''; + } + + + /** + * Fetch posts from Mastodon API using the access token. + * + * @param string $urlAPI The URL of the API endpoint + * @param int $maxNb Maximum number of posts to retrieve + * @param int $cacheDelay Cache delay in seconds + * @param string $cacheDir Directory for caching + * @param array $authParams Authentication parameters + * @return array|false Array of posts if successful, False otherwise + */ + public function fetch($urlAPI, $maxNb = 5, $cacheDelay = 60, $cacheDir = '', $authParams = []) + { + if (empty($this->accessToken) && isset($authParams['access_token'])) { return false; } + $cacheFile = $cacheDir.'/'.dol_hash($urlAPI, 3); + $foundInCache = false; + $data = null; - $data = json_decode($result['content'], true); - if (!is_array($data)) { - $this->error = 'Invalid JSON format'; - return false; + // Check cache + if ($cacheDelay > 0 && $cacheDir && dol_is_file($cacheFile)) { + $fileDate = dol_filemtime($cacheFile); + if ($fileDate >= (dol_now() - $cacheDelay)) { + $foundInCache = true; + $data = file_get_contents($cacheFile); + } } - $this->posts = array_slice(array_map([$this, 'normalizeData'], $data), 0, $maxNb); - return true; + if (!$foundInCache) { + $headers = [ + 'Authorization: Bearer ' . $this->accessToken, + 'Content-Type: application/json' + ]; + + $result = getURLContent($urlAPI, 'GET', '', 1, $headers, array('http', 'https'), 0); + if (!empty($result['content'])) { + $data = $result['content']; + + if ($cacheDir) { + dol_mkdir($cacheDir); + file_put_contents($cacheFile, $data); + } + } else { + $this->error = 'Error retrieving URL ' . $urlAPI; + return false; + } + } + if (!is_null($data)) { + $data = json_decode($data, true); + if (is_array($data)) { + $this->posts = []; + $count = 0; + + foreach ($data as $postData) { + if ($count >= $maxNb) { + break; + } + $this->posts[$count] = $this->normalizeData($postData); + $count++; + } + return $this->posts; + } else { + $this->error = 'Invalid data format or empty response'; + return false; + } + } else { + $this->error = 'Failed to retrieve or decode data'; + return false; + } } /** @@ -109,4 +187,40 @@ class MastodonHandler { return $this->posts; } + + /** + * Getter for url to redirect + * @return string url + */ + public function getRedirectUri() + { + return $this->redirectUri; + } + + /** + * Getter for access token + * @return string token + */ + public function getAccessToken() + { + return $this->accessToken; + } + + /** + * Getter for client Id + * @return string client Id + */ + public function getClientId() + { + return $this->clientId; + } + + /** + * Getter for secret client + * @return string secret client + */ + public function getClientSecret() + { + return $this->clientSecret; + } } diff --git a/htdocs/core/class/socialnetworkmanager.class.php b/htdocs/core/class/socialnetworkmanager.class.php index 4f76720bff3..636242844c8 100644 --- a/htdocs/core/class/socialnetworkmanager.class.php +++ b/htdocs/core/class/socialnetworkmanager.class.php @@ -59,22 +59,24 @@ class SocialNetworkManager * Constructor * * @param string $platform name of social network + * @param array $authParams other parameters */ - public function __construct($platform) + public function __construct($platform, $authParams = []) { $this->platform = $platform; - $this->initializeHandler(); + $this->initializeHandler($authParams); } /** * Initialize the social network needed + * @param array $authParams other parameters * @return void new instance if founded */ - private function initializeHandler() + private function initializeHandler($authParams) { $handlerClass = dol_ucfirst($this->platform).'Handler'; if (class_exists($handlerClass)) { - $this->handler = new $handlerClass(); + $this->handler = new $handlerClass($authParams); } else { $this->error = "Handler for $this->platform not found."; } @@ -87,14 +89,15 @@ class SocialNetworkManager * @param int $maxNb Maximum number of posts to retrieve (default is 5). * @param int $cacheDelay Number of seconds to use cached data (0 to disable caching). * @param string $cacheDir Directory to store cached data. + * @param array $authParams Authentication parameters * @return bool Status code: false if error, array if success. */ - public function fetchPosts($urlAPI, $maxNb = 5, $cacheDelay = 60, $cacheDir = '') + public function fetchPosts($urlAPI, $maxNb = 5, $cacheDelay = 60, $cacheDir = '', $authParams = []) { if (!$this->handler) { return false; } - return $this->handler->fetch($urlAPI, $maxNb, $cacheDelay, $cacheDir); + return $this->handler->fetch($urlAPI, $maxNb, $cacheDelay, $cacheDir, $authParams); } /** diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index dbbf3e18d04..242fc0d79a4 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2549,3 +2549,6 @@ ConfirmDeleteSocialNetwork= Are you sure want to delete this record ? AnOwnerMustBeSetIfEmailTemplateIsPrivate=An owner must be set if the email template is set as private ContactsDefaultRoles=For third parties of the "individual" type, a contact can be created simultaneously. Define here the roles that will be systematically assigned to this contact. MenuDict=Dictionary +AddMoreParams=Add more parameters for connection (cookies, tokens, ...)
Exemple: token : value token +ParamName=Name of parameter +ParamValue=Value of parameter \ No newline at end of file