diff --git a/php/federator/api.php b/php/federator/api.php index 62f7c4e..ec8e9fa 100644 --- a/php/federator/api.php +++ b/php/federator/api.php @@ -47,7 +47,7 @@ class Api extends Main public function __construct() { $this->contentType = "application/json"; - Main::__construct(); + parent::__construct(); } /** diff --git a/php/federator/api/fedusers/inbox.php b/php/federator/api/fedusers/inbox.php index c16f4e7..3c1ff50 100644 --- a/php/federator/api/fedusers/inbox.php +++ b/php/federator/api/fedusers/inbox.php @@ -107,7 +107,7 @@ class Inbox implements \Federator\Api\FedUsers\FedUsersInterface } // Extract username from the actor URL - $username = basename((string)(parse_url($actor, PHP_URL_PATH) ?? '')); + $username = basename((string) (parse_url($actor, PHP_URL_PATH) ?? '')); $domain = parse_url($actor, PHP_URL_HOST); if ($username === null || $domain === null) { error_log("Inbox::post no username or domain found"); @@ -127,7 +127,6 @@ class Inbox implements \Federator\Api\FedUsers\FedUsersInterface if (!isset($user)) { continue; } - $token = \Resque::enqueue('inbox', 'Federator\\Jobs\\InboxJob', [ 'user' => $user, 'activity' => $inboxActivity->toObject(), @@ -160,6 +159,9 @@ class Inbox implements \Federator\Api\FedUsers\FedUsersInterface if ($user === null || $user->id === null) { throw new \Federator\Exceptions\ServerError("Inbox::postForUser couldn't find user: $_user"); } + } else { + // Not a local user, nothing to do + return false; } $rootDir = PROJECT_ROOT . '/'; @@ -170,6 +172,44 @@ class Inbox implements \Federator\Api\FedUsers\FedUsersInterface FILE_APPEND ); + $type = $inboxActivity->getType(); + + if ($type === 'Follow') { + // Someone wants to follow our user + $actor = $inboxActivity->getAActor(); // The follower's actor URI + if ($actor !== '') { + // Extract follower username (you may need to adjust this logic) + $followerUsername = basename((string) (parse_url($actor, PHP_URL_PATH) ?? '')); + $followerDomain = parse_url($actor, PHP_URL_HOST); + if (is_string($followerDomain)) { + $followerId = "{$followerUsername}@{$followerDomain}"; + + // Save the follow relationship + \Federator\DIO\Followers::addFollow($dbh, $followerId, $user->id, $followerDomain); + error_log("Inbox::postForUser: Added follower $followerId for user $user->id"); + } + } + } elseif ($type === 'Undo') { + // Check if this is an Undo of a Follow (i.e., Unfollow) + $object = $inboxActivity->getObject(); + if (is_object($object) && method_exists($object, 'getType') && $object->getType() === 'Follow') { + if ($object instanceof \Federator\Data\ActivityPub\Common\Activity) { + $actor = $object->getAActor(); + if ($actor !== '') { + $followerUsername = basename((string) (parse_url($actor, PHP_URL_PATH) ?? '')); + $followerDomain = parse_url($actor, PHP_URL_HOST); + if (is_string($followerDomain)) { + $followerId = "{$followerUsername}@{$followerDomain}"; + + // Remove the follow relationship + \Federator\DIO\Followers::removeFollow($dbh, $followerId, $user->id); + error_log("Inbox::postForUser: Removed follower $followerId for user $user->id"); + } + } + } + } + } + return true; } } diff --git a/php/federator/data/activitypub/common/activity.php b/php/federator/data/activitypub/common/activity.php index 6e8289c..7cccc92 100644 --- a/php/federator/data/activitypub/common/activity.php +++ b/php/federator/data/activitypub/common/activity.php @@ -47,7 +47,7 @@ class Activity extends APObject return $this; } - public function getAActor() : string + public function getAActor(): string { return $this->aactor; } diff --git a/php/federator/jobs/inboxJob.php b/php/federator/jobs/inboxJob.php index b02c313..6452d3b 100644 --- a/php/federator/jobs/inboxJob.php +++ b/php/federator/jobs/inboxJob.php @@ -2,7 +2,7 @@ namespace Federator\Jobs; -class InboxJob +class InboxJob extends \Federator\Api { /** @var array $args Arguments for the job */ public $args = []; @@ -28,19 +28,21 @@ class InboxJob */ protected $dbh; + /** + * constructor + */ + public function __construct() + { + parent::__construct(); + } + /** * Set up environment for this job */ public function setUp(): void { - $contentnation = new \Federator\Api(); - $contentnation->openDatabase(); - $contentnation->loadPlugins(); - - // Recreate dependencies as needed - $this->dbh = $contentnation->getDatabase(); // get DB connection - $this->connector = $contentnation->getConnector(); // get connector - $this->cache = $contentnation->getCache(); // get cache + $this->openDatabase(); + $this->loadPlugins(); } /** diff --git a/php/federator/main.php b/php/federator/main.php index fb77f3f..f9b966c 100644 --- a/php/federator/main.php +++ b/php/federator/main.php @@ -232,9 +232,10 @@ class Main */ public function renderTemplate($template, $data) { + $rootDir = PROJECT_ROOT . '/'; $smarty = new \Smarty\Smarty(); - $smarty->setCompileDir(PROJECT_ROOT . $this->config['templates']['compiledir']); - $smarty->setTemplateDir((string) realpath(PROJECT_ROOT . $this->config['templates']['path'])); + $smarty->setCompileDir($rootDir . $this->config['templates']['compiledir']); + $smarty->setTemplateDir((string) realpath($rootDir . $this->config['templates']['path'])); $smarty->assign('database', $this->dbh); $smarty->assign('maininstance', $this); foreach ($data as $key => $value) { diff --git a/php/federator/workers/worker_inbox.php b/php/federator/workers/worker_inbox.php index 4eb3646..a264ec2 100644 --- a/php/federator/workers/worker_inbox.php +++ b/php/federator/workers/worker_inbox.php @@ -4,6 +4,18 @@ define('PROJECT_ROOT', dirname(__DIR__, 3)); require_once PROJECT_ROOT . '/vendor/autoload.php'; +$config = parse_ini_file(PROJECT_ROOT . '/rediscache.ini'); + +// Set the Redis backend for Resque +$redisUrl = sprintf( + 'redis://%s:%s@%s:%d', + urlencode($config['username']), + urlencode($config['password']), + $config['host'], + intval($config['port'], 10) +); +\Resque::setBackend($redisUrl); + // Start the worker $worker = new \Resque_Worker(['inbox']); diff --git a/plugins/federator/contentnation.php b/plugins/federator/contentnation.php index 9e8cda8..11a9a92 100644 --- a/plugins/federator/contentnation.php +++ b/plugins/federator/contentnation.php @@ -170,8 +170,17 @@ class ContentNation implements Connector $posts[] = $create; break; // Article case 'Comment': - $comment = new \Federator\Data\ActivityPub\Common\Activity('Comment'); - $create->setObject($comment); + $commentJson = $activity; + $commentJson['type'] = 'Note'; + $commentJson['summary'] = $activity['subject']; + $note = \Federator\Data\ActivityPub\Factory::newFromJson($commentJson, ""); + if ($note === null) { + error_log("ContentNation::getRemotePostsByUser couldn't create comment"); + $comment = new \Federator\Data\ActivityPub\Common\Activity('Comment'); + $create->setObject($comment); + break; + } + $create->setObject($note); $posts[] = $create; break; // Comment case 'Vote': diff --git a/plugins/federator/rediscache.php b/plugins/federator/rediscache.php index 17b8deb..0c74936 100644 --- a/plugins/federator/rediscache.php +++ b/plugins/federator/rediscache.php @@ -71,6 +71,16 @@ class RedisCache implements Cache $this->redis->pconnect($this->config['host'], intval($this->config['port'], 10)); // @phan-suppress-next-line PhanTypeMismatchArgumentInternalProbablyReal $this->redis->auth([$this->config['username'], $this->config['password']]); + + // Set the Redis backend for Resque + $redisUrl = sprintf( + 'redis://%s:%s@%s:%d', + urlencode($this->config['username']), + urlencode($this->config['password']), + $this->config['host'], + intval($this->config['port'], 10) + ); + \Resque::setBackend($redisUrl); } /** @@ -104,7 +114,8 @@ class RedisCache implements Cache * @param array $jsonData the json data from our platfrom @unused-param * @return \Federator\Data\ActivityPub\Common\Activity|false */ - public function jsonToActivity(array $jsonData) { + public function jsonToActivity(array $jsonData) + { error_log("rediscache::jsonToActivity not implemented"); return false; } @@ -298,7 +309,7 @@ class RedisCache implements Cache { $key = self::createKey('s', $_session . $_user); $serialized = $user->toJson(); - $this->redis->setEx($key, $this->userTTL, $serialized,); + $this->redis->setEx($key, $this->userTTL, $serialized); } /** @@ -314,7 +325,7 @@ class RedisCache implements Cache $this->connect(); } $key = self::createKey('publickey', $keyId); - $this->redis->setEx($key, $this->publicKeyPemTTL, $publicKeyPem); // TTL = 1 hour + $this->redis->setEx($key, $this->publicKeyPemTTL, $publicKeyPem); } /**