From 6fceee6efc79f60783c2beb5499a0f7a6a9ce7ee Mon Sep 17 00:00:00 2001 From: Timothy Quilling Date: Tue, 8 Aug 2023 13:49:57 -0400 Subject: [PATCH] chore: additional testing, refactor --- fedifetcher/api/__init__.py | 5 +- fedifetcher/api/api.py | 26 + fedifetcher/api/mastodon/api_mastodon.py | 193 ++-- lcov.info | 1183 +++++++++++----------- tests/test_api_mastodon.py | 161 ++- 5 files changed, 873 insertions(+), 695 deletions(-) diff --git a/fedifetcher/api/__init__.py b/fedifetcher/api/__init__.py index 5495fc4e..6453ed07 100644 --- a/fedifetcher/api/__init__.py +++ b/fedifetcher/api/__init__.py @@ -1,13 +1,14 @@ """__init__.py for api.""" -from . import api +from .api import API, FederationInterface from .firefish import api_firefish, api_firefish_types from .lemmy import api_lemmy from .mastodon import api_mastodon, api_mastodon_types from .postgresql import postgresql __all__ = [ - "api", + "API", + "FederationInterface", "api_firefish", "api_firefish_types", "api_lemmy", diff --git a/fedifetcher/api/api.py b/fedifetcher/api/api.py index d402a549..8b70f68e 100644 --- a/fedifetcher/api/api.py +++ b/fedifetcher/api/api.py @@ -29,3 +29,29 @@ def get_ids_from_list(self, uris: list[str]) -> Coroutine[Any, Any, dict[str, st def get_context(self, uri: str) -> Coroutine[Any, Any, list[str]]: """Get the context of an object by URI.""" raise NotImplementedError + +class FederationInterface: + """Interface for dependency injection of different federation APIs.""" + + _equipped_api: API + + def __init__(self, equippable_api: API) -> None: + """Initialize the API.""" + self._equipped_api: API = equippable_api + + def get(self, uri: str) -> Coroutine[Any, Any, dict | bool]: + """Get an object by URI.""" + return self._equipped_api.get(uri) + + def get_id(self, uri: str) -> Coroutine[Any, Any, str | None]: + """Get the ID of an object by URI.""" + return self._equipped_api.get_id(uri) + + def get_ids_from_list(self, uris: list[str]) -> Coroutine[Any, Any, dict[str, str]]: + """Get the IDs of objects by URIs.""" + return self._equipped_api.get_ids_from_list(uris) + + def get_context(self, uri: str) -> Coroutine[Any, Any, list[str]]: + """Get the context of an object by URI.""" + return self._equipped_api.get_context(uri) + diff --git a/fedifetcher/api/mastodon/api_mastodon.py b/fedifetcher/api/mastodon/api_mastodon.py index 881c891f..a39494af 100644 --- a/fedifetcher/api/mastodon/api_mastodon.py +++ b/fedifetcher/api/mastodon/api_mastodon.py @@ -7,9 +7,8 @@ from typing import Any, ClassVar, cast import aiohttp -from fedifetcher.api.api import API -from fedifetcher.api.firefish.api_firefish_types import UserLite +from fedifetcher.api.api import API from fedifetcher.api.mastodon.api_mastodon_types import Status from fedifetcher.api.postgresql import PostgreSQLUpdater from fedifetcher.helpers.helpers import Response @@ -32,7 +31,7 @@ def __init__(self, async def get(self, endpoint: str, params: dict | None = None, tries: int = 0, - semaphore: asyncio.Semaphore | None = None) -> dict[str, Any]: + semaphore: asyncio.Semaphore | None = None) -> dict[str, Any] | None: """Perform a GET request to the Mastodon server.""" if semaphore is None: semaphore = asyncio.Semaphore(1) @@ -55,7 +54,7 @@ async def get(self, f"Error with Mastodon API on server {self.api_base_url}. " f"Too many requests: {response}", ) - return {} + return None logging.warning( f"Too many requests to {self.api_base_url}. " f"Waiting 60 seconds before trying again.", @@ -63,7 +62,7 @@ async def get(self, await asyncio.sleep(60) return await self.get( endpoint=endpoint, params=params, tries=tries + 1) - return await self.handle_response_errors(response) + return await self.handle_response(response) except asyncio.TimeoutError: logging.warning( f"Timeout error with Mastodon API on server {self.api_base_url}.") @@ -79,37 +78,47 @@ async def get(self, except Exception: logging.exception( f"Unknown error with Mastodon API on server {self.api_base_url}.") - return {} + return None - async def handle_response_errors(self, response: aiohttp.ClientResponse, - ) -> dict: + def handle_response_lists(self, + body : dict | list[dict], + ) -> dict[str, Any]: + """Process the response into a dict.""" + if isinstance(body, list): + body = {"list": body} + if not isinstance(body, dict): + msg = \ + f"Error with Mastodon API on server {self.api_base_url}. \ +The server returned an unexpected response: {body}" + raise TypeError( + msg, + ) + return body + + def handle_response_pagination(self, + body : dict, + response : aiohttp.ClientResponse, + ) -> dict[str, Any]: + """Handle pagination in the response.""" + link_header = response.headers.get("Link") + if link_header: + links = {} + link_parts = link_header.split(", ") + for link_part in link_parts: + url, rel = link_part.split("; ") + url = url.strip("<>") + rel = rel.strip('rel="') + links[rel] = url + if links.get("next"): + body["_pagination_next"] = links["next"] + if links.get("prev"): + body["_pagination_prev"] = links["prev"] + return body + + def handle_response_errors(self, + response : aiohttp.ClientResponse, + ) -> None: """Handle errors in the response.""" - if response.status == Response.OK: - body = await response.json() - if body: - if isinstance(body, list): - body = {"list": body} - if not isinstance(body, dict): - logging.error( - f"Error with Mastodon API on server {self.api_base_url}. " - f"The server returned an unexpected response: {body}", - ) - return {} - link_header = response.headers.get("Link") - if link_header: - links = {} - link_parts = link_header.split(", ") - for link_part in link_parts: - url, rel = link_part.split("; ") - url = url.strip("<>") - rel = rel.strip('rel="') - links[rel] = url - if links.get("next"): - body["_pagination_next"] = links["next"] - if links.get("prev"): - body["_pagination_prev"] = links["prev"] - return body - return {"Status": "OK"} if response.status == Response.BAD_REQUEST: logging.error( f"Error with Mastodon API on server {self.api_base_url}. " @@ -140,7 +149,24 @@ async def handle_response_errors(self, response: aiohttp.ClientResponse, f"Error with Mastodon API on server {self.api_base_url}. " f"The server encountered an error: {response}", ) - return {} + + async def handle_response(self, response: aiohttp.ClientResponse, + ) -> dict | None: + """Handle errors in the response.""" + if response.status != Response.OK: + return self.handle_response_errors(response) + body = await response.json() + if not body: # Successful response with no body + return {"Status": "OK"} + try: + body: dict[str, Any] = self.handle_response_lists(body) + except TypeError: + logging.error( + f"Error with Mastodon API on server {self.api_base_url}. " + f"The server returned an unexpected response: {body}", + ) + return None + return self.handle_response_pagination(body, response) class Mastodon(API): """A class representing a Mastodon instance.""" @@ -197,8 +223,8 @@ async def get_user_id( account_search = await self.account_lookup( acct = f"{user}", ) - if not isinstance(account_search, bool) \ - and account_search.get("username") == user: + if account_search and \ + account_search.get("username") == user: return account_search["id"] return None @@ -226,7 +252,8 @@ async def get_home_timeline( Exception: If the server returns an unexpected status code. """ timeline_toots_dict = await self.timelines_home(limit=limit) - if not (timeline_toots := timeline_toots_dict.get("list")): + if not timeline_toots_dict or ( + timeline_toots := timeline_toots_dict.get("list")): return [] toots = cast(list[dict[str, str]], ( timeline_toots)) @@ -235,7 +262,7 @@ async def get_home_timeline( while isinstance(toots, dict) and number_of_toots_received < limit and \ timeline_toots_dict.get("_pagination_next"): toots_dict = await self.fetch_next(toots) - if not (toots := toots_dict.get("list")): + if not toots_dict or not (toots := toots_dict.get("list")): break number_of_toots_received += len(toots) toots_result.extend(toots) @@ -268,10 +295,13 @@ async def get_active_user_ids( logging.debug(f"Reply interval: {reply_interval_hours} hours") since = datetime.now(UTC) - timedelta(days=reply_interval_hours / 24 + 1) logging.debug(f"Since: {since}") - local_accounts = (await self.admin_accounts_v2( + account_list = await self.admin_accounts_v2( origin="local", status="active", - )).get("list") + ) + if not account_list: + return [] + local_accounts = (account_list).get("list") active_user_ids = [] if local_accounts: logging.debug(f"Found {len(local_accounts)} accounts") @@ -308,7 +338,10 @@ async def get_me(self) -> str | None: Exception: If the access token does not have the correct scope. Exception: If the server returns an unexpected status code. """ - return (await self.account_verify_credentials()).get("id") + me = await self.account_verify_credentials() + if me: + return (me).get("id") + return None async def get_user_posts_from_id( self, @@ -390,6 +423,8 @@ async def get_toot_context( return [] # Get the context of a toot context = await self.status_context(status_id=toot_id) + if not context: + return [] # List of status URLs ancestors = context.get("ancestors") or [] descendants = context.get("descendants") or [] @@ -443,7 +478,8 @@ async def get_notifications( exclude_types=exclude_types, account_id=account_id, ) - if not (notifications := notifications_dict.get("list")): + if not notifications_dict or \ + not (notifications := notifications_dict.get("list")): return [] number_of_notifications_received = len(notifications) notifications_result = notifications.copy() @@ -451,7 +487,8 @@ async def get_notifications( and number_of_notifications_received < limit \ and notifications_dict.get("_pagination_next"): more_notifications_dict = await self.fetch_next(notifications_dict) - if not (more_notifications := more_notifications_dict.get("list")): + if not more_notifications_dict or \ + not (more_notifications := more_notifications_dict.get("list")): break number_of_notifications_received += len(more_notifications) notifications_result.extend(more_notifications) @@ -474,7 +511,7 @@ async def get_bookmarks( list[dict[str, str]]: A list of bookmarks, or [] if the request fails. """ bookmarks_dict = await self.bookmarks(limit=limit) - if not (bookmarks := bookmarks_dict.get("list")): + if not bookmarks_dict or not (bookmarks := bookmarks_dict.get("list")): return [] number_of_bookmarks_received = len(bookmarks) bookmarks_result = bookmarks.copy() @@ -482,7 +519,8 @@ async def get_bookmarks( and number_of_bookmarks_received < limit \ and bookmarks_dict.get("_pagination_next"): more_bookmarks_dict = await self.fetch_next(bookmarks_dict) - if not (more_bookmarks := more_bookmarks_dict.get("list")): + if not more_bookmarks_dict or \ + not (more_bookmarks := more_bookmarks_dict.get("list")): break number_of_bookmarks_received += len(more_bookmarks) bookmarks_result.extend(more_bookmarks) @@ -505,7 +543,7 @@ async def get_favourites( list[dict[str, str]]: A list of favourites, or [] if the request fails. """ favourites_dict = await self.favourites(limit=limit) - if not (favourites := favourites_dict.get("list")): + if not favourites_dict or not (favourites := favourites_dict.get("list")): return [] number_of_favourites_received = len(favourites) favourites_result = favourites.copy() @@ -513,7 +551,8 @@ async def get_favourites( while number_of_favourites_received < limit \ and favourites_dict.get("_pagination_next"): more_favourites_dict = await self.fetch_next(favourites_dict) - if not (more_favourites := more_favourites_dict.get("list")): + if not more_favourites_dict or \ + not (more_favourites := more_favourites_dict.get("list")): break number_of_favourites_received += len(more_favourites) favourites_result.extend(more_favourites) @@ -536,7 +575,8 @@ async def get_follow_requests( list[dict[str, str]]: A list of follow requests, or [] if the request fails. """ follow_requests_dict = await self.follow_requests(limit=limit) - if not (follow_requests := follow_requests_dict.get("list")): + if not follow_requests_dict or \ + not (follow_requests := follow_requests_dict.get("list")): return [] number_of_follow_requests_received = len(follow_requests) follow_requests_result = follow_requests.copy() @@ -569,7 +609,7 @@ async def get_followers( list[dict[str, str]]: A list of followers, or [] if the request fails. """ followers_dict = await self.account_followers(account_id=user_id, limit=limit) - if not (followers := followers_dict.get("list")): + if not followers_dict or not (followers := followers_dict.get("list")): return [] number_of_followers_received = len(followers) followers_result = followers.copy() @@ -577,7 +617,8 @@ async def get_followers( and number_of_followers_received < limit \ and followers_dict.get("_pagination_next"): more_followers_dict = await self.fetch_next(followers_dict) - if not (more_followers := more_followers_dict.get("list")): + if not more_followers_dict or \ + not (more_followers := more_followers_dict.get("list")): break number_of_followers_received += len(more_followers) followers_result.extend(more_followers) @@ -602,7 +643,7 @@ async def get_following( list[dict[str, str]]: A list of following, or [] if the request fails. """ following_dict = await self.account_following(account_id=user_id, limit=limit) - if not (following := following_dict.get("list")): + if not following_dict or not (following := following_dict.get("list")): return [] number_of_following_received = len(following) following_result = following.copy() @@ -610,7 +651,8 @@ async def get_following( and number_of_following_received < limit \ and following_dict.get("_pagination_next"): more_following_dict = await self.fetch_next(following_dict) - if not (more_following := more_following_dict.get("list")): + if not more_following_dict or \ + not (more_following := more_following_dict.get("list")): break number_of_following_received += len(more_following) following_result.extend(more_following) @@ -649,7 +691,7 @@ async def add_context_url( logging.exception( f"Error adding context url {url} to {self.client.api_base_url}") return False - if (statuses := result.get("statuses")): + if result and (statuses := result.get("statuses")): for _status in statuses: if _status.get("url") == url: self.client.pgupdater.cache_status(_status) @@ -692,7 +734,8 @@ async def _get_trending_posts( """Get a page of trending posts and return it.""" getting_trending_posts_dict = await self.trending_statuses( limit=40, offset=offset) - if not (getting_trending_posts := getting_trending_posts_dict.get("list")): + if not getting_trending_posts_dict or not ( + getting_trending_posts := getting_trending_posts_dict.get("list")): return [] return cast(list[dict[str, str]], getting_trending_posts) @@ -858,7 +901,7 @@ def status( self, status_id: str, semaphore: asyncio.Semaphore | None = None, - ) -> Coroutine[Any, Any, dict[str, Any] | Status]: + ) -> Coroutine[Any, Any, dict[str, Any] | Status | None]: """Obtain information about a status. Reference: https://docs.joinmastodon.org/methods/statuses/#get @@ -868,7 +911,7 @@ def status( def status_context( self, status_id: str, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """View statuses above and below this status in the thread. Reference: https://docs.joinmastodon.org/methods/statuses/#context @@ -878,7 +921,7 @@ def status_context( def account_lookup( self, acct: str, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """Quickly lookup a username to see if it is available. Skips WebFinger resolution. @@ -926,14 +969,16 @@ async def account_statuses( status_json = await self.client.get( f"/api/v1/accounts/{account_id}/statuses", params=params) + if not status_json: + return [] status_list = status_json.get("list") - if status_list: - return status_list - return [] + if not status_list: + return [] + return status_list def account_verify_credentials( self, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """Test to make sure that the user token works. Reference: https://docs.joinmastodon.org/methods/accounts/#verify_credentials @@ -950,7 +995,7 @@ def notifications( # noqa: PLR0913 types: list[str] | None = None, exclude_types: list[str] | None = None, account_id: str | None = None, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """Notifications concerning the user. Reference: https://docs.joinmastodon.org/methods/notifications/#get @@ -982,7 +1027,7 @@ def bookmarks( since_id: str | None = None, min_id: str | None = None, limit: int | None = None, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """Statuses the user has bookmarked. Reference: https://docs.joinmastodon.org/methods/bookmarks/#get @@ -1004,7 +1049,7 @@ def favourites( min_id: str | None = None, since_id: str | None = None, limit: int | None = None, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """Statuses the user has favourited. Reference: https://docs.joinmastodon.org/methods/favourites/#get @@ -1025,7 +1070,7 @@ def follow_requests( max_id: str | None = None, since_id: str | None = None, limit: int | None = None, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """Follow requests the user has received. Reference: https://docs.joinmastodon.org/methods/follow_requests/#get @@ -1051,7 +1096,7 @@ def search_v2( # noqa: PLR0913 min_id: str | None = None, limit: int | None = None, offset: int | None = None, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """Perform a search. Reference: https://docs.joinmastodon.org/methods/search/#v2 @@ -1093,7 +1138,7 @@ def admin_accounts_v2( since_id: str | None = None, min_id: str | None = None, limit: int | None = None, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """View all accounts. View all accounts, optionally matching certain criteria for filtering, @@ -1134,7 +1179,7 @@ def admin_accounts_v2( return self.client.get("/api/v2/admin/accounts", params=params) def fetch_next(self, previous_page: dict[str, Any], - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """Fetch the next page of results. Reference: https://docs.joinmastodon.org/api/guidelines/#pagination @@ -1147,7 +1192,7 @@ def account_followers( max_id: str | None = None, since_id: str | None = None, limit: int | None = None, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """Accounts which follow the given account. If network is not hidden by the account owner. @@ -1170,7 +1215,7 @@ def account_following( max_id: str | None = None, since_id: str | None = None, limit: int | None = None, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """Accounts which the given account is following. If network is not hidden by the account owner. @@ -1191,7 +1236,7 @@ def trending_statuses( self, limit: int | None = None, offset: int | None = None, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """Get trending statuses. Reference: https://docs.joinmastodon.org/methods/trends/#statuses @@ -1209,7 +1254,7 @@ def timelines_home( since_id: str | None = None, min_id: str | None = None, limit: int | None = None, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """Home timeline. Reference: https://docs.joinmastodon.org/methods/timelines/#home @@ -1234,7 +1279,7 @@ def timelines_public( since_id: str | None = None, min_id: str | None = None, limit: int | None = None, - ) -> Coroutine[Any, Any, dict[str, Any]]: + ) -> Coroutine[Any, Any, dict[str, Any] | None]: """Public timeline. Reference: https://docs.joinmastodon.org/methods/timelines/#public diff --git a/lcov.info b/lcov.info index 73d6dca3..f255edc4 100644 --- a/lcov.info +++ b/lcov.info @@ -16,7 +16,7 @@ end_of_record TN: SF:fedifetcher\api\__init__.py DA:1,1,ucNS134G+oHn19wS3+1JGw -DA:3,1,6y1dM/7yL6sN82+Pnk7ufQ +DA:3,1,rVggN5bCbYf/OOOsVZ/ImQ DA:4,1,sGHMNhpjQXmI8jqlR7xyWQ DA:5,1,17FtLN7Fy8imM3Jn9dwYmg DA:6,1,6uFpK9uXpegYy6KdrrUT8Q @@ -551,581 +551,618 @@ DA:5,1,q2SfeQvg2Pu23hAoTkxkgQ DA:6,1,YgPHxeUnZvGQKEq84WHuuw DA:7,1,kuSvEyeRCiu7/TW/fqEqzw DA:9,1,x2rU71IPijCTcnXLQBWEjw -DA:11,1,S2uSnSSe2oHuPK7f5VO4Jw -DA:12,1,1B2M2Y8AsgTpgAmY7PhCfg -DA:13,1,D+l6YWsHWuGi25qlImrd5A +DA:11,1,bVX6F+17njKx8eo6xUX05w +DA:12,1,D+l6YWsHWuGi25qlImrd5A +DA:13,1,XZGKsazXjlym+Csyy1dBPg DA:16,1,1B2M2Y8AsgTpgAmY7PhCfg -DA:17,1,1B2M2Y8AsgTpgAmY7PhCfg -DA:19,1,joe/9LtamZimhkLzbuPlfg -DA:20,1,1B2M2Y8AsgTpgAmY7PhCfg -DA:21,1,hTE1rgDMrPr3J1EpZDoxSA -DA:31,1,IreNhM4AZeEM/K2TzbOOBg -DA:32,1,1B2M2Y8AsgTpgAmY7PhCfg -DA:33,1,uDCzQGjY0NwDx4sWT7OTcA -DA:82,1,/epQTfp1jOvjGFsvUkRYHA -DA:83,1,1B2M2Y8AsgTpgAmY7PhCfg -DA:143,1,zl1rFSYAKDKdsRsH+EJTcQ -DA:144,1,1B2M2Y8AsgTpgAmY7PhCfg -DA:146,1,zoovQ7CICFmiZh9/12GLbA -DA:147,1,1B2M2Y8AsgTpgAmY7PhCfg -DA:148,1,ROs40pbjANDFKGws4199Jg -DA:149,1,hTE1rgDMrPr3J1EpZDoxSA -DA:176,1,JA8+cAeyHuPCGnrHBbqXUw -DA:178,1,Mee0OUWUoWQbhCw+zB7mAA -DA:203,1,apkQQtiiE4JOuDIBvLOUjQ -DA:205,1,2BiY/s2QK87iIH3qHuTGLw -DA:243,1,IZqWZOTsWvAqSe/PFraq9w -DA:245,1,+cF6UqNU8lOA4yjHHlTmLA -DA:290,1,4ITW4OYJHSXEAadkyzrbZg -DA:311,1,fKNeXQVrX6woFAieym2BwQ -DA:313,1,F2/4qaK6sx5q98dZowyB2g -DA:337,1,lJTPCSDMH24i26mCMOI+Rw -DA:342,1,f2DZT8vigRLWtdN0n2hKkA -DA:379,1,apkQQtiiE4JOuDIBvLOUjQ -DA:381,1,RcyR7blD3k+5ByLAYMTEdw -DA:411,1,10JUNym+3lqk9WVPiaqQiQ -DA:413,1,32Re8V66dXRYtXl4420mkw -DA:458,1,Xa6MJWa1goKiIlT73MxLBg -DA:460,1,NmEj+NoaWjr8GW9MO7ciMw -DA:489,1,hiA1YHf2IMvOTS6q5OGGEw -DA:491,1,4/gWcalEmzQJ2j07AxkH6g -DA:520,1,jC8fZqhggGRwbqt7CFX/Ng -DA:522,1,YsIBpVmHprt3psAn5fTOdQ -DA:551,1,oHxyUjkM5k23OXyy97bgow -DA:553,1,/APRDzagsh1SY55Vx4k7yw -DA:584,1,HFDjddiDbkIPCUW/q34kJA -DA:586,1,wG84PcQBZ5EPrdWft4nB0g -DA:617,1,DH5AL+WrJcJ5aw+DZUC9MQ -DA:619,1,tfAKjJYdo0EWF3Sxdqsw/Q -DA:669,1,kycMaH6XbPuAfUpgfG1Lbg -DA:671,1,bAsJHlcLAGvDwizXRIaHtQ -DA:732,1,xv/snrRzxrlGnA7265NxKQ -DA:734,1,SkdDdiGij68sVrHvlB0NWQ -DA:778,1,apkQQtiiE4JOuDIBvLOUjQ -DA:780,1,jEKSYfikD4FxMUO8998Srg -DA:837,1,h8v58CjcqhG/CCBFWdi4Qg -DA:839,1,QEmgDbbXOYcteN5plE4GvA -DA:855,1,AttrAvjZUi95la5E1cT/KA -DA:857,1,N68YF3DP9LmJNl+7VWmVRg -DA:866,1,l1M1TDXvvQ5yUbmtnjqn2w -DA:868,1,nOqVrRMCkXFh/NswKgK/+g -DA:876,1,cVvClAJ7fPb430fcfUDB/w -DA:878,1,sJ+kAId7e0J9Z9VYHWwspQ -DA:888,1,ZymDT9SV55t8XzPfBTwYNA -DA:890,1,v/OelOV6I/zRJUkmIpaUAg -DA:932,1,/8OSaRsMmJp+uF82kF50RQ -DA:934,1,+VPBq9vj/FooJgSDGIQpVQ -DA:941,1,/zQfDZVZn+WvFlLPSbio6A -DA:943,1,iBffJob4HxZC2KUE2+tBIw -DA:976,1,GJiiEiXIBBYlbmAc2d20cw -DA:979,1,4ih6Cba7T6MFgo5qzn7mMg -DA:999,1,WtdXhA+c4ECL45VDhBvLNQ -DA:1001,1,JM4bFqyvgS32fsAUrW00+w -DA:1021,1,Lcf3cpDRxIxgEHeCaUjOdQ -DA:1023,1,qq75Yj5maPMF3NEGoCEUwA -DA:1040,1,RetsfkMpeeaB7RRieu8d5g -DA:1042,1,yqYXQ5/tdxB4pm97QLyicw -DA:1078,1,ez2ifEfw0w1reEqj3l+HXQ -DA:1080,1,75M+HYmT7IpGsjQSCJbqQg -DA:1134,1,oiUqYk9mXmgBFyYoL965Ew -DA:1135,1,1B2M2Y8AsgTpgAmY7PhCfg -DA:1142,1,2ZYwYJ+Jl0IFMDuN/9J6hg -DA:1144,1,E9URW+kr6yM/gPe0diDy0w -DA:1164,1,GJiiEiXIBBYlbmAc2d20cw -DA:1167,1,uy/+2UQ1hurYXR3WNfVC+Q -DA:1187,1,GJiiEiXIBBYlbmAc2d20cw -DA:1190,1,5cvehKpcl8YyUB4amhtabQ -DA:1204,1,HQTMASG9arIFBAUEplTVGw -DA:1206,1,VpVF/b/JwE3a3UeLWNySmw -DA:1226,1,FdOIhKMNDTWmArY6mE+p8Q -DA:1228,1,BvqBNJ5drKAqiaIfoEeOUg -DA:1255,1,KGOcZ7tNS2cPR1ePCY+sEg -DA:1256,1,1B2M2Y8AsgTpgAmY7PhCfg -DA:1257,1,tFmTo3GN7D476fTmu2ha9g -DA:10,0,bVX6F+17njKx8eo6xUX05w -DA:14,0,XZGKsazXjlym+Csyy1dBPg -DA:15,0,25JmQhfpJE3/1TMKqa64Zg -DA:18,0,6OGgj7RRn6C8Uq1OUmjHQA -DA:28,0,p9VObvqSCRj8hcqJMkKDlA -DA:29,0,zBjO06PAbZZW4g+bTyqW5Q -DA:30,0,JS74W3nICDgQiP5wLso2mQ -DA:37,0,44kgpEfTnufzieeeqpuFBQ -DA:38,0,khr4jjSbKCmUSDSkn9542w -DA:39,0,Czt1tw8x/ym/XaWP2S5cBA -DA:40,0,xvWIcpcyNr0gyGcTkdMxXw -DA:41,0,0FtrCMosXSaurDdZdyoNSw -DA:42,0,T2GmA/KrsmextvuNF6pEdg -DA:43,0,0BH60IeV3dj2ff+ttSAwWQ -DA:50,0,Z387ldJEJTGYGvk6V05k4Q -DA:51,0,9j4l37rppgKJMhUrO5DY5g -DA:52,0,eiO+X5cOpgI5VfexPgdpHg -DA:53,0,lWWLo5RM9bWPLYNOEHaELg -DA:54,0,DS71dJSuULr9SUHgZmMJxA -DA:58,0,QRW1zu5SjVdd9YDT92ZPVQ -DA:59,0,6NheNDITGp582x23bNiDVA -DA:63,0,gKuQAzAbg+y7MTiGq97hkQ -DA:64,0,AWrg01p1wblEI5Q7AuxJqQ -DA:66,0,yZqDniMMuo5e9WTFZHAl6Q -DA:67,0,368GSSPPh9Nb/29q1R9W9Q -DA:68,0,wE/HVD7tdITXHHTVApw90Q -DA:70,0,vU3aaiuq9XvgN9mjgDtxDw -DA:71,0,wE/HVD7tdITXHHTVApw90Q -DA:73,0,pCocN4k10WZ/cYUGmTQcZw -DA:74,0,5Rn4oX7c4pPaXSvRAjy2qA -DA:76,0,VqOLNdKenpg2SNLNQd0cJQ -DA:77,0,5Rn4oX7c4pPaXSvRAjy2qA -DA:79,0,Pkwsntebe693LwjKD9saWA -DA:80,0,5Rn4oX7c4pPaXSvRAjy2qA -DA:84,0,gYKpzwT/YEbdguFox3rrlg -DA:87,0,AIksWlLsYA8w/3gOjq9G2A -DA:88,0,fGC6ofdfv46j2hQnHNhRTw -DA:89,0,e3ikH9h+EYIci4k0Eum0yQ -DA:90,0,+dRM2510Vea3I+gXfAgZfg -DA:91,0,yQLlSPElS5y7J0Sbs528Sw -DA:92,0,7NzqDP/5gDfF7/7bN4P3bw -DA:93,0,nccmmjobZElUjJt/bqipTg -DA:97,0,yA5vh+rEmGX5nDORfAl/yg -DA:98,0,S+N7Wpflt2kGGEPGhUFWpQ -DA:99,0,h/eQDeqqcMxmcB2P2LnjYQ -DA:100,0,hamCVEvj4WJ+Ii1x+Rta1A -DA:101,0,P+TyEGPIA/Gz4nQOsmZ2fg -DA:102,0,y15WjSriO4pQZ01Y3z0sJA -DA:103,0,JsixOike6WVzvbn00Ke17g -DA:104,0,WU5DdQBQCA5EBrvPidXwOQ -DA:105,0,KhZknOMCAszX+v2goAxSvw -DA:106,0,KKKgFRkZN5FfFSewVKXHHQ -DA:107,0,DUJnlxhOjzSEkxLnJp0z6A -DA:108,0,YJ29CfKL29eT2BdOJA5QcA -DA:109,0,QZp+wCSS+bRYstRsI9QojA -DA:110,0,2fpZat1R9oocou870vlKQA -DA:111,0,GDs6RfutuKr88FmeG2ax0A -DA:112,0,Pc49EbAgGAyxW8VSvinGug -DA:113,0,ZJMQKZgDAlye4jp61Yq0Pg -DA:114,0,Sl7CegX2CveFT4pHpVwD8g -DA:118,0,78Hbj6SM5UIaaJytjmYfvA -DA:119,0,Sl7CegX2CveFT4pHpVwD8g -DA:123,0,oL/4o4g/4ob2E5nXenm86w -DA:124,0,Sl7CegX2CveFT4pHpVwD8g -DA:128,0,dJFaXiSMspie5FRQRvgb/w -DA:129,0,Sl7CegX2CveFT4pHpVwD8g -DA:133,0,Kfsq9A5CdwanjkV6f4glzw -DA:134,0,VdJ5KSGdN1AmU/IO2DW8vg -DA:139,0,Sl7CegX2CveFT4pHpVwD8g -DA:145,0,Bt/Zp3S+5k4PfN6YoR5Qhw -DA:155,0,lkXgvotEVtlpg1yvFIAv0Q -DA:159,0,Env7HnARD0RqQeOVlh5dww -DA:160,0,Z4XZnYHKPrSQi1H2dgjjIw -DA:161,0,wCX8YfaarZ/3GROSUgXujQ -DA:162,0,90Q1WIj/uxwtePu7xe4r5g -DA:163,0,3A9LdVO6r2Za695tInT0lQ -DA:164,0,9hwOohZvE3EKTjYEU/bYBg -DA:170,0,aNjgHzUwQiw7DGJixOKPSQ -DA:197,0,7g8Yo0YMxES17wG7TYXndw -DA:200,0,LxytcTTJSwCJeiqWJoWs1g -DA:202,0,oF3SlTRNSZaf1ZuXg+V76A -DA:228,0,ssIF1fCEOBHLBkh3a3sXXQ -DA:229,0,ucn3gxyN3NjsKoPy8zm8EA -DA:230,0,OIAvCMSD+70detM1HMKKPQ -DA:231,0,f90UtmyNW0kxxdhBJVzAgw -DA:233,0,P8eCOjooHxDWajIkhBnl+A -DA:234,0,bT066rreWOjkYXAnw/1B9w -DA:235,0,wt/9Iwd9kPx02oaZcC/flg -DA:237,0,/k7T79k9lU6K5iFv+Ju9SQ -DA:238,0,rLZSp90UfcHkSGabEi5ClA -DA:239,0,pOJwuGdEbe7GLbMcySd1QA -DA:240,0,CkgigQ/3i3chcws6hKAbLw -DA:241,0,JPJezm3Yy+H+Kl+PZB6YYA -DA:242,0,NGmVALe18KXEQxtsOhGX2Q -DA:267,0,zoDLejlqQlRf2ucU3scAuw -DA:268,0,+vAPgpQFVaHcAvHTqcXZBg -DA:269,0,H1O15Pwpt/+0JwGoOqzrKg -DA:270,0,ydnhx2+coBT9AEjxgQItxQ -DA:271,0,mIqfZffgdeyO70uODAJtbw -DA:275,0,H/VeMVqH986O8noeK2YCNg -DA:276,0,oND+H7Qxvl9ouDTvJjFv0Q -DA:277,0,PbmX1Cd0U0qZKWTMU7B28A -DA:278,0,PoHKNNDCoyXNnpH8u7HNBg -DA:279,0,gjRspMkr/oTxsUC0FkGMvA -DA:280,0,misTxSWDsBzaqTqV8vKBPA -DA:281,0,2uHV1gZHr0Y6lWeYUQ6nKg -DA:282,0,pUD+Odh5opnxVcZra+mVcQ -DA:283,0,HAUEys9fOYKJfmObitzkpg -DA:284,0,aiUkAlUyIsQ+CSd7Y/RJzQ -DA:285,0,3hp7pN/rYHqrEc/YHc1Pag -DA:286,0,+rk5RUyo97sF/BTCgPRVGQ -DA:287,0,nuLZTkfkBrnm/oc0sr1NYg -DA:288,0,S/Pxlc+XlLxDdwEBcSNUWA -DA:289,0,t0p4xTIPmSe6ByP0gHlnng -DA:292,0,z7i0Jn7UbBUL9TBo6pAz4A -DA:336,0,qEq5fkr8P4P4MS4gSEhPxg -DA:362,0,hYX17cQO11ozXTscC7m0bw -DA:363,0,Dwjd91USmMoWKfkSCVg/jg -DA:364,0,xjcDBnSwra0OiNOAYAwoHA -DA:365,0,/q39rlzr8yvOkjYCOooFdQ -DA:366,0,w/tTPAQnqaFNbPE+sYWqLQ -DA:367,0,Y2zHg3ew+eUpe2Vsli99yg -DA:376,0,o7tvNiq40uwo8eP+lY5kyg -DA:377,0,2bX0G6/iuxFHcsTheYCilQ -DA:378,0,NvVxGrDiJsGH6QhWsv4EYA -DA:389,0,J2pxm/Ku8kYvNxyokeJ/Yw -DA:390,0,OIAvCMSD+70detM1HMKKPQ -DA:392,0,Nd911YyrSQlctqiMugvD2g -DA:394,0,Nbc84V1Eh7Rb1tz/Bxq+UQ -DA:395,0,lWBV0nNGbbwGmQTw8Riq6w -DA:396,0,ve/6DLF89DaE65hW5Ywi1Q -DA:398,0,SEkYr6QZYyPj82QRdJgfgA -DA:399,0,7PnyeIbECxsDoMUYhFwOxA -DA:400,0,K07RF0tDLqh1XZNYu+QxtA -DA:403,0,bc2Vw7machgI/cDMnpXluw -DA:404,0,gJGTG71mLgYjQPHtvN0tBw -DA:405,0,bPJZ8H04vE8zvkzKN6nSfQ -DA:406,0,BjfYGdrX2Veb+w6Y8zURvQ -DA:410,0,Xp7+rPxMQjxi39F4SB3Urw -DA:436,0,nCe307NZqsBSXVKOPL4D2g -DA:446,0,uFx6hwAyi5XzaYQGVISzBg -DA:447,0,OIAvCMSD+70detM1HMKKPQ -DA:448,0,Xo3Uzq/VjN+4Wjb0XxfW4w -DA:449,0,qjBDwAAq5yrN5AvDV82xCQ -DA:450,0,4wMl+Y9js3X2j+sg6r+MrQ -DA:453,0,vPmoYAkk5mWKy4nAMwMuQA -DA:454,0,kcEEbj1Suac5/reAxOH50A -DA:455,0,pOJwuGdEbe7GLbMcySd1QA -DA:456,0,3uDomgen0H7ssa/7H6BIdw -DA:457,0,AikhBaKlay5AOwJ9Lf+cjw -DA:476,0,Deqg8IaE1TZ/89UDz9pSnQ -DA:477,0,zwbYFqlvl6CJKTntPbrTMQ -DA:478,0,OIAvCMSD+70detM1HMKKPQ -DA:479,0,qON5Q8kMMQd+wJmUtiP6qQ -DA:480,0,87S0e2UdncmknbloW2MT5g -DA:481,0,HPmQuJkizrnLt1Tc6Zhj5A -DA:484,0,dhfgkLlQ/kviB8Tlyj19dQ -DA:485,0,o+jNRdmnJPIhqQSnxwZ/RA -DA:486,0,pOJwuGdEbe7GLbMcySd1QA -DA:487,0,tyNxfY7vT9ZlS1cHISmUxA -DA:488,0,C7xfJKwVV6LBFC/q8rqGrA -DA:507,0,K1pD10TOqr24ExaL8shO+w -DA:508,0,EI4q/g/zdrwDnLOlRtw1CQ -DA:509,0,OIAvCMSD+70detM1HMKKPQ -DA:510,0,XAjDhgxNfsbcN/x82UDxng -DA:511,0,qC5FeznKMSlxLFkHDkWx4Q -DA:512,0,3GdOG6n96KH/TbmEYBlpPg -DA:513,0,xiWrfzeC9oVEHf9G+DO1oQ -DA:515,0,KKG15zvIPtvoNSgthJ+KRA -DA:516,0,TohqhMz+qL/3q9F5PMVNkw -DA:517,0,bILj4pY/pxwJC6+WfN+YlQ -DA:518,0,wYSKU2GjSZ96y0T07xtQpw -DA:519,0,yTbqBr6HQSizZUpN0b3XzQ -DA:538,0,Z20taHYCkKzMTao9MwAt9g -DA:539,0,+jfbnZTw1GH2dzgiA7Hk4w -DA:540,0,OIAvCMSD+70detM1HMKKPQ -DA:541,0,uNesUF1Y5OHb5wIaxYx19g -DA:542,0,7A4RCTwP0TmIoZIWggxXjQ -DA:543,0,povivu613SUSYJrLDbP32w -DA:546,0,5VdSzVp86P3jHg9JkJKT4A -DA:547,0,8tYo5xfHpto3Drut5kGLBA -DA:548,0,pOJwuGdEbe7GLbMcySd1QA -DA:549,0,bmpbJC7vNPgDPJ7/xn4OCQ -DA:550,0,hNJpx4CJWkMIldgv+2bgJw -DA:571,0,DEgBEdAQlrv7F6Z8G7WISw -DA:572,0,3tAyVXwXXVPSHmRCorQZiA -DA:573,0,OIAvCMSD+70detM1HMKKPQ -DA:574,0,SMvm25QO0xdB2Dfh5GfzhA -DA:575,0,DMNgeW8dLHGC6BnsQC639w -DA:576,0,PNY9Z0y1bFXoKllyTXiPrQ -DA:579,0,DJ1oXezx9PgsV9+CaowifA -DA:580,0,/ouEgL5RTVgNUtYem7zgwg -DA:581,0,pOJwuGdEbe7GLbMcySd1QA -DA:582,0,MzIeuhBUVqbLiLoP1M7k3A -DA:583,0,F+cdGhJp0PrpkDd97tgNxg -DA:604,0,xLVEq7SDHCZARy6tDCx18g -DA:605,0,6UWj7NLuzQU4nhdER/0Oyw -DA:606,0,OIAvCMSD+70detM1HMKKPQ -DA:607,0,qmeqAzuVHRPtwls9LEBE7A -DA:608,0,tTKa9XigdgdgAt2MPEYiNQ -DA:609,0,9yc8ioRJFGmWSGrWEfaBuw -DA:612,0,hsFhmsuVZV83e3FNRjXl6A -DA:613,0,OgKM0UULCtVpgmOqLtUJxg -DA:614,0,pOJwuGdEbe7GLbMcySd1QA -DA:615,0,rcuoVkXyH9U23e/o7Qk0eg -DA:616,0,G1K9+4K+AHiDRDLbdcxQvw -DA:636,0,44kgpEfTnufzieeeqpuFBQ -DA:637,0,khr4jjSbKCmUSDSkn9542w -DA:638,0,Czt1tw8x/ym/XaWP2S5cBA -DA:639,0,Lp6NtrGYtaYTjkz5LfPrew -DA:640,0,FXY7pE2az48kTP6dTQ8+cg -DA:641,0,1gjv8u6rmDjUrxHj0DK38w -DA:642,0,7N/JFuOs+JgNw/t49ouLjw -DA:643,0,xvWIcpcyNr0gyGcTkdMxXw -DA:644,0,Ygnj/f9s5B1HsWQyg6GTwQ -DA:648,0,Pkwsntebe693LwjKD9saWA -DA:649,0,5Rn4oX7c4pPaXSvRAjy2qA -DA:651,0,7N/JFuOs+JgNw/t49ouLjw -DA:652,0,RnXkzpJZHL8yRDTeZbtPcQ -DA:653,0,EcelnZBotHBBj7PAW9y44Q -DA:654,0,rtCZlVCp/+V5nnZEnMSXyA -DA:655,0,ZNwaDuDzjOW6Gcc1JWwqag -DA:656,0,9RNlxIVQd8ELKSnJgdqqNw -DA:657,0,t/3Evj2mxo1UgS725wC5lg -DA:658,0,ZNwaDuDzjOW6Gcc1JWwqag -DA:659,0,9RNlxIVQd8ELKSnJgdqqNw -DA:660,0,R3mibLSzntE+zpPxvWyBpA -DA:661,0,GNdcY6BbfXQQAYXnuy5Wdw -DA:662,0,eCFxir4ylqOE+KJTKO3eZw -DA:666,0,7N/JFuOs+JgNw/t49ouLjw -DA:667,0,cS2c5MzvHaJZu6OhL7/BoQ -DA:689,0,wDCrZIQGT+N6FFgFAwOL8A -DA:693,0,KtAIkaSMuosGnVHsKc898w -DA:695,0,GCpRiMzVRjoDAKG4tm/VTw -DA:696,0,1EzUlnkh83sQJdyFyzNf9Q -DA:697,0,zh3jAnhfGHJc5ATHQ4YftA -DA:699,0,S1EcqDe0cseJGjz3ix0X1w -DA:700,0,lQ2mSyG7Qu4T8qZK/hrVVg -DA:701,0,76adChDOtwljsuEQG56IWQ -DA:702,0,xjcDBnSwra0OiNOAYAwoHA -DA:703,0,xS1tOnpU4NDQUQTbzLJrjw -DA:704,0,o7tvNiq40uwo8eP+lY5kyg -DA:705,0,Z1acuyd5F/twKnoLZFcZuQ -DA:707,0,OIAvCMSD+70detM1HMKKPQ -DA:708,0,T2aYcC58jo7CYUTH21xjLg -DA:710,0,9UHpPhDqBObuuMUvRF+GXw -DA:711,0,bSRrlCK5G2nrMmFrc/F2kA -DA:712,0,Bmeg5PLpflotVWFasVK+Fw -DA:713,0,HGNi7z2wXYES/avdAz/agw -DA:714,0,bjNz7Olc2GktDIPb2D7oFQ -DA:715,0,Uk1iEqLYWHwxE4nbWtF0CQ -DA:716,0,QslMkU+duRcv9wSY4Qw41Q -DA:718,0,jcUcrUlQLqPE/0vq4Sa+DA -DA:719,0,TQH2O63KzTdM3CrHcZncfQ -DA:721,0,bILj4pY/pxwJC6+WfN+YlQ -DA:722,0,lDyOAxBfKP6t7QC+pSzxwA -DA:723,0,GzICmhod4hECo/ofC8zi0g -DA:724,0,vSR0XCjjY7k2OIZ8pZg6iA -DA:725,0,gmhFTV7NRxIQDtVnbRAOlA -DA:727,0,ZOSfJGjLHdLuTqvq8SB4XA -DA:728,0,bILj4pY/pxwJC6+WfN+YlQ -DA:730,0,T2aYcC58jo7CYUTH21xjLg -DA:752,0,hYX17cQO11ozXTscC7m0bw -DA:753,0,Dwjd91USmMoWKfkSCVg/jg -DA:754,0,VbaE/G1b7B2RwWYtMLmGdw -DA:755,0,o8ApIVKCV2EV6g3DmqLIxQ -DA:756,0,xJkbl8AwnBgzMKLf2c98Jw -DA:757,0,dm0tNXAv/i+XGj1DE6xiDg -DA:758,0,SmwC0oF0xIaSX9uGYhZzjA -DA:759,0,wI45Gv8Va79VU/ulub3wIw -DA:760,0,uPEdyqPqLibq0yNtISnkzw -DA:761,0,EP8c6cPUigIwwHj4yJ2E2w -DA:762,0,0akzjwhJggRrYJ12v0N6Fw -DA:763,0,UEYI0TbwRoprT2fEecD0bA -DA:764,0,sTzYkB2nSH1BGT8bm7pXFw -DA:765,0,oq/JLywZoh8IDQFUNYMprg -DA:766,0,sFZJ3ffKJOutSiuV52Dexg -DA:767,0,gmhFTV7NRxIQDtVnbRAOlA -DA:769,0,NRaGyfL4v/s9SpDaLQFBfg -DA:770,0,Sl7CegX2CveFT4pHpVwD8g -DA:773,0,lhvKMIcycKMLD14p1/ChjA -DA:774,0,IyduQbYNoDu06bqOIcWhSQ -DA:775,0,VdJ5KSGdN1AmU/IO2DW8vg -DA:777,0,JYXzCjPcXLgXUOxJyLiy6w -DA:798,0,hYX17cQO11ozXTscC7m0bw -DA:799,0,/epQTfp1jOvjGFsvUkRYHA -DA:800,0,wxFv6rbdChkvjcZvwWdmcA -DA:801,0,zugkBFqDZ7VViDjwdvibSg -DA:803,0,pDY8RXHifrKbZN8QenZZeA -DA:804,0,gFJNHd9pjwcMDlqfzxYLEg -DA:805,0,3trbLAhrr4fiKf3MG4yXZw -DA:806,0,ceDoWrDcpqjiPl68Ds8Qkg -DA:807,0,G/9Jd/T48iEr/mQ5lDA3HA -DA:808,0,8tAHNK5mE+W2H8DjKYqwCg -DA:809,0,Pw+w0MMOerVUNo4HqNjjqQ -DA:810,0,EnBBf7CRvGy1YujPjXbBSw -DA:811,0,8b9AHviIhbD4DSgrsW9+Vg -DA:812,0,eqbXBPv2ES+sqKXPKY+Ruw -DA:813,0,OoaN4sB9H/8TY2+ncXvL+A -DA:814,0,Z4XZnYHKPrSQi1H2dgjjIw -DA:815,0,bQ9jj3BWfkB+N2YkPSB2sw -DA:817,0,2x3SuUJbls9BLzkabIULcQ -DA:818,0,OT3tUNz7g0TiLJRM2wU6YA -DA:819,0,H89SuakSSNQ4kbWVJOq4SA -DA:820,0,7T+Qx9miJrCIo4l+rUJ1IQ -DA:821,0,7yNWUJSFewmJDDlJTc8/nA -DA:822,0,khEubzkv6Nhz70Pcd+rrMQ -DA:823,0,Rk5haYhYqGzzMAb5kbSMCA -DA:824,0,LhyjzvGMWGV0Y2eWt2aN7A -DA:825,0,8b9AHviIhbD4DSgrsW9+Vg -DA:826,0,uwqq0zLcZfs/DKQQw2s1iA -DA:828,0,eqbXBPv2ES+sqKXPKY+Ruw -DA:829,0,09eElGS7zu8QJw1cszkplQ -DA:832,0,9T7SGFNm0cbt95OKrXncMA -DA:833,0,7LqqpM+c74rzrDs1HS+OTQ -DA:834,0,wE/HVD7tdITXHHTVApw90Q -DA:836,0,S3cF/pF4BON4M7K+uB3WFQ -DA:907,0,9cV8W5UeXduG1imUtCrMlw -DA:908,0,gc1YS2P2NrTmxtA+/NTutg -DA:909,0,T6svk+GmbNvwYZTWl5eFEg -DA:910,0,eSu+zxv6VSsaHPt4hzvPkg -DA:911,0,PZAVeElNc2bLBkoxjZk/hA -DA:912,0,p7hIHgfCEImiQYUddUTjSA -DA:913,0,I0eMmJUjBqFgpnTuxtxN5w -DA:914,0,CYIpm03GXRV91Ij0v1uT/A -DA:915,0,kTx8llzamiM9s7pdgEz3/w -DA:916,0,yiXSjXNBqpbJkFKbvXT6XQ -DA:917,0,5xNw45q0u0Ig/8k53gmdgQ -DA:918,0,4Gfqqqj46zkBe2xdMHIz4w -DA:919,0,Mv5fAWr4P/jAMT+2tAx7kQ -DA:920,0,48Sb3QlPXMd8uoGl/yJC1g -DA:921,0,ijAt2fh4m8/IRfDg/fY5rQ -DA:922,0,Usc5n9g49bLKznXHIwi5Vg -DA:923,0,A5HbmlLMILLjqIl2m3OYfw -DA:924,0,PCQPucxMZR6+Q+GIjc6FZg -DA:925,0,j/aLc6TsqdbmOs/I8FofcA -DA:927,0,j0smrnPK1Rz9rC3qDK6zYQ -DA:929,0,E73L9uPOBvs1t9eViiGbaQ -DA:930,0,6AQswYkJKp5kMWZXDFdURQ -DA:931,0,ILd4feGANCtjjFU7aKHY0w -DA:958,0,9cV8W5UeXduG1imUtCrMlw -DA:959,0,4Gfqqqj46zkBe2xdMHIz4w -DA:960,0,Mv5fAWr4P/jAMT+2tAx7kQ -DA:961,0,Usc5n9g49bLKznXHIwi5Vg -DA:962,0,A5HbmlLMILLjqIl2m3OYfw +DA:17,1,6OGgj7RRn6C8Uq1OUmjHQA +DA:19,1,1B2M2Y8AsgTpgAmY7PhCfg +DA:20,1,hTE1rgDMrPr3J1EpZDoxSA +DA:31,1,1B2M2Y8AsgTpgAmY7PhCfg +DA:32,1,uDCzQGjY0NwDx4sWT7OTcA +DA:82,1,1B2M2Y8AsgTpgAmY7PhCfg +DA:83,1,ZLHlWyibA/mOGWQtI53DnQ +DA:143,1,VdJ5KSGdN1AmU/IO2DW8vg +DA:147,1,qVjExF2Da/89CUVs02KVnA +DA:148,1,Sl7CegX2CveFT4pHpVwD8g +DA:175,1,hTE1rgDMrPr3J1EpZDoxSA +DA:203,1,1B2M2Y8AsgTpgAmY7PhCfg +DA:204,1,Mee0OUWUoWQbhCw+zB7mAA +DA:235,1,+WSML7H1mTlyX0P8Odk4iQ +DA:276,1,eyG4am5iBLT2gpjx5Ze5qw +DA:311,1,2uHV1gZHr0Y6lWeYUQ6nKg +DA:313,1,HAUEys9fOYKJfmObitzkpg +DA:314,1,aiUkAlUyIsQ+CSd7Y/RJzQ +DA:323,1,SZ3b2CfFDJCycDh+81IALA +DA:342,1,ok41w1hbBE3T6tZBRaNbzQ +DA:343,1,o3pAHrKEZ2rRW3z2oX8U6A +DA:344,1,apkQQtiiE4JOuDIBvLOUjQ +DA:375,1,f2DZT8vigRLWtdN0n2hKkA +DA:380,1,I00ItWveJ1uoD7DylfYjVg +DA:411,1,NvVxGrDiJsGH6QhWsv4EYA +DA:413,1,1B2M2Y8AsgTpgAmY7PhCfg +DA:414,1,RcyR7blD3k+5ByLAYMTEdw +DA:421,1,2kT17u5yZ53/q2/jTJYPLA +DA:448,1,32Re8V66dXRYtXl4420mkw +DA:459,1,njTfoNp+iIq1CwcPV2y9pA +DA:489,1,vPmoYAkk5mWKy4nAMwMuQA +DA:490,1,NMkmfWNNUsgwe0aaHORO2A +DA:492,1,pOJwuGdEbe7GLbMcySd1QA +DA:518,1,HPmQuJkizrnLt1Tc6Zhj5A +DA:522,1,/q6tofHPIVRpiy0vnSW2hQ +DA:551,1,xiWrfzeC9oVEHf9G+DO1oQ +DA:553,1,KKG15zvIPtvoNSgthJ+KRA +DA:554,1,Ik77xV+wPjxMiOWuTiGZOQ +DA:583,1,povivu613SUSYJrLDbP32w +DA:586,1,5VdSzVp86P3jHg9JkJKT4A +DA:587,1,8tYo5xfHpto3Drut5kGLBA +DA:588,1,pOJwuGdEbe7GLbMcySd1QA +DA:616,1,PNY9Z0y1bFXoKllyTXiPrQ +DA:619,1,DJ1oXezx9PgsV9+CaowifA +DA:620,1,wD6KNqz5vSGcP3HDirI0Hg +DA:666,1,pBbi/QI+pyqe78FAOJUdMQ +DA:731,1,wDCrZIQGT+N6FFgFAwOL8A +DA:734,1,YlUEPQCJpqjDP11xhFBK2g +DA:735,1,KtAIkaSMuosGnVHsKc898w +DA:777,1,SkdDdiGij68sVrHvlB0NWQ +DA:781,1,qZxEK0tS/E41UkxfTCHWRg +DA:827,1,eeC5WBtOX7qb/ZSC6ZiG2g +DA:841,1,hYX17cQO11ozXTscC7m0bw +DA:855,1,eqbXBPv2ES+sqKXPKY+Ruw +DA:857,1,Z4XZnYHKPrSQi1H2dgjjIw +DA:858,1,bQ9jj3BWfkB+N2YkPSB2sw +DA:866,1,Rk5haYhYqGzzMAb5kbSMCA +DA:868,1,8b9AHviIhbD4DSgrsW9+Vg +DA:869,1,uwqq0zLcZfs/DKQQw2s1iA +DA:876,1,7LqqpM+c74rzrDs1HS+OTQ +DA:877,1,wE/HVD7tdITXHHTVApw90Q +DA:879,1,S3cF/pF4BON4M7K+uB3WFQ +DA:887,1,wHGxXVpvYON3irtGbo5bIw +DA:898,1,AttrAvjZUi95la5E1cT/KA +DA:899,1,1B2M2Y8AsgTpgAmY7PhCfg +DA:900,1,N68YF3DP9LmJNl+7VWmVRg +DA:932,1,1B2M2Y8AsgTpgAmY7PhCfg +DA:933,1,v/OelOV6I/zRJUkmIpaUAg +DA:946,1,r5FxUaqACj+DUhIDSrgkBA +DA:950,1,9cV8W5UeXduG1imUtCrMlw +DA:951,1,gc1YS2P2NrTmxtA+/NTutg +DA:977,1,/QQEVqa5dpL5qsFJ7DWMpw +DA:979,1,+VPBq9vj/FooJgSDGIQpVQ +DA:982,1,/A6pCJUSARZ12ueCDtnpxw +DA:999,1,dvOUJ8P0qVISB8y5p0pvmQ +DA:1003,1,9cV8W5UeXduG1imUtCrMlw +DA:1004,1,4Gfqqqj46zkBe2xdMHIz4w +DA:1005,1,Mv5fAWr4P/jAMT+2tAx7kQ +DA:1021,1,GJiiEiXIBBYlbmAc2d20cw +DA:1023,1,1B2M2Y8AsgTpgAmY7PhCfg +DA:1024,1,4ih6Cba7T6MFgo5qzn7mMg +DA:1040,1,48Sb3QlPXMd8uoGl/yJC1g +DA:1042,1,PCQPucxMZR6+Q+GIjc6FZg +DA:1043,1,j/aLc6TsqdbmOs/I8FofcA +DA:1044,1,WtdXhA+c4ECL45VDhBvLNQ +DA:1045,1,1B2M2Y8AsgTpgAmY7PhCfg +DA:1046,1,JM4bFqyvgS32fsAUrW00+w +DA:1078,1,9cV8W5UeXduG1imUtCrMlw +DA:1080,1,Mv5fAWr4P/jAMT+2tAx7kQ +DA:1081,1,Usc5n9g49bLKznXHIwi5Vg +DA:1082,1,A5HbmlLMILLjqIl2m3OYfw +DA:1083,1,PCQPucxMZR6+Q+GIjc6FZg +DA:1084,1,j/aLc6TsqdbmOs/I8FofcA +DA:1085,1,RetsfkMpeeaB7RRieu8d5g +DA:1086,1,1B2M2Y8AsgTpgAmY7PhCfg +DA:1087,1,yqYXQ5/tdxB4pm97QLyicw +DA:1125,1,75M+HYmT7IpGsjQSCJbqQg +DA:1142,1,PL8bs5yLpoM2rSAEgChzRw +DA:1165,1,ouYu0qekp6QoQcmbpwOjOQ +DA:1167,1,97OAFCKzJY3dLBrQT/f9RQ +DA:1168,1,NvaodfDPfP75F7gQbjia0A +DA:1169,1,1Yrly00DiQ+gh8DcvlSpdg +DA:1170,1,Rx9xa4OkHQrAYkRIbc8OAQ +DA:1171,1,4Gfqqqj46zkBe2xdMHIz4w +DA:1188,1,1B2M2Y8AsgTpgAmY7PhCfg +DA:1189,1,E9URW+kr6yM/gPe0diDy0w +DA:1204,1,Mv5fAWr4P/jAMT+2tAx7kQ +DA:1206,1,A5HbmlLMILLjqIl2m3OYfw +DA:1207,1,PCQPucxMZR6+Q+GIjc6FZg +DA:1208,1,j/aLc6TsqdbmOs/I8FofcA +DA:1209,1,GJiiEiXIBBYlbmAc2d20cw +DA:1226,1,4Gfqqqj46zkBe2xdMHIz4w +DA:1228,1,Usc5n9g49bLKznXHIwi5Vg +DA:1229,1,A5HbmlLMILLjqIl2m3OYfw +DA:1230,1,PCQPucxMZR6+Q+GIjc6FZg +DA:1231,1,j/aLc6TsqdbmOs/I8FofcA +DA:1232,1,GJiiEiXIBBYlbmAc2d20cw +DA:1234,1,1B2M2Y8AsgTpgAmY7PhCfg +DA:1235,1,5cvehKpcl8YyUB4amhtabQ +DA:1251,1,VpVF/b/JwE3a3UeLWNySmw +DA:1258,1,NCPBonC1YqDTHOkQfPlhFA +DA:14,0,25JmQhfpJE3/1TMKqa64Zg +DA:27,0,p9VObvqSCRj8hcqJMkKDlA +DA:28,0,zBjO06PAbZZW4g+bTyqW5Q +DA:29,0,JS74W3nICDgQiP5wLso2mQ +DA:30,0,IreNhM4AZeEM/K2TzbOOBg +DA:36,0,44kgpEfTnufzieeeqpuFBQ +DA:37,0,khr4jjSbKCmUSDSkn9542w +DA:38,0,Czt1tw8x/ym/XaWP2S5cBA +DA:39,0,xvWIcpcyNr0gyGcTkdMxXw +DA:40,0,0FtrCMosXSaurDdZdyoNSw +DA:41,0,T2GmA/KrsmextvuNF6pEdg +DA:42,0,0BH60IeV3dj2ff+ttSAwWQ +DA:49,0,Z387ldJEJTGYGvk6V05k4Q +DA:50,0,9j4l37rppgKJMhUrO5DY5g +DA:51,0,eiO+X5cOpgI5VfexPgdpHg +DA:52,0,lWWLo5RM9bWPLYNOEHaELg +DA:53,0,DS71dJSuULr9SUHgZmMJxA +DA:57,0,DtP2M6FJbJdTERF52acYcA +DA:58,0,6NheNDITGp582x23bNiDVA +DA:62,0,gKuQAzAbg+y7MTiGq97hkQ +DA:63,0,AWrg01p1wblEI5Q7AuxJqQ +DA:65,0,olFOwoZDIbKK1foKh36bKQ +DA:66,0,368GSSPPh9Nb/29q1R9W9Q +DA:67,0,wE/HVD7tdITXHHTVApw90Q +DA:69,0,vU3aaiuq9XvgN9mjgDtxDw +DA:70,0,wE/HVD7tdITXHHTVApw90Q +DA:72,0,pCocN4k10WZ/cYUGmTQcZw +DA:73,0,5Rn4oX7c4pPaXSvRAjy2qA +DA:75,0,VqOLNdKenpg2SNLNQd0cJQ +DA:76,0,5Rn4oX7c4pPaXSvRAjy2qA +DA:78,0,Pkwsntebe693LwjKD9saWA +DA:79,0,5Rn4oX7c4pPaXSvRAjy2qA +DA:81,0,Dwjd91USmMoWKfkSCVg/jg +DA:87,0,QDWULBdYIjA4OVONiiczjw +DA:88,0,bk7XzKzxBHIUBzFSBsp67A +DA:89,0,cfsd66AVWx680iSyupczag +DA:90,0,h159UiyjNz+F1xwkg/hyhA +DA:93,0,TPhI68HIHb7oNbZ9muW07g +DA:96,0,u0d3NohsYdkMAZtj6ndvrA +DA:98,0,RqbrQmsqu+pGBYPxaY5lGg +DA:103,0,GsNgPheIifE3UJDzrON47g +DA:104,0,zrIP2OBuIpKNAGXrayxX8g +DA:105,0,wohijRi9buNpCJeEQmsP+Q +DA:106,0,bFxke1ZTTTYTHqXjdtOChA +DA:107,0,CQRslI5ahVtj4jepgSet4A +DA:108,0,VCB0TGad7wK8/aaie6JxAQ +DA:109,0,u7vThuipUfyW8eH7Kq7Syw +DA:110,0,qhr2PI2PMOsfdmBqSXPn0A +DA:111,0,mHIsz4N1ifbKR/7Dvu1QHg +DA:112,0,/1CzcGogNX8+5pBmTQ/snA +DA:113,0,+NJ1lBhJ0COm9tfCM+57RQ +DA:114,0,nE8XPPoiuqkTra6GgXtDaQ +DA:115,0,u2hOZlME9/jpTv+YuwPgbQ +DA:116,0,u0d3NohsYdkMAZtj6ndvrA +DA:118,0,wrZTzjx3Vyloi/yYoNlK2Q +DA:122,0,ZJMQKZgDAlye4jp61Yq0Pg +DA:123,0,Sl7CegX2CveFT4pHpVwD8g +DA:127,0,78Hbj6SM5UIaaJytjmYfvA +DA:128,0,Sl7CegX2CveFT4pHpVwD8g +DA:132,0,oL/4o4g/4ob2E5nXenm86w +DA:133,0,Sl7CegX2CveFT4pHpVwD8g +DA:137,0,dJFaXiSMspie5FRQRvgb/w +DA:138,0,Sl7CegX2CveFT4pHpVwD8g +DA:142,0,Kfsq9A5CdwanjkV6f4glzw +DA:153,0,TUeqdXnqXtcr3hK0onyjLQ +DA:156,0,HaqLT2TwAHQBGNgl65xJ8Q +DA:157,0,5/saescnAL68wAgwm0M6DQ +DA:158,0,/Po7NmOBftQ2bz4gENNiig +DA:159,0,SkINmudUpZQZiSD08cgsyA +DA:160,0,Pc49EbAgGAyxW8VSvinGug +DA:161,0,xjcDBnSwra0OiNOAYAwoHA +DA:162,0,tKBwo2uT7zvYxGbsBNPc9A +DA:163,0,aG8hzM939a6klmerpUAbhg +DA:164,0,Sl7CegX2CveFT4pHpVwD8g +DA:168,0,Dwjd91USmMoWKfkSCVg/jg +DA:169,0,PsRrqTpgMpxR2UNLmfEZuA +DA:171,0,Bt/Zp3S+5k4PfN6YoR5Qhw +DA:174,0,ROs40pbjANDFKGws4199Jg +DA:181,0,lkXgvotEVtlpg1yvFIAv0Q +DA:185,0,Env7HnARD0RqQeOVlh5dww +DA:186,0,Z4XZnYHKPrSQi1H2dgjjIw +DA:187,0,wCX8YfaarZ/3GROSUgXujQ +DA:188,0,90Q1WIj/uxwtePu7xe4r5g +DA:189,0,3A9LdVO6r2Za695tInT0lQ +DA:190,0,9hwOohZvE3EKTjYEU/bYBg +DA:196,0,aNjgHzUwQiw7DGJixOKPSQ +DA:202,0,JA8+cAeyHuPCGnrHBbqXUw +DA:223,0,7g8Yo0YMxES17wG7TYXndw +DA:226,0,HipVOupxYB97FQJLjEiTHg +DA:228,0,oF3SlTRNSZaf1ZuXg+V76A +DA:229,0,apkQQtiiE4JOuDIBvLOUjQ +DA:231,0,2BiY/s2QK87iIH3qHuTGLw +DA:254,0,ssIF1fCEOBHLBkh3a3sXXQ +DA:255,0,hy5w67fIeYwvWJR7GwpqDA +DA:257,0,OIAvCMSD+70detM1HMKKPQ +DA:258,0,f90UtmyNW0kxxdhBJVzAgw +DA:260,0,P8eCOjooHxDWajIkhBnl+A +DA:261,0,bT066rreWOjkYXAnw/1B9w +DA:262,0,wt/9Iwd9kPx02oaZcC/flg +DA:264,0,/k7T79k9lU6K5iFv+Ju9SQ +DA:265,0,rTqtjWtycJz+103ySdtnrw +DA:266,0,pOJwuGdEbe7GLbMcySd1QA +DA:267,0,CkgigQ/3i3chcws6hKAbLw +DA:268,0,JPJezm3Yy+H+Kl+PZB6YYA +DA:269,0,NGmVALe18KXEQxtsOhGX2Q +DA:270,0,IZqWZOTsWvAqSe/PFraq9w +DA:272,0,+cF6UqNU8lOA4yjHHlTmLA +DA:294,0,zoDLejlqQlRf2ucU3scAuw +DA:295,0,+vAPgpQFVaHcAvHTqcXZBg +DA:296,0,H1O15Pwpt/+0JwGoOqzrKg +DA:297,0,ydnhx2+coBT9AEjxgQItxQ +DA:298,0,kgsUtMoGMxtrl/gjg0RdEQ +DA:302,0,Cisf3Xpb28cfDfmy+fBBiQ +DA:303,0,OIAvCMSD+70detM1HMKKPQ +DA:304,0,ODkyqx/ZUVs4MuWO4yW9hQ +DA:305,0,H/VeMVqH986O8noeK2YCNg +DA:306,0,oND+H7Qxvl9ouDTvJjFv0Q +DA:307,0,PbmX1Cd0U0qZKWTMU7B28A +DA:308,0,PoHKNNDCoyXNnpH8u7HNBg +DA:309,0,gjRspMkr/oTxsUC0FkGMvA +DA:310,0,misTxSWDsBzaqTqV8vKBPA +DA:312,0,pUD+Odh5opnxVcZra+mVcQ +DA:315,0,3hp7pN/rYHqrEc/YHc1Pag +DA:316,0,+rk5RUyo97sF/BTCgPRVGQ +DA:317,0,nuLZTkfkBrnm/oc0sr1NYg +DA:318,0,S/Pxlc+XlLxDdwEBcSNUWA +DA:319,0,t0p4xTIPmSe6ByP0gHlnng +DA:320,0,4ITW4OYJHSXEAadkyzrbZg +DA:322,0,z7i0Jn7UbBUL9TBo6pAz4A +DA:341,0,zLK89YUL1tX2aR5JHq5RSw +DA:346,0,F2/4qaK6sx5q98dZowyB2g +DA:369,0,qEq5fkr8P4P4MS4gSEhPxg +DA:370,0,lJTPCSDMH24i26mCMOI+Rw +DA:395,0,hYX17cQO11ozXTscC7m0bw +DA:396,0,Dwjd91USmMoWKfkSCVg/jg +DA:397,0,xjcDBnSwra0OiNOAYAwoHA +DA:398,0,/q39rlzr8yvOkjYCOooFdQ +DA:399,0,w/tTPAQnqaFNbPE+sYWqLQ +DA:400,0,Y2zHg3ew+eUpe2Vsli99yg +DA:409,0,o7tvNiq40uwo8eP+lY5kyg +DA:410,0,2bX0G6/iuxFHcsTheYCilQ +DA:412,0,apkQQtiiE4JOuDIBvLOUjQ +DA:422,0,J2pxm/Ku8kYvNxyokeJ/Yw +DA:423,0,OIAvCMSD+70detM1HMKKPQ +DA:425,0,Nd911YyrSQlctqiMugvD2g +DA:426,0,Di9bygrFA8iOFbygeRk3OQ +DA:427,0,OIAvCMSD+70detM1HMKKPQ +DA:429,0,Nbc84V1Eh7Rb1tz/Bxq+UQ +DA:430,0,lWBV0nNGbbwGmQTw8Riq6w +DA:431,0,ve/6DLF89DaE65hW5Ywi1Q +DA:433,0,SEkYr6QZYyPj82QRdJgfgA +DA:434,0,7PnyeIbECxsDoMUYhFwOxA +DA:435,0,K07RF0tDLqh1XZNYu+QxtA +DA:438,0,bc2Vw7machgI/cDMnpXluw +DA:439,0,gJGTG71mLgYjQPHtvN0tBw +DA:440,0,bPJZ8H04vE8zvkzKN6nSfQ +DA:441,0,BjfYGdrX2Veb+w6Y8zURvQ +DA:445,0,Xp7+rPxMQjxi39F4SB3Urw +DA:446,0,10JUNym+3lqk9WVPiaqQiQ +DA:471,0,nCe307NZqsBSXVKOPL4D2g +DA:481,0,/Tuxc8l9NnST8Fb+VqAmvQ +DA:483,0,OIAvCMSD+70detM1HMKKPQ +DA:484,0,Xo3Uzq/VjN+4Wjb0XxfW4w +DA:485,0,qjBDwAAq5yrN5AvDV82xCQ +DA:486,0,4wMl+Y9js3X2j+sg6r+MrQ +DA:493,0,3uDomgen0H7ssa/7H6BIdw +DA:494,0,AikhBaKlay5AOwJ9Lf+cjw +DA:495,0,Xa6MJWa1goKiIlT73MxLBg +DA:497,0,NmEj+NoaWjr8GW9MO7ciMw +DA:513,0,Deqg8IaE1TZ/89UDz9pSnQ +DA:514,0,20ScMWBqQ//CTGGaQhAnHQ +DA:515,0,OIAvCMSD+70detM1HMKKPQ +DA:516,0,qON5Q8kMMQd+wJmUtiP6qQ +DA:517,0,87S0e2UdncmknbloW2MT5g +DA:521,0,dhfgkLlQ/kviB8Tlyj19dQ +DA:524,0,pOJwuGdEbe7GLbMcySd1QA +DA:525,0,tyNxfY7vT9ZlS1cHISmUxA +DA:526,0,C7xfJKwVV6LBFC/q8rqGrA +DA:527,0,hiA1YHf2IMvOTS6q5OGGEw +DA:529,0,4/gWcalEmzQJ2j07AxkH6g +DA:545,0,K1pD10TOqr24ExaL8shO+w +DA:546,0,xTwgWS+8G9HRgyUgeYGeKQ +DA:547,0,OIAvCMSD+70detM1HMKKPQ +DA:548,0,XAjDhgxNfsbcN/x82UDxng +DA:549,0,qC5FeznKMSlxLFkHDkWx4Q +DA:550,0,3GdOG6n96KH/TbmEYBlpPg +DA:556,0,bILj4pY/pxwJC6+WfN+YlQ +DA:557,0,wYSKU2GjSZ96y0T07xtQpw +DA:558,0,yTbqBr6HQSizZUpN0b3XzQ +DA:559,0,jC8fZqhggGRwbqt7CFX/Ng +DA:561,0,YsIBpVmHprt3psAn5fTOdQ +DA:577,0,Z20taHYCkKzMTao9MwAt9g +DA:578,0,qBjfufw32H47jiZHR57P1w +DA:580,0,OIAvCMSD+70detM1HMKKPQ +DA:581,0,uNesUF1Y5OHb5wIaxYx19g +DA:582,0,7A4RCTwP0TmIoZIWggxXjQ +DA:589,0,bmpbJC7vNPgDPJ7/xn4OCQ +DA:590,0,hNJpx4CJWkMIldgv+2bgJw +DA:591,0,oHxyUjkM5k23OXyy97bgow +DA:593,0,/APRDzagsh1SY55Vx4k7yw +DA:611,0,DEgBEdAQlrv7F6Z8G7WISw +DA:612,0,FFPD5SaKnd1hiE5brQnCyQ +DA:613,0,OIAvCMSD+70detM1HMKKPQ +DA:614,0,SMvm25QO0xdB2Dfh5GfzhA +DA:615,0,DMNgeW8dLHGC6BnsQC639w +DA:622,0,pOJwuGdEbe7GLbMcySd1QA +DA:623,0,MzIeuhBUVqbLiLoP1M7k3A +DA:624,0,F+cdGhJp0PrpkDd97tgNxg +DA:625,0,HFDjddiDbkIPCUW/q34kJA +DA:627,0,wG84PcQBZ5EPrdWft4nB0g +DA:645,0,xLVEq7SDHCZARy6tDCx18g +DA:646,0,qmDwq4TUCAT3BPcUmUPVvQ +DA:647,0,OIAvCMSD+70detM1HMKKPQ +DA:648,0,qmeqAzuVHRPtwls9LEBE7A +DA:649,0,tTKa9XigdgdgAt2MPEYiNQ +DA:650,0,9yc8ioRJFGmWSGrWEfaBuw +DA:653,0,hsFhmsuVZV83e3FNRjXl6A +DA:654,0,iwWQBvdjaIFGnIWsacn83Q +DA:656,0,pOJwuGdEbe7GLbMcySd1QA +DA:657,0,rcuoVkXyH9U23e/o7Qk0eg +DA:658,0,G1K9+4K+AHiDRDLbdcxQvw +DA:659,0,DH5AL+WrJcJ5aw+DZUC9MQ +DA:661,0,tfAKjJYdo0EWF3Sxdqsw/Q +DA:678,0,44kgpEfTnufzieeeqpuFBQ +DA:679,0,khr4jjSbKCmUSDSkn9542w +DA:680,0,Czt1tw8x/ym/XaWP2S5cBA +DA:681,0,Lp6NtrGYtaYTjkz5LfPrew +DA:682,0,FXY7pE2az48kTP6dTQ8+cg +DA:683,0,1gjv8u6rmDjUrxHj0DK38w +DA:684,0,7N/JFuOs+JgNw/t49ouLjw +DA:685,0,xvWIcpcyNr0gyGcTkdMxXw +DA:686,0,Ygnj/f9s5B1HsWQyg6GTwQ +DA:690,0,Pkwsntebe693LwjKD9saWA +DA:691,0,5Rn4oX7c4pPaXSvRAjy2qA +DA:693,0,7N/JFuOs+JgNw/t49ouLjw +DA:694,0,fc3PvaeyI6rCQoLk/U4PMg +DA:695,0,EcelnZBotHBBj7PAW9y44Q +DA:696,0,rtCZlVCp/+V5nnZEnMSXyA +DA:697,0,ZNwaDuDzjOW6Gcc1JWwqag +DA:698,0,9RNlxIVQd8ELKSnJgdqqNw +DA:699,0,t/3Evj2mxo1UgS725wC5lg +DA:700,0,ZNwaDuDzjOW6Gcc1JWwqag +DA:701,0,9RNlxIVQd8ELKSnJgdqqNw +DA:702,0,R3mibLSzntE+zpPxvWyBpA +DA:703,0,GNdcY6BbfXQQAYXnuy5Wdw +DA:704,0,eCFxir4ylqOE+KJTKO3eZw +DA:708,0,7N/JFuOs+JgNw/t49ouLjw +DA:709,0,cS2c5MzvHaJZu6OhL7/BoQ +DA:711,0,kycMaH6XbPuAfUpgfG1Lbg +DA:713,0,bAsJHlcLAGvDwizXRIaHtQ +DA:737,0,jL6v/QxldFQ3Pgbx2cY7vw +DA:739,0,1EzUlnkh83sQJdyFyzNf9Q +DA:740,0,zh3jAnhfGHJc5ATHQ4YftA +DA:742,0,S1EcqDe0cseJGjz3ix0X1w +DA:743,0,lQ2mSyG7Qu4T8qZK/hrVVg +DA:744,0,76adChDOtwljsuEQG56IWQ +DA:745,0,xjcDBnSwra0OiNOAYAwoHA +DA:746,0,xS1tOnpU4NDQUQTbzLJrjw +DA:747,0,o7tvNiq40uwo8eP+lY5kyg +DA:748,0,Z1acuyd5F/twKnoLZFcZuQ +DA:750,0,OIAvCMSD+70detM1HMKKPQ +DA:751,0,T2aYcC58jo7CYUTH21xjLg +DA:753,0,9UHpPhDqBObuuMUvRF+GXw +DA:754,0,bSRrlCK5G2nrMmFrc/F2kA +DA:755,0,Bmeg5PLpflotVWFasVK+Fw +DA:756,0,HGNi7z2wXYES/avdAz/agw +DA:757,0,bjNz7Olc2GktDIPb2D7oFQ +DA:758,0,Uk1iEqLYWHwxE4nbWtF0CQ +DA:759,0,QslMkU+duRcv9wSY4Qw41Q +DA:761,0,jcUcrUlQLqPE/0vq4Sa+DA +DA:762,0,TQH2O63KzTdM3CrHcZncfQ +DA:764,0,bILj4pY/pxwJC6+WfN+YlQ +DA:765,0,lDyOAxBfKP6t7QC+pSzxwA +DA:766,0,GzICmhod4hECo/ofC8zi0g +DA:767,0,vSR0XCjjY7k2OIZ8pZg6iA +DA:768,0,gmhFTV7NRxIQDtVnbRAOlA +DA:770,0,ZOSfJGjLHdLuTqvq8SB4XA +DA:771,0,bILj4pY/pxwJC6+WfN+YlQ +DA:773,0,T2aYcC58jo7CYUTH21xjLg +DA:775,0,xv/snrRzxrlGnA7265NxKQ +DA:795,0,hYX17cQO11ozXTscC7m0bw +DA:796,0,Dwjd91USmMoWKfkSCVg/jg +DA:797,0,VbaE/G1b7B2RwWYtMLmGdw +DA:798,0,o8ApIVKCV2EV6g3DmqLIxQ +DA:799,0,xJkbl8AwnBgzMKLf2c98Jw +DA:800,0,dm0tNXAv/i+XGj1DE6xiDg +DA:801,0,SmwC0oF0xIaSX9uGYhZzjA +DA:802,0,wI45Gv8Va79VU/ulub3wIw +DA:803,0,uPEdyqPqLibq0yNtISnkzw +DA:804,0,EP8c6cPUigIwwHj4yJ2E2w +DA:805,0,0akzjwhJggRrYJ12v0N6Fw +DA:806,0,UEYI0TbwRoprT2fEecD0bA +DA:807,0,sTzYkB2nSH1BGT8bm7pXFw +DA:808,0,oq/JLywZoh8IDQFUNYMprg +DA:809,0,sFZJ3ffKJOutSiuV52Dexg +DA:810,0,gmhFTV7NRxIQDtVnbRAOlA +DA:812,0,NRaGyfL4v/s9SpDaLQFBfg +DA:813,0,Sl7CegX2CveFT4pHpVwD8g +DA:816,0,lhvKMIcycKMLD14p1/ChjA +DA:817,0,IyduQbYNoDu06bqOIcWhSQ +DA:818,0,VdJ5KSGdN1AmU/IO2DW8vg +DA:820,0,JYXzCjPcXLgXUOxJyLiy6w +DA:821,0,apkQQtiiE4JOuDIBvLOUjQ +DA:823,0,jEKSYfikD4FxMUO8998Srg +DA:842,0,/epQTfp1jOvjGFsvUkRYHA +DA:843,0,wxFv6rbdChkvjcZvwWdmcA +DA:844,0,zugkBFqDZ7VViDjwdvibSg +DA:846,0,pDY8RXHifrKbZN8QenZZeA +DA:847,0,gFJNHd9pjwcMDlqfzxYLEg +DA:848,0,3trbLAhrr4fiKf3MG4yXZw +DA:849,0,ceDoWrDcpqjiPl68Ds8Qkg +DA:850,0,G/9Jd/T48iEr/mQ5lDA3HA +DA:851,0,8tAHNK5mE+W2H8DjKYqwCg +DA:852,0,Pw+w0MMOerVUNo4HqNjjqQ +DA:853,0,EnBBf7CRvGy1YujPjXbBSw +DA:854,0,8b9AHviIhbD4DSgrsW9+Vg +DA:856,0,OoaN4sB9H/8TY2+ncXvL+A +DA:860,0,2x3SuUJbls9BLzkabIULcQ +DA:861,0,OT3tUNz7g0TiLJRM2wU6YA +DA:862,0,H89SuakSSNQ4kbWVJOq4SA +DA:863,0,7T+Qx9miJrCIo4l+rUJ1IQ +DA:864,0,7yNWUJSFewmJDDlJTc8/nA +DA:865,0,khEubzkv6Nhz70Pcd+rrMQ +DA:867,0,LhyjzvGMWGV0Y2eWt2aN7A +DA:871,0,eqbXBPv2ES+sqKXPKY+Ruw +DA:872,0,09eElGS7zu8QJw1cszkplQ +DA:875,0,9T7SGFNm0cbt95OKrXncMA +DA:880,0,h8v58CjcqhG/CCBFWdi4Qg +DA:882,0,QEmgDbbXOYcteN5plE4GvA +DA:909,0,l1M1TDXvvQ5yUbmtnjqn2w +DA:911,0,nOqVrRMCkXFh/NswKgK/+g +DA:919,0,cVvClAJ7fPb430fcfUDB/w +DA:921,0,sJ+kAId7e0J9Z9VYHWwspQ +DA:931,0,ZymDT9SV55t8XzPfBTwYNA +DA:952,0,T6svk+GmbNvwYZTWl5eFEg +DA:953,0,eSu+zxv6VSsaHPt4hzvPkg +DA:954,0,PZAVeElNc2bLBkoxjZk/hA +DA:955,0,p7hIHgfCEImiQYUddUTjSA +DA:956,0,I0eMmJUjBqFgpnTuxtxN5w +DA:957,0,CYIpm03GXRV91Ij0v1uT/A +DA:958,0,kTx8llzamiM9s7pdgEz3/w +DA:959,0,yiXSjXNBqpbJkFKbvXT6XQ +DA:960,0,5xNw45q0u0Ig/8k53gmdgQ +DA:961,0,4Gfqqqj46zkBe2xdMHIz4w +DA:962,0,Mv5fAWr4P/jAMT+2tAx7kQ DA:963,0,48Sb3QlPXMd8uoGl/yJC1g DA:964,0,ijAt2fh4m8/IRfDg/fY5rQ -DA:965,0,PCQPucxMZR6+Q+GIjc6FZg -DA:966,0,j/aLc6TsqdbmOs/I8FofcA -DA:967,0,0OwnoE7Y5uAVENaSQYm8CQ -DA:968,0,gskjDcLVV6dG9Sge0MYtQg -DA:969,0,/n7FnY7z650/Y2+vHHEGlw -DA:970,0,EAS4VUYbsQQOG7e6TwuH2w -DA:971,0,VlykEUF/L6SJe2LdJruIyQ -DA:972,0,Y92t7Z+9+F97P6PkT5tkFQ -DA:973,0,oZJOe3ygPr+xdv7to85yjA -DA:974,0,ZeHcTsKtbH3L1QDGxo3a6A -DA:990,0,9cV8W5UeXduG1imUtCrMlw -DA:991,0,4Gfqqqj46zkBe2xdMHIz4w -DA:992,0,Mv5fAWr4P/jAMT+2tAx7kQ -DA:993,0,Usc5n9g49bLKznXHIwi5Vg -DA:994,0,A5HbmlLMILLjqIl2m3OYfw -DA:995,0,48Sb3QlPXMd8uoGl/yJC1g -DA:996,0,ijAt2fh4m8/IRfDg/fY5rQ -DA:997,0,PCQPucxMZR6+Q+GIjc6FZg -DA:998,0,j/aLc6TsqdbmOs/I8FofcA -DA:1012,0,9cV8W5UeXduG1imUtCrMlw -DA:1013,0,4Gfqqqj46zkBe2xdMHIz4w -DA:1014,0,Mv5fAWr4P/jAMT+2tAx7kQ -DA:1015,0,48Sb3QlPXMd8uoGl/yJC1g -DA:1016,0,ijAt2fh4m8/IRfDg/fY5rQ -DA:1017,0,Usc5n9g49bLKznXHIwi5Vg -DA:1018,0,A5HbmlLMILLjqIl2m3OYfw -DA:1019,0,PCQPucxMZR6+Q+GIjc6FZg -DA:1020,0,j/aLc6TsqdbmOs/I8FofcA -DA:1033,0,9cV8W5UeXduG1imUtCrMlw -DA:1034,0,4Gfqqqj46zkBe2xdMHIz4w -DA:1035,0,Mv5fAWr4P/jAMT+2tAx7kQ -DA:1036,0,Usc5n9g49bLKznXHIwi5Vg -DA:1037,0,A5HbmlLMILLjqIl2m3OYfw -DA:1038,0,PCQPucxMZR6+Q+GIjc6FZg -DA:1039,0,j/aLc6TsqdbmOs/I8FofcA -DA:1059,0,sqDcvWAMYbFVRhYJzAnKuQ -DA:1060,0,casWXR9kI2g5CUkfLEwkDg -DA:1061,0,HdMxc30KI5RwRuzP80n4mQ -DA:1062,0,ycHhLNwnNtdk14CkozGuKw -DA:1063,0,qEM4bFBwiIDS8RaYgzc5zg -DA:1064,0,dVC+HNutklYwapJbJOKpmA -DA:1065,0,+EEmt9hAIdEP9X04tBxl9w -DA:1066,0,VlykEUF/L6SJe2LdJruIyQ -DA:1067,0,Y92t7Z+9+F97P6PkT5tkFQ -DA:1068,0,G3mcvMB3lXh8w6tywZBAOA -DA:1069,0,1PXwnVeUCFnHbcZUQ9jPLA -DA:1070,0,4Gfqqqj46zkBe2xdMHIz4w -DA:1071,0,Mv5fAWr4P/jAMT+2tAx7kQ -DA:1072,0,48Sb3QlPXMd8uoGl/yJC1g -DA:1073,0,ijAt2fh4m8/IRfDg/fY5rQ -DA:1074,0,PCQPucxMZR6+Q+GIjc6FZg -DA:1075,0,wdh/QmMUagMJRmY+In4a4w -DA:1076,0,NAb+yx8cYatQPWufQ/F2gw -DA:1077,0,oheGhifbWWPJ4iFqxf4R0Q -DA:1105,0,9cV8W5UeXduG1imUtCrMlw -DA:1106,0,NXLT8fGxYkYE0As1PrCrDQ -DA:1107,0,RtcXjjjB+V2Z4UYGACE5hQ -DA:1108,0,s8mAvqmKWFBv8V8rEn+1Cg -DA:1109,0,gwhY6VIUPEpLrExbYyUiyw -DA:1110,0,6UEvCn4eLGcq3m0JECBbxw -DA:1111,0,yJH3NVPEoYSr9fwqjrcKeQ -DA:1112,0,RJyslH0hnEN5fKJzecaIGw -DA:1113,0,X6oOwJxhX6CqzKW+QsruRg -DA:1114,0,XDVWP7nnOcNpQBgmhe07jg -DA:1115,0,Vi9txnjQgnq0jNZeM0vdlQ -DA:1116,0,Ajm12kj/WRGQfH3VwLGl9Q -DA:1117,0,yFULWgPpMc+ETtS+ybp3HA -DA:1118,0,sMKYwWmdeIO5GuVO68gcsg -DA:1119,0,wRHNUVDX9gluuZvOgg5svw -DA:1120,0,ouYu0qekp6QoQcmbpwOjOQ -DA:1121,0,Nn5GMzhSw6dSJPlbYgFv+w -DA:1122,0,97OAFCKzJY3dLBrQT/f9RQ -DA:1123,0,NvaodfDPfP75F7gQbjia0A -DA:1124,0,1Yrly00DiQ+gh8DcvlSpdg -DA:1125,0,Rx9xa4OkHQrAYkRIbc8OAQ -DA:1126,0,4Gfqqqj46zkBe2xdMHIz4w -DA:1127,0,Mv5fAWr4P/jAMT+2tAx7kQ -DA:1128,0,Usc5n9g49bLKznXHIwi5Vg -DA:1129,0,A5HbmlLMILLjqIl2m3OYfw -DA:1130,0,48Sb3QlPXMd8uoGl/yJC1g -DA:1131,0,ijAt2fh4m8/IRfDg/fY5rQ -DA:1132,0,PCQPucxMZR6+Q+GIjc6FZg -DA:1133,0,j/aLc6TsqdbmOs/I8FofcA -DA:1136,0,az4Fvn7qSOE98+6xTi5RBA -DA:1157,0,9cV8W5UeXduG1imUtCrMlw -DA:1158,0,4Gfqqqj46zkBe2xdMHIz4w -DA:1159,0,Mv5fAWr4P/jAMT+2tAx7kQ -DA:1160,0,Usc5n9g49bLKznXHIwi5Vg -DA:1161,0,A5HbmlLMILLjqIl2m3OYfw -DA:1162,0,PCQPucxMZR6+Q+GIjc6FZg -DA:1163,0,j/aLc6TsqdbmOs/I8FofcA -DA:1180,0,9cV8W5UeXduG1imUtCrMlw -DA:1181,0,4Gfqqqj46zkBe2xdMHIz4w -DA:1182,0,Mv5fAWr4P/jAMT+2tAx7kQ -DA:1183,0,Usc5n9g49bLKznXHIwi5Vg -DA:1184,0,A5HbmlLMILLjqIl2m3OYfw -DA:1185,0,PCQPucxMZR6+Q+GIjc6FZg -DA:1186,0,j/aLc6TsqdbmOs/I8FofcA -DA:1199,0,9cV8W5UeXduG1imUtCrMlw -DA:1200,0,PCQPucxMZR6+Q+GIjc6FZg -DA:1201,0,j/aLc6TsqdbmOs/I8FofcA -DA:1202,0,NAb+yx8cYatQPWufQ/F2gw -DA:1203,0,l56R6qbnP2dr35c+6/9nEQ -DA:1217,0,9cV8W5UeXduG1imUtCrMlw -DA:1218,0,4Gfqqqj46zkBe2xdMHIz4w -DA:1219,0,Mv5fAWr4P/jAMT+2tAx7kQ -DA:1220,0,Usc5n9g49bLKznXHIwi5Vg -DA:1221,0,A5HbmlLMILLjqIl2m3OYfw -DA:1222,0,48Sb3QlPXMd8uoGl/yJC1g -DA:1223,0,ijAt2fh4m8/IRfDg/fY5rQ -DA:1224,0,PCQPucxMZR6+Q+GIjc6FZg -DA:1225,0,j/aLc6TsqdbmOs/I8FofcA -DA:1242,0,9cV8W5UeXduG1imUtCrMlw -DA:1243,0,UFFCtPhs0sfQjRD1mwlg0A -DA:1244,0,uaetSitAoD2KfPp3FZWY0g -DA:1245,0,gc1YS2P2NrTmxtA+/NTutg -DA:1246,0,T6svk+GmbNvwYZTWl5eFEg -DA:1247,0,4Gfqqqj46zkBe2xdMHIz4w -DA:1248,0,Mv5fAWr4P/jAMT+2tAx7kQ -DA:1249,0,Usc5n9g49bLKznXHIwi5Vg -DA:1250,0,A5HbmlLMILLjqIl2m3OYfw -DA:1251,0,48Sb3QlPXMd8uoGl/yJC1g -DA:1252,0,ijAt2fh4m8/IRfDg/fY5rQ -DA:1253,0,PCQPucxMZR6+Q+GIjc6FZg -DA:1254,0,j/aLc6TsqdbmOs/I8FofcA -DA:1260,0,UBNGC/4l7TzKcaSA+0L9uA -DA:1262,0,+QtiGVnedZ8VTL+9cC4NtQ -DA:1264,0,euf6lOR86/57UQkIb6uazQ -DA:1266,0,ScJ+iN3uJIonM2tp/9c5Kg -DA:1269,0,XwvwP+oSfJ3TUBEvkXdRyA -DA:1271,0,kIgx4Wi+djqKM3fe4ijqIA -DA:1274,0,V4+xklXWxTwAYK19NwcKeg -DA:1275,0,zPSneSsl8uDRRZeGHr0LjA -DA:1277,0,NLutwL79TYgL7XiU0N9UeQ -DA:1292,0,RpsYhfBo/59t2F406Ez31w -LF:568 -LH:86 +DA:965,0,Usc5n9g49bLKznXHIwi5Vg +DA:966,0,A5HbmlLMILLjqIl2m3OYfw +DA:967,0,PCQPucxMZR6+Q+GIjc6FZg +DA:968,0,j/aLc6TsqdbmOs/I8FofcA +DA:970,0,j0smrnPK1Rz9rC3qDK6zYQ +DA:972,0,LFU+K2PFiEWuphE67kzntQ +DA:973,0,OIAvCMSD+70detM1HMKKPQ +DA:974,0,E73L9uPOBvs1t9eViiGbaQ +DA:975,0,AIbdFYRIUAmJkikUQAF7mA +DA:976,0,OIAvCMSD+70detM1HMKKPQ +DA:986,0,/zQfDZVZn+WvFlLPSbio6A +DA:988,0,iBffJob4HxZC2KUE2+tBIw +DA:1006,0,Usc5n9g49bLKznXHIwi5Vg +DA:1007,0,A5HbmlLMILLjqIl2m3OYfw +DA:1008,0,48Sb3QlPXMd8uoGl/yJC1g +DA:1009,0,ijAt2fh4m8/IRfDg/fY5rQ +DA:1010,0,PCQPucxMZR6+Q+GIjc6FZg +DA:1011,0,j/aLc6TsqdbmOs/I8FofcA +DA:1012,0,0OwnoE7Y5uAVENaSQYm8CQ +DA:1013,0,gskjDcLVV6dG9Sge0MYtQg +DA:1014,0,/n7FnY7z650/Y2+vHHEGlw +DA:1015,0,EAS4VUYbsQQOG7e6TwuH2w +DA:1016,0,VlykEUF/L6SJe2LdJruIyQ +DA:1017,0,Y92t7Z+9+F97P6PkT5tkFQ +DA:1018,0,oZJOe3ygPr+xdv7to85yjA +DA:1019,0,ZeHcTsKtbH3L1QDGxo3a6A +DA:1035,0,9cV8W5UeXduG1imUtCrMlw +DA:1036,0,4Gfqqqj46zkBe2xdMHIz4w +DA:1037,0,Mv5fAWr4P/jAMT+2tAx7kQ +DA:1038,0,Usc5n9g49bLKznXHIwi5Vg +DA:1039,0,A5HbmlLMILLjqIl2m3OYfw +DA:1041,0,ijAt2fh4m8/IRfDg/fY5rQ +DA:1057,0,9cV8W5UeXduG1imUtCrMlw +DA:1058,0,4Gfqqqj46zkBe2xdMHIz4w +DA:1059,0,Mv5fAWr4P/jAMT+2tAx7kQ +DA:1060,0,48Sb3QlPXMd8uoGl/yJC1g +DA:1061,0,ijAt2fh4m8/IRfDg/fY5rQ +DA:1062,0,Usc5n9g49bLKznXHIwi5Vg +DA:1063,0,A5HbmlLMILLjqIl2m3OYfw +DA:1064,0,PCQPucxMZR6+Q+GIjc6FZg +DA:1065,0,j/aLc6TsqdbmOs/I8FofcA +DA:1066,0,Lcf3cpDRxIxgEHeCaUjOdQ +DA:1068,0,qq75Yj5maPMF3NEGoCEUwA +DA:1079,0,4Gfqqqj46zkBe2xdMHIz4w +DA:1104,0,sqDcvWAMYbFVRhYJzAnKuQ +DA:1105,0,casWXR9kI2g5CUkfLEwkDg +DA:1106,0,HdMxc30KI5RwRuzP80n4mQ +DA:1107,0,ycHhLNwnNtdk14CkozGuKw +DA:1108,0,qEM4bFBwiIDS8RaYgzc5zg +DA:1109,0,dVC+HNutklYwapJbJOKpmA +DA:1110,0,+EEmt9hAIdEP9X04tBxl9w +DA:1111,0,VlykEUF/L6SJe2LdJruIyQ +DA:1112,0,Y92t7Z+9+F97P6PkT5tkFQ +DA:1113,0,G3mcvMB3lXh8w6tywZBAOA +DA:1114,0,1PXwnVeUCFnHbcZUQ9jPLA +DA:1115,0,4Gfqqqj46zkBe2xdMHIz4w +DA:1116,0,Mv5fAWr4P/jAMT+2tAx7kQ +DA:1117,0,48Sb3QlPXMd8uoGl/yJC1g +DA:1118,0,ijAt2fh4m8/IRfDg/fY5rQ +DA:1119,0,PCQPucxMZR6+Q+GIjc6FZg +DA:1120,0,wdh/QmMUagMJRmY+In4a4w +DA:1121,0,NAb+yx8cYatQPWufQ/F2gw +DA:1122,0,oheGhifbWWPJ4iFqxf4R0Q +DA:1123,0,ez2ifEfw0w1reEqj3l+HXQ +DA:1150,0,9cV8W5UeXduG1imUtCrMlw +DA:1151,0,NXLT8fGxYkYE0As1PrCrDQ +DA:1152,0,RtcXjjjB+V2Z4UYGACE5hQ +DA:1153,0,s8mAvqmKWFBv8V8rEn+1Cg +DA:1154,0,gwhY6VIUPEpLrExbYyUiyw +DA:1155,0,6UEvCn4eLGcq3m0JECBbxw +DA:1156,0,yJH3NVPEoYSr9fwqjrcKeQ +DA:1157,0,RJyslH0hnEN5fKJzecaIGw +DA:1158,0,X6oOwJxhX6CqzKW+QsruRg +DA:1159,0,XDVWP7nnOcNpQBgmhe07jg +DA:1160,0,Vi9txnjQgnq0jNZeM0vdlQ +DA:1161,0,Ajm12kj/WRGQfH3VwLGl9Q +DA:1162,0,yFULWgPpMc+ETtS+ybp3HA +DA:1163,0,sMKYwWmdeIO5GuVO68gcsg +DA:1164,0,wRHNUVDX9gluuZvOgg5svw +DA:1166,0,Nn5GMzhSw6dSJPlbYgFv+w +DA:1172,0,Mv5fAWr4P/jAMT+2tAx7kQ +DA:1173,0,Usc5n9g49bLKznXHIwi5Vg +DA:1174,0,A5HbmlLMILLjqIl2m3OYfw +DA:1175,0,48Sb3QlPXMd8uoGl/yJC1g +DA:1176,0,ijAt2fh4m8/IRfDg/fY5rQ +DA:1177,0,PCQPucxMZR6+Q+GIjc6FZg +DA:1178,0,j/aLc6TsqdbmOs/I8FofcA +DA:1179,0,oiUqYk9mXmgBFyYoL965Ew +DA:1181,0,az4Fvn7qSOE98+6xTi5RBA +DA:1187,0,2ZYwYJ+Jl0IFMDuN/9J6hg +DA:1202,0,9cV8W5UeXduG1imUtCrMlw +DA:1203,0,4Gfqqqj46zkBe2xdMHIz4w +DA:1205,0,Usc5n9g49bLKznXHIwi5Vg +DA:1212,0,uy/+2UQ1hurYXR3WNfVC+Q +DA:1225,0,9cV8W5UeXduG1imUtCrMlw +DA:1227,0,Mv5fAWr4P/jAMT+2tAx7kQ +DA:1244,0,9cV8W5UeXduG1imUtCrMlw +DA:1245,0,PCQPucxMZR6+Q+GIjc6FZg +DA:1246,0,j/aLc6TsqdbmOs/I8FofcA +DA:1247,0,NAb+yx8cYatQPWufQ/F2gw +DA:1248,0,l56R6qbnP2dr35c+6/9nEQ +DA:1249,0,HQTMASG9arIFBAUEplTVGw +DA:1262,0,9cV8W5UeXduG1imUtCrMlw +DA:1263,0,4Gfqqqj46zkBe2xdMHIz4w +DA:1264,0,Mv5fAWr4P/jAMT+2tAx7kQ +DA:1265,0,Usc5n9g49bLKznXHIwi5Vg +DA:1266,0,A5HbmlLMILLjqIl2m3OYfw +DA:1267,0,48Sb3QlPXMd8uoGl/yJC1g +DA:1268,0,ijAt2fh4m8/IRfDg/fY5rQ +DA:1269,0,PCQPucxMZR6+Q+GIjc6FZg +DA:1270,0,j/aLc6TsqdbmOs/I8FofcA +DA:1271,0,FdOIhKMNDTWmArY6mE+p8Q +DA:1273,0,BvqBNJ5drKAqiaIfoEeOUg +DA:1287,0,9cV8W5UeXduG1imUtCrMlw +DA:1288,0,UFFCtPhs0sfQjRD1mwlg0A +DA:1289,0,uaetSitAoD2KfPp3FZWY0g +DA:1290,0,gc1YS2P2NrTmxtA+/NTutg +DA:1291,0,T6svk+GmbNvwYZTWl5eFEg +DA:1292,0,4Gfqqqj46zkBe2xdMHIz4w +DA:1293,0,Mv5fAWr4P/jAMT+2tAx7kQ +DA:1294,0,Usc5n9g49bLKznXHIwi5Vg +DA:1295,0,A5HbmlLMILLjqIl2m3OYfw +DA:1296,0,48Sb3QlPXMd8uoGl/yJC1g +DA:1297,0,ijAt2fh4m8/IRfDg/fY5rQ +DA:1298,0,PCQPucxMZR6+Q+GIjc6FZg +DA:1299,0,j/aLc6TsqdbmOs/I8FofcA +DA:1300,0,KGOcZ7tNS2cPR1ePCY+sEg +DA:1302,0,tFmTo3GN7D476fTmu2ha9g +DA:1305,0,UBNGC/4l7TzKcaSA+0L9uA +DA:1307,0,+QtiGVnedZ8VTL+9cC4NtQ +DA:1309,0,euf6lOR86/57UQkIb6uazQ +DA:1311,0,ScJ+iN3uJIonM2tp/9c5Kg +DA:1314,0,XwvwP+oSfJ3TUBEvkXdRyA +DA:1316,0,kIgx4Wi+djqKM3fe4ijqIA +DA:1319,0,V4+xklXWxTwAYK19NwcKeg +DA:1320,0,zPSneSsl8uDRRZeGHr0LjA +DA:1322,0,NLutwL79TYgL7XiU0N9UeQ +DA:1337,0,RpsYhfBo/59t2F406Ez31w +LF:587 +LH:102 end_of_record TN: SF:fedifetcher\api\mastodon\api_mastodon_compat.py diff --git a/tests/test_api_mastodon.py b/tests/test_api_mastodon.py index dab163d4..b621fc8f 100644 --- a/tests/test_api_mastodon.py +++ b/tests/test_api_mastodon.py @@ -1,13 +1,10 @@ """Test the Mastodon class.""" -from typing import ClassVar +from typing import Any, ClassVar from unittest.mock import AsyncMock, MagicMock import pytest from fedifetcher.api.mastodon.api_mastodon import Mastodon, MastodonClient -from fedifetcher.api.mastodon.api_mastodon_types import ( - Status, -) pytest_plugins = ('pytest_asyncio',) # noqa: Q000 @@ -21,7 +18,7 @@ class TestMastodonClient: ) class TestHandleResponseErrors: - """Test the handle_response_errors method.""" + """Test the handle_response method.""" async def test_success(self) -> None: """Test a 200 response with a body (success).""" @@ -30,7 +27,7 @@ async def test_success(self) -> None: json=AsyncMock(return_value={"key": "value"}), ) expected_result = {"key": "value"} - result = await TestMastodonClient.client.handle_response_errors(response) + result = await TestMastodonClient.client.handle_response(response) assert result == expected_result async def test_success_no_body(self) -> None: @@ -39,8 +36,8 @@ async def test_success_no_body(self) -> None: status=200, json=AsyncMock(return_value={}), ) - expected_result = True - result = await TestMastodonClient.client.handle_response_errors(response) + expected_result = {"Status": "OK"} + result = await TestMastodonClient.client.handle_response(response) assert result == expected_result async def test_failure(self) -> None: @@ -49,8 +46,8 @@ async def test_failure(self) -> None: status=400, json=AsyncMock(return_value={"error": "error"}), ) - expected_result = False - result = await TestMastodonClient.client.handle_response_errors(response) + expected_result = None + result = await TestMastodonClient.client.handle_response(response) assert result == expected_result async def test_failure_no_body(self) -> None: @@ -59,8 +56,8 @@ async def test_failure_no_body(self) -> None: status=401, json=AsyncMock(return_value={"error": "error"}), ) - expected_result = False - result = await TestMastodonClient.client.handle_response_errors(response) + expected_result = None + result = await TestMastodonClient.client.handle_response(response) assert result == expected_result async def test_failure_no_json(self) -> None: @@ -69,8 +66,8 @@ async def test_failure_no_json(self) -> None: status=403, json=AsyncMock(return_value={"error": "error"}), ) - expected_result = False - result = await TestMastodonClient.client.handle_response_errors(response) + expected_result = None + result = await TestMastodonClient.client.handle_response(response) assert result == expected_result async def test_failure_no_error(self) -> None: @@ -79,8 +76,8 @@ async def test_failure_no_error(self) -> None: status=418, json=AsyncMock(return_value={"error": "error"}), ) - expected_result = False - result = await TestMastodonClient.client.handle_response_errors(response) + expected_result = None + result = await TestMastodonClient.client.handle_response(response) assert result == expected_result async def test_failure_no_status(self) -> None: @@ -89,8 +86,8 @@ async def test_failure_no_status(self) -> None: status=429, json=AsyncMock(return_value={"error": "error"}), ) - expected_result = False - result = await TestMastodonClient.client.handle_response_errors(response) + expected_result = None + result = await TestMastodonClient.client.handle_response(response) assert result == expected_result async def test_failure_no_response(self) -> None: @@ -99,8 +96,8 @@ async def test_failure_no_response(self) -> None: status=500, json=AsyncMock(return_value={"error": "error"}), ) - expected_result = False - result = await TestMastodonClient.client.handle_response_errors(response) + expected_result = None + result = await TestMastodonClient.client.handle_response(response) assert result == expected_result async def test_unknown_response(self) -> None: @@ -108,8 +105,8 @@ async def test_unknown_response(self) -> None: response = MagicMock( json=AsyncMock(return_value={"error": "error"}), ) - expected_result = False - result = await TestMastodonClient.client.handle_response_errors(response) + expected_result = None + result = await TestMastodonClient.client.handle_response(response) assert result == expected_result @@ -120,27 +117,98 @@ class TestMastodon: mastodon: ClassVar[Mastodon] = Mastodon("example.com", "token", pgupdater) # userlite_mock: ClassVar[UserLite] = UserLite( - # id="123456", - # username="username", - # name="name", - # avatarUrl="https://example.com/avatar.png", - # avatarBlurhash="blurhash", # avatarColor="#000000", - # host="example.com", - # ) - note_mock: ClassVar[Status] = Status( - id="123456", - text="text", - createdAt="2021-01-01T00:00:00.000Z", - cw="text", - userId="123456", - # user=userlite_mock, - replyId="123456", - renoteId="123456", - renoteCount=1, - repliesCount=1, - uri="https://example.com/@username/123456", - ) + status_mock: ClassVar[dict[str, Any]] = { + "id": "109612104811129202", + "created_at": "2023-01-01T04:39:46.013Z", + "in_reply_to_id": None, + "in_reply_to_account_id": None, + "sensitive": False, + "spoiler_text": "", + "visibility": "public", + "language": "en", + "uri": "https://mastodon.shatteredsky.net/users/teq/statuses/109612104811129202", + "url": "https://mastodon.shatteredsky.net/@teq/109612104811129202", + "replies_count": 0, + "reblogs_count": 0, + "favourites_count": 1, + "edited_at": None, + "favourited": True, + "reblogged": False, + "muted": False, + "bookmarked": False, + "pinned": False, + "local_only": None, + "content": "

Hello, world! 🦣

", + "filtered": [], + "reblog": None, + "application": { + "name": "Web", + "website": None, + }, + "account": { + "id": "109608061015969173", + "username": "teq", + "acct": "teq", + "display_name": "Teq", + "locked": False, + "bot": False, + "discoverable": True, + "group": False, + "created_at": "2022-12-31T00:00:00.000Z", + "note": "

Hello, I'm Teq (Timothy E. Quilling) 👋

🫠 Born to solve problems that didn't exist before.
❤️‍🔥 Loves open source software!

", + "url": "https://mastodon.shatteredsky.net/@teq", + "avatar": "https://mastodon.shatteredsky.net/system/accounts/avatars/109/608/061/015/969/173/original/a42c6a222db7bc7f.gif", + "avatar_static": "https://mastodon.shatteredsky.net/system/accounts/avatars/109/608/061/015/969/173/static/a42c6a222db7bc7f.png", + "header": "https://mastodon.shatteredsky.net/system/accounts/headers/109/608/061/015/969/173/original/1e3f22fe19524ada.png", + "header_static": "https://mastodon.shatteredsky.net/system/accounts/headers/109/608/061/015/969/173/original/1e3f22fe19524ada.png", + "followers_count": 11, + "following_count": 51, + "statuses_count": 12, + "last_status_at": "2023-08-03", + "noindex": False, + "emojis": [ + { + "shortcode": "verified_animate", + "url": "https://mastodon.shatteredsky.net/system/custom_emojis/images/000/029/576/original/2fa90b024d54a0f0.gif", + "static_url": "https://mastodon.shatteredsky.net/system/custom_emojis/images/000/029/576/static/2fa90b024d54a0f0.png", + "visible_in_picker": True, + }, + { + "shortcode": "party_github", + "url": "https://mastodon.shatteredsky.net/system/custom_emojis/images/000/029/786/original/ef6ea29e513ccd2d.gif", + "static_url": "https://mastodon.shatteredsky.net/system/custom_emojis/images/000/029/786/static/ef6ea29e513ccd2d.png", + "visible_in_picker": True, + }, + ], + "roles": [ + { + "id": "3", + "name": "Owner", + "color": "", + }, + ], + "fields": [ + { + "name": ":verified_animate: Home", + "value": 'shatteredsky.net', + "verified_at": "2023-07-02T20:56:08.588+00:00", + }, + { + "name": ":party_github:\u200b GitHub", + "value": 'github.com/Teqed', + "verified_at": "2023-07-02T20:56:09.155+00:00", + }, + ], + }, + "media_attachments": [], + "mentions": [], + "tags": [], + "emojis": [], + "reactions": [], + "card": None, + "poll": None, + } async def test_init(self) -> None: """Test the __init__ method.""" @@ -150,13 +218,14 @@ async def test_init(self) -> None: async def test_add_context_url_success(self)-> None: """Test the add_context_url method.""" # Test a successful add_context_url - self.mastodon.client.ap_show = AsyncMock(return_value=("Note", self.note_mock)) - result = await self.mastodon.get("url") - assert result == self.note_mock + search_mock: dict[str, list[dict[str, Any]]] = {"statuses": [self.status_mock]} + self.mastodon.client.get = AsyncMock(return_value=search_mock) + result = await self.mastodon.get("https://mastodon.shatteredsky.net/users/teq/statuses/109612104811129202") + assert result == self.status_mock async def test_add_context_url_failed(self)-> None: """Test the add_context_url method.""" - self.mastodon.client.ap_show = AsyncMock(return_value=False) + self.mastodon.client.get = AsyncMock(return_value=False) result = await self.mastodon.get("url") assert result is False