from typing import List, Dict import FAAPI import Submission class User: """ A FurAffinity user. """ _usercache = {} def __init__(self, api, username: str): self._api = api self.username: str = username self._gallery: List[Submission.Submission] = None self._faves: List[Submission.Submission] = None self._watching: List[User] = None self._watchers: List[User] = None @property def username_lower(self) -> str: return self.username.lower() @property def gallery(self) -> List[Submission.Submission]: # Get the gallery if we don't have it already if not self._gallery: self._gallery = self._get_gallery() return self._gallery @property def faves(self) -> List[Submission.Submission]: # Get faves if we don't have them already if not self._faves: self._faves = self._get_faves() return self._faves @property def watching(self): # -> List[User]: # Get the list if we don't have it already if not self._watching: self._watching = self._get_watching() return self._watching @property def watchers(self): # -> List[User]: # Get the list if we don't have it already if not self._watchers: self._watchers = self._get_watchers() return self._watchers @staticmethod def new_or_cached(api, username: str): # -> User: if username not in User._usercache: User._usercache[username] = User(api, username) return User._usercache[username] def _get_gallery(self) -> List[Submission.Submission]: submissions = [] next_page_url = '{}/gallery/{}/'.format(FAAPI.FA_BASE_URL, self.username) while next_page_url: soup = self._api.get_soup(next_page_url) # Try get the next page try: next_page_button = soup.select('.submission-list form button[type=submit]')[0] next_page_url = FAAPI.FA_BASE_URL + next_page_button.parent().get('action') except: # No next page, null the url to break the loop next_page_url = None # Get all the submissions on this page for item in soup.select('.gallery figure'): sub = Submission.Submission.new_or_cached(self._api, int(item.get('id')[4:])) # IDs look like 'sid-35908275', so we just skip the 'sid-' submissions.append(sub) return submissions def _get_faves(self): submissions = [] next_page_url = '{}/favorites/{}/'.format(FAAPI.FA_BASE_URL, self.username) while next_page_url: soup = self._api.get_soup(next_page_url) # Try get the next page try: next_page_button = soup.select('.pagination a.button:last-child')[0] next_page_url = FAAPI.FA_BASE_URL + next_page_button.get('href') except: # No next page, null the url to break the loop next_page_url = None # Get all the submissions on this page for item in soup.select('.gallery figure'): sub = Submission.Submission.new_or_cached(self._api, int(item.get('id')[4:])) # IDs look like 'sid-35908275', so we just skip the 'sid-' submissions.append(sub) return submissions def _get_watching(self): watching = [] next_page_url = '{}/watchlist/by/{}/'.format(FAAPI.FA_BASE_URL, self.username) while True: soup = self._api.get_soup(next_page_url) # Stop processing if there aren't any users left users = soup.select('.watch-list .watch-list-items a') if len(users) == 0: break for item in users: watching.append(User.new_or_cached(self._api, item.text.strip())) # Try get the next page try: next_page_button = soup.select('.floatright form button[type=submit]')[0] next_page_url = FAAPI.FA_BASE_URL + next_page_button.parent().get('href') except: # No next page, break out break return watching def _get_watchers(self): watchers = [] next_page_url = '{}/watchlist/to/{}/'.format(FAAPI.FA_BASE_URL, self.username) while True: soup = self._api.get_soup(next_page_url) # Stop processing if there aren't any users left users = soup.select('.watch-list .watch-list-items a') if len(users) == 0: break for item in users: watchers.append(User.new_or_cached(self._api, item.text.strip())) # Try get the next page try: next_page_button = soup.select('.floatright form button[type=submit]')[0] next_page_url = FAAPI.FA_BASE_URL + next_page_button.parent().get('href') except: # No next page, break out break return watchers def __str__(self): return self.username