fix following from mastodon -> CN

This commit is contained in:
Yannis Vogel 2025-05-25 20:22:34 +02:00
parent 5c90b4cfc9
commit 30c577c82f
No known key found for this signature in database
4 changed files with 94 additions and 31 deletions

View file

@ -77,6 +77,16 @@ class Inbox implements \Federator\Api\FedUsers\FedUsersInterface
$user = $inboxActivity->getAActor(); // url of the sender https://contentnation.net/username
$username = basename((string) (parse_url($user, PHP_URL_PATH) ?? ''));
$domain = parse_url($user, PHP_URL_HOST);
$userId = $username . '@' . $domain;
$user = \Federator\DIO\FedUser::getUserByName(
$dbh,
$userId,
$cache
);
if ($user === null || $user->id === null) {
error_log("Inbox::post couldn't find user: $userId");
throw new \Federator\Exceptions\ServerError("Inbox::post couldn't find user: $userId");
}
$users = [];
@ -97,9 +107,26 @@ class Inbox implements \Federator\Api\FedUsers\FedUsersInterface
&& (filter_var($receiver, FILTER_VALIDATE_URL) !== false);
});
if (!in_array($username, $receivers, true)) {
$receivers[] = $username;
// Special handling for Follow and Undo follow activities
if (strtolower($inboxActivity->getType()) === 'follow') {
// For Follow, the object should hold the target
$object = $inboxActivity->getObject();
if ($object !== null && is_string($object)) {
$receivers[] = $object;
}
} elseif (strtolower($inboxActivity->getType()) === 'undo') {
$object = $inboxActivity->getObject();
if ($object !== null && is_object($object)) {
// For Undo, the objects object should hold the target
if (strtolower($object->getType()) === 'follow') {
$objObject = $object->getObject();
if ($objObject !== null && is_string($objObject)) {
$receivers[] = $objObject;
}
}
}
}
foreach ($receivers as $receiver) {
if ($receiver === '' || !is_string($receiver)) {
continue;
@ -136,14 +163,14 @@ class Inbox implements \Federator\Api\FedUsers\FedUsersInterface
continue;
}
$receiverName = basename((string) (parse_url($receiver, PHP_URL_PATH) ?? ''));
$domain = parse_url($receiver, PHP_URL_HOST);
if ($receiverName === null || $domain === null) {
$ourDomain = parse_url($receiver, PHP_URL_HOST);
if ($receiverName === null || $ourDomain === null) {
error_log("Inbox::post no receiverName or domain found for receiver: " . $receiver);
continue;
}
$receiver = $receiverName . '@' . $domain;
$receiver = $receiverName . '@' . $ourDomain;
try {
$user = \Federator\DIO\User::getUserByName(
$localUser = \Federator\DIO\User::getUserByName(
$dbh,
$receiver,
$connector,
@ -153,11 +180,11 @@ class Inbox implements \Federator\Api\FedUsers\FedUsersInterface
error_log("Inbox::post get user by name: " . $receiver . ". Exception: " . $e->getMessage());
continue;
}
if ($user === null || $user->id === null) {
if ($localUser === null || $localUser->id === null) {
error_log("Inbox::post couldn't find user: $receiver");
continue;
}
$users[] = $user->id;
$users[] = $localUser->id;
}
}
@ -172,15 +199,15 @@ class Inbox implements \Federator\Api\FedUsers\FedUsersInterface
}
foreach ($users as $receiver) {
if (!isset($user)) {
if (!isset($receiver)) {
continue;
}
$token = \Resque::enqueue('inbox', 'Federator\\Jobs\\InboxJob', [
'user' => $username . '@' . $domain,
'user' => $user->id,
'recipientId' => $receiver,
'activity' => $inboxActivity->toObject(),
]);
error_log("Inbox::post enqueued job for user: $user with token: $token");
error_log("Inbox::post enqueued job for user: $user->id with token: $token");
}
return "success";
}
@ -241,12 +268,7 @@ class Inbox implements \Federator\Api\FedUsers\FedUsersInterface
$success = false;
$actor = $inboxActivity->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}";
$success = \Federator\DIO\Followers::addFollow($dbh, $followerId, $user->id, $followerDomain);
}
$success = \Federator\DIO\Followers::addExternalFollow($dbh, $inboxActivity->getID(), $user->id, $recipient->id);
}
if ($success === false) {
error_log("Inbox::postForUser: Failed to add follower for user $user->id");
@ -273,12 +295,7 @@ class Inbox implements \Federator\Api\FedUsers\FedUsersInterface
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}";
$success = \Federator\DIO\Followers::removeFollow($dbh, $followerId, $user->id);
}
$success = \Federator\DIO\Followers::removeFollow($dbh, $user->id, $recipient->id);
}
}
if ($success === false) {

View file

@ -276,21 +276,21 @@ class NewContent implements \Federator\Api\APIInterface
switch ($type) {
case 'Follow':
$success = false;
// $success = false;
$actor = $newActivity->getAActor();
if ($actor !== '') {
$followerUsername = basename((string) (parse_url($actor, PHP_URL_PATH) ?? ''));
$followerDomain = parse_url($actor, PHP_URL_HOST);
// $followerUsername = basename((string) (parse_url($actor, PHP_URL_PATH) ?? ''));
// $followerDomain = parse_url($actor, PHP_URL_HOST);
$newIdUrl = \Federator\DIO\Followers::generateNewFollowId($dbh, $host);
$newActivity->setID($newIdUrl);
if (is_string($followerDomain)) {
/* if (is_string($followerDomain)) {
$followerId = "{$followerUsername}@{$followerDomain}";
// $success = \Federator\DIO\Followers::sendFollowRequest($dbh, $connector, $cache, $user->id, $followerId, $followerDomain);
}
$success = \Federator\DIO\Followers::sendFollowRequest($dbh, $connector, $cache, $user->id, $followerId, $followerDomain);
} */
}
if ($success === false) {
/* if ($success === false) {
error_log("NewContent::postForUser Failed to add follower for user $user->id");
}
} */
break;
case 'Delete':

View file

@ -21,6 +21,11 @@ class Follow extends Activity
$this->object = $object;
}
public function getObject(): string
{
return $this->object;
}
public function __construct()
{
parent::__construct("Follow");

View file

@ -388,6 +388,47 @@ class Followers
return $idurl; // Return the generated follow ID
}
/**
* add follow
*
* @param \mysqli $dbh database handle
* @param string $followId the follow ID to use (should be an external url)
* @param string $sourceUser source user id
* @param string $targetUserId target user id
* @return boolean true on success, false on failure
*/
public static function addExternalFollow($dbh, $followId, $sourceUser, $targetUserId)
{
// Check if we already follow this user
$sql = 'select id from follows where source_user = ? and target_user = ?';
$stmt = $dbh->prepare($sql);
if ($stmt === false) {
throw new \Federator\Exceptions\ServerError("Followers::addExternalFollow Failed to prepare statement");
}
$stmt->bind_param("ss", $sourceUser, $targetUserId);
$foundId = 0;
$ret = $stmt->bind_result($foundId);
$stmt->execute();
if ($ret) {
$stmt->fetch();
}
$stmt->close();
if ($foundId != 0) {
return false; // Already following this user
}
// Add follow with created_at timestamp
$sql = 'insert into follows (id, source_user, target_user, created_at) values (?, ?, ?, NOW())';
$stmt = $dbh->prepare($sql);
if ($stmt === false) {
throw new \Federator\Exceptions\ServerError("Followers::addExternalFollow Failed to prepare insert statement");
}
$stmt->bind_param("sss", $followId, $sourceUser, $targetUserId);
$stmt->execute();
$stmt->close();
return true;
}
/**
* generate new follow id
*