hydrus/hydrus/client/ClientLocalServerResources.py

1996 lines
70 KiB
Python
Raw Normal View History

2019-02-27 23:03:30 +00:00
import collections
2021-01-27 22:14:03 +00:00
import collections.abc
2020-05-20 21:36:02 +00:00
import json
import os
import time
import traceback
from twisted.web.static import File as FileResource
2020-04-22 21:00:35 +00:00
from hydrus.core import HydrusConstants as HC
from hydrus.core import HydrusData
from hydrus.core import HydrusExceptions
from hydrus.core import HydrusGlobals as HG
from hydrus.core import HydrusNetworking
from hydrus.core import HydrusPaths
from hydrus.core import HydrusServerResources
from hydrus.core import HydrusTags
2015-12-02 22:32:18 +00:00
2020-07-29 20:52:44 +00:00
from hydrus.client import ClientAPI
from hydrus.client import ClientConstants as CC
from hydrus.client import ClientSearch
from hydrus.client.importing import ClientImportFileSeeds
from hydrus.client.media import ClientMedia
from hydrus.client.metadata import ClientTags
2020-07-29 20:52:44 +00:00
from hydrus.client.networking import ClientNetworkingContexts
from hydrus.client.networking import ClientNetworkingDomain
2015-12-02 22:32:18 +00:00
local_booru_css = FileResource( os.path.join( HC.STATIC_DIR, 'local_booru_style.css' ), defaultType = 'text/css' )
2015-08-05 18:42:35 +00:00
2019-02-06 22:41:35 +00:00
LOCAL_BOORU_INT_PARAMS = set()
LOCAL_BOORU_BYTE_PARAMS = { 'share_key', 'hash' }
LOCAL_BOORU_STRING_PARAMS = set()
LOCAL_BOORU_JSON_PARAMS = set()
2019-06-26 21:27:18 +00:00
LOCAL_BOORU_JSON_BYTE_LIST_PARAMS = set()
2019-02-06 22:41:35 +00:00
2019-03-13 21:04:21 +00:00
CLIENT_API_INT_PARAMS = { 'file_id' }
2019-07-17 22:10:19 +00:00
CLIENT_API_BYTE_PARAMS = { 'hash', 'destination_page_key', 'page_key', 'Hydrus-Client-API-Access-Key', 'Hydrus-Client-API-Session-Key' }
2019-08-07 22:59:53 +00:00
CLIENT_API_STRING_PARAMS = { 'name', 'url', 'domain' }
CLIENT_API_JSON_PARAMS = { 'basic_permissions', 'system_inbox', 'system_archive', 'tags', 'file_ids', 'only_return_identifiers', 'detailed_url_information', 'simple' }
2019-06-26 21:27:18 +00:00
CLIENT_API_JSON_BYTE_LIST_PARAMS = { 'hashes' }
2019-02-06 22:41:35 +00:00
def ParseLocalBooruGETArgs( requests_args ):
2019-06-26 21:27:18 +00:00
args = HydrusNetworking.ParseTwistedRequestGETArgs( requests_args, LOCAL_BOORU_INT_PARAMS, LOCAL_BOORU_BYTE_PARAMS, LOCAL_BOORU_STRING_PARAMS, LOCAL_BOORU_JSON_PARAMS, LOCAL_BOORU_JSON_BYTE_LIST_PARAMS )
2019-02-06 22:41:35 +00:00
return args
def ParseClientAPIGETArgs( requests_args ):
2019-06-26 21:27:18 +00:00
args = HydrusNetworking.ParseTwistedRequestGETArgs( requests_args, CLIENT_API_INT_PARAMS, CLIENT_API_BYTE_PARAMS, CLIENT_API_STRING_PARAMS, CLIENT_API_JSON_PARAMS, CLIENT_API_JSON_BYTE_LIST_PARAMS )
2019-02-06 22:41:35 +00:00
return args
2019-06-26 21:27:18 +00:00
def ParseClientAPIPOSTByteArgs( args ):
2019-02-27 23:03:30 +00:00
if not isinstance( args, dict ):
raise HydrusExceptions.BadRequestException( 'The given parameter did not seem to be a JSON Object!' )
parsed_request_args = HydrusNetworking.ParsedRequestArguments( args )
2019-06-26 21:27:18 +00:00
for var_name in CLIENT_API_BYTE_PARAMS:
2019-02-27 23:03:30 +00:00
2019-06-26 21:27:18 +00:00
if var_name in parsed_request_args:
2019-02-27 23:03:30 +00:00
2019-06-26 21:27:18 +00:00
try:
2019-02-27 23:03:30 +00:00
2019-06-26 21:27:18 +00:00
v = bytes.fromhex( parsed_request_args[ var_name ] )
2019-02-27 23:03:30 +00:00
2019-06-26 21:27:18 +00:00
if len( v ) == 0:
del parsed_request_args[ var_name ]
else:
parsed_request_args[ var_name ] = v
2019-02-27 23:03:30 +00:00
2019-06-26 21:27:18 +00:00
except:
raise HydrusExceptions.BadRequestException( 'I was expecting to parse \'{}\' as a hex string, but it failed.'.format( var_name ) )
2019-02-27 23:03:30 +00:00
2019-06-26 21:27:18 +00:00
for var_name in CLIENT_API_JSON_BYTE_LIST_PARAMS:
2019-02-27 23:03:30 +00:00
2019-06-26 21:27:18 +00:00
if var_name in parsed_request_args:
2019-02-27 23:03:30 +00:00
2019-06-26 21:27:18 +00:00
try:
2019-02-27 23:03:30 +00:00
2019-06-26 21:27:18 +00:00
v_list = [ bytes.fromhex( hash_hex ) for hash_hex in parsed_request_args[ var_name ] ]
2019-02-27 23:03:30 +00:00
2019-06-26 21:27:18 +00:00
v_list = [ v for v in v_list if len( v ) > 0 ]
2019-02-27 23:03:30 +00:00
2019-06-26 21:27:18 +00:00
if len( v_list ) == 0:
del parsed_request_args[ var_name ]
else:
parsed_request_args[ var_name ] = v_list
except:
raise HydrusExceptions.BadRequestException( 'I was expecting to parse \'{}\' as a list of hex strings, but it failed.'.format( var_name ) )
2019-02-27 23:03:30 +00:00
return parsed_request_args
2019-02-06 22:41:35 +00:00
2019-02-27 23:03:30 +00:00
def ParseClientAPIPOSTArgs( request ):
2019-02-06 22:41:35 +00:00
request.content.seek( 0 )
if not request.requestHeaders.hasHeader( 'Content-Type' ):
2019-02-27 23:03:30 +00:00
parsed_request_args = HydrusNetworking.ParsedRequestArguments()
2019-02-06 22:41:35 +00:00
total_bytes_read = 0
else:
content_types = request.requestHeaders.getRawHeaders( 'Content-Type' )
content_type = content_types[0]
try:
mime = HC.mime_enum_lookup[ content_type ]
except:
2019-02-27 23:03:30 +00:00
raise HydrusExceptions.BadRequestException( 'Did not recognise Content-Type header!' )
2019-02-06 22:41:35 +00:00
total_bytes_read = 0
if mime == HC.APPLICATION_JSON:
json_bytes = request.content.read()
total_bytes_read += len( json_bytes )
json_string = str( json_bytes, 'utf-8' )
2019-02-27 23:03:30 +00:00
args = json.loads( json_string )
2019-06-26 21:27:18 +00:00
parsed_request_args = ParseClientAPIPOSTByteArgs( args )
2019-02-06 22:41:35 +00:00
else:
2019-02-27 23:03:30 +00:00
parsed_request_args = HydrusNetworking.ParsedRequestArguments()
2019-02-06 22:41:35 +00:00
( os_file_handle, temp_path ) = HydrusPaths.GetTempPath()
request.temp_file_info = ( os_file_handle, temp_path )
with open( temp_path, 'wb' ) as f:
for block in HydrusPaths.ReadFileLikeAsBlocks( request.content ):
f.write( block )
total_bytes_read += len( block )
2019-02-27 23:03:30 +00:00
return ( parsed_request_args, total_bytes_read )
2019-02-06 22:41:35 +00:00
2019-03-06 23:06:22 +00:00
def ParseClientAPISearchPredicates( request ):
default_search_values = {}
default_search_values[ 'tags' ] = []
default_search_values[ 'system_inbox' ] = False
default_search_values[ 'system_archive' ] = False
for ( key, value ) in default_search_values.items():
if key not in request.parsed_request_args:
request.parsed_request_args[ key ] = value
tags = request.parsed_request_args[ 'tags' ]
system_inbox = request.parsed_request_args[ 'system_inbox' ]
system_archive = request.parsed_request_args[ 'system_archive' ]
negated_tags = [ tag for tag in tags if tag.startswith( '-' ) ]
tags = [ tag for tag in tags if not tag.startswith( '-' ) ]
negated_tags = HydrusTags.CleanTags( negated_tags )
tags = HydrusTags.CleanTags( tags )
request.client_api_permissions.CheckCanSearchTags( tags )
predicates = []
for tag in negated_tags:
2020-03-11 21:52:11 +00:00
predicates.append( ClientSearch.Predicate( predicate_type = ClientSearch.PREDICATE_TYPE_TAG, value = tag, inclusive = False ) )
2019-03-06 23:06:22 +00:00
for tag in tags:
2020-03-11 21:52:11 +00:00
predicates.append( ClientSearch.Predicate( predicate_type = ClientSearch.PREDICATE_TYPE_TAG, value = tag ) )
2019-03-06 23:06:22 +00:00
if system_inbox:
2020-03-11 21:52:11 +00:00
predicates.append( ClientSearch.Predicate( predicate_type = ClientSearch.PREDICATE_TYPE_SYSTEM_INBOX ) )
2019-03-06 23:06:22 +00:00
elif system_archive:
2020-03-11 21:52:11 +00:00
predicates.append( ClientSearch.Predicate( predicate_type = ClientSearch.PREDICATE_TYPE_SYSTEM_ARCHIVE ) )
2019-03-06 23:06:22 +00:00
return predicates
2017-03-02 02:14:56 +00:00
class HydrusResourceBooru( HydrusServerResources.HydrusResource ):
2015-08-05 18:42:35 +00:00
2019-02-06 22:41:35 +00:00
def _callbackParseGETArgs( self, request ):
2019-02-27 23:03:30 +00:00
parsed_request_args = ParseLocalBooruGETArgs( request.args )
2019-02-06 22:41:35 +00:00
2019-02-27 23:03:30 +00:00
request.parsed_request_args = parsed_request_args
2019-02-06 22:41:35 +00:00
return request
def _callbackParsePOSTArgs( self, request ):
return request
2017-06-21 21:15:59 +00:00
def _reportDataUsed( self, request, num_bytes ):
2015-08-05 18:42:35 +00:00
2017-06-21 21:15:59 +00:00
self._service.ReportDataUsed( num_bytes )
2015-08-05 18:42:35 +00:00
2017-06-21 21:15:59 +00:00
def _reportRequestUsed( self, request ):
2015-08-05 18:42:35 +00:00
2017-06-21 21:15:59 +00:00
self._service.ReportRequestUsed()
2015-08-05 18:42:35 +00:00
2017-03-02 02:14:56 +00:00
def _checkService( self, request ):
2015-08-05 18:42:35 +00:00
2017-03-02 02:14:56 +00:00
HydrusServerResources.HydrusResource._checkService( self, request )
2015-08-05 18:42:35 +00:00
2017-06-07 22:05:15 +00:00
if not self._service.BandwidthOK():
2017-03-02 02:14:56 +00:00
raise HydrusExceptions.BandwidthException( 'This service has run out of bandwidth. Please try again later.' )
2015-08-05 18:42:35 +00:00
2017-03-02 02:14:56 +00:00
class HydrusResourceBooruFile( HydrusResourceBooru ):
2015-08-05 18:42:35 +00:00
def _threadDoGETJob( self, request ):
2019-02-27 23:03:30 +00:00
share_key = request.parsed_request_args[ 'share_key' ]
hash = request.parsed_request_args[ 'hash' ]
2015-08-05 18:42:35 +00:00
2017-12-06 22:06:56 +00:00
HG.client_controller.local_booru_manager.CheckFileAuthorised( share_key, hash )
2015-08-05 18:42:35 +00:00
2018-03-07 22:48:29 +00:00
media_result = HG.client_controller.local_booru_manager.GetMediaResult( share_key, hash )
2020-07-22 20:59:16 +00:00
try:
mime = media_result.GetMime()
path = HG.client_controller.client_files_manager.GetFilePath( hash, mime )
except HydrusExceptions.FileMissingException:
raise HydrusExceptions.NotFoundException( 'Could not find that file!' )
2015-08-05 18:42:35 +00:00
2018-03-07 22:48:29 +00:00
response_context = HydrusServerResources.ResponseContext( 200, mime = mime, path = path )
2015-08-05 18:42:35 +00:00
return response_context
2017-03-02 02:14:56 +00:00
class HydrusResourceBooruGallery( HydrusResourceBooru ):
2015-08-05 18:42:35 +00:00
def _threadDoGETJob( self, request ):
# in future, make this a standard frame with a search key that'll load xml or yaml AJAX stuff
# with file info included, so the page can sort and whatever
2019-08-21 21:34:01 +00:00
share_key = request.parsed_request_args.GetValue( 'share_key', bytes )
2015-08-05 18:42:35 +00:00
2017-12-06 22:06:56 +00:00
local_booru_manager = HG.client_controller.local_booru_manager
2015-08-05 18:42:35 +00:00
local_booru_manager.CheckShareAuthorised( share_key )
( name, text, timeout, media_results ) = local_booru_manager.GetGalleryInfo( share_key )
body = '''<html>
<head>'''
if name == '': body += '''
<title>hydrus network local booru share</title>'''
else: body += '''
<title>''' + name + '''</title>'''
body += '''
<link href="hydrus.ico" rel="shortcut icon" />
<link href="style.css" rel="stylesheet" type="text/css" />'''
( thumbnail_width, thumbnail_height ) = HC.options[ 'thumbnail_dimensions' ]
body += '''
<style>
.thumbnail_container { width: ''' + str( thumbnail_width ) + '''px; height: ''' + str( thumbnail_height ) + '''px; }
</style>'''
body += '''
</head>
<body>'''
body += '''
<div class="timeout">This share ''' + HydrusData.ConvertTimestampToPrettyExpires( timeout ) + '''.</div>'''
if name != '': body += '''
<h3>''' + name + '''</h3>'''
if text != '':
newline = '''</p>
<p>'''
body += '''
<p>''' + text.replace( os.linesep, newline ).replace( '\n', newline ) + '''</p>'''
body+= '''
<div class="media">'''
for media_result in media_results:
hash = media_result.GetHash()
mime = media_result.GetMime()
# if mime in flash or pdf or whatever, get other thumbnail
body += '''
<span class="thumbnail">
<span class="thumbnail_container">
2019-01-09 22:59:03 +00:00
<a href="page?share_key=''' + share_key.hex() + '''&hash=''' + hash.hex() + '''">
<img src="thumbnail?share_key=''' + share_key.hex() + '''&hash=''' + hash.hex() + '''" />
2015-08-05 18:42:35 +00:00
</a>
</span>
</span>'''
body += '''
</div>
2015-10-21 21:53:10 +00:00
<div class="footer"><a href="https://hydrusnetwork.github.io/hydrus/">hydrus network</a></div>
2015-08-05 18:42:35 +00:00
</body>
</html>'''
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.TEXT_HTML, body = body )
return response_context
2017-03-02 02:14:56 +00:00
class HydrusResourceBooruPage( HydrusResourceBooru ):
2015-08-05 18:42:35 +00:00
def _threadDoGETJob( self, request ):
2019-08-21 21:34:01 +00:00
share_key = request.parsed_request_args.GetValue( 'share_key', bytes )
hash = request.parsed_request_args.GetValue( 'hash', bytes )
2015-08-05 18:42:35 +00:00
2017-12-06 22:06:56 +00:00
local_booru_manager = HG.client_controller.local_booru_manager
2015-08-05 18:42:35 +00:00
local_booru_manager.CheckFileAuthorised( share_key, hash )
( name, text, timeout, media_result ) = local_booru_manager.GetPageInfo( share_key, hash )
body = '''<html>
<head>'''
if name == '': body += '''
<title>hydrus network local booru share</title>'''
else: body += '''
<title>''' + name + '''</title>'''
body += '''
<link href="hydrus.ico" rel="shortcut icon" />
<link href="style.css" rel="stylesheet" type="text/css" />'''
body += '''
</head>
<body>'''
body += '''
<div class="timeout">This share ''' + HydrusData.ConvertTimestampToPrettyExpires( timeout ) + '''.</div>'''
if name != '': body += '''
<h3>''' + name + '''</h3>'''
if text != '':
newline = '''</p>
<p>'''
body += '''
<p>''' + text.replace( os.linesep, newline ).replace( '\n', newline ) + '''</p>'''
body+= '''
<div class="media">'''
mime = media_result.GetMime()
2020-01-22 21:04:43 +00:00
if mime in HC.IMAGES or mime in HC.ANIMATIONS:
2015-08-05 18:42:35 +00:00
( width, height ) = media_result.GetResolution()
body += '''
2019-01-09 22:59:03 +00:00
<img width="''' + str( width ) + '''" height="''' + str( height ) + '''" src="file?share_key=''' + share_key.hex() + '''&hash=''' + hash.hex() + '''" />'''
2015-08-05 18:42:35 +00:00
elif mime in HC.VIDEO:
( width, height ) = media_result.GetResolution()
body += '''
2019-01-09 22:59:03 +00:00
<video width="''' + str( width ) + '''" height="''' + str( height ) + '''" controls="" loop="" autoplay="" src="file?share_key=''' + share_key.hex() + '''&hash=''' + hash.hex() + '''" />
<p><a href="file?share_key=''' + share_key.hex() + '''&hash=''' + hash.hex() + '''">link to ''' + HC.mime_string_lookup[ mime ] + ''' file</a></p>'''
2015-08-05 18:42:35 +00:00
elif mime == HC.APPLICATION_FLASH:
( width, height ) = media_result.GetResolution()
body += '''
2019-01-09 22:59:03 +00:00
<embed width="''' + str( width ) + '''" height="''' + str( height ) + '''" src="file?share_key=''' + share_key.hex() + '''&hash=''' + hash.hex() + '''" />
<p><a href="file?share_key=''' + share_key.hex() + '''&hash=''' + hash.hex() + '''">link to ''' + HC.mime_string_lookup[ mime ] + ''' file</a></p>'''
2015-08-05 18:42:35 +00:00
else:
body += '''
2019-01-09 22:59:03 +00:00
<p><a href="file?share_key=''' + share_key.hex() + '''&hash=''' + hash.hex() + '''">link to ''' + HC.mime_string_lookup[ mime ] + ''' file</a></p>'''
2015-08-05 18:42:35 +00:00
body += '''
</div>
2015-10-21 21:53:10 +00:00
<div class="footer"><a href="https://hydrusnetwork.github.io/hydrus/">hydrus network</a></div>
2015-08-05 18:42:35 +00:00
</body>
</html>'''
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.TEXT_HTML, body = body )
return response_context
2017-03-02 02:14:56 +00:00
class HydrusResourceBooruThumbnail( HydrusResourceBooru ):
2015-08-05 18:42:35 +00:00
def _threadDoGETJob( self, request ):
2019-08-21 21:34:01 +00:00
share_key = request.parsed_request_args.GetValue( 'share_key', bytes )
hash = request.parsed_request_args.GetValue( 'hash', bytes )
2015-08-05 18:42:35 +00:00
2017-12-06 22:06:56 +00:00
local_booru_manager = HG.client_controller.local_booru_manager
2015-08-05 18:42:35 +00:00
local_booru_manager.CheckFileAuthorised( share_key, hash )
media_result = local_booru_manager.GetMediaResult( share_key, hash )
mime = media_result.GetMime()
2017-03-02 02:14:56 +00:00
response_context_mime = HC.IMAGE_PNG
2016-06-08 20:27:22 +00:00
if mime in HC.MIMES_WITH_THUMBNAILS:
2017-06-28 20:23:21 +00:00
client_files_manager = HG.client_controller.client_files_manager
2016-06-08 20:27:22 +00:00
2019-04-24 22:18:50 +00:00
path = client_files_manager.GetThumbnailPath( media_result )
2016-06-08 20:27:22 +00:00
2017-03-02 02:14:56 +00:00
response_context_mime = HC.APPLICATION_UNKNOWN
2018-03-07 22:48:29 +00:00
elif mime in HC.AUDIO:
path = os.path.join( HC.STATIC_DIR, 'audio.png' )
elif mime == HC.APPLICATION_PDF:
path = os.path.join( HC.STATIC_DIR, 'pdf.png' )
2019-03-20 21:22:10 +00:00
elif mime == HC.APPLICATION_PSD:
path = os.path.join( HC.STATIC_DIR, 'psd.png' )
2018-03-07 22:48:29 +00:00
else:
path = os.path.join( HC.STATIC_DIR, 'hydrus.png' )
2015-08-05 18:42:35 +00:00
2020-07-22 20:59:16 +00:00
if not os.path.exists( path ):
raise HydrusExceptions.NotFoundException( 'Could not find that thumbnail!' )
2017-03-02 02:14:56 +00:00
response_context = HydrusServerResources.ResponseContext( 200, mime = response_context_mime, path = path )
2015-08-05 18:42:35 +00:00
return response_context
2019-02-06 22:41:35 +00:00
class HydrusResourceClientAPI( HydrusServerResources.HydrusResource ):
def _callbackParseGETArgs( self, request ):
2019-02-27 23:03:30 +00:00
parsed_request_args = ParseClientAPIGETArgs( request.args )
2019-02-06 22:41:35 +00:00
2019-02-27 23:03:30 +00:00
request.parsed_request_args = parsed_request_args
2019-02-06 22:41:35 +00:00
return request
def _callbackParsePOSTArgs( self, request ):
2019-02-27 23:03:30 +00:00
( parsed_request_args, total_bytes_read ) = ParseClientAPIPOSTArgs( request )
2019-02-06 22:41:35 +00:00
self._reportDataUsed( request, total_bytes_read )
2019-02-27 23:03:30 +00:00
request.parsed_request_args = parsed_request_args
2019-02-06 22:41:35 +00:00
return request
def _reportDataUsed( self, request, num_bytes ):
self._service.ReportDataUsed( num_bytes )
def _reportRequestUsed( self, request ):
self._service.ReportRequestUsed()
def _checkService( self, request ):
HydrusServerResources.HydrusResource._checkService( self, request )
if not self._service.BandwidthOK():
raise HydrusExceptions.BandwidthException( 'This service has run out of bandwidth. Please try again later.' )
class HydrusResourceClientAPIPermissionsRequest( HydrusResourceClientAPI ):
2015-08-05 18:42:35 +00:00
def _threadDoGETJob( self, request ):
2019-02-06 22:41:35 +00:00
if not ClientAPI.api_request_dialog_open:
2020-05-06 21:31:41 +00:00
raise HydrusExceptions.ConflictException( 'The permission registration dialog is not open. Please open it under "review services" in the hydrus client.' )
2019-02-06 22:41:35 +00:00
2019-08-21 21:34:01 +00:00
name = request.parsed_request_args.GetValue( 'name', str )
basic_permissions = request.parsed_request_args.GetValue( 'basic_permissions', list )
2019-02-06 22:41:35 +00:00
basic_permissions = [ int( value ) for value in basic_permissions ]
api_permissions = ClientAPI.APIPermissions( name = name, basic_permissions = basic_permissions )
ClientAPI.last_api_permissions_request = api_permissions
access_key = api_permissions.GetAccessKey()
2019-02-13 22:26:43 +00:00
body_dict = {}
body_dict[ 'access_key' ] = access_key.hex()
body = json.dumps( body_dict )
2019-02-06 22:41:35 +00:00
2019-02-13 22:26:43 +00:00
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
2019-02-06 22:41:35 +00:00
return response_context
class HydrusResourceClientAPIVersion( HydrusResourceClientAPI ):
def _threadDoGETJob( self, request ):
2019-02-13 22:26:43 +00:00
body_dict = {}
body_dict[ 'version' ] = HC.CLIENT_API_VERSION
body = json.dumps( body_dict )
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
2019-02-06 22:41:35 +00:00
return response_context
class HydrusResourceClientAPIRestricted( HydrusResourceClientAPI ):
2019-06-26 21:27:18 +00:00
def _callbackCheckAccountRestrictions( self, request ):
2019-02-06 22:41:35 +00:00
2019-06-26 21:27:18 +00:00
HydrusResourceClientAPI._callbackCheckAccountRestrictions( self, request )
2019-02-06 22:41:35 +00:00
2019-06-26 21:27:18 +00:00
self._CheckAPIPermissions( request )
2019-02-06 22:41:35 +00:00
return request
2019-07-03 22:49:27 +00:00
def _callbackEstablishAccountFromHeader( self, request ):
2019-02-06 22:41:35 +00:00
2019-07-03 22:49:27 +00:00
access_key = self._ParseClientAPIAccessKey( request, 'header' )
if access_key is not None:
self._EstablishAPIPermissions( request, access_key )
return request
2019-02-06 22:41:35 +00:00
2019-07-03 22:49:27 +00:00
def _callbackEstablishAccountFromArgs( self, request ):
2019-02-06 22:41:35 +00:00
2019-07-03 22:49:27 +00:00
if request.client_api_permissions is None:
access_key = self._ParseClientAPIAccessKey( request, 'args' )
if access_key is not None:
self._EstablishAPIPermissions( request, access_key )
if request.client_api_permissions is None:
raise HydrusExceptions.MissingCredentialsException( 'No access key or session key provided!' )
return request
def _CheckAPIPermissions( self, request ):
2019-06-26 21:27:18 +00:00
2019-07-03 22:49:27 +00:00
raise NotImplementedError()
def _EstablishAPIPermissions( self, request, access_key ):
2019-02-06 22:41:35 +00:00
try:
2019-07-03 22:49:27 +00:00
api_permissions = HG.client_controller.client_api_manager.GetPermissions( access_key )
2019-02-06 22:41:35 +00:00
2019-06-26 21:27:18 +00:00
except HydrusExceptions.DataMissing as e:
2019-02-06 22:41:35 +00:00
2019-06-26 21:27:18 +00:00
raise HydrusExceptions.InsufficientCredentialsException( str( e ) )
2019-02-06 22:41:35 +00:00
request.client_api_permissions = api_permissions
2019-07-03 22:49:27 +00:00
def _ParseClientAPIKey( self, request, source, name_of_key ):
key = None
if source == 'header':
if request.requestHeaders.hasHeader( name_of_key ):
key_texts = request.requestHeaders.getRawHeaders( name_of_key )
key_text = key_texts[0]
try:
key = bytes.fromhex( key_text )
except:
raise Exception( 'Problem parsing {}!'.format( name_of_key ) )
elif source == 'args':
if name_of_key in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
key = request.parsed_request_args.GetValue( name_of_key, bytes )
2019-07-03 22:49:27 +00:00
return key
def _ParseClientAPIAccessKey( self, request, source ):
access_key = self._ParseClientAPIKey( request, source, 'Hydrus-Client-API-Access-Key' )
if access_key is None:
session_key = self._ParseClientAPIKey( request, source, 'Hydrus-Client-API-Session-Key' )
if session_key is None:
return None
try:
access_key = HG.client_controller.client_api_manager.GetAccessKey( session_key )
except HydrusExceptions.DataMissing as e:
raise HydrusExceptions.SessionException( str( e ) )
return access_key
2019-06-26 21:27:18 +00:00
class HydrusResourceClientAPIRestrictedAccount( HydrusResourceClientAPIRestricted ):
def _CheckAPIPermissions( self, request ):
pass
class HydrusResourceClientAPIRestrictedAccountSessionKey( HydrusResourceClientAPIRestrictedAccount ):
def _threadDoGETJob( self, request ):
new_session_key = HG.client_controller.client_api_manager.GenerateSessionKey( request.client_api_permissions.GetAccessKey() )
body_dict = {}
body_dict[ 'session_key' ] = new_session_key.hex()
body = json.dumps( body_dict )
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
return response_context
class HydrusResourceClientAPIRestrictedAccountVerify( HydrusResourceClientAPIRestrictedAccount ):
def _threadDoGETJob( self, request ):
api_permissions = request.client_api_permissions
basic_permissions = api_permissions.GetBasicPermissions()
human_description = api_permissions.ToHumanString()
body_dict = {}
body_dict[ 'basic_permissions' ] = list( basic_permissions ) # set->list for json
body_dict[ 'human_description' ] = human_description
body = json.dumps( body_dict )
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
return response_context
2020-10-28 22:20:33 +00:00
class HydrusResourceClientAPIRestrictedAddFiles( HydrusResourceClientAPIRestricted ):
2019-02-06 22:41:35 +00:00
def _CheckAPIPermissions( self, request ):
request.client_api_permissions.CheckPermission( ClientAPI.CLIENT_API_PERMISSION_ADD_FILES )
2020-10-28 22:20:33 +00:00
class HydrusResourceClientAPIRestrictedAddFilesAddFile( HydrusResourceClientAPIRestrictedAddFiles ):
2019-02-06 22:41:35 +00:00
def _threadDoPOSTJob( self, request ):
2019-02-13 22:26:43 +00:00
if not hasattr( request, 'temp_file_info' ):
2019-08-21 21:34:01 +00:00
path = request.parsed_request_args.GetValue( 'path', str )
2019-02-13 22:26:43 +00:00
if not os.path.exists( path ):
2019-02-27 23:03:30 +00:00
raise HydrusExceptions.BadRequestException( 'Path "{}" does not exist!'.format( path ) )
2019-02-13 22:26:43 +00:00
( os_file_handle, temp_path ) = HydrusPaths.GetTempPath()
request.temp_file_info = ( os_file_handle, temp_path )
HydrusPaths.MirrorFile( path, temp_path )
( os_file_handle, temp_path ) = request.temp_file_info
2019-02-06 22:41:35 +00:00
2019-02-13 22:26:43 +00:00
file_import_options = HG.client_controller.new_options.GetDefaultFileImportOptions( 'quiet' )
2019-02-06 22:41:35 +00:00
2019-02-13 22:26:43 +00:00
file_import_job = ClientImportFileSeeds.FileImportJob( temp_path, file_import_options )
2019-02-06 22:41:35 +00:00
2019-02-13 22:26:43 +00:00
try:
2019-05-08 21:06:42 +00:00
( status, hash, note ) = file_import_job.DoWork()
2019-02-13 22:26:43 +00:00
except:
status = CC.STATUS_ERROR
hash = file_import_job.GetHash()
note = traceback.format_exc()
body_dict = {}
body_dict[ 'status' ] = status
body_dict[ 'hash' ] = hash.hex()
body_dict[ 'note' ] = note
2019-02-06 22:41:35 +00:00
body = json.dumps( body_dict )
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
return response_context
2020-10-28 22:20:33 +00:00
class HydrusResourceClientAPIRestrictedAddFilesArchiveFiles( HydrusResourceClientAPIRestrictedAddFiles ):
def _threadDoPOSTJob( self, request ):
hashes = set()
if 'hash' in request.parsed_request_args:
hash = request.parsed_request_args.GetValue( 'hash', bytes )
hashes.add( hash )
if 'hashes' in request.parsed_request_args:
more_hashes = request.parsed_request_args.GetValue( 'hashes', list )
hashes.update( more_hashes )
content_update = HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_ARCHIVE, hashes )
service_keys_to_content_updates = { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ content_update ] }
if len( service_keys_to_content_updates ) > 0:
HG.client_controller.WriteSynchronous( 'content_updates', service_keys_to_content_updates )
response_context = HydrusServerResources.ResponseContext( 200 )
return response_context
class HydrusResourceClientAPIRestrictedAddFilesDeleteFiles( HydrusResourceClientAPIRestrictedAddFiles ):
def _threadDoPOSTJob( self, request ):
hashes = set()
if 'hash' in request.parsed_request_args:
hash = request.parsed_request_args.GetValue( 'hash', bytes )
hashes.add( hash )
if 'hashes' in request.parsed_request_args:
more_hashes = request.parsed_request_args.GetValue( 'hashes', list )
hashes.update( more_hashes )
# expand this to take file service and reason
content_update = HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_DELETE, hashes )
service_keys_to_content_updates = { CC.LOCAL_FILE_SERVICE_KEY : [ content_update ] }
if len( service_keys_to_content_updates ) > 0:
HG.client_controller.WriteSynchronous( 'content_updates', service_keys_to_content_updates )
response_context = HydrusServerResources.ResponseContext( 200 )
return response_context
class HydrusResourceClientAPIRestrictedAddFilesUnarchiveFiles( HydrusResourceClientAPIRestrictedAddFiles ):
def _threadDoPOSTJob( self, request ):
hashes = set()
if 'hash' in request.parsed_request_args:
hash = request.parsed_request_args.GetValue( 'hash', bytes )
hashes.add( hash )
if 'hashes' in request.parsed_request_args:
more_hashes = request.parsed_request_args.GetValue( 'hashes', list )
hashes.update( more_hashes )
content_update = HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_INBOX, hashes )
service_keys_to_content_updates = { CC.COMBINED_LOCAL_FILE_SERVICE_KEY : [ content_update ] }
if len( service_keys_to_content_updates ) > 0:
HG.client_controller.WriteSynchronous( 'content_updates', service_keys_to_content_updates )
response_context = HydrusServerResources.ResponseContext( 200 )
return response_context
class HydrusResourceClientAPIRestrictedAddFilesUndeleteFiles( HydrusResourceClientAPIRestrictedAddFiles ):
def _threadDoPOSTJob( self, request ):
hashes = set()
if 'hash' in request.parsed_request_args:
hash = request.parsed_request_args.GetValue( 'hash', bytes )
hashes.add( hash )
if 'hashes' in request.parsed_request_args:
more_hashes = request.parsed_request_args.GetValue( 'hashes', list )
hashes.update( more_hashes )
# expand this to take file service, if and when we move to multiple trashes or whatever
content_update = HydrusData.ContentUpdate( HC.CONTENT_TYPE_FILES, HC.CONTENT_UPDATE_UNDELETE, hashes )
service_keys_to_content_updates = { CC.TRASH_SERVICE_KEY : [ content_update ] }
if len( service_keys_to_content_updates ) > 0:
HG.client_controller.WriteSynchronous( 'content_updates', service_keys_to_content_updates )
response_context = HydrusServerResources.ResponseContext( 200 )
return response_context
2019-02-06 22:41:35 +00:00
class HydrusResourceClientAPIRestrictedAddTags( HydrusResourceClientAPIRestricted ):
def _CheckAPIPermissions( self, request ):
request.client_api_permissions.CheckPermission( ClientAPI.CLIENT_API_PERMISSION_ADD_TAGS )
2019-02-13 22:26:43 +00:00
class HydrusResourceClientAPIRestrictedAddTagsAddTags( HydrusResourceClientAPIRestrictedAddTags ):
2019-02-06 22:41:35 +00:00
def _threadDoPOSTJob( self, request ):
2019-02-27 23:03:30 +00:00
hashes = set()
if 'hash' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
hash = request.parsed_request_args.GetValue( 'hash', bytes )
2019-02-27 23:03:30 +00:00
hashes.add( hash )
if 'hashes' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
more_hashes = request.parsed_request_args.GetValue( 'hashes', list )
2019-02-27 23:03:30 +00:00
2019-04-17 21:51:50 +00:00
hashes.update( more_hashes )
2019-02-27 23:03:30 +00:00
if len( hashes ) == 0:
raise HydrusExceptions.BadRequestException( 'There were no hashes given!' )
#
service_keys_to_content_updates = collections.defaultdict( list )
if 'service_names_to_tags' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
service_names_to_tags = request.parsed_request_args.GetValue( 'service_names_to_tags', dict )
2019-02-27 23:03:30 +00:00
for ( service_name, tags ) in service_names_to_tags.items():
try:
2020-03-11 21:52:11 +00:00
service_key = HG.client_controller.services_manager.GetServiceKeyFromName( HC.REAL_TAG_SERVICES, service_name )
2019-02-27 23:03:30 +00:00
except:
raise HydrusExceptions.BadRequestException( 'Could not find the service "{}"!'.format( service_name ) )
2019-09-18 22:40:39 +00:00
service = HG.client_controller.services_manager.GetService( service_key )
2019-02-27 23:03:30 +00:00
tags = HydrusTags.CleanTags( tags )
if len( tags ) == 0:
continue
2019-09-18 22:40:39 +00:00
if service.GetServiceType() == HC.LOCAL_TAG:
2019-02-27 23:03:30 +00:00
content_action = HC.CONTENT_UPDATE_ADD
else:
content_action = HC.CONTENT_UPDATE_PEND
content_updates = [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_MAPPINGS, content_action, ( tag, hashes ) ) for tag in tags ]
service_keys_to_content_updates[ service_key ].extend( content_updates )
if 'service_names_to_actions_to_tags' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
service_names_to_actions_to_tags = request.parsed_request_args.GetValue( 'service_names_to_actions_to_tags', dict )
2019-02-27 23:03:30 +00:00
for ( service_name, actions_to_tags ) in service_names_to_actions_to_tags.items():
try:
2020-03-11 21:52:11 +00:00
service_key = HG.client_controller.services_manager.GetServiceKeyFromName( HC.REAL_TAG_SERVICES, service_name )
2019-02-27 23:03:30 +00:00
except:
raise HydrusExceptions.BadRequestException( 'Could not find the service "{}"!'.format( service_name ) )
2019-09-18 22:40:39 +00:00
service = HG.client_controller.services_manager.GetService( service_key )
2019-02-27 23:03:30 +00:00
for ( content_action, tags ) in actions_to_tags.items():
2020-04-16 00:09:42 +00:00
tags = list( tags )
2020-09-23 21:02:02 +00:00
if len( tags ) == 0:
2020-04-16 00:09:42 +00:00
2020-09-23 21:02:02 +00:00
continue
2020-04-16 00:09:42 +00:00
2019-02-27 23:03:30 +00:00
2021-01-27 22:14:03 +00:00
content_action = int( content_action )
actual_tags = []
tags_to_reasons = {}
for tag_item in tags:
2019-02-27 23:03:30 +00:00
2021-01-27 22:14:03 +00:00
reason = 'Petitioned from API'
if isinstance( tag_item, str ):
tag = tag_item
elif isinstance( tag_item, collections.abc.Collection ) and len( tag_item ) == 2:
( tag, reason ) = tag_item
if not ( isinstance( tag, str ) and isinstance( reason, str ) ):
continue
else:
continue
actual_tags.append( tag )
tags_to_reasons[ tag ] = reason
2019-02-27 23:03:30 +00:00
2021-01-27 22:14:03 +00:00
actual_tags = HydrusTags.CleanTags( actual_tags )
if len( actual_tags ) == 0:
continue
tags = actual_tags
2020-09-23 21:02:02 +00:00
2019-09-18 22:40:39 +00:00
if service.GetServiceType() == HC.LOCAL_TAG:
2019-02-27 23:03:30 +00:00
if content_action not in ( HC.CONTENT_UPDATE_ADD, HC.CONTENT_UPDATE_DELETE ):
continue
else:
if content_action in ( HC.CONTENT_UPDATE_ADD, HC.CONTENT_UPDATE_DELETE ):
continue
if content_action == HC.CONTENT_UPDATE_PETITION:
2021-01-27 22:14:03 +00:00
content_updates = [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_MAPPINGS, content_action, ( tag, hashes ), reason = tags_to_reasons[ tag ] ) for tag in tags ]
2019-02-27 23:03:30 +00:00
else:
content_updates = [ HydrusData.ContentUpdate( HC.CONTENT_TYPE_MAPPINGS, content_action, ( tag, hashes ) ) for tag in tags ]
service_keys_to_content_updates[ service_key ].extend( content_updates )
2019-02-06 22:41:35 +00:00
2019-02-27 23:03:30 +00:00
if len( service_keys_to_content_updates ) > 0:
HG.client_controller.WriteSynchronous( 'content_updates', service_keys_to_content_updates )
2019-02-06 22:41:35 +00:00
response_context = HydrusServerResources.ResponseContext( 200 )
return response_context
2019-02-13 22:26:43 +00:00
class HydrusResourceClientAPIRestrictedAddTagsGetTagServices( HydrusResourceClientAPIRestrictedAddTags ):
def _threadDoGETJob( self, request ):
local_tags = HG.client_controller.services_manager.GetServices( ( HC.LOCAL_TAG, ) )
tag_repos = HG.client_controller.services_manager.GetServices( ( HC.TAG_REPOSITORY, ) )
body_dict = {}
body_dict[ 'local_tags' ] = [ service.GetName() for service in local_tags ]
body_dict[ 'tag_repositories' ] = [ service.GetName() for service in tag_repos ]
body = json.dumps( body_dict )
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
return response_context
2019-02-27 23:03:30 +00:00
class HydrusResourceClientAPIRestrictedAddTagsCleanTags( HydrusResourceClientAPIRestrictedAddTags ):
def _threadDoGETJob( self, request ):
2019-08-21 21:34:01 +00:00
tags = request.parsed_request_args.GetValue( 'tags', list )
2019-02-27 23:03:30 +00:00
tags = list( HydrusTags.CleanTags( tags ) )
tags = HydrusTags.SortNumericTags( tags )
body_dict = {}
body_dict[ 'tags' ] = tags
body = json.dumps( body_dict )
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
return response_context
2019-02-06 22:41:35 +00:00
class HydrusResourceClientAPIRestrictedAddURLs( HydrusResourceClientAPIRestricted ):
def _CheckAPIPermissions( self, request ):
request.client_api_permissions.CheckPermission( ClientAPI.CLIENT_API_PERMISSION_ADD_URLS )
2019-02-27 23:03:30 +00:00
class HydrusResourceClientAPIRestrictedAddURLsAssociateURL( HydrusResourceClientAPIRestrictedAddURLs ):
def _threadDoPOSTJob( self, request ):
urls_to_add = []
if 'url_to_add' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
url = request.parsed_request_args.GetValue( 'url_to_add', str )
2019-02-27 23:03:30 +00:00
urls_to_add.append( url )
if 'urls_to_add' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
urls = request.parsed_request_args.GetValue( 'urls_to_add', list )
2019-02-27 23:03:30 +00:00
for url in urls:
if not isinstance( url, str ):
continue
urls_to_add.append( url )
urls_to_delete = []
if 'url_to_delete' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
url = request.parsed_request_args.GetValue( 'url_to_delete', str )
2019-02-27 23:03:30 +00:00
urls_to_delete.append( url )
if 'urls_to_delete' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
urls = request.parsed_request_args.GetValue( 'urls_to_delete', list )
2019-02-27 23:03:30 +00:00
for url in urls:
if not isinstance( url, str ):
continue
urls_to_delete.append( url )
2020-04-01 21:51:42 +00:00
domain_manager = HG.client_controller.network_engine.domain_manager
try:
urls_to_add = [ domain_manager.NormaliseURL( url ) for url in urls_to_add ]
except HydrusExceptions.URLClassException as e:
raise HydrusExceptions.BadRequestException( e )
2019-08-21 21:34:01 +00:00
if len( urls_to_add ) == 0 and len( urls_to_delete ) == 0:
raise HydrusExceptions.BadRequestException( 'Did not find any URLs to add or delete!' )
2019-02-27 23:03:30 +00:00
applicable_hashes = []
if 'hash' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
hash = request.parsed_request_args.GetValue( 'hash', bytes )
applicable_hashes.append( hash )
2019-02-27 23:03:30 +00:00
if 'hashes' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
hashes = request.parsed_request_args.GetValue( 'hashes', list )
applicable_hashes.extend( hashes )
2019-02-27 23:03:30 +00:00
2019-08-21 21:34:01 +00:00
if len( applicable_hashes ) == 0:
2019-02-27 23:03:30 +00:00
2019-08-21 21:34:01 +00:00
raise HydrusExceptions.BadRequestException( 'Did not find any hashes to apply the urls to!' )
2019-02-27 23:03:30 +00:00
service_keys_to_content_updates = collections.defaultdict( list )
if len( urls_to_add ) > 0:
content_update = HydrusData.ContentUpdate( HC.CONTENT_TYPE_URLS, HC.CONTENT_UPDATE_ADD, ( urls_to_add, applicable_hashes ) )
service_keys_to_content_updates[ CC.COMBINED_LOCAL_FILE_SERVICE_KEY ].append( content_update )
if len( urls_to_delete ) > 0:
content_update = HydrusData.ContentUpdate( HC.CONTENT_TYPE_URLS, HC.CONTENT_UPDATE_DELETE, ( urls_to_delete, applicable_hashes ) )
service_keys_to_content_updates[ CC.COMBINED_LOCAL_FILE_SERVICE_KEY ].append( content_update )
HG.client_controller.WriteSynchronous( 'content_updates', service_keys_to_content_updates )
response_context = HydrusServerResources.ResponseContext( 200 )
return response_context
2019-02-13 22:26:43 +00:00
class HydrusResourceClientAPIRestrictedAddURLsGetURLFiles( HydrusResourceClientAPIRestrictedAddURLs ):
2019-02-06 22:41:35 +00:00
def _threadDoGETJob( self, request ):
2019-08-21 21:34:01 +00:00
url = request.parsed_request_args.GetValue( 'url', str )
2019-02-06 22:41:35 +00:00
2019-07-03 22:49:27 +00:00
if url == '':
raise HydrusExceptions.BadRequestException( 'Given URL was empty!' )
try:
normalised_url = HG.client_controller.network_engine.domain_manager.NormaliseURL( url )
except HydrusExceptions.URLClassException as e:
raise HydrusExceptions.BadRequestException( e )
2019-02-13 22:26:43 +00:00
url_statuses = HG.client_controller.Read( 'url_statuses', normalised_url )
2019-02-06 22:41:35 +00:00
2019-02-13 22:26:43 +00:00
json_happy_url_statuses = []
for ( status, hash, note ) in url_statuses:
d = {}
d[ 'status' ] = status
d[ 'hash' ] = hash.hex()
d[ 'note' ] = note
json_happy_url_statuses.append( d )
body_dict = { 'normalised_url' : normalised_url, 'url_file_statuses' : json_happy_url_statuses }
body = json.dumps( body_dict )
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
return response_context
class HydrusResourceClientAPIRestrictedAddURLsGetURLInfo( HydrusResourceClientAPIRestrictedAddURLs ):
def _threadDoGETJob( self, request ):
2019-08-21 21:34:01 +00:00
url = request.parsed_request_args.GetValue( 'url', str )
2019-02-13 22:26:43 +00:00
2019-07-03 22:49:27 +00:00
if url == '':
raise HydrusExceptions.BadRequestException( 'Given URL was empty!' )
try:
normalised_url = HG.client_controller.network_engine.domain_manager.NormaliseURL( url )
( url_type, match_name, can_parse ) = HG.client_controller.network_engine.domain_manager.GetURLParseCapability( normalised_url )
2019-07-03 22:49:27 +00:00
except HydrusExceptions.URLClassException as e:
raise HydrusExceptions.BadRequestException( e )
2019-02-13 22:26:43 +00:00
body_dict = { 'normalised_url' : normalised_url, 'url_type' : url_type, 'url_type_string' : HC.url_type_string_lookup[ url_type ], 'match_name' : match_name, 'can_parse' : can_parse }
2019-02-06 22:41:35 +00:00
body = json.dumps( body_dict )
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
return response_context
class HydrusResourceClientAPIRestrictedAddURLsImportURL( HydrusResourceClientAPIRestrictedAddURLs ):
def _threadDoPOSTJob( self, request ):
2019-08-21 21:34:01 +00:00
url = request.parsed_request_args.GetValue( 'url', str )
2019-02-06 22:41:35 +00:00
2019-07-03 22:49:27 +00:00
if url == '':
raise HydrusExceptions.BadRequestException( 'Given URL was empty!' )
2020-09-16 20:46:54 +00:00
filterable_tags = set()
2019-02-13 22:26:43 +00:00
2020-09-16 20:46:54 +00:00
if 'filterable_tags' in request.parsed_request_args:
request.client_api_permissions.CheckPermission( ClientAPI.CLIENT_API_PERMISSION_ADD_TAGS )
filterable_tags = request.parsed_request_args.GetValue( 'filterable_tags', list )
2019-02-27 23:03:30 +00:00
2020-09-16 20:46:54 +00:00
filterable_tags = HydrusTags.CleanTags( filterable_tags )
additional_service_keys_to_tags = ClientTags.ServiceKeysToTags()
if 'service_names_to_tags' in request.parsed_request_args or 'service_names_to_additional_tags' in request.parsed_request_args:
2019-02-13 22:26:43 +00:00
request.client_api_permissions.CheckPermission( ClientAPI.CLIENT_API_PERMISSION_ADD_TAGS )
2020-09-16 20:46:54 +00:00
if 'service_names_to_tags' in request.parsed_request_args:
service_names_to_additional_tags = request.parsed_request_args.GetValue( 'service_names_to_tags', dict )
else:
service_names_to_additional_tags = request.parsed_request_args.GetValue( 'service_names_to_additional_tags', dict )
2019-02-13 22:26:43 +00:00
2020-09-16 20:46:54 +00:00
for ( service_name, tags ) in service_names_to_additional_tags.items():
2019-02-13 22:26:43 +00:00
try:
2020-03-11 21:52:11 +00:00
service_key = HG.client_controller.services_manager.GetServiceKeyFromName( HC.REAL_TAG_SERVICES, service_name )
2019-02-13 22:26:43 +00:00
except:
2019-02-27 23:03:30 +00:00
raise HydrusExceptions.BadRequestException( 'Could not find the service "{}"!'.format( service_name ) )
tags = HydrusTags.CleanTags( tags )
if len( tags ) == 0:
continue
2019-02-13 22:26:43 +00:00
2020-09-16 20:46:54 +00:00
additional_service_keys_to_tags[ service_key ] = tags
2019-02-13 22:26:43 +00:00
2019-02-27 23:03:30 +00:00
destination_page_name = None
if 'destination_page_name' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
destination_page_name = request.parsed_request_args.GetValue( 'destination_page_name', str )
2019-02-27 23:03:30 +00:00
2019-06-26 21:27:18 +00:00
destination_page_key = None
if 'destination_page_key' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
destination_page_key = request.parsed_request_args.GetValue( 'destination_page_key', bytes )
2019-06-26 21:27:18 +00:00
2019-08-21 21:34:01 +00:00
show_destination_page = request.parsed_request_args.GetValue( 'show_destination_page', bool, default_value = False )
2019-03-20 21:22:10 +00:00
2019-06-05 19:42:39 +00:00
def do_it():
2020-09-16 20:46:54 +00:00
return HG.client_controller.gui.ImportURLFromAPI( url, filterable_tags, additional_service_keys_to_tags, destination_page_name, destination_page_key, show_destination_page )
2019-06-05 19:42:39 +00:00
2019-02-06 22:41:35 +00:00
2019-07-03 22:49:27 +00:00
try:
2019-11-14 03:56:30 +00:00
( normalised_url, result_text ) = HG.client_controller.CallBlockingToQt( HG.client_controller.gui, do_it )
2019-07-03 22:49:27 +00:00
except HydrusExceptions.URLClassException as e:
raise HydrusExceptions.BadRequestException( e )
2019-02-13 22:26:43 +00:00
2019-03-06 23:06:22 +00:00
time.sleep( 0.05 ) # yield and give the ui time to catch up with new URL pubsubs in case this is being spammed
2019-02-13 22:26:43 +00:00
body_dict = { 'human_result_text' : result_text, 'normalised_url' : normalised_url }
body = json.dumps( body_dict )
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
2019-02-06 22:41:35 +00:00
return response_context
2019-03-06 23:06:22 +00:00
class HydrusResourceClientAPIRestrictedGetFiles( HydrusResourceClientAPIRestricted ):
2019-02-06 22:41:35 +00:00
def _CheckAPIPermissions( self, request ):
request.client_api_permissions.CheckPermission( ClientAPI.CLIENT_API_PERMISSION_SEARCH_FILES )
2019-03-06 23:06:22 +00:00
class HydrusResourceClientAPIRestrictedGetFilesSearchFiles( HydrusResourceClientAPIRestrictedGetFiles ):
2019-02-06 22:41:35 +00:00
def _threadDoGETJob( self, request ):
2020-03-11 21:52:11 +00:00
tag_search_context = ClientSearch.TagSearchContext( service_key = CC.COMBINED_TAG_SERVICE_KEY )
2019-03-06 23:06:22 +00:00
predicates = ParseClientAPISearchPredicates( request )
2019-02-06 22:41:35 +00:00
2020-03-11 21:52:11 +00:00
file_search_context = ClientSearch.FileSearchContext( file_service_key = CC.LOCAL_FILE_SERVICE_KEY, tag_search_context = tag_search_context, predicates = predicates )
2019-02-06 22:41:35 +00:00
2019-08-21 21:34:01 +00:00
# newest first
2020-07-22 20:59:16 +00:00
sort_by = ClientMedia.MediaSort( sort_type = ( 'system', CC.SORT_FILES_BY_IMPORT_TIME ), sort_order = CC.SORT_DESC )
2019-08-21 21:34:01 +00:00
hash_ids = HG.client_controller.Read( 'file_query_ids', file_search_context, sort_by = sort_by )
2019-02-06 22:41:35 +00:00
2019-03-13 21:04:21 +00:00
request.client_api_permissions.SetLastSearchResults( hash_ids )
2019-03-06 23:06:22 +00:00
body_dict = { 'file_ids' : list( hash_ids ) }
2019-02-06 22:41:35 +00:00
2019-03-06 23:06:22 +00:00
body = json.dumps( body_dict )
2019-02-06 22:41:35 +00:00
2019-03-06 23:06:22 +00:00
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
2019-02-06 22:41:35 +00:00
return response_context
2019-03-06 23:06:22 +00:00
class HydrusResourceClientAPIRestrictedGetFilesGetFile( HydrusResourceClientAPIRestrictedGetFiles ):
2019-02-06 22:41:35 +00:00
def _threadDoGETJob( self, request ):
2019-03-13 21:04:21 +00:00
try:
if 'file_id' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
file_id = request.parsed_request_args.GetValue( 'file_id', int )
2019-03-13 21:04:21 +00:00
request.client_api_permissions.CheckPermissionToSeeFiles( ( file_id, ) )
( media_result, ) = HG.client_controller.Read( 'media_results_from_ids', ( file_id, ) )
elif 'hash' in request.parsed_request_args:
request.client_api_permissions.CheckCanSeeAllFiles()
2019-08-21 21:34:01 +00:00
hash = request.parsed_request_args.GetValue( 'hash', bytes )
2019-03-13 21:04:21 +00:00
2020-04-29 21:44:12 +00:00
media_result = HG.client_controller.Read( 'media_result', hash )
2019-03-13 21:04:21 +00:00
else:
raise HydrusExceptions.BadRequestException( 'Please include a file_id or hash parameter!' )
except HydrusExceptions.DataMissing as e:
raise HydrusExceptions.NotFoundException( 'One or more of those file identifiers was missing!' )
2015-12-02 22:32:18 +00:00
2019-03-13 21:04:21 +00:00
try:
hash = media_result.GetHash()
mime = media_result.GetMime()
path = HG.client_controller.client_files_manager.GetFilePath( hash, mime )
except HydrusExceptions.FileMissingException:
raise HydrusExceptions.NotFoundException( 'Could not find that file!' )
2015-08-05 18:42:35 +00:00
2019-02-06 22:41:35 +00:00
response_context = HydrusServerResources.ResponseContext( 200, mime = mime, path = path )
2015-08-05 18:42:35 +00:00
return response_context
2019-03-13 21:04:21 +00:00
class HydrusResourceClientAPIRestrictedGetFilesFileMetadata( HydrusResourceClientAPIRestrictedGetFiles ):
2015-08-05 18:42:35 +00:00
def _threadDoGETJob( self, request ):
2019-08-21 21:34:01 +00:00
only_return_identifiers = request.parsed_request_args.GetValue( 'only_return_identifiers', bool, default_value = False )
detailed_url_information = request.parsed_request_args.GetValue( 'detailed_url_information', bool, default_value = False )
2019-03-13 21:04:21 +00:00
try:
if 'file_ids' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
file_ids = request.parsed_request_args.GetValue( 'file_ids', list )
2019-03-13 21:04:21 +00:00
request.client_api_permissions.CheckPermissionToSeeFiles( file_ids )
if only_return_identifiers:
2019-03-27 22:01:02 +00:00
file_ids_to_hashes = HG.client_controller.Read( 'hash_ids_to_hashes', hash_ids = file_ids )
2019-03-13 21:04:21 +00:00
else:
media_results = HG.client_controller.Read( 'media_results_from_ids', file_ids )
elif 'hashes' in request.parsed_request_args:
request.client_api_permissions.CheckCanSeeAllFiles()
2019-08-21 21:34:01 +00:00
hashes = request.parsed_request_args.GetValue( 'hashes', list )
2019-03-13 21:04:21 +00:00
if only_return_identifiers:
file_ids_to_hashes = HG.client_controller.Read( 'hash_ids_to_hashes', hashes = hashes )
else:
media_results = HG.client_controller.Read( 'media_results', hashes )
else:
raise HydrusExceptions.BadRequestException( 'Please include a file_ids or hashes parameter!' )
except HydrusExceptions.DataMissing as e:
2020-07-22 20:59:16 +00:00
raise HydrusExceptions.NotFoundException( 'One or more of those file identifiers did not exist in the database!' )
2019-03-13 21:04:21 +00:00
body_dict = {}
2019-02-06 22:41:35 +00:00
2019-03-13 21:04:21 +00:00
metadata = []
2019-02-06 22:41:35 +00:00
2019-03-13 21:04:21 +00:00
if only_return_identifiers:
for ( file_id, hash ) in file_ids_to_hashes.items():
metadata_row = {}
metadata_row[ 'file_id' ] = file_id
metadata_row[ 'hash' ] = hash.hex()
metadata.append( metadata_row )
else:
services_manager = HG.client_controller.services_manager
service_keys_to_names = {}
for media_result in media_results:
metadata_row = {}
file_info_manager = media_result.GetFileInfoManager()
metadata_row[ 'file_id' ] = file_info_manager.hash_id
metadata_row[ 'hash' ] = file_info_manager.hash.hex()
metadata_row[ 'size' ] = file_info_manager.size
2020-01-16 02:08:23 +00:00
metadata_row[ 'mime' ] = HC.mime_mimetype_string_lookup[ file_info_manager.mime ]
2020-04-16 00:09:42 +00:00
metadata_row[ 'ext' ] = HC.mime_ext_lookup[ file_info_manager.mime ]
2019-03-13 21:04:21 +00:00
metadata_row[ 'width' ] = file_info_manager.width
metadata_row[ 'height' ] = file_info_manager.height
metadata_row[ 'duration' ] = file_info_manager.duration
metadata_row[ 'num_frames' ] = file_info_manager.num_frames
metadata_row[ 'num_words' ] = file_info_manager.num_words
2019-08-07 22:59:53 +00:00
metadata_row[ 'has_audio' ] = file_info_manager.has_audio
2020-06-11 12:01:08 +00:00
locations_manager = media_result.GetLocationsManager()
metadata_row[ 'is_inbox' ] = locations_manager.inbox
metadata_row[ 'is_local' ] = locations_manager.IsLocal()
metadata_row[ 'is_trashed' ] = locations_manager.IsTrashed()
known_urls = sorted( locations_manager.GetURLs() )
2019-08-07 22:59:53 +00:00
metadata_row[ 'known_urls' ] = known_urls
2019-03-13 21:04:21 +00:00
if detailed_url_information:
detailed_known_urls = []
for known_url in known_urls:
try:
normalised_url = HG.client_controller.network_engine.domain_manager.NormaliseURL( known_url )
( url_type, match_name, can_parse ) = HG.client_controller.network_engine.domain_manager.GetURLParseCapability( normalised_url )
except HydrusExceptions.URLClassException as e:
continue
detailed_dict = { 'normalised_url' : normalised_url, 'url_type' : url_type, 'url_type_string' : HC.url_type_string_lookup[ url_type ], 'match_name' : match_name, 'can_parse' : can_parse }
detailed_known_urls.append( detailed_dict )
metadata_row[ 'detailed_known_urls' ] = detailed_known_urls
2019-03-13 21:04:21 +00:00
tags_manager = media_result.GetTagsManager()
service_names_to_statuses_to_tags = {}
2019-10-02 23:38:59 +00:00
service_keys_to_statuses_to_tags = tags_manager.GetServiceKeysToStatusesToTags( ClientTags.TAG_DISPLAY_STORAGE )
2019-03-13 21:04:21 +00:00
for ( service_key, statuses_to_tags ) in service_keys_to_statuses_to_tags.items():
if service_key not in service_keys_to_names:
service_keys_to_names[ service_key ] = services_manager.GetName( service_key )
service_name = service_keys_to_names[ service_key ]
service_names_to_statuses_to_tags[ service_name ] = { str( status ) : list( tags ) for ( status, tags ) in statuses_to_tags.items() }
metadata_row[ 'service_names_to_statuses_to_tags' ] = service_names_to_statuses_to_tags
2020-11-25 22:22:47 +00:00
#
service_names_to_statuses_to_tags = {}
service_keys_to_statuses_to_tags = tags_manager.GetServiceKeysToStatusesToTags( ClientTags.TAG_DISPLAY_ACTUAL )
for ( service_key, statuses_to_tags ) in service_keys_to_statuses_to_tags.items():
if service_key not in service_keys_to_names:
service_keys_to_names[ service_key ] = services_manager.GetName( service_key )
service_name = service_keys_to_names[ service_key ]
service_names_to_statuses_to_tags[ service_name ] = { str( status ) : list( tags ) for ( status, tags ) in statuses_to_tags.items() }
metadata_row[ 'service_names_to_statuses_to_display_tags' ] = service_names_to_statuses_to_tags
#
2019-03-13 21:04:21 +00:00
metadata.append( metadata_row )
2019-02-06 22:41:35 +00:00
2019-03-13 21:04:21 +00:00
body_dict[ 'metadata' ] = metadata
2019-02-06 22:41:35 +00:00
mime = HC.APPLICATION_JSON
2019-03-13 21:04:21 +00:00
body = json.dumps( body_dict )
2019-02-06 22:41:35 +00:00
response_context = HydrusServerResources.ResponseContext( 200, mime = mime, body = body )
return response_context
2019-03-06 23:06:22 +00:00
class HydrusResourceClientAPIRestrictedGetFilesGetThumbnail( HydrusResourceClientAPIRestrictedGetFiles ):
2019-02-06 22:41:35 +00:00
def _threadDoGETJob( self, request ):
2019-03-13 21:04:21 +00:00
try:
if 'file_id' in request.parsed_request_args:
2019-08-21 21:34:01 +00:00
file_id = request.parsed_request_args.GetValue( 'file_id', int )
2019-03-13 21:04:21 +00:00
request.client_api_permissions.CheckPermissionToSeeFiles( ( file_id, ) )
( media_result, ) = HG.client_controller.Read( 'media_results_from_ids', ( file_id, ) )
elif 'hash' in request.parsed_request_args:
request.client_api_permissions.CheckCanSeeAllFiles()
2019-08-21 21:34:01 +00:00
hash = request.parsed_request_args.GetValue( 'hash', bytes )
2019-03-13 21:04:21 +00:00
2020-04-29 21:44:12 +00:00
media_result = HG.client_controller.Read( 'media_result', hash )
2019-03-13 21:04:21 +00:00
else:
raise HydrusExceptions.BadRequestException( 'Please include a file_id or hash parameter!' )
except HydrusExceptions.DataMissing as e:
raise HydrusExceptions.NotFoundException( 'One or more of those file identifiers was missing!' )
2016-06-08 20:27:22 +00:00
2019-03-13 21:04:21 +00:00
try:
2019-04-24 22:18:50 +00:00
path = HG.client_controller.client_files_manager.GetThumbnailPath( media_result )
2019-03-13 21:04:21 +00:00
except HydrusExceptions.FileMissingException:
raise HydrusExceptions.NotFoundException( 'Could not find that file!' )
2015-08-05 18:42:35 +00:00
2019-03-13 21:04:21 +00:00
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_OCTET_STREAM, path = path )
2015-08-05 18:42:35 +00:00
return response_context
2017-03-02 02:14:56 +00:00
2019-08-07 22:59:53 +00:00
class HydrusResourceClientAPIRestrictedManageCookies( HydrusResourceClientAPIRestricted ):
def _CheckAPIPermissions( self, request ):
request.client_api_permissions.CheckPermission( ClientAPI.CLIENT_API_PERMISSION_MANAGE_COOKIES )
class HydrusResourceClientAPIRestrictedManageCookiesGetCookies( HydrusResourceClientAPIRestrictedManageCookies ):
def _threadDoGETJob( self, request ):
2019-08-21 21:34:01 +00:00
domain = request.parsed_request_args.GetValue( 'domain', str )
2019-08-07 22:59:53 +00:00
if '.' not in domain:
raise HydrusExceptions.BadRequestException( 'The value "{}" does not seem to be a domain!'.format( domain ) )
network_context = ClientNetworkingContexts.NetworkContext( CC.NETWORK_CONTEXT_DOMAIN, domain )
session = HG.client_controller.network_engine.session_manager.GetSession( network_context )
body_cookies_list = []
for cookie in session.cookies:
name = cookie.name
value = cookie.value
domain = cookie.domain
path = cookie.path
expires = cookie.expires
body_cookies_list.append( [ name, value, domain, path, expires ] )
body_dict = {}
body_dict = { 'cookies' : body_cookies_list }
body = json.dumps( body_dict )
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
return response_context
class HydrusResourceClientAPIRestrictedManageCookiesSetCookies( HydrusResourceClientAPIRestrictedManageCookies ):
def _threadDoPOSTJob( self, request ):
2019-08-21 21:34:01 +00:00
cookie_rows = request.parsed_request_args.GetValue( 'cookies', list )
2019-08-07 22:59:53 +00:00
2020-04-16 00:09:42 +00:00
domains_cleared = set()
domains_set = set()
2019-08-07 22:59:53 +00:00
for cookie_row in cookie_rows:
if len( cookie_row ) != 5:
raise HydrusExceptions.BadRequestException( 'The cookie "{}" did not come in the format [ name, value, domain, path, expires ]!'.format( cookie_row ) )
( name, value, domain, path, expires ) = cookie_row
ndp_bad = True in ( not isinstance( var, str ) for var in ( name, domain, path ) )
v_bad = value is not None and not isinstance( value, str )
e_bad = expires is not None and not isinstance( expires, int )
if ndp_bad or v_bad or e_bad:
raise HydrusExceptions.BadRequestException( 'In the row [ name, value, domain, path, expires ], which I received as "{}", name, domain, and path need to be strings, value needs to be null or a string, and expires needs to be null or an integer!'.format( cookie_row ) )
network_context = ClientNetworkingContexts.NetworkContext( CC.NETWORK_CONTEXT_DOMAIN, domain )
session = HG.client_controller.network_engine.session_manager.GetSession( network_context )
if value is None:
2020-04-16 00:09:42 +00:00
domains_cleared.add( domain )
2019-08-07 22:59:53 +00:00
session.cookies.clear( domain, path, name )
else:
2020-04-16 00:09:42 +00:00
domains_set.add( domain )
2019-08-07 22:59:53 +00:00
2020-04-16 00:09:42 +00:00
ClientNetworkingDomain.AddCookieToSession( session, name, value, domain, path, expires )
2019-08-07 22:59:53 +00:00
2020-04-16 00:09:42 +00:00
if HG.client_controller.new_options.GetBoolean( 'notify_client_api_cookies' ) and len( domains_cleared ) + len( domains_set ) > 0:
2020-05-13 19:03:16 +00:00
domains_cleared = sorted( domains_cleared )
domains_set = sorted( domains_set )
2020-04-16 00:09:42 +00:00
message = 'Cookies sent from API:'
if len( domains_cleared ) > 0:
message = '{} ({} cleared)'.format( message, ', '.join( domains_cleared ) )
if len( domains_set ) > 0:
message = '{} ({} set)'.format( message, ', '.join( domains_set ) )
2019-08-07 22:59:53 +00:00
2020-04-22 21:00:35 +00:00
from hydrus.client import ClientThreading
2020-04-16 00:09:42 +00:00
job_key = ClientThreading.JobKey()
job_key.SetVariable( 'popup_text_1', message )
job_key.Delete( 5 )
HG.client_controller.pub( 'message', job_key )
2019-08-07 22:59:53 +00:00
2021-01-13 21:48:58 +00:00
HG.client_controller.network_engine.session_manager.SetSessionDirty( network_context )
2019-08-07 22:59:53 +00:00
response_context = HydrusServerResources.ResponseContext( 200 )
return response_context
2019-06-05 19:42:39 +00:00
class HydrusResourceClientAPIRestrictedManagePages( HydrusResourceClientAPIRestricted ):
def _CheckAPIPermissions( self, request ):
request.client_api_permissions.CheckPermission( ClientAPI.CLIENT_API_PERMISSION_MANAGE_PAGES )
2019-07-17 22:10:19 +00:00
class HydrusResourceClientAPIRestrictedManagePagesFocusPage( HydrusResourceClientAPIRestrictedManagePages ):
def _threadDoPOSTJob( self, request ):
def do_it( page_key ):
return HG.client_controller.gui.ShowPage( page_key )
2019-08-21 21:34:01 +00:00
page_key = request.parsed_request_args.GetValue( 'page_key', bytes )
2019-07-17 22:10:19 +00:00
try:
2019-11-14 03:56:30 +00:00
HG.client_controller.CallBlockingToQt( HG.client_controller.gui, do_it, page_key )
2019-07-17 22:10:19 +00:00
except HydrusExceptions.DataMissing as e:
raise HydrusExceptions.NotFoundException( 'Could not find that page!' )
response_context = HydrusServerResources.ResponseContext( 200 )
return response_context
2019-06-05 19:42:39 +00:00
class HydrusResourceClientAPIRestrictedManagePagesGetPages( HydrusResourceClientAPIRestrictedManagePages ):
def _threadDoGETJob( self, request ):
def do_it():
2019-08-21 21:34:01 +00:00
return HG.client_controller.gui.GetCurrentSessionPageAPIInfoDict()
2019-06-05 19:42:39 +00:00
2019-11-14 03:56:30 +00:00
page_info_dict = HG.client_controller.CallBlockingToQt( HG.client_controller.gui, do_it )
2019-06-05 19:42:39 +00:00
body_dict = { 'pages' : page_info_dict }
body = json.dumps( body_dict )
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
return response_context
2019-08-21 21:34:01 +00:00
class HydrusResourceClientAPIRestrictedManagePagesGetPageInfo( HydrusResourceClientAPIRestrictedManagePages ):
def _threadDoGETJob( self, request ):
def do_it( page_key, simple ):
return HG.client_controller.gui.GetPageAPIInfoDict( page_key, simple )
page_key = request.parsed_request_args.GetValue( 'page_key', bytes )
simple = request.parsed_request_args.GetValue( 'simple', bool, default_value = True )
2019-11-14 03:56:30 +00:00
page_info_dict = HG.client_controller.CallBlockingToQt( HG.client_controller.gui, do_it, page_key, simple )
2019-08-21 21:34:01 +00:00
if page_info_dict is None:
raise HydrusExceptions.NotFoundException( 'Did not find a page for "{}"!'.format( page_key.hex() ) )
body_dict = { 'page_info' : page_info_dict }
body = json.dumps( body_dict )
response_context = HydrusServerResources.ResponseContext( 200, mime = HC.APPLICATION_JSON, body = body )
return response_context