Merge pull request #546 from jrwren/001-ignore-user

This commit is contained in:
Serene
2021-11-24 12:59:06 +10:00
committed by GitHub
12 changed files with 65 additions and 18 deletions

View File

@@ -78,6 +78,9 @@ The following options are common between both the `archive` and `download` comma
- Can be specified multiple times - Can be specified multiple times
- Disables certain modules from being used - Disables certain modules from being used
- See [Disabling Modules](#disabling-modules) for more information and a list of module names - See [Disabling Modules](#disabling-modules) for more information and a list of module names
- `--ignore-user`
- This will add a user to ignore
- Can be specified multiple times
- `--include-id-file` - `--include-id-file`
- This will add any submission with the IDs in the files provided - This will add any submission with the IDs in the files provided
- Can be specified multiple times - Can be specified multiple times

View File

@@ -17,6 +17,7 @@ _common_options = [
click.option('--authenticate', is_flag=True, default=None), click.option('--authenticate', is_flag=True, default=None),
click.option('--config', type=str, default=None), click.option('--config', type=str, default=None),
click.option('--disable-module', multiple=True, default=None, type=str), click.option('--disable-module', multiple=True, default=None, type=str),
click.option('--ignore-user', type=str, multiple=True, default=None),
click.option('--include-id-file', multiple=True, default=None), click.option('--include-id-file', multiple=True, default=None),
click.option('--log', type=str, default=None), click.option('--log', type=str, default=None),
click.option('--saved', is_flag=True, default=None), click.option('--saved', is_flag=True, default=None),

View File

@@ -28,6 +28,11 @@ class Archiver(RedditConnector):
def download(self): def download(self):
for generator in self.reddit_lists: for generator in self.reddit_lists:
for submission in generator: for submission in generator:
if submission.author.name in self.args.ignore_user:
logger.debug(
f'Submission {submission.id} in {submission.subreddit.display_name} skipped'
f' due to {submission.author.name} being an ignored user')
continue
logger.debug(f'Attempting to archive submission {submission.id}') logger.debug(f'Attempting to archive submission {submission.id}')
self.write_entry(submission) self.write_entry(submission)

View File

@@ -18,6 +18,7 @@ class Configuration(Namespace):
self.exclude_id_file = [] self.exclude_id_file = []
self.file_scheme: str = '{REDDITOR}_{TITLE}_{POSTID}' self.file_scheme: str = '{REDDITOR}_{TITLE}_{POSTID}'
self.folder_scheme: str = '{SUBREDDIT}' self.folder_scheme: str = '{SUBREDDIT}'
self.ignore_user = []
self.include_id_file = [] self.include_id_file = []
self.limit: Optional[int] = None self.limit: Optional[int] = None
self.link: list[str] = [] self.link: list[str] = []

View File

@@ -51,6 +51,11 @@ class RedditDownloader(RedditConnector):
elif submission.subreddit.display_name.lower() in self.args.skip_subreddit: elif submission.subreddit.display_name.lower() in self.args.skip_subreddit:
logger.debug(f'Submission {submission.id} in {submission.subreddit.display_name} in skip list') logger.debug(f'Submission {submission.id} in {submission.subreddit.display_name} in skip list')
return return
elif submission.author.name in self.args.ignore_user:
logger.debug(
f'Submission {submission.id} in {submission.subreddit.display_name} skipped'
f' due to {submission.author.name} being an ignored user')
return
elif not isinstance(submission, praw.models.Submission): elif not isinstance(submission, praw.models.Submission):
logger.warning(f'{submission.id} is not a submission') logger.warning(f'{submission.id} is not a submission')
return return

View File

@@ -9,7 +9,7 @@ from bdfr.exceptions import NotADownloadableLinkError
from bdfr.site_downloaders.base_downloader import BaseDownloader from bdfr.site_downloaders.base_downloader import BaseDownloader
from bdfr.site_downloaders.direct import Direct from bdfr.site_downloaders.direct import Direct
from bdfr.site_downloaders.erome import Erome from bdfr.site_downloaders.erome import Erome
from bdfr.site_downloaders.fallback_downloaders.youtubedl_fallback import YoutubeDlFallback from bdfr.site_downloaders.fallback_downloaders.ytdlp_fallback import YtdlpFallback
from bdfr.site_downloaders.gallery import Gallery from bdfr.site_downloaders.gallery import Gallery
from bdfr.site_downloaders.gfycat import Gfycat from bdfr.site_downloaders.gfycat import Gfycat
from bdfr.site_downloaders.imgur import Imgur from bdfr.site_downloaders.imgur import Imgur
@@ -49,8 +49,8 @@ class DownloadFactory:
return PornHub return PornHub
elif re.match(r'vidble\.com', sanitised_url): elif re.match(r'vidble\.com', sanitised_url):
return Vidble return Vidble
elif YoutubeDlFallback.can_handle_link(sanitised_url): elif YtdlpFallback.can_handle_link(sanitised_url):
return YoutubeDlFallback return YtdlpFallback
else: else:
raise NotADownloadableLinkError(f'No downloader module exists for url {url}') raise NotADownloadableLinkError(f'No downloader module exists for url {url}')

View File

@@ -15,9 +15,9 @@ from bdfr.site_downloaders.youtube import Youtube
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class YoutubeDlFallback(BaseFallbackDownloader, Youtube): class YtdlpFallback(BaseFallbackDownloader, Youtube):
def __init__(self, post: Submission): def __init__(self, post: Submission):
super(YoutubeDlFallback, self).__init__(post) super(YtdlpFallback, self).__init__(post)
def find_resources(self, authenticator: Optional[SiteAuthenticator] = None) -> list[Resource]: def find_resources(self, authenticator: Optional[SiteAuthenticator] = None) -> list[Resource]:
out = Resource( out = Resource(
@@ -31,7 +31,7 @@ class YoutubeDlFallback(BaseFallbackDownloader, Youtube):
@staticmethod @staticmethod
def can_handle_link(url: str) -> bool: def can_handle_link(url: str) -> bool:
try: try:
attributes = YoutubeDlFallback.get_video_attributes(url) attributes = YtdlpFallback.get_video_attributes(url)
except NotADownloadableLinkError: except NotADownloadableLinkError:
return False return False
if attributes: if attributes:

View File

@@ -106,3 +106,18 @@ def test_cli_archive_long(test_args: list[str], tmp_path: Path):
result = runner.invoke(cli, test_args) result = runner.invoke(cli, test_args)
assert result.exit_code == 0 assert result.exit_code == 0
assert re.search(r'Writing entry .*? to file in .*? format', result.output) assert re.search(r'Writing entry .*? to file in .*? format', result.output)
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--ignore-user', 'ArjanEgges', '-l', 'm3hxzd'],
))
def test_cli_archive_ignore_user(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_archive_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'being an ignored user' in result.output
assert 'Attempting to archive submission' not in result.output

View File

@@ -337,3 +337,18 @@ def test_cli_download_include_id_file(tmp_path: Path):
result = runner.invoke(cli, test_args) result = runner.invoke(cli, test_args)
assert result.exit_code == 0 assert result.exit_code == 0
assert 'Downloaded submission' in result.output assert 'Downloaded submission' in result.output
@pytest.mark.online
@pytest.mark.reddit
@pytest.mark.skipif(not does_test_config_exist, reason='A test config file is required for integration tests')
@pytest.mark.parametrize('test_args', (
['--ignore-user', 'ArjanEgges', '-l', 'm3hxzd'],
))
def test_cli_download_ignore_user(test_args: list[str], tmp_path: Path):
runner = CliRunner()
test_args = create_basic_args_for_download_runner(test_args, tmp_path)
result = runner.invoke(cli, test_args)
assert result.exit_code == 0
assert 'Downloaded submission' not in result.output
assert 'being an ignored user' in result.output

View File

@@ -6,7 +6,7 @@ import pytest
from bdfr.exceptions import NotADownloadableLinkError from bdfr.exceptions import NotADownloadableLinkError
from bdfr.resource import Resource from bdfr.resource import Resource
from bdfr.site_downloaders.fallback_downloaders.youtubedl_fallback import YoutubeDlFallback from bdfr.site_downloaders.fallback_downloaders.ytdlp_fallback import YtdlpFallback
@pytest.mark.online @pytest.mark.online
@@ -17,7 +17,7 @@ from bdfr.site_downloaders.fallback_downloaders.youtubedl_fallback import Youtub
('https://milesmatrix.bandcamp.com/album/la-boum/', False), ('https://milesmatrix.bandcamp.com/album/la-boum/', False),
)) ))
def test_can_handle_link(test_url: str, expected: bool): def test_can_handle_link(test_url: str, expected: bool):
result = YoutubeDlFallback.can_handle_link(test_url) result = YtdlpFallback.can_handle_link(test_url)
assert result == expected assert result == expected
@@ -27,7 +27,7 @@ def test_can_handle_link(test_url: str, expected: bool):
)) ))
def test_info_extraction_bad(test_url: str): def test_info_extraction_bad(test_url: str):
with pytest.raises(NotADownloadableLinkError): with pytest.raises(NotADownloadableLinkError):
YoutubeDlFallback.get_video_attributes(test_url) YtdlpFallback.get_video_attributes(test_url)
@pytest.mark.online @pytest.mark.online
@@ -41,7 +41,7 @@ def test_info_extraction_bad(test_url: str):
def test_find_resources(test_url: str, expected_hash: str): def test_find_resources(test_url: str, expected_hash: str):
test_submission = MagicMock() test_submission = MagicMock()
test_submission.url = test_url test_submission.url = test_url
downloader = YoutubeDlFallback(test_submission) downloader = YtdlpFallback(test_submission)
resources = downloader.find_resources() resources = downloader.find_resources()
assert len(resources) == 1 assert len(resources) == 1
assert isinstance(resources[0], Resource) assert isinstance(resources[0], Resource)

View File

@@ -9,7 +9,7 @@ from bdfr.site_downloaders.base_downloader import BaseDownloader
from bdfr.site_downloaders.direct import Direct from bdfr.site_downloaders.direct import Direct
from bdfr.site_downloaders.download_factory import DownloadFactory from bdfr.site_downloaders.download_factory import DownloadFactory
from bdfr.site_downloaders.erome import Erome from bdfr.site_downloaders.erome import Erome
from bdfr.site_downloaders.fallback_downloaders.youtubedl_fallback import YoutubeDlFallback from bdfr.site_downloaders.fallback_downloaders.ytdlp_fallback import YtdlpFallback
from bdfr.site_downloaders.gallery import Gallery from bdfr.site_downloaders.gallery import Gallery
from bdfr.site_downloaders.gfycat import Gfycat from bdfr.site_downloaders.gfycat import Gfycat
from bdfr.site_downloaders.imgur import Imgur from bdfr.site_downloaders.imgur import Imgur
@@ -42,10 +42,10 @@ from bdfr.site_downloaders.youtube import Youtube
('https://i.imgur.com/3SKrQfK.jpg?1', Direct), ('https://i.imgur.com/3SKrQfK.jpg?1', Direct),
('https://dynasty-scans.com/system/images_images/000/017/819/original/80215103_p0.png?1612232781', Direct), ('https://dynasty-scans.com/system/images_images/000/017/819/original/80215103_p0.png?1612232781', Direct),
('https://m.imgur.com/a/py3RW0j', Imgur), ('https://m.imgur.com/a/py3RW0j', Imgur),
('https://v.redd.it/9z1dnk3xr5k61', YoutubeDlFallback), ('https://v.redd.it/9z1dnk3xr5k61', YtdlpFallback),
('https://streamable.com/dt46y', YoutubeDlFallback), ('https://streamable.com/dt46y', YtdlpFallback),
('https://vimeo.com/channels/31259/53576664', YoutubeDlFallback), ('https://vimeo.com/channels/31259/53576664', YtdlpFallback),
('http://video.pbs.org/viralplayer/2365173446/', YoutubeDlFallback), ('http://video.pbs.org/viralplayer/2365173446/', YtdlpFallback),
('https://www.pornhub.com/view_video.php?viewkey=ph5a2ee0461a8d0', PornHub), ('https://www.pornhub.com/view_video.php?viewkey=ph5a2ee0461a8d0', PornHub),
)) ))
def test_factory_lever_good(test_submission_url: str, expected_class: BaseDownloader, reddit_instance: praw.Reddit): def test_factory_lever_good(test_submission_url: str, expected_class: BaseDownloader, reddit_instance: praw.Reddit):

View File

@@ -2,6 +2,7 @@
# coding=utf-8 # coding=utf-8
import platform import platform
import sys
import unittest.mock import unittest.mock
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
@@ -14,7 +15,7 @@ import pytest
from bdfr.file_name_formatter import FileNameFormatter from bdfr.file_name_formatter import FileNameFormatter
from bdfr.resource import Resource from bdfr.resource import Resource
from bdfr.site_downloaders.base_downloader import BaseDownloader from bdfr.site_downloaders.base_downloader import BaseDownloader
from bdfr.site_downloaders.fallback_downloaders.youtubedl_fallback import YoutubeDlFallback from bdfr.site_downloaders.fallback_downloaders.ytdlp_fallback import YtdlpFallback
@pytest.fixture() @pytest.fixture()
@@ -213,6 +214,7 @@ def test_preserve_id_append_when_shortening(test_filename: str, test_ending: str
assert len(str(result)) <= FileNameFormatter.find_max_path_length() assert len(str(result)) <= FileNameFormatter.find_max_path_length()
@pytest.mark.skipif(sys.platform == 'win32', reason='Test broken on windows github')
def test_shorten_filename_real(submission: MagicMock, tmp_path: Path): def test_shorten_filename_real(submission: MagicMock, tmp_path: Path):
submission.title = 'A' * 500 submission.title = 'A' * 500
submission.author.name = 'test' submission.author.name = 'test'
@@ -402,8 +404,8 @@ def test_windows_max_path(tmp_path: Path):
@pytest.mark.online @pytest.mark.online
@pytest.mark.reddit @pytest.mark.reddit
@pytest.mark.parametrize(('test_reddit_id', 'test_downloader', 'expected_names'), ( @pytest.mark.parametrize(('test_reddit_id', 'test_downloader', 'expected_names'), (
('gphmnr', YoutubeDlFallback, {'He has a lot to say today.mp4'}), ('gphmnr', YtdlpFallback, {'He has a lot to say today.mp4'}),
('d0oir2', YoutubeDlFallback, {"Crunk's finest moment. Welcome to the new subreddit!.mp4"}), ('d0oir2', YtdlpFallback, {"Crunk's finest moment. Welcome to the new subreddit!.mp4"}),
)) ))
def test_name_submission( def test_name_submission(
test_reddit_id: str, test_reddit_id: str,