2021-07-30 11:48:32 +02:00
|
|
|
from asyncio import gather, run
|
|
|
|
from collections.abc import Iterable
|
|
|
|
|
|
|
|
from aiohttp import ClientResponse, ClientSession
|
2021-08-01 17:02:15 +02:00
|
|
|
from inject import autoparams
|
2021-07-30 11:48:32 +02:00
|
|
|
|
2021-08-06 00:07:30 +02:00
|
|
|
from ytrssil.config import Configuration
|
2021-07-30 11:48:32 +02:00
|
|
|
from ytrssil.datatypes import Channel, Video
|
2021-11-19 19:44:46 +01:00
|
|
|
from ytrssil.protocols import Fetcher, Parser
|
2021-07-30 11:48:32 +02:00
|
|
|
|
|
|
|
|
2021-11-19 19:44:46 +01:00
|
|
|
class FetcherBase:
|
2021-08-06 00:07:30 +02:00
|
|
|
def fetch_feeds(
|
|
|
|
self,
|
|
|
|
urls: Iterable[str],
|
|
|
|
) -> Iterable[str]: # pragma: no cover
|
2021-11-19 19:44:46 +01:00
|
|
|
raise NotImplementedError
|
2021-08-02 01:38:28 +02:00
|
|
|
|
2021-08-06 00:07:30 +02:00
|
|
|
@autoparams()
|
2021-08-02 01:38:28 +02:00
|
|
|
def fetch_new_videos(
|
|
|
|
self,
|
2021-08-06 00:07:30 +02:00
|
|
|
config: Configuration,
|
2021-08-02 01:38:28 +02:00
|
|
|
parser: Parser,
|
|
|
|
) -> tuple[dict[str, Channel], dict[str, Video]]:
|
2021-08-06 00:07:30 +02:00
|
|
|
feed_urls = config.get_feed_urls()
|
2021-08-02 01:38:28 +02:00
|
|
|
channels: dict[str, Channel] = {}
|
|
|
|
new_videos: dict[str, Video] = {}
|
|
|
|
for feed in self.fetch_feeds(feed_urls):
|
|
|
|
channel = parser(feed)
|
|
|
|
channels[channel.channel_id] = channel
|
|
|
|
new_videos.update(channel.new_videos)
|
|
|
|
|
|
|
|
return channels, new_videos
|
|
|
|
|
|
|
|
|
2021-11-19 19:44:46 +01:00
|
|
|
class AioHttpFetcher(FetcherBase):
|
|
|
|
async def request(
|
|
|
|
self,
|
|
|
|
session: ClientSession,
|
|
|
|
url: str,
|
|
|
|
) -> ClientResponse:
|
2021-08-06 00:07:30 +02:00
|
|
|
return await session.get(url=url)
|
2021-08-02 01:38:28 +02:00
|
|
|
|
|
|
|
async def async_fetch_feeds(self, urls: Iterable[str]) -> Iterable[str]:
|
|
|
|
async with ClientSession() as session:
|
2021-08-06 00:07:30 +02:00
|
|
|
responses: Iterable[ClientResponse] = await gather(*[
|
2021-08-02 01:38:28 +02:00
|
|
|
self.request(session, url) for url in urls
|
|
|
|
])
|
|
|
|
return [
|
|
|
|
await response.text(encoding='UTF-8')
|
|
|
|
for response in responses
|
|
|
|
]
|
|
|
|
|
|
|
|
def fetch_feeds(self, urls: Iterable[str]) -> Iterable[str]:
|
|
|
|
return run(self.async_fetch_feeds(urls))
|
|
|
|
|
|
|
|
|
|
|
|
@autoparams()
|
|
|
|
def create_fetcher(config: Configuration) -> Fetcher:
|
|
|
|
fetcher_type = config.fetcher_type
|
|
|
|
if fetcher_type == 'aiohttp':
|
|
|
|
return AioHttpFetcher()
|
|
|
|
else:
|
|
|
|
raise Exception(f'Unknown feed fetcher type: "{fetcher_type}"')
|