enable-mastodon-apps icon indicating copy to clipboard operation
enable-mastodon-apps copied to clipboard

Ivory for macOS and iOS: `token-required`

Open qmoya opened this issue 1 year ago • 8 comments

Hi there!

I’m trying to make this work, but, when used with Ivory, I keep getting a token-required error for some API calls.

These work:

/api/v1/accounts/4/followers?limit=16
/api/v1/accounts/4
/api/v1/instance/languages
/api/v2/instance
/api/v1/preferences
/api/v1/accounts/verify_credentials
/api/v1/notifications?limit=80&types%5B%5D=mention&types%5B%5D=status&types%5B%5D=reblog&types%5B%5D=follow&types%5B%5D=follow_request&types%5B%5D=favourite&types%5B%5D=poll&types%5B%5D=update
/api/v1/notifications?limit=80&types%5B%5D=mention
/api/v1/timelines/home?limit=40&min_id=159
/api/v1/lists

but these fail:

/api/v1/accounts/4/statuses?limit=5&pinned=1
/api/v1/accounts/4/statuses?limit=50
/api/v1/featured_tags?limit=80
/api/v1/accounts/4/statuses?exclude_reblogs=1&limit=40

Ivory properly sets the Authorization header to Bearer 123123.

Am I missing something?

Thank you so much!

qmoya avatar Apr 12 '24 07:04 qmoya

Hi, sorry for the trouble! I think you discovered a bug here. The ! should be removed in this line: https://github.com/akirk/enable-mastodon-apps/blob/c9fbb3b7c2017d4346acc4af6efb63670a0d917e/includes/class-mastodon-api.php#L724

We're in the middle of a refactoring which will take some time until we can do a new release but we'll fix it in the next version. For now, you could just patch it yourself, if you feel comfortable with that.

akirk avatar Apr 12 '24 07:04 akirk

Thanks, @akirk — that fixed it!

But there’s another issue now: an infinite loop when fetching statuses.

/api/v1/accounts/4/statuses?exclude_reblogs=1&limit=40&max_id=159

This gets called non-stop. My assumption is that it’s related to the pagination logic.

I think this one is a bit more concerning — most users won’t notice that their servers are under a constant load while using their clients.

qmoya avatar Apr 12 '24 08:04 qmoya

How fast does it get polled? Because this plugin cannot provide websocket push, the client needs to repeatedly check if there are new statuses.

akirk avatar Apr 12 '24 08:04 akirk

Once every second, maybe a bit less.

I’m inspecting the headers. I only have two test posts, and I believe the Links are incorrect:

Link: <.../api/v1/accounts/4/statuses?max_id=159>; rel="next"
Link: <.../api/v1/accounts/4/statuses?min_id=164>; rel="prev"

I’m not familiar with the Mastodon API, but possibly there should be no next, because there are no posts left...

qmoya avatar Apr 12 '24 09:04 qmoya

This seems to fix that issue and another one I found: the posts were not being returned from newest to oldest. All credit goes to ChatGPT :)

	private function get_posts( $args, $min_id = null, $max_id = null ) {
		// Modify the limit to fetch one more post than requested to check for more posts
		$original_limit = $args['posts_per_page'];
		$args['posts_per_page'] += 1;
	
		if ( $min_id ) {
			$min_filter_handler = function ( $where ) use ( $min_id ) {
				global $wpdb;
				return $where . $wpdb->prepare( " AND {$wpdb->posts}.ID > %d", $min_id );
			};
			add_filter( 'posts_where', $min_filter_handler );
		}
	
		if ( $max_id ) {
			$max_filter_handler = function ( $where ) use ( $max_id ) {
				global $wpdb;
				return $where . $wpdb->prepare( " AND {$wpdb->posts}.ID < %d", $max_id );
			};
			add_filter( 'posts_where', $max_filter_handler );
		}
	
		$posts = get_posts( $args );
		if ( $min_id ) {
			remove_filter( 'posts_where', $min_filter_handler );
		}
		if ( $max_id ) {
			remove_filter( 'posts_where', $max_filter_handler );
		}
	
		// Determine if there are more posts beyond the limit
		$has_more_posts = count($posts) > $original_limit;
	
		// If there are more posts, remove the extra post from the results
		if ($has_more_posts) {
			array_pop($posts); // Adjust the posts array to the original limit
		}
	
		$statuses = array();
		foreach ( $posts as $post ) {
			$status = $this->get_status_array( $post );
			if ( $status ) {
				$statuses[$post->post_date] = $status;
			}
		}
	
		// Sort statuses by their post date in reverse order
		krsort($statuses);
	
		$ret = array();
		foreach ($statuses as $status) {
			$ret[] = $status;
		}
	
		// Adjusting the header logic based on the existence of more posts
		if (!empty($ret)) {
			if ($has_more_posts) {
				// Only add "next" link if there are more posts
				$last_post_id = end($ret)['id'];
				header('Link: <' . add_query_arg('max_id', $last_post_id, home_url(strtok($_SERVER['REQUEST_URI'], '?'))) . '>; rel="next"', false);
			}
			header('Link: <' . add_query_arg('min_id', $ret[0]['id'], home_url(strtok($_SERVER['REQUEST_URI'], '?'))) . '>; rel="prev"', false);
		}
	
		return $ret;
	}

qmoya avatar Apr 12 '24 09:04 qmoya

Thanks! We've touched/fixed the pagination in #99 and we hope to ship it soon so that it will work out of the box again.

akirk avatar Apr 12 '24 09:04 akirk

May this also be why Mona frequently requests new tokens? Especially if I switch to my profile page, Mona claims that there is no token or the token has expired, and requests I log in again. In the Mastodon Apps admin page, I see two or more apps, all tokens are set to expire in two years, but still several calls seem to cause the token to be considered expired. Also, I only get posts from the Friends plugin that I follow via ActivityPub. I don't get posts from a blog I follow via RSS, nor do I see my own recently published posts.

MarcoZehe avatar Jun 04 '24 07:06 MarcoZehe

I've released version 0.9.0, I'd be curious if this fixed it. Could you check? Thanks!

akirk avatar Jun 05 '24 14:06 akirk