From 167c74df848c65f56b29ae1d528df62f0d7f12fe Mon Sep 17 00:00:00 2001 From: Ivan Habunek Date: Thu, 29 Jun 2023 11:10:23 +0200 Subject: [PATCH] wip --- requirements-dev.txt | 2 ++ requirements-test.txt | 1 + toot/aapi.py | 26 ++++++++++++++++++++++++ toot/commands.py | 47 +++++++++++++++++++------------------------ 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index dfa5b15..8124474 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,5 +1,7 @@ coverage +ipython keyring +pudb pyxdg pyyaml sphinx diff --git a/requirements-test.txt b/requirements-test.txt index 3a35c72..19ab840 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,5 +1,6 @@ flake8 psycopg2-binary pytest +pytest-cov pytest-xdist[psutil] vermin diff --git a/toot/aapi.py b/toot/aapi.py index 7ad3861..5e82562 100644 --- a/toot/aapi.py +++ b/toot/aapi.py @@ -1,4 +1,6 @@ +import re from typing import Optional +from urllib.parse import urlparse from uuid import uuid4 from toot import Context @@ -126,3 +128,27 @@ async def get_status(ctx: Context, status_id) -> Response: async def get_status_context(ctx: Context, status_id) -> Response: url = f"/api/v1/statuses/{status_id}/context" return await request(ctx, "GET", url) + + +# Timelines + +async def home_timeline_generator(ctx: Context, limit=20): + path = "/api/v1/timelines/home" + params = {"limit": limit} + return _timeline_generator(ctx, path, params) + + +async def _timeline_generator(ctx: Context, path: str, params=None): + while path: + response = await request(ctx, "GET", path, params=params) + yield response.json + path = _get_next_path(response.headers) + + +def _get_next_path(headers: dict): + """Given timeline response headers, returns the path to the next batch""" + links = headers.get('Link', '') + matches = re.match('<([^>]+)>; rel="next"', links) + if matches: + parsed = urlparse(matches.group(1)) + return "?".join([parsed.path, parsed.query]) diff --git a/toot/commands.py b/toot/commands.py index c0c72b6..916d58b 100644 --- a/toot/commands.py +++ b/toot/commands.py @@ -16,7 +16,7 @@ from toot.tui.utils import parse_datetime from toot.utils import args_get_instance, delete_tmp_status_file, editor_input, multiline_input, EOF_KEY -def get_timeline_generator(app, user, args): +async def get_timeline_generator(ctx, args): if len([arg for arg in [args.tag, args.list, args.public, args.account] if arg]) > 1: raise ConsoleError("Only one of --public, --tag, --account, or --list can be used at one time.") @@ -26,35 +26,30 @@ def get_timeline_generator(app, user, args): if args.instance and not (args.public or args.tag): raise ConsoleError("The --instance option is only valid alongside --public or --tag.") - if args.public: - if args.instance: - return api.anon_public_timeline_generator(args.instance, local=args.local, limit=args.count) - else: - return api.public_timeline_generator(app, user, local=args.local, limit=args.count) - elif args.tag: - if args.instance: - return api.anon_tag_timeline_generator(args.instance, args.tag, limit=args.count) - else: - return api.tag_timeline_generator(app, user, args.tag, local=args.local, limit=args.count) - elif args.account: - return api.account_timeline_generator(app, user, args.account, limit=args.count) - elif args.list: - return api.timeline_list_generator(app, user, args.list, limit=args.count) - else: - return api.home_timeline_generator(app, user, limit=args.count) + return await aapi.home_timeline_generator(ctx, limit=args.count) + # if args.public: + # if args.instance: + # return api.anon_public_timeline_generator(args.instance, local=args.local, limit=args.count) + # else: + # return api.public_timeline_generator(app, user, local=args.local, limit=args.count) + # elif args.tag: + # if args.instance: + # return api.anon_tag_timeline_generator(args.instance, args.tag, limit=args.count) + # else: + # return api.tag_timeline_generator(app, user, args.tag, local=args.local, limit=args.count) + # elif args.account: + # return api.account_timeline_generator(app, user, args.account, limit=args.count) + # elif args.list: + # return api.timeline_list_generator(app, user, args.list, limit=args.count) + # else: + # return api.home_timeline_generator(app, user, limit=args.count) -def timeline(app, user, args, generator=None): +async def timeline(ctx: Context, args, generator=None): if not generator: - generator = get_timeline_generator(app, user, args) - - while True: - try: - items = next(generator) - except StopIteration: - print_out("That's all folks.") - return + generator = await get_timeline_generator(ctx, args) + async for items in generator: if args.reverse: items = reversed(items)