hydrus/hydrus/client/importing/options/FileImportOptions.py

546 lines
24 KiB
Python
Raw Normal View History

2021-06-30 21:27:35 +00:00
import os
2022-08-03 20:59:51 +00:00
import typing
2021-06-30 21:27:35 +00:00
from hydrus.core import HydrusConstants as HC
from hydrus.core import HydrusData
from hydrus.core import HydrusExceptions
2022-08-10 21:32:27 +00:00
from hydrus.core import HydrusGlobals as HG
2021-06-30 21:27:35 +00:00
from hydrus.core import HydrusSerialisable
2022-01-19 21:28:59 +00:00
from hydrus.client import ClientConstants as CC
from hydrus.client import ClientLocation
2022-08-03 20:59:51 +00:00
from hydrus.client import ClientSearch
2021-11-24 21:59:58 +00:00
from hydrus.client.importing.options import PresentationImportOptions
2021-06-30 21:27:35 +00:00
2022-08-03 20:59:51 +00:00
IMPORT_TYPE_QUIET = 0
IMPORT_TYPE_LOUD = 1
2022-08-10 21:32:27 +00:00
def GetRealFileImportOptions( file_import_options: "FileImportOptions", loud_or_quiet: int ) -> "FileImportOptions":
if file_import_options.IsDefault():
file_import_options = HG.client_controller.new_options.GetDefaultFileImportOptions( loud_or_quiet )
return file_import_options
def GetRealPresentationImportOptions( file_import_options: "FileImportOptions", loud_or_quiet: int ) -> PresentationImportOptions.PresentationImportOptions:
real_file_import_options = GetRealFileImportOptions( file_import_options, loud_or_quiet )
return real_file_import_options.GetPresentationImportOptions()
2022-12-21 22:00:27 +00:00
DO_NOT_CHECK = 0
DO_CHECK = 1
DO_CHECK_AND_MATCHES_ARE_DISPOSITIVE = 2
2021-06-30 21:27:35 +00:00
class FileImportOptions( HydrusSerialisable.SerialisableBase ):
SERIALISABLE_TYPE = HydrusSerialisable.SERIALISABLE_TYPE_FILE_IMPORT_OPTIONS
SERIALISABLE_NAME = 'File Import Options'
2022-12-21 22:00:27 +00:00
SERIALISABLE_VERSION = 9
2021-06-30 21:27:35 +00:00
def __init__( self ):
HydrusSerialisable.SerialisableBase.__init__( self )
self._exclude_deleted = True
2022-12-21 22:00:27 +00:00
self._preimport_hash_check_type = DO_CHECK_AND_MATCHES_ARE_DISPOSITIVE
self._preimport_url_check_type = DO_CHECK
self._preimport_url_check_looks_for_neighbours = True
2021-06-30 21:27:35 +00:00
self._allow_decompression_bombs = True
2022-08-03 20:59:51 +00:00
self._filetype_filter_predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_MIME, value = set( HC.GENERAL_FILETYPES ) )
2021-06-30 21:27:35 +00:00
self._min_size = None
self._max_size = None
self._max_gif_size = None
self._min_resolution = None
self._max_resolution = None
self._automatic_archive = False
2021-10-13 20:16:57 +00:00
self._associate_primary_urls = True
2021-06-30 21:27:35 +00:00
self._associate_source_urls = True
2021-11-24 21:59:58 +00:00
self._presentation_import_options = PresentationImportOptions.PresentationImportOptions()
2022-03-23 20:57:10 +00:00
self._import_destination_location_context = ClientLocation.LocationContext.STATICCreateSimple( CC.LOCAL_FILE_SERVICE_KEY )
2021-06-30 21:27:35 +00:00
2022-08-03 20:59:51 +00:00
self._is_default = False
2021-06-30 21:27:35 +00:00
def _GetSerialisableInfo( self ):
2022-03-23 20:57:10 +00:00
serialisable_import_destination_location_context = self._import_destination_location_context.GetSerialisableTuple()
2022-08-03 20:59:51 +00:00
serialisable_filetype_filter_predicate = self._filetype_filter_predicate.GetSerialisableTuple()
2022-12-21 22:00:27 +00:00
pre_import_options = ( self._exclude_deleted, self._preimport_hash_check_type, self._preimport_url_check_type, self._preimport_url_check_looks_for_neighbours, self._allow_decompression_bombs, serialisable_filetype_filter_predicate, self._min_size, self._max_size, self._max_gif_size, self._min_resolution, self._max_resolution, serialisable_import_destination_location_context )
2021-10-13 20:16:57 +00:00
post_import_options = ( self._automatic_archive, self._associate_primary_urls, self._associate_source_urls )
2021-11-24 21:59:58 +00:00
serialisable_presentation_import_options = self._presentation_import_options.GetSerialisableTuple()
2021-06-30 21:27:35 +00:00
2022-08-03 20:59:51 +00:00
return ( pre_import_options, post_import_options, serialisable_presentation_import_options, self._is_default )
2021-06-30 21:27:35 +00:00
def _InitialiseFromSerialisableInfo( self, serialisable_info ):
2022-08-03 20:59:51 +00:00
( pre_import_options, post_import_options, serialisable_presentation_import_options, self._is_default ) = serialisable_info
2021-06-30 21:27:35 +00:00
2022-12-21 22:00:27 +00:00
( self._exclude_deleted, self._preimport_hash_check_type, self._preimport_url_check_type, self._preimport_url_check_looks_for_neighbours, self._allow_decompression_bombs, serialisable_filetype_filter_predicate, self._min_size, self._max_size, self._max_gif_size, self._min_resolution, self._max_resolution, serialisable_import_destination_location_context ) = pre_import_options
2021-10-13 20:16:57 +00:00
( self._automatic_archive, self._associate_primary_urls, self._associate_source_urls ) = post_import_options
2021-11-24 21:59:58 +00:00
self._presentation_import_options = HydrusSerialisable.CreateFromSerialisableTuple( serialisable_presentation_import_options )
2021-06-30 21:27:35 +00:00
2022-08-03 20:59:51 +00:00
self._filetype_filter_predicate = HydrusSerialisable.CreateFromSerialisableTuple( serialisable_filetype_filter_predicate )
2022-03-23 20:57:10 +00:00
self._import_destination_location_context = HydrusSerialisable.CreateFromSerialisableTuple( serialisable_import_destination_location_context )
2021-06-30 21:27:35 +00:00
def _UpdateSerialisableInfo( self, version, old_serialisable_info ):
if version == 1:
( automatic_archive, exclude_deleted, min_size, min_resolution ) = old_serialisable_info
present_new_files = True
present_already_in_inbox_files = False
present_already_in_archive_files = False
new_serialisable_info = ( automatic_archive, exclude_deleted, present_new_files, present_already_in_inbox_files, present_already_in_archive_files, min_size, min_resolution )
return ( 2, new_serialisable_info )
if version == 2:
( automatic_archive, exclude_deleted, present_new_files, present_already_in_inbox_files, present_already_in_archive_files, min_size, min_resolution ) = old_serialisable_info
max_size = None
max_resolution = None
allow_decompression_bombs = True
max_gif_size = 32 * 1048576
pre_import_options = ( exclude_deleted, allow_decompression_bombs, min_size, max_size, max_gif_size, min_resolution, max_resolution )
post_import_options = automatic_archive
presentation_options = ( present_new_files, present_already_in_inbox_files, present_already_in_archive_files )
new_serialisable_info = ( pre_import_options, post_import_options, presentation_options )
return ( 3, new_serialisable_info )
if version == 3:
( pre_import_options, post_import_options, presentation_options ) = old_serialisable_info
( exclude_deleted, allow_decompression_bombs, min_size, max_size, max_gif_size, min_resolution, max_resolution ) = pre_import_options
automatic_archive = post_import_options
do_not_check_known_urls_before_importing = False
do_not_check_hashes_before_importing = False
associate_source_urls = True
pre_import_options = ( exclude_deleted, do_not_check_known_urls_before_importing, do_not_check_hashes_before_importing, allow_decompression_bombs, min_size, max_size, max_gif_size, min_resolution, max_resolution )
post_import_options = ( automatic_archive, associate_source_urls )
new_serialisable_info = ( pre_import_options, post_import_options, presentation_options )
return ( 4, new_serialisable_info )
2021-10-13 20:16:57 +00:00
if version == 4:
( pre_import_options, post_import_options, presentation_options ) = old_serialisable_info
( automatic_archive, associate_source_urls ) = post_import_options
associate_primary_urls = True
post_import_options = ( automatic_archive, associate_primary_urls, associate_source_urls )
new_serialisable_info = ( pre_import_options, post_import_options, presentation_options )
return ( 5, new_serialisable_info )
2021-11-24 21:59:58 +00:00
if version == 5:
( pre_import_options, post_import_options, presentation_options ) = old_serialisable_info
( present_new_files, present_already_in_inbox_files, present_already_in_archive_files ) = presentation_options
presentation_import_options = PresentationImportOptions.PresentationImportOptions()
if not present_new_files:
presentation_import_options.SetPresentationStatus( PresentationImportOptions.PRESENTATION_STATUS_NONE )
else:
if present_already_in_archive_files and present_already_in_inbox_files:
presentation_import_options.SetPresentationStatus( PresentationImportOptions.PRESENTATION_STATUS_ANY_GOOD )
else:
presentation_import_options.SetPresentationStatus( PresentationImportOptions.PRESENTATION_STATUS_NEW_ONLY )
if present_already_in_inbox_files:
presentation_import_options.SetPresentationInbox( PresentationImportOptions.PRESENTATION_INBOX_INCLUDE_INBOX )
serialisable_presentation_import_options = presentation_import_options.GetSerialisableTuple()
new_serialisable_info = ( pre_import_options, post_import_options, serialisable_presentation_import_options )
return ( 6, new_serialisable_info )
2022-03-23 20:57:10 +00:00
if version == 6:
( pre_import_options, post_import_options, serialisable_presentation_import_options ) = old_serialisable_info
( exclude_deleted, do_not_check_known_urls_before_importing, do_not_check_hashes_before_importing, allow_decompression_bombs, min_size, max_size, max_gif_size, min_resolution, max_resolution ) = pre_import_options
import_destination_location_context = ClientLocation.LocationContext.STATICCreateSimple( CC.LOCAL_FILE_SERVICE_KEY )
serialisable_import_destination_location_context = import_destination_location_context.GetSerialisableTuple()
pre_import_options = ( exclude_deleted, do_not_check_known_urls_before_importing, do_not_check_hashes_before_importing, allow_decompression_bombs, min_size, max_size, max_gif_size, min_resolution, max_resolution, serialisable_import_destination_location_context )
new_serialisable_info = ( pre_import_options, post_import_options, serialisable_presentation_import_options )
return ( 7, new_serialisable_info )
2022-08-03 20:59:51 +00:00
if version == 7:
( pre_import_options, post_import_options, serialisable_presentation_import_options ) = old_serialisable_info
( exclude_deleted, do_not_check_known_urls_before_importing, do_not_check_hashes_before_importing, allow_decompression_bombs, min_size, max_size, max_gif_size, min_resolution, max_resolution, serialisable_import_destination_location_context ) = pre_import_options
filetype_filter_predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_MIME, value = set( HC.GENERAL_FILETYPES ) )
serialisable_filetype_filter_predicate = filetype_filter_predicate.GetSerialisableTuple()
pre_import_options = ( exclude_deleted, do_not_check_known_urls_before_importing, do_not_check_hashes_before_importing, allow_decompression_bombs, serialisable_filetype_filter_predicate, min_size, max_size, max_gif_size, min_resolution, max_resolution, serialisable_import_destination_location_context )
is_default = False
new_serialisable_info = ( pre_import_options, post_import_options, serialisable_presentation_import_options, is_default )
return ( 8, new_serialisable_info )
2022-12-21 22:00:27 +00:00
if version == 8:
( pre_import_options, post_import_options, serialisable_presentation_import_options, is_default ) = old_serialisable_info
( exclude_deleted, do_not_check_known_urls_before_importing, do_not_check_hashes_before_importing, allow_decompression_bombs, serialisable_filetype_filter_predicate, min_size, max_size, max_gif_size, min_resolution, max_resolution, serialisable_import_destination_location_context ) = pre_import_options
if do_not_check_hashes_before_importing:
preimport_hash_check_type = DO_NOT_CHECK
else:
preimport_hash_check_type = DO_CHECK_AND_MATCHES_ARE_DISPOSITIVE
if do_not_check_known_urls_before_importing:
preimport_url_check_type = DO_NOT_CHECK
else:
preimport_url_check_type = DO_CHECK
preimport_url_check_looks_for_neighbours = True
pre_import_options = ( exclude_deleted, preimport_hash_check_type, preimport_url_check_type, preimport_url_check_looks_for_neighbours, allow_decompression_bombs, serialisable_filetype_filter_predicate, min_size, max_size, max_gif_size, min_resolution, max_resolution, serialisable_import_destination_location_context )
new_serialisable_info = ( pre_import_options, post_import_options, serialisable_presentation_import_options, is_default )
return ( 9, new_serialisable_info )
2021-06-30 21:27:35 +00:00
def AllowsDecompressionBombs( self ):
return self._allow_decompression_bombs
2021-10-13 20:16:57 +00:00
def AutomaticallyArchives( self ) -> bool:
2021-06-30 21:27:35 +00:00
return self._automatic_archive
def CheckFileIsValid( self, size, mime, width, height ):
2022-08-03 20:59:51 +00:00
allowed_mimes = self.GetAllowedSpecificFiletypes()
if mime not in allowed_mimes:
raise HydrusExceptions.FileImportRulesException( 'File was a {}, which is not allowed by the File Import Options.'.format( HC.mime_string_lookup[ mime ] ) )
2021-06-30 21:27:35 +00:00
if self._min_size is not None and size < self._min_size:
raise HydrusExceptions.FileImportRulesException( 'File was ' + HydrusData.ToHumanBytes( size ) + ' but the lower limit is ' + HydrusData.ToHumanBytes( self._min_size ) + '.' )
2021-06-30 21:27:35 +00:00
if self._max_size is not None and size > self._max_size:
raise HydrusExceptions.FileImportRulesException( 'File was ' + HydrusData.ToHumanBytes( size ) + ' but the upper limit is ' + HydrusData.ToHumanBytes( self._max_size ) + '.' )
2021-06-30 21:27:35 +00:00
if mime == HC.IMAGE_GIF and self._max_gif_size is not None and size > self._max_gif_size:
raise HydrusExceptions.FileImportRulesException( 'File was ' + HydrusData.ToHumanBytes( size ) + ' but the upper limit for gifs is ' + HydrusData.ToHumanBytes( self._max_gif_size ) + '.' )
2021-06-30 21:27:35 +00:00
if self._min_resolution is not None:
( min_width, min_height ) = self._min_resolution
too_thin = width is not None and width < min_width
too_short = height is not None and height < min_height
if too_thin or too_short:
raise HydrusExceptions.FileImportRulesException( 'File had resolution ' + HydrusData.ConvertResolutionToPrettyString( ( width, height ) ) + ' but the lower limit is ' + HydrusData.ConvertResolutionToPrettyString( self._min_resolution ) )
2021-06-30 21:27:35 +00:00
if self._max_resolution is not None:
( max_width, max_height ) = self._max_resolution
too_wide = width is not None and width > max_width
too_tall = height is not None and height > max_height
if too_wide or too_tall:
raise HydrusExceptions.FileImportRulesException( 'File had resolution ' + HydrusData.ConvertResolutionToPrettyString( ( width, height ) ) + ' but the upper limit is ' + HydrusData.ConvertResolutionToPrettyString( self._max_resolution ) )
2021-06-30 21:27:35 +00:00
2022-08-03 20:59:51 +00:00
def CheckReadyToImport( self ) -> None:
if self._import_destination_location_context.IsEmpty():
raise HydrusExceptions.FileImportBlockException( 'There is no import destination set in the File Import Options!' )
2021-06-30 21:27:35 +00:00
def CheckNetworkDownload( self, possible_mime, num_bytes, is_complete_file_size ):
if is_complete_file_size:
error_prefix = 'Download was apparently '
else:
error_prefix = 'Download was at least '
if possible_mime is not None:
if possible_mime == HC.IMAGE_GIF and self._max_gif_size is not None and num_bytes > self._max_gif_size:
raise HydrusExceptions.FileImportRulesException( error_prefix + HydrusData.ToHumanBytes( num_bytes ) + ' but the upper limit for gifs is ' + HydrusData.ToHumanBytes( self._max_gif_size ) + '.' )
2021-06-30 21:27:35 +00:00
if self._max_size is not None and num_bytes > self._max_size:
raise HydrusExceptions.FileImportRulesException( error_prefix + HydrusData.ToHumanBytes( num_bytes ) + ' but the upper limit is ' + HydrusData.ToHumanBytes( self._max_size ) + '.' )
2021-06-30 21:27:35 +00:00
if is_complete_file_size:
if self._min_size is not None and num_bytes < self._min_size:
raise HydrusExceptions.FileImportRulesException( error_prefix + HydrusData.ToHumanBytes( num_bytes ) + ' but the lower limit is ' + HydrusData.ToHumanBytes( self._min_size ) + '.' )
2021-06-30 21:27:35 +00:00
def ExcludesDeleted( self ):
return self._exclude_deleted
2022-08-03 20:59:51 +00:00
def GetAllowedSpecificFiletypes( self ) -> typing.Collection[ int ]:
return ClientSearch.ConvertSummaryFiletypesToSpecific( self._filetype_filter_predicate.GetValue(), only_searchable = False )
2022-01-19 21:28:59 +00:00
def GetDestinationLocationContext( self ) -> ClientLocation.LocationContext:
2022-03-23 20:57:10 +00:00
return self._import_destination_location_context
2022-01-19 21:28:59 +00:00
2022-08-10 21:32:27 +00:00
def GetPresentationImportOptions( self ) -> PresentationImportOptions.PresentationImportOptions:
2021-06-30 21:27:35 +00:00
2021-11-24 21:59:58 +00:00
return self._presentation_import_options
2021-06-30 21:27:35 +00:00
2022-12-21 22:00:27 +00:00
def GetPreImportHashCheckType( self ):
return self._preimport_hash_check_type
def GetPreImportURLCheckType( self ):
return self._preimport_url_check_type
2021-06-30 21:27:35 +00:00
def GetPreImportOptions( self ):
2022-12-21 22:00:27 +00:00
pre_import_options = ( self._exclude_deleted, self._preimport_hash_check_type, self._preimport_url_check_type, self._allow_decompression_bombs, self._min_size, self._max_size, self._max_gif_size, self._min_resolution, self._max_resolution )
2021-06-30 21:27:35 +00:00
return pre_import_options
def GetSummary( self ):
2022-08-03 20:59:51 +00:00
if self._is_default:
return 'Using whatever the default file import options is at at time of import.'
2021-06-30 21:27:35 +00:00
statements = []
2022-08-03 20:59:51 +00:00
statements.append( 'allowing {}'.format( ClientSearch.ConvertSummaryFiletypesToString( self._filetype_filter_predicate.GetValue() ) ) )
2021-06-30 21:27:35 +00:00
if self._exclude_deleted:
statements.append( 'excluding previously deleted' )
if not self._allow_decompression_bombs:
statements.append( 'excluding decompression bombs' )
if self._min_size is not None:
statements.append( 'excluding < ' + HydrusData.ToHumanBytes( self._min_size ) )
if self._max_size is not None:
statements.append( 'excluding > ' + HydrusData.ToHumanBytes( self._max_size ) )
if self._max_gif_size is not None:
statements.append( 'excluding gifs > ' + HydrusData.ToHumanBytes( self._max_gif_size ) )
if self._min_resolution is not None:
( width, height ) = self._min_resolution
statements.append( 'excluding < ( ' + HydrusData.ToHumanInt( width ) + ' x ' + HydrusData.ToHumanInt( height ) + ' )' )
if self._max_resolution is not None:
( width, height ) = self._max_resolution
statements.append( 'excluding > ( ' + HydrusData.ToHumanInt( width ) + ' x ' + HydrusData.ToHumanInt( height ) + ' )' )
#
if self._automatic_archive:
statements.append( 'automatically archiving' )
#
2021-11-24 21:59:58 +00:00
statements.append( self._presentation_import_options.GetSummary() )
2021-06-30 21:27:35 +00:00
2021-11-24 21:59:58 +00:00
#
2021-06-30 21:27:35 +00:00
summary = os.linesep.join( statements )
return summary
2022-08-03 20:59:51 +00:00
def IsDefault( self ) -> bool:
2022-04-13 21:39:26 +00:00
2022-08-03 20:59:51 +00:00
return self._is_default
2022-04-13 21:39:26 +00:00
2022-12-21 22:00:27 +00:00
def PreImportURLCheckLooksForNeighbours( self ) -> bool:
2022-03-23 20:57:10 +00:00
2022-12-21 22:00:27 +00:00
return self._preimport_url_check_looks_for_neighbours
2022-03-23 20:57:10 +00:00
2022-08-03 20:59:51 +00:00
def SetAllowedSpecificFiletypes( self, mimes ) -> None:
mimes = ClientSearch.ConvertSpecificFiletypesToSummary( mimes, only_searchable = False )
self._filetype_filter_predicate = ClientSearch.Predicate( ClientSearch.PREDICATE_TYPE_SYSTEM_MIME, value = mimes )
2022-12-21 22:00:27 +00:00
def SetDestinationLocationContext( self, location_context: ClientLocation.LocationContext ):
self._import_destination_location_context = location_context.Duplicate()
2022-08-03 20:59:51 +00:00
def SetIsDefault( self, value: bool ) -> None:
self._is_default = value
2021-10-13 20:16:57 +00:00
def SetPostImportOptions( self, automatic_archive: bool, associate_primary_urls: bool, associate_source_urls: bool ):
2021-06-30 21:27:35 +00:00
self._automatic_archive = automatic_archive
2021-10-13 20:16:57 +00:00
self._associate_primary_urls = associate_primary_urls
2021-06-30 21:27:35 +00:00
self._associate_source_urls = associate_source_urls
2022-12-21 22:00:27 +00:00
def SetPreImportURLCheckLooksForNeighbours( self, preimport_url_check_looks_for_neighbours: bool ):
self._preimport_url_check_looks_for_neighbours = preimport_url_check_looks_for_neighbours
2021-11-24 21:59:58 +00:00
def SetPresentationImportOptions( self, presentation_import_options: PresentationImportOptions.PresentationImportOptions ):
2021-06-30 21:27:35 +00:00
2021-11-24 21:59:58 +00:00
self._presentation_import_options = presentation_import_options
2021-06-30 21:27:35 +00:00
2022-12-21 22:00:27 +00:00
def SetPreImportOptions( self, exclude_deleted, preimport_hash_check_type, preimport_url_check_type, allow_decompression_bombs, min_size, max_size, max_gif_size, min_resolution, max_resolution ):
2021-06-30 21:27:35 +00:00
self._exclude_deleted = exclude_deleted
2022-12-21 22:00:27 +00:00
self._preimport_hash_check_type = preimport_hash_check_type
self._preimport_url_check_type = preimport_url_check_type
2021-06-30 21:27:35 +00:00
self._allow_decompression_bombs = allow_decompression_bombs
self._min_size = min_size
self._max_size = max_size
self._max_gif_size = max_gif_size
self._min_resolution = min_resolution
self._max_resolution = max_resolution
2021-10-13 20:16:57 +00:00
def ShouldAssociatePrimaryURLs( self ) -> bool:
return self._associate_primary_urls
def ShouldAssociateSourceURLs( self ) -> bool:
2021-06-30 21:27:35 +00:00
return self._associate_source_urls
HydrusSerialisable.SERIALISABLE_TYPES_TO_OBJECT_TYPES[ HydrusSerialisable.SERIALISABLE_TYPE_FILE_IMPORT_OPTIONS ] = FileImportOptions