From ef52f66af89d0f6c0646a2faa684146c12db789f Mon Sep 17 00:00:00 2001 From: Daniel Langbein Date: Wed, 14 Dec 2022 12:13:25 +0100 Subject: [PATCH] add class ReadingPosition --- .../conversation/conversation.py | 43 ++++++++++--------- .../conversation/reading_position.py | 26 +++++++++++ src/mastodon_toot_follower/main.py | 11 +++-- .../server/flask_server.py | 14 +++--- static/style.css | 6 --- 5 files changed, 63 insertions(+), 37 deletions(-) create mode 100644 src/mastodon_toot_follower/conversation/reading_position.py diff --git a/src/mastodon_toot_follower/conversation/conversation.py b/src/mastodon_toot_follower/conversation/conversation.py index b708a10..a642d8b 100644 --- a/src/mastodon_toot_follower/conversation/conversation.py +++ b/src/mastodon_toot_follower/conversation/conversation.py @@ -2,31 +2,37 @@ from feedgen.feed import FeedGenerator from flask import url_for from mastodon_toot_follower import path_util +from mastodon_toot_follower.conversation.reading_position import ReadingPosition from mastodon_toot_follower.mastodon_factory import MastodonFactory from mastodon_toot_follower.conversation.update import Update as ConversationUpdate class Conversation: - def __init__(self, mastodon_factory: MastodonFactory, mastodon_instance: str, toot_id: str, seed: str = ''): + def __init__(self, mastodon_factory: MastodonFactory, mastodon_instance: str, toot_id: str): self.mastodon = mastodon_factory.get_mastodon(mastodon_instance) self.toot_id = toot_id self.toot = self.mastodon.status(id=self.toot_id) escaped_uri = path_util.escape(self.toot["uri"]) - if len(seed) > 0: - escaped_seed = path_util.escape(seed) - self.file = mastodon_factory.toot_cache_dir().joinpath(f'{escaped_uri}_{escaped_seed}.json') - else: - self.file = mastodon_factory.toot_cache_dir().joinpath(f'{escaped_uri}.json') + self.file = mastodon_factory.toot_cache_dir().joinpath(f'{escaped_uri}.json') # List of replies to initial toot. self.replies = self.mastodon.status_context(id=self.toot_id)['descendants'] - self.previous_updates: list[ConversationUpdate] = ConversationUpdate.load(self.file) - self.new_updates = ConversationUpdate.get_new_updates(self.previous_updates, self.toots()) + previous_updates: list[ConversationUpdate] = ConversationUpdate.load(file=self.file) + new_updates = ConversationUpdate.get_new_updates(previous_updates, self.toots()) + self._updates = previous_updates + new_updates + if len(new_updates) > 0: + ConversationUpdate.save(updates=self._updates, file=self.file) - self._changes_saved = False + def get_and_update_reading_position(self, user_id: str): + filename = self.file.stem + '_ReadingPosition.json' + file = self.file.parent.joinpath(filename) + + rp = ReadingPosition(file=file, user_id=user_id) + new_reading_position = len(self.toots()) + return rp.get_and_set(pos=new_reading_position) def as_feed(self, feed_url) -> FeedGenerator: """ @@ -47,7 +53,7 @@ class Conversation: fg.language('en') update: ConversationUpdate - for update in self.updates(): + for update in self._updates: fe = fg.add_entry() fe.id(update.dict['uri']) acct = update.dict['acct'] @@ -65,17 +71,14 @@ class Conversation: def conversation_length(self) -> int: return len(self.toots()) - def toots(self) -> list: + def updates(self, reading_position: int = 0) -> list: + """ + :param: reading_position: If given, returns only conversation updates after the reading position. + """ + return self._updates[reading_position:] + + def toots(self, reading_position: int = 0) -> list: """ :return: List of initial toot and it's replies. """ return [self.toot] + self.replies - - def updates(self) -> list[ConversationUpdate]: - return self.previous_updates + self.new_updates - - def save_changes(self) -> None: - if self._changes_saved: - return - ConversationUpdate.save(self.updates(), self.file) - self._changes_saved = True diff --git a/src/mastodon_toot_follower/conversation/reading_position.py b/src/mastodon_toot_follower/conversation/reading_position.py new file mode 100644 index 0000000..38325de --- /dev/null +++ b/src/mastodon_toot_follower/conversation/reading_position.py @@ -0,0 +1,26 @@ +import json +from pathlib import Path + + +class ReadingPosition: + def __init__(self, file: Path, user_id: str): + self.file = file + self.user_id = user_id + + if file.exists(): + self.dict = json.loads(self.file.read_text()) + else: + self.dict = {} + + def get(self) -> int: + return self.dict.get(self.user_id, 0) + + def set(self, pos: int): + self.dict[self.user_id] = pos + with self.file.open('w') as f: + f.write(json.dumps(self.dict)) + + def get_and_set(self, pos: int) -> int: + old_pos = self.get() + self.set(pos) + return old_pos diff --git a/src/mastodon_toot_follower/main.py b/src/mastodon_toot_follower/main.py index 89ce043..dc38b56 100644 --- a/src/mastodon_toot_follower/main.py +++ b/src/mastodon_toot_follower/main.py @@ -24,11 +24,16 @@ def main(): conversation = Conversation(mastodon_factory=mastodon_factory, mastodon_instance=instance_url, toot_id=toot_id) - conversation.save_changes() + reading_position = conversation.get_and_update_reading_position('local_user') + print(f'Reading position: {reading_position}') print(f'Conversation length: {conversation.conversation_length()}') - print(f'Conversation updates:\n') - print('\n'.join([str(update) for update in conversation.new_updates])) + new_updates = conversation.updates(reading_position=reading_position) + if len(new_updates) == 0: + print('No new updates.') + else: + print(f'New updates:\n') + print('\n'.join([str(update) for update in new_updates])) def usage(): diff --git a/src/mastodon_toot_follower/server/flask_server.py b/src/mastodon_toot_follower/server/flask_server.py index dee0446..9850f4f 100644 --- a/src/mastodon_toot_follower/server/flask_server.py +++ b/src/mastodon_toot_follower/server/flask_server.py @@ -36,7 +36,6 @@ def rss(): instance_url, username, toot_id = mastodon_util.parse_toot_url(url=url) conversation = Conversation(mastodon_factory=mastodon_factory, mastodon_instance=instance_url, toot_id=toot_id) - conversation.save_changes() fg = conversation.as_feed(request.url) return Response(fg.rss_str(), mimetype='application/rss+xml') @@ -49,10 +48,10 @@ def html(seed: str): conversation = Conversation(mastodon_factory=mastodon_factory, mastodon_instance=instance_url, - toot_id=toot_id, seed=seed) - conversation.save_changes() + toot_id=toot_id) + reading_position = conversation.get_and_update_reading_position(user_id=seed) - return render_template(Templates.updates.value, updates=conversation.new_updates) + return render_template(Templates.updates.value, updates=conversation.updates(reading_position=reading_position)) @app.route('/json//') @@ -62,12 +61,11 @@ def json(seed: str): conversation = Conversation(mastodon_factory=mastodon_factory, mastodon_instance=instance_url, - toot_id=toot_id, - seed=seed) - conversation.save_changes() + toot_id=toot_id) + reading_position = conversation.get_and_update_reading_position(user_id=seed) # If you return a dict or list from a view, it will be converted to a JSON response. - return [update.dict for update in conversation.new_updates] + return [update.dict for update in conversation.updates(reading_position=reading_position)] if __name__ == '__main__': diff --git a/static/style.css b/static/style.css index 3997e74..cb6750d 100644 --- a/static/style.css +++ b/static/style.css @@ -42,9 +42,3 @@ .styled-table tbody tr:last-of-type { border-bottom: medium solid #009879; } - -/* Make the active row look different */ -.styled-table tbody tr.active-row { - font-weight: bold; - color: #009879; -}