diff --git a/database.sql b/database.sql index da39341f15..1c361b6762 100644 --- a/database.sql +++ b/database.sql @@ -523,17 +523,14 @@ CREATE TABLE IF NOT EXISTS `workerqueue` ( CREATE TABLE IF NOT EXISTS `delayed-post` ( `id` int unsigned NOT NULL auto_increment, `uri` varchar(255) COMMENT 'URI of the post that will be distributed later', - `title` varchar(255) COMMENT 'post title', - `body` mediumtext COMMENT 'post body content', - `private` tinyint unsigned COMMENT '0=public, 1=private, 2=unlisted', - `wid` int unsigned COMMENT 'Workerqueue id', `uid` mediumint unsigned COMMENT 'Owner User id', `delayed` datetime COMMENT 'delay time', + `wid` int unsigned COMMENT 'Workerqueue id', PRIMARY KEY(`id`), UNIQUE INDEX `uid_uri` (`uid`,`uri`(190)), INDEX `wid` (`wid`), - FOREIGN KEY (`wid`) REFERENCES `workerqueue` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE, - FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE + FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE, + FOREIGN KEY (`wid`) REFERENCES `workerqueue` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE ) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Posts that are about to be distributed at a later time'; -- diff --git a/doc/database/db_delayed-post.md b/doc/database/db_delayed-post.md index 77cd677f65..b792f2f005 100644 --- a/doc/database/db_delayed-post.md +++ b/doc/database/db_delayed-post.md @@ -10,12 +10,9 @@ Fields | ------- | ---------------------------------------------- | ------------------ | ---- | --- | ------- | -------------- | | id | | int unsigned | NO | PRI | NULL | auto_increment | | uri | URI of the post that will be distributed later | varchar(255) | YES | | NULL | | -| title | post title | varchar(255) | YES | | NULL | | -| body | post body content | mediumtext | YES | | NULL | | -| private | 0=public, 1=private, 2=unlisted | tinyint unsigned | YES | | NULL | | -| wid | Workerqueue id | int unsigned | YES | | NULL | | | uid | Owner User id | mediumint unsigned | YES | | NULL | | | delayed | delay time | datetime | YES | | NULL | | +| wid | Workerqueue id | int unsigned | YES | | NULL | | Indexes ------------ @@ -31,7 +28,7 @@ Foreign Keys | Field | Target Table | Target Field | |-------|--------------|--------------| -| wid | [workerqueue](help/database/db_workerqueue) | id | | uid | [user](help/database/db_user) | uid | +| wid | [workerqueue](help/database/db_workerqueue) | id | Return to [database documentation](help/database) diff --git a/src/DI.php b/src/DI.php index d8e51b4398..0bfaacf89a 100644 --- a/src/DI.php +++ b/src/DI.php @@ -311,6 +311,14 @@ abstract class DI return self::$dice->create(Factory\Api\Mastodon\Status::class); } + /** + * @return Factory\Api\Mastodon\ScheduledStatus + */ + public static function mstdnScheduledStatus() + { + return self::$dice->create(Factory\Api\Mastodon\ScheduledStatus::class); + } + /** * @return Factory\Api\Mastodon\ListEntity */ diff --git a/src/Factory/Api/Mastodon/ScheduledStatus.php b/src/Factory/Api/Mastodon/ScheduledStatus.php new file mode 100644 index 0000000000..f0d846fc00 --- /dev/null +++ b/src/Factory/Api/Mastodon/ScheduledStatus.php @@ -0,0 +1,59 @@ +. + * + */ + +namespace Friendica\Factory\Api\Mastodon; + +use Friendica\BaseFactory; +use Friendica\Database\Database; +use Friendica\Model\Post; +use Friendica\Network\HTTPException; +use Psr\Log\LoggerInterface; + +class ScheduledStatus extends BaseFactory +{ + /** @var Database */ + private $dba; + + public function __construct(LoggerInterface $logger, Database $dba) + { + parent::__construct($logger); + $this->dba = $dba; + } + + /** + * @param int $id Id of the delayed post + * @param int $uid Post user + * + * @return \Friendica\Object\Api\Mastodon\ScheduledStatus + * @throws HTTPException\InternalServerErrorException + */ + public function createFromId(int $id, int $uid): \Friendica\Object\Api\Mastodon\ScheduledStatus + { + $delayed_post = $this->dba->selectFirst('delayed-post', [], ['id' => $id, 'uid' => $uid]); + if (empty($delayed_post)) { + throw new HTTPException\NotFoundException('Scheduled status with ID ' . $id . ' not found for user ' . $uid . '.'); + } + + $parameters = Post\Delayed::getParametersForid($delayed_post['id']); + + return new \Friendica\Object\Api\Mastodon\ScheduledStatus($delayed_post, $parameters); + } +} diff --git a/src/Model/Post/Delayed.php b/src/Model/Post/Delayed.php index d75c380f3f..5af32d52ef 100644 --- a/src/Model/Post/Delayed.php +++ b/src/Model/Post/Delayed.php @@ -73,12 +73,9 @@ class Delayed $delayed_post = [ 'uri' => $uri, - 'title' => $item['title'], - 'body' => $item['body'], - 'private' => $item['private'], - 'wid' => $wid, 'uid' => $item['uid'], 'delayed' => $delayed, + 'wid' => $wid, ]; return DBA::insert('delayed-post', $delayed_post, Database::INSERT_IGNORE); @@ -110,6 +107,40 @@ class Delayed return DBA::exists('delayed-post', ['uri' => $uri, 'uid' => $uid]); } + /** + * Fetch parameters for delayed posts + * + * @param integer $id + * @return array + */ + public static function getParametersForid(int $id) + { + $delayed = DBA::selectFirst('delayed-post', ['id', 'wid', 'delayed'], ['id' => $id]); + if (empty($delayed['wid'])) { + return []; + } + + $worker = DBA::selectFirst('workerqueue', ['parameter'], ['id' => $delayed['wid'], 'command' => 'DelayedPublish']); + if (empty($worker)) { + return []; + } + + $parameters = json_decode($worker['parameter']); + if (empty($parameters)) { + return []; + } + + return [ + 'parameters' => $delayed, + 'item' => $parameters[0], + 'notify' => $parameters[1], + 'taglist' => $parameters[2], + 'attachments' => $parameters[3], + 'unprepared' => $parameters[4], + 'uri' => $parameters[5], + ]; + } + /** * Publish a delayed post * diff --git a/src/Module/Api/Mastodon/ScheduledStatuses.php b/src/Module/Api/Mastodon/ScheduledStatuses.php index 28f174da18..fbf451e6ca 100644 --- a/src/Module/Api/Mastodon/ScheduledStatuses.php +++ b/src/Module/Api/Mastodon/ScheduledStatuses.php @@ -22,6 +22,7 @@ namespace Friendica\Module\Api\Mastodon; use Friendica\Core\System; +use Friendica\DI; use Friendica\Module\BaseApi; /** @@ -35,6 +36,20 @@ class ScheduledStatuses extends BaseApi */ public static function rawContent(array $parameters = []) { + self::checkAllowedScope(self::SCOPE_READ); + $uid = self::getCurrentUserID(); + + if (isset($parameters['id'])) { + System::jsonExit(DI::mstdnScheduledStatus()->createFromId($parameters['id'], $uid)); + } + + $request = self::getRequest([ + 'limit' => 20, // Max number of results to return. Defaults to 20. + 'max_id' => 0, // Return results older than ID + 'since_id' => 0, // Return results newer than ID + 'min_id' => 0, // Return results immediately newer than ID + ]); + System::jsonExit([]); } } diff --git a/src/Object/Api/Mastodon/ScheduledStatus.php b/src/Object/Api/Mastodon/ScheduledStatus.php new file mode 100644 index 0000000000..3e78ce69a6 --- /dev/null +++ b/src/Object/Api/Mastodon/ScheduledStatus.php @@ -0,0 +1,83 @@ +. + * + */ + +namespace Friendica\Object\Api\Mastodon; + +use Friendica\BaseDataTransferObject; +use Friendica\Content\Text\BBCode; +use Friendica\Util\DateTimeFormat; + +/** + * Class ScheduledStatus + * + * @see https://docs.joinmastodon.org/entities/scheduledstatus + */ +class ScheduledStatus extends BaseDataTransferObject +{ + /** @var string */ + protected $id; + /** @var string (Datetime) */ + protected $scheduled_at; + /** @var array */ + protected $params = [ + 'text' => '', + 'media_ids' => null, + 'sensitive' => null, + 'spoiler_text' => null, + 'visibility' => '', + 'scheduled_at' => null, + 'poll' => null, + 'idempotency' => null, + 'in_reply_to_id' => null, + 'application_id' => '' + ]; + /** @var Attachment */ + protected $media_attachments = []; + + /** + * Creates a status record from a delayed-post record. + * + * @param array $delayed_post + * @throws \Friendica\Network\HTTPException\InternalServerErrorException + */ + public function __construct(array $delayed_post, array $parameters) + { + $visibility = ['public', 'private', 'unlisted']; + + $this->id = (string)$delayed_post['uri-id']; + $this->scheduled_at = DateTimeFormat::utc($delayed_post['scheduled_at'], DateTimeFormat::JSON); + + $this->params = [ + 'text' => BBCode::convert(BBCode::setMentionsToNicknames($parameters['item']['body'] ?? ''), false, BBCode::API), + 'media_ids' => null, + 'sensitive' => null, + 'spoiler_text' => $parameters['item']['title'] ?? '', + 'visibility' => $visibility[$parameters['item']['private']], + 'scheduled_at' => $this->scheduled_at, + 'poll' => null, + 'idempotency' => null, + 'in_reply_to_id' => null, + 'application_id' => '' + ]; + + $this->media_attachments = []; + } +} diff --git a/static/dbstructure.config.php b/static/dbstructure.config.php index 0376315e3f..d1cc42033a 100644 --- a/static/dbstructure.config.php +++ b/static/dbstructure.config.php @@ -585,12 +585,9 @@ return [ "fields" => [ "id" => ["type" => "int unsigned", "not null" => "1", "extra" => "auto_increment", "primary" => "1"], "uri" => ["type" => "varchar(255)", "comment" => "URI of the post that will be distributed later"], - "title" => ["type" => "varchar(255)", "comment" => "post title"], - "body" => ["type" => "mediumtext", "comment" => "post body content"], - "private" => ["type" => "tinyint unsigned", "comment" => "0=public, 1=private, 2=unlisted"], - "wid" => ["type" => "int unsigned", "foreign" => ["workerqueue" => "id"], "comment" => "Workerqueue id"], "uid" => ["type" => "mediumint unsigned", "foreign" => ["user" => "uid"], "comment" => "Owner User id"], "delayed" => ["type" => "datetime", "comment" => "delay time"], + "wid" => ["type" => "int unsigned", "foreign" => ["workerqueue" => "id"], "comment" => "Workerqueue id"], ], "indexes" => [ "PRIMARY" => ["id"], diff --git a/static/routes.config.php b/static/routes.config.php index 74cc59df81..87a8242d8f 100644 --- a/static/routes.config.php +++ b/static/routes.config.php @@ -128,7 +128,7 @@ return [ '/push/subscription' => [Module\Api\Mastodon\Unimplemented::class, [R::GET, R::POST, R::PUT, R::DELETE]], // not supported '/reports' => [Module\Api\Mastodon\Unimplemented::class, [ R::POST]], // not supported '/scheduled_statuses' => [Module\Api\Mastodon\ScheduledStatuses::class, [R::GET ]], // Dummy, not supported - '/scheduled_statuses/{id:\d+}' => [Module\Api\Mastodon\Unimplemented::class, [R::GET, R::PUT, R::DELETE]], // not supported + '/scheduled_statuses/{id:\d+}' => [Module\Api\Mastodon\ScheduledStatuses::class, [R::GET, R::PUT, R::DELETE]], '/statuses' => [Module\Api\Mastodon\Statuses::class, [ R::POST]], '/statuses/{id:\d+}' => [Module\Api\Mastodon\Statuses::class, [R::GET, R::DELETE]], '/statuses/{id:\d+}/card' => [Module\Api\Mastodon\Statuses\Card::class, [R::GET ]],