diff --git a/data/interfaces/default/css/tautulli.css b/data/interfaces/default/css/tautulli.css index ca76687d..5c9c8076 100644 --- a/data/interfaces/default/css/tautulli.css +++ b/data/interfaces/default/css/tautulli.css @@ -70,6 +70,7 @@ div.form-control .selectize-input { background-color: #555; border-radius: 3px; transition: background-color .3s; + height: 32px !important; } .react-selectize.root-node .react-selectize-control, .selectize-control.form-control .selectize-input { diff --git a/data/interfaces/default/settings.html b/data/interfaces/default/settings.html index 3bd177b6..0f45535e 100644 --- a/data/interfaces/default/settings.html +++ b/data/interfaces/default/settings.html @@ -1007,12 +1007,19 @@
- +
+ + % if config['notify_upload_posters'] in (1, 3): + + + + % endif +

Select where to host Plex images for notifications and newsletters.

@@ -2615,11 +2622,37 @@ $(document).ready(function() { } else { $('#cloudinary_upload_options').slideUp(); } + var parent; + if (upload_val === '1' || upload_val === '3') { + parent = $('#notify_upload_posters').parent(); + if ($('#delete_all_uploads_container').length === 0){ + parent.addClass('input-group'); + parent.append( + '' + + '' + + ''); + } + } else { + parent = $('#notify_upload_posters').parent(); + parent.removeClass('input-group'); + $('#delete_all_uploads_container').remove(); + } } $('#notify_upload_posters').change(function () { imageUpload(); }); + $('body').on('click', '#delete_all_uploads', function () { + var image_hosting_option = $('#notify_upload_posters').find(':selected'); + var name = image_hosting_option.text(); + + var msg = 'Are you sure you want to delete all uploaded images on ' + name + '?' + + '
All previous links to the images will no longer work. This cannot be undone!'; + var url = 'delete_hosted_images'; + var data = { service: name, delete_all: true }; + confirmAjaxCall(url, msg, data, false); + }); + function baseURLSet() { if ($('#http_base_url').val()) { $('.base-url-warning').hide(); diff --git a/plexpy/datafactory.py b/plexpy/datafactory.py index 9dbc24f7..9e971bb6 100644 --- a/plexpy/datafactory.py +++ b/plexpy/datafactory.py @@ -1215,52 +1215,64 @@ class DataFactory(object): monitor_db.upsert(table, key_dict=keys, value_dict=values) - def delete_img_info(self, rating_key=None, service=None): + def delete_img_info(self, rating_key=None, service='', delete_all=False): monitor_db = database.MonitorDatabase() - if rating_key: - service = service or helpers.get_img_service() + if not delete_all: + service = helpers.get_img_service() - if service == 'imgur': - # Delete from Imgur - query = 'SELECT imgur_title, delete_hash, fallback FROM imgur_lookup ' \ - 'JOIN image_hash_lookup ON imgur_lookup.img_hash = image_hash_lookup.img_hash ' \ - 'WHERE rating_key = ? ' - args = [rating_key] - results = monitor_db.select(query, args=args) - - for imgur_info in results: - if imgur_info['delete_hash']: - helpers.delete_from_imgur(delete_hash=imgur_info['delete_hash'], - img_title=imgur_info['imgur_title'], - fallback=imgur_info['fallback']) - - logger.info(u"Tautulli DataFactory :: Deleting Imgur info for rating_key %s from the database." - % rating_key) - result = monitor_db.action('DELETE FROM imgur_lookup WHERE img_hash ' - 'IN (SELECT img_hash FROM image_hash_lookup WHERE rating_key = ?)', - [rating_key]) - - elif service == 'cloudinary': - # Delete from Cloudinary - helpers.delete_from_cloudinary(rating_key=rating_key) - - logger.info(u"Tautulli DataFactory :: Deleting Cloudinary info for rating_key %s from the database." - % rating_key) - result = monitor_db.action('DELETE FROM cloudinary_lookup WHERE img_hash ' - 'IN (SELECT img_hash FROM image_hash_lookup WHERE rating_key = ?)', - [rating_key]) - - else: - logger.error(u"Tautulli DataFactory :: Unable to delete hosted images: invalid service '%s' provided." - % service) - - return service - - else: + if not rating_key and not delete_all: logger.error(u"Tautulli DataFactory :: Unable to delete hosted images: rating_key not provided.") return False + where = '' + args = [] + log_msg = '' + if rating_key: + where = 'WHERE rating_key = ?' + args = [rating_key] + log_msg = ' for rating_key %s' % rating_key + + if service.lower() == 'imgur': + # Delete from Imgur + query = 'SELECT imgur_title, delete_hash, fallback FROM imgur_lookup ' \ + 'JOIN image_hash_lookup ON imgur_lookup.img_hash = image_hash_lookup.img_hash %s' % where + results = monitor_db.select(query, args=args) + + for imgur_info in results: + if imgur_info['delete_hash']: + helpers.delete_from_imgur(delete_hash=imgur_info['delete_hash'], + img_title=imgur_info['imgur_title'], + fallback=imgur_info['fallback']) + + logger.info(u"Tautulli DataFactory :: Deleting Imgur info%s from the database." + % log_msg) + result = monitor_db.action('DELETE FROM imgur_lookup WHERE img_hash ' + 'IN (SELECT img_hash FROM image_hash_lookup %s)' % where, + args) + + elif service.lower() == 'cloudinary': + # Delete from Cloudinary + query = 'SELECT cloudinary_title, rating_key, fallback FROM cloudinary_lookup ' \ + 'JOIN image_hash_lookup ON cloudinary_lookup.img_hash = image_hash_lookup.img_hash %s ' \ + 'GROUP BY rating_key' % where + results = monitor_db.select(query, args=args) + + for cloudinary_info in results: + helpers.delete_from_cloudinary(rating_key=cloudinary_info['rating_key']) + + logger.info(u"Tautulli DataFactory :: Deleting Cloudinary info%s from the database." + % log_msg) + result = monitor_db.action('DELETE FROM cloudinary_lookup WHERE img_hash ' + 'IN (SELECT img_hash FROM image_hash_lookup %s)' % where, + args) + + else: + logger.error(u"Tautulli DataFactory :: Unable to delete hosted images: invalid service '%s' provided." + % service) + + return service + def get_poster_info(self, rating_key='', metadata=None, service=None): poster_key = '' if str(rating_key).isdigit(): diff --git a/plexpy/webserve.py b/plexpy/webserve.py index 5fd77f78..ae902955 100644 --- a/plexpy/webserve.py +++ b/plexpy/webserve.py @@ -4250,16 +4250,18 @@ class WebInterface(object): @cherrypy.tools.json_out() @requireAuth(member_of("admin")) @addtoapi() - def delete_hosted_images(self, rating_key='', service='', **kwargs): + def delete_hosted_images(self, rating_key='', service='', delete_all=False, **kwargs): """ Delete the images uploaded to image hosting services. ``` Required parameters: + None + + Optional parameters: rating_key (int): 1234 (Note: Must be the movie, show, season, artist, or album rating key) - Optional parameters: - service (str): imgur or cloudinary - (Note: Defaults to service in Image Hosting setting) + service (str): 'imgur' or 'cloudinary' + delete_all (bool): 'true' to delete all images form the service Returns: json: @@ -4268,8 +4270,10 @@ class WebInterface(object): ``` """ + delete_all = (delete_all == 'true') + data_factory = datafactory.DataFactory() - result = data_factory.delete_img_info(rating_key=rating_key, service=service) + result = data_factory.delete_img_info(rating_key=rating_key, service=service, delete_all=delete_all) if result: return {'result': 'success', 'message': 'Deleted hosted images from %s.' % result.capitalize()}