Merge pull request #546 from jrwren/001-ignore-user
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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] = []
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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}')
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -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):
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user