diff --git a/fimfarchive/fetchers.py b/fimfarchive/fetchers.py index d605b45..b54c228 100644 --- a/fimfarchive/fetchers.py +++ b/fimfarchive/fetchers.py @@ -22,6 +22,11 @@ Fetchers for Fimfarchive. # +import requests + +from fimfarchive.exceptions import InvalidStoryError, StorySourceError + + class Fetcher: """ Abstract base class for story fetchers. @@ -95,3 +100,77 @@ class Fetcher: StorySourceError: If source does not return any data. """ raise NotImplementedError() + + +class FimfictionFetcher(Fetcher): + """ + Fetcher for Fimfiction. + """ + data_path = 'https://www.fimfiction.net/download_story.php' + meta_path = 'https://www.fimfiction.net/api/story.php' + + def close(self): + pass + + def get(self, url, **kwargs): + """ + Performs an HTTP GET request. + + Args: + url: Target of the HTTP request. + **kwargs: HTTP query parameters. + + Returns: + Response: A new `Response` object. + + Raises: + StorySourceError: If the server does not return HTTP 200 OK. + """ + try: + response = requests.get(url, params=kwargs) + except IOError as e: + raise StorySourceError("Could not read from server.") from e + + if not response.ok: + raise StorySourceError( + "Server responded with HTTP {} {}." + .format(response.status_code, response.reason) + ) + + return response + + def fetch_data(self, pk): + response = self.get(self.data_path, story=pk, html=True) + data = response.content + + if len(data) == 0: + raise InvalidStoryError("Server returned empty response body.") + + if b'