Merge pull request #11615 from annando/api-markers
API: Support for markers added
This commit is contained in:
commit
21d4726619
7 changed files with 116 additions and 7 deletions
18
database.sql
18
database.sql
|
@ -1,6 +1,6 @@
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
-- Friendica 2022.05-rc (Siberian Iris)
|
-- Friendica 2022.05-rc (Siberian Iris)
|
||||||
-- DB_UPDATE_VERSION 1467
|
-- DB_UPDATE_VERSION 1468
|
||||||
-- ------------------------------------------
|
-- ------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@ -386,6 +386,22 @@ CREATE TABLE IF NOT EXISTS `application` (
|
||||||
UNIQUE INDEX `client_id` (`client_id`)
|
UNIQUE INDEX `client_id` (`client_id`)
|
||||||
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='OAuth application';
|
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='OAuth application';
|
||||||
|
|
||||||
|
--
|
||||||
|
-- TABLE application-marker
|
||||||
|
--
|
||||||
|
CREATE TABLE IF NOT EXISTS `application-marker` (
|
||||||
|
`application-id` int unsigned NOT NULL COMMENT '',
|
||||||
|
`uid` mediumint unsigned NOT NULL COMMENT 'Owner User id',
|
||||||
|
`timeline` varchar(64) NOT NULL COMMENT 'Marker (home, notifications)',
|
||||||
|
`last_read_id` varchar(255) COMMENT 'Marker id for the timeline',
|
||||||
|
`version` smallint unsigned COMMENT 'Version number',
|
||||||
|
`updated_at` datetime COMMENT 'creation time',
|
||||||
|
PRIMARY KEY(`application-id`,`uid`,`timeline`),
|
||||||
|
INDEX `uid_id` (`uid`),
|
||||||
|
FOREIGN KEY (`application-id`) REFERENCES `application` (`id`) ON UPDATE RESTRICT ON DELETE CASCADE,
|
||||||
|
FOREIGN KEY (`uid`) REFERENCES `user` (`uid`) ON UPDATE RESTRICT ON DELETE CASCADE
|
||||||
|
) DEFAULT COLLATE utf8mb4_general_ci COMMENT='Timeline marker';
|
||||||
|
|
||||||
--
|
--
|
||||||
-- TABLE application-token
|
-- TABLE application-token
|
||||||
--
|
--
|
||||||
|
|
|
@ -84,6 +84,8 @@ These endpoints use the [Mastodon API entities](https://docs.joinmastodon.org/en
|
||||||
- [`GET /api/v1/lists/:id/accounts`](https://docs.joinmastodon.org/methods/timelines/lists/)
|
- [`GET /api/v1/lists/:id/accounts`](https://docs.joinmastodon.org/methods/timelines/lists/)
|
||||||
- [`POST /api/v1/lists/:id/accounts`](https://docs.joinmastodon.org/methods/timelines/lists/)
|
- [`POST /api/v1/lists/:id/accounts`](https://docs.joinmastodon.org/methods/timelines/lists/)
|
||||||
- [`DELETE /api/v1/lists/:id/accounts`](https://docs.joinmastodon.org/methods/timelines/lists/)
|
- [`DELETE /api/v1/lists/:id/accounts`](https://docs.joinmastodon.org/methods/timelines/lists/)
|
||||||
|
- [`POST /api/v1/markers`](https://docs.joinmastodon.org/methods/timelines/markers/)
|
||||||
|
- [`GET /api/v1/markers`](https://docs.joinmastodon.org/methods/timelines/markers/)
|
||||||
- [`POST /api/v1/media`](https://docs.joinmastodon.org/methods/statuses/media/)
|
- [`POST /api/v1/media`](https://docs.joinmastodon.org/methods/statuses/media/)
|
||||||
- [`GET /api/v1/media/:id`](https://docs.joinmastodon.org/methods/statuses/media/)
|
- [`GET /api/v1/media/:id`](https://docs.joinmastodon.org/methods/statuses/media/)
|
||||||
- [`PUT /api/v1/media/:id`](https://docs.joinmastodon.org/methods/statuses/media/)
|
- [`PUT /api/v1/media/:id`](https://docs.joinmastodon.org/methods/statuses/media/)
|
||||||
|
@ -156,7 +158,6 @@ They refer to features that don't exist in Friendica yet.
|
||||||
- [`GET /api/v1/announcements`](https://docs.joinmastodon.org/methods/announcements/)
|
- [`GET /api/v1/announcements`](https://docs.joinmastodon.org/methods/announcements/)
|
||||||
- [`GET /api/v1/endorsements`](https://docs.joinmastodon.org/methods/accounts/endorsements/)
|
- [`GET /api/v1/endorsements`](https://docs.joinmastodon.org/methods/accounts/endorsements/)
|
||||||
- [`GET /api/v1/filters`](https://docs.joinmastodon.org/methods/accounts/filters/)
|
- [`GET /api/v1/filters`](https://docs.joinmastodon.org/methods/accounts/filters/)
|
||||||
- [`GET /api/v1/markers`](https://docs.joinmastodon.org/methods/timelines/markers/)
|
|
||||||
|
|
||||||
## Non supportable endpoints
|
## Non supportable endpoints
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ Database Tables
|
||||||
| [addon](help/database/db_addon) | registered addons |
|
| [addon](help/database/db_addon) | registered addons |
|
||||||
| [apcontact](help/database/db_apcontact) | ActivityPub compatible contacts - used in the ActivityPub implementation |
|
| [apcontact](help/database/db_apcontact) | ActivityPub compatible contacts - used in the ActivityPub implementation |
|
||||||
| [application](help/database/db_application) | OAuth application |
|
| [application](help/database/db_application) | OAuth application |
|
||||||
|
| [application-marker](help/database/db_application-marker) | Timeline marker |
|
||||||
| [application-token](help/database/db_application-token) | OAuth user token |
|
| [application-token](help/database/db_application-token) | OAuth user token |
|
||||||
| [attach](help/database/db_attach) | file attachments |
|
| [attach](help/database/db_attach) | file attachments |
|
||||||
| [cache](help/database/db_cache) | Stores temporary data |
|
| [cache](help/database/db_cache) | Stores temporary data |
|
||||||
|
|
34
doc/database/db_application-marker.md
Normal file
34
doc/database/db_application-marker.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
Table application-marker
|
||||||
|
===========
|
||||||
|
|
||||||
|
Timeline marker
|
||||||
|
|
||||||
|
Fields
|
||||||
|
------
|
||||||
|
|
||||||
|
| Field | Description | Type | Null | Key | Default | Extra |
|
||||||
|
| -------------- | ---------------------------- | ------------------ | ---- | --- | ------- | ----- |
|
||||||
|
| application-id | | int unsigned | NO | PRI | NULL | |
|
||||||
|
| uid | Owner User id | mediumint unsigned | NO | PRI | NULL | |
|
||||||
|
| timeline | Marker (home, notifications) | varchar(64) | NO | PRI | NULL | |
|
||||||
|
| last_read_id | Marker id for the timeline | varchar(255) | YES | | NULL | |
|
||||||
|
| version | Version number | smallint unsigned | YES | | NULL | |
|
||||||
|
| updated_at | creation time | datetime | YES | | NULL | |
|
||||||
|
|
||||||
|
Indexes
|
||||||
|
------------
|
||||||
|
|
||||||
|
| Name | Fields |
|
||||||
|
| ------- | ----------------------------- |
|
||||||
|
| PRIMARY | application-id, uid, timeline |
|
||||||
|
| uid_id | uid |
|
||||||
|
|
||||||
|
Foreign Keys
|
||||||
|
------------
|
||||||
|
|
||||||
|
| Field | Target Table | Target Field |
|
||||||
|
|-------|--------------|--------------|
|
||||||
|
| application-id | [application](help/database/db_application) | id |
|
||||||
|
| uid | [user](help/database/db_user) | uid |
|
||||||
|
|
||||||
|
Return to [database documentation](help/database)
|
|
@ -21,10 +21,11 @@
|
||||||
|
|
||||||
namespace Friendica\Module\Api\Mastodon;
|
namespace Friendica\Module\Api\Mastodon;
|
||||||
|
|
||||||
use Friendica\App\Router;
|
|
||||||
use Friendica\Core\System;
|
use Friendica\Core\System;
|
||||||
|
use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Module\BaseApi;
|
use Friendica\Module\BaseApi;
|
||||||
|
use Friendica\Util\DateTimeFormat;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://docs.joinmastodon.org/methods/timelines/markers/
|
* @see https://docs.joinmastodon.org/methods/timelines/markers/
|
||||||
|
@ -34,8 +35,33 @@ class Markers extends BaseApi
|
||||||
protected function post(array $request = [])
|
protected function post(array $request = [])
|
||||||
{
|
{
|
||||||
self::checkAllowedScope(self::SCOPE_WRITE);
|
self::checkAllowedScope(self::SCOPE_WRITE);
|
||||||
|
$uid = self::getCurrentUserID();
|
||||||
|
$application = self::getCurrentApplication();
|
||||||
|
|
||||||
$this->response->unsupported(Router::POST, $request);
|
$timeline = '';
|
||||||
|
$last_read_id = '';
|
||||||
|
foreach (['home', 'notifications'] as $name) {
|
||||||
|
if (!empty($request[$name])) {
|
||||||
|
$timeline = $name;
|
||||||
|
$last_read_id = $request[$name]['last_read_id'] ?? '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($timeline) || empty($last_read_id) || empty($application['id'])) {
|
||||||
|
DI::mstdnError()->UnprocessableEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
$condition = ['application-id' => $application['id'], 'uid' => $uid, 'timeline' => $timeline];
|
||||||
|
$marker = DBA::selectFirst('application-marker', [], $condition);
|
||||||
|
if (!empty($marker['version'])) {
|
||||||
|
$version = $marker['version'] + 1;
|
||||||
|
} else {
|
||||||
|
$version = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$fields = ['last_read_id' => $last_read_id, 'version' => $version, 'updated_at' => DateTimeFormat::utcNow()];
|
||||||
|
DBA::update('application-marker', $fields, $condition, true);
|
||||||
|
System::jsonExit($this->fetchTimelines($application['id'], $uid));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,7 +70,23 @@ class Markers extends BaseApi
|
||||||
protected function rawContent(array $request = [])
|
protected function rawContent(array $request = [])
|
||||||
{
|
{
|
||||||
self::checkAllowedScope(self::SCOPE_READ);
|
self::checkAllowedScope(self::SCOPE_READ);
|
||||||
|
$uid = self::getCurrentUserID();
|
||||||
|
$application = self::getCurrentApplication();
|
||||||
|
|
||||||
System::jsonExit([]);
|
System::jsonExit($this->fetchTimelines($application['id'], $uid));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function fetchTimelines(int $application_id, int $uid)
|
||||||
|
{
|
||||||
|
$values = [];
|
||||||
|
$markers = DBA::select('application-marker', [], ['application-id' => $application_id, 'uid' => $uid]);
|
||||||
|
while ($marker = DBA::fetch($markers)) {
|
||||||
|
$values[$marker['timeline']] = [
|
||||||
|
'last_read_id' => $marker['last_read_id'],
|
||||||
|
'version' => $marker['version'],
|
||||||
|
'updated_at' => $marker['updated_at']
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $values;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
|
|
||||||
if (!defined('DB_UPDATE_VERSION')) {
|
if (!defined('DB_UPDATE_VERSION')) {
|
||||||
define('DB_UPDATE_VERSION', 1467);
|
define('DB_UPDATE_VERSION', 1468);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -449,6 +449,21 @@ return [
|
||||||
"client_id" => ["UNIQUE", "client_id"]
|
"client_id" => ["UNIQUE", "client_id"]
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
"application-marker" => [
|
||||||
|
"comment" => "Timeline marker",
|
||||||
|
"fields" => [
|
||||||
|
"application-id" => ["type" => "int unsigned", "not null" => "1", "primary" => "1", "foreign" => ["application" => "id"], "comment" => ""],
|
||||||
|
"uid" => ["type" => "mediumint unsigned", "not null" => "1", "primary" => "1", "foreign" => ["user" => "uid"], "comment" => "Owner User id"],
|
||||||
|
"timeline" => ["type" => "varchar(64)", "not null" => "1", "primary" => "1", "comment" => "Marker (home, notifications)"],
|
||||||
|
"last_read_id" => ["type" => "varchar(255)", "comment" => "Marker id for the timeline"],
|
||||||
|
"version" => ["type" => "smallint unsigned", "comment" => "Version number"],
|
||||||
|
"updated_at" => ["type" => "datetime", "comment" => "creation time"],
|
||||||
|
],
|
||||||
|
"indexes" => [
|
||||||
|
"PRIMARY" => ["application-id", "uid", "timeline"],
|
||||||
|
"uid_id" => ["uid"],
|
||||||
|
]
|
||||||
|
],
|
||||||
"application-token" => [
|
"application-token" => [
|
||||||
"comment" => "OAuth user token",
|
"comment" => "OAuth user token",
|
||||||
"fields" => [
|
"fields" => [
|
||||||
|
|
|
@ -237,7 +237,7 @@ return [
|
||||||
'/lists' => [Module\Api\Mastodon\Lists::class, [R::GET, R::POST]],
|
'/lists' => [Module\Api\Mastodon\Lists::class, [R::GET, R::POST]],
|
||||||
'/lists/{id:\d+}' => [Module\Api\Mastodon\Lists::class, [R::GET, R::PUT, R::DELETE]],
|
'/lists/{id:\d+}' => [Module\Api\Mastodon\Lists::class, [R::GET, R::PUT, R::DELETE]],
|
||||||
'/lists/{id:\d+}/accounts' => [Module\Api\Mastodon\Lists\Accounts::class, [R::GET, R::POST, R::DELETE]],
|
'/lists/{id:\d+}/accounts' => [Module\Api\Mastodon\Lists\Accounts::class, [R::GET, R::POST, R::DELETE]],
|
||||||
'/markers' => [Module\Api\Mastodon\Markers::class, [R::GET, R::POST]], // Dummy, not supported
|
'/markers' => [Module\Api\Mastodon\Markers::class, [R::GET, R::POST]],
|
||||||
'/media/{id:\d+}' => [Module\Api\Mastodon\Media::class, [R::GET, R::PUT ]],
|
'/media/{id:\d+}' => [Module\Api\Mastodon\Media::class, [R::GET, R::PUT ]],
|
||||||
'/mutes' => [Module\Api\Mastodon\Mutes::class, [R::GET ]],
|
'/mutes' => [Module\Api\Mastodon\Mutes::class, [R::GET ]],
|
||||||
'/notifications' => [Module\Api\Mastodon\Notifications::class, [R::GET ]],
|
'/notifications' => [Module\Api\Mastodon\Notifications::class, [R::GET ]],
|
||||||
|
|
Loading…
Reference in a new issue