diff options
| author | uvok | 2025-01-21 20:26:58 +0100 | 
|---|---|---|
| committer | uvok | 2025-01-21 20:27:21 +0100 | 
| commit | 35891f6eaf8e5eb923cef5a2eb57afb503937936 (patch) | |
| tree | 67e3df37344437a30d47cdfacf4d5677ed60e85a | |
| parent | cd7c102ca59d2c59065e5b369ebc862104ad1607 (diff) | |
Handle paging, thread quit
| -rw-r--r-- | hello-fusepy.py | 71 | 
1 files changed, 45 insertions, 26 deletions
diff --git a/hello-fusepy.py b/hello-fusepy.py index a02bd9f..1db302b 100644 --- a/hello-fusepy.py +++ b/hello-fusepy.py @@ -6,7 +6,9 @@ import time  import requests  import sys  import stat -from threading import Thread, Lock + +from typing import Optional +from threading import Thread, Lock, Event  from queue import Queue  from datetime import datetime as dtp @@ -42,7 +44,7 @@ class Status(object):  class StatusProvider: -    def load_statuses(self) -> list[Status]: +    def load_statuses(self, max_id="") -> tuple[list[Status], Optional[str]]:          raise NotImplementedError      def _fallback_not_found(self): @@ -57,24 +59,30 @@ class ActivityPubStatusProvider(StatusProvider):          self.server = server          self.user = user -    def load_statuses(self) -> list[Status]: +    def load_statuses(self, max_id="") -> tuple[list[Status], Optional[str]]:          url = api_url_ap_template.format(server=self.server, user=self.user) +        if max_id: +            url += "&" + urllib.parse.urlencode({"max_id": max_id}) +        logger.debug("Get AP status from %s", url)          res = requests.get(url)          if res.status_code == 404: -            return self._fallback_not_found() +            return self._fallback_not_found(), None          try:              res.raise_for_status()          except requests.exceptions.RequestException as e:              logging.error("Request error: %s", e) -            return self._fallback_error(getattr(e, "message", str(e))) +            return self._fallback_error(getattr(e, "message", str(e))), None          stats = res.json()          status_items = stats.get("orderedItems", None)          if not status_items: -            return self._fallback_error("Malformed content in querying AP outbox.") +            return ( +                self._fallback_error("Malformed content in querying AP outbox."), +                None, +            ) -        return [ +        ss = [              Status(                  s["object"]["id"].split("/")[-1],                  s["object"]["content"], @@ -86,6 +94,7 @@ class ActivityPubStatusProvider(StatusProvider):              and all(key in s["object"] for key in ["id", "content", "published"])              and len(s["object"]["content"])          ] +        return ss, ss[-1].id  class MastodonStatusProvider(StatusProvider): @@ -94,36 +103,41 @@ class MastodonStatusProvider(StatusProvider):          self.user = user          self.userid = 0 -    def load_statuses(self) -> list[Status]: +    def load_statuses(self, max_id="") -> tuple[list[Status], Optional[str]]:          url = api_url_m_lookup_template.format(server=self.server)          url += "?" + urllib.parse.urlencode({"acct": self.user})          res = requests.get(url)          if res.status_code == 404: -            return self._fallback_not_found() +            return self._fallback_not_found(), None          try:              res.raise_for_status()          except requests.exceptions.RequestException as e:              logging.error("Request error: %s", e) -            return self._fallback_error(getattr(e, "message", str(e))) +            return self._fallback_error(getattr(e, "message", str(e))), None          user = res.json()          self.userid = user.get("id", None)          if not self.userid: -            return self._fallback_error("Malformed content in querying user ID.") +            return self._fallback_error("Malformed content in querying user ID."), None          url = api_url_m_status_template.format(              server=self.server, uid=urllib.parse.quote(self.userid)          ) + +        if max_id: +            url += "?" + urllib.parse.urlencode({"max_id": max_id}) +        logger.debug("Get Masto status from %s", url) +          res = requests.get(url)          if res.status_code == 404: -            return self._fallback_not_found() +            return self._fallback_not_found(), None          try:              res.raise_for_status()          except requests.exceptions.RequestException as e:              logging.error("Request error: %s", e) -            return self._fallback_error(getattr(e, "message", str(e))) +            return self._fallback_error(getattr(e, "message", str(e))), None          statuses = res.json() -        return [ +        ss = [              Status(                  s["id"],                  s["content"], @@ -133,6 +147,7 @@ class MastodonStatusProvider(StatusProvider):              if all(key in s for key in ["id", "content", "created_at"])              and len(s["content"])          ] +        return ss, ss[-1].id  class StatusFileSystem(Operations, LoggingMixIn): @@ -227,20 +242,23 @@ def parse_arguments():      return args +  # todo: make this a loop supporting paging -def status_fetcher(fs: StatusFileSystem, sp: StatusProvider): -    logger.debug("Waiting to fetch statuses.") -    time.sleep(5) -    logger.debug("Fetch statuses.") -    st = sp.load_statuses() -    logger.debug("Add statuses to FS.") -    fs.add_statuses(st) -    logger.debug("Wait...") -    time.sleep(5) +def status_fetcher(fs: StatusFileSystem, sp: StatusProvider, sig_quit: Event): +    max_id = "" +    while (max_id is not None) and not (sig_quit.wait(5)): +        logger.debug("Fetch statuses.") +        st_rep = sp.load_statuses(max_id) +        logger.debug("Add statuses to FS.") +        fs.add_statuses(st_rep[0]) +        max_id = st_rep[1] +        logger.debug("Waiting to fetch statuses.")      logger.debug("Done.")  def main(args): +    quit_evt = Event() +    t = None      try:          if args.api_choice == APIChoice.MASTODON:              status_provider = MastodonStatusProvider(args.server, args.username) @@ -249,7 +267,7 @@ def main(args):          myfs = StatusFileSystem() -        t = Thread(target=status_fetcher, args=(myfs, status_provider)) +        t = Thread(target=status_fetcher, args=(myfs, status_provider, quit_evt))          t.start()          f = FUSE(myfs, args.mountpoint, nothreads=True, foreground=True) @@ -257,8 +275,9 @@ def main(args):          fuse_exit()          raise      finally: -        # q.join() -        t.join() +        quit_evt.set() +        if t: +            t.join()  if __name__ == "__main__":  | 
