Delete Photos Without Descriptions From Google Photos

Updated about 1 yr, 2 mths ago (August 13, 2016). Know a better answer? Let me know!

Delete Photos without Descriptions from Google Photos

How to delete photos without descriptions from Google Photos using a Greasemonkey/Tampermonkey script.

Google Photos is quite rubbish and has almost no useful features, but at the same time is quite useful due to their unlimited free hosting of photos.

I made the mistake of uploading a heap of photos without descriptions, and then adding descriptions to my local copies of the photos. The Google Uploader then sees the photos as different, and re-uploads them.

To manually go through and delete photos without descriptions would take months… so I hacked together this Greasemonkey script to do it for me.

Note that it is very hacky, the timings and delays have been tweaked to work on my current internet connection speed, there is very little error checking, it may or may not actually work for you, and it may somehow delete all your photos… so use with extreme caution.

It makes a button when you are viewing photos, which if you click it, tries to check if the photo has a description, and then clicks the Next Photo button. If it doesn’t have a description, it clicks the delete icon, and then the remove button, and then does it all over again…

When it all goes horribly wrong, which it does frequently, it waits a short while, clicks the Previous Photo button, and then tries again.

It also adds a quick delete button, which automatically clicks Delete and then the Remove button to make deleting photos quicker.

// ==UserScript==
// @name        Delete Google Photos
// @namespace   photos.google.com
// @description Delete Google Photos with blank descriptions
// @include     https://photos.google.com/photo/*
// @include     https://photos.google.com/u/*/photo/*
// @include     https://photos.google.com/search/*
// @include     https://photos.google.com/u/*/search/*
// @version     1
// @grant       none
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// ==/UserScript==
this.$ = this.jQuery = jQuery.noConflict(true);
$(document).ready(function()
{
	var nedSearchDeletePhotos = {
		count: { deleted: 0, kept: 0 },
		run: false,
		init: function() {
			// add a button
			this.button = $('<button style="position:fixed;top:20px;left:160px;z-index:9000">Search and delete empty descriptions</button>').on('click', function() {
				if(confirm("Are you sure?")) {
					nedSearchDeletePhotos.click();
				}
			}).appendTo('body');

			// add delete button
			$('<button style="position:fixed;top:20px;left:100px;z-index:9000">[DEL]</button>').on('click', function() {
				$('div:visible[aria-label="Delete"]').click();
				// click confirm
				setTimeout(function() {
					$('span:visible').filter(function() { return ($(this).text() === 'Remove'); }).click();
				}, 250);
			}).appendTo('body');
		},
		click: function() {
			if(this.run) { this.stop(); } else { this.start(); }
		},
		start: function() {
			this.run = true;
			this.doSearch();
		},
		stop: function() {
			this.button.text('[Stopped: Click to start] Kept: ' + this.count.kept + ' Deleted: ' + this.count.deleted);
			this.run = false;
		},
		doSearch: function() {
			if(!this.run) {
				console.log('Stopping');
				return;
			}

			// update button count
			this.button.text('[Started: Click to stop] Kept: ' + this.count.kept + ' Deleted: ' + this.count.deleted);

			var description = $('textarea:visible[placeholder="Add a description"]'),
				filename = $('div:visible[aria-label^="Filename:"]').text();
			if(description && filename) {
				if(description.val()) {
					console.log('KEEP', filename, description.val());
					this.count.kept++;

					// get next
					this.next();

				} else {
					// check it is not an auto creation
					// PANO|ANIMATION|EFFECTS|HDR|COLLAGE|MOTION
					if(filename.match(/PANO|ANIMATION|EFFECTS|HDR|COLLAGE|MOTION|MOV|AVI|MPEG|MPG|MP4/i)) {
						console.log('EFFECT', filename, description.val());
						this.count.kept++;
						this.next();
					} else {
						console.log('DELETE', filename, description.val());
						// delete
						this.del();
					}
				}
			} else {
				console.log('No description or filename fields found. Retry in 1 seconds');
				//this.setTimeout(function() {
					// go back
					$('div[aria-label="View previous photo"]').click();
					nedSearchDeletePhotos.setTimeout(function() { nedSearchDeletePhotos.doSearch(); }, 1000);
				//}, 2500);
			}

		},
		del: function() {
			// delete
			// setTimeout(function() {
				$('div:visible[aria-label="Delete"]').click();

				// click confirm
				this.setTimeout(function() {
					$('span:visible').filter(function() { return ($(this).text() === 'Remove'); }).click();

					// console.log('Delete clicked');
					nedSearchDeletePhotos.count.deleted++;

					// timeout and next
					// next automatically called by Google when deleting
					nedSearchDeletePhotos.setTimeout(function() { nedSearchDeletePhotos.doSearch(); }, 2500);
				}, 250);
			// }, 1000);
		},
		next: function() {
			// setTimeout(function() {
				var next = $('div[aria-label="View next photo"]');
				next.click();

				// run it all again
				this.setTimeout(function() { nedSearchDeletePhotos.doSearch(); }, 750);
			// }, 1000);
		},
		setTimeout: function(fn, time) {
			var that = nedSearchDeletePhotos;
			if(that.timer) { clearTimeout(that.timer); }
			that.timer = setTimeout(fn, time);
		}
	};

	nedSearchDeletePhotos.init();
});

 

 

 

More Information

Information above gathered from the following sources:

 

Updated about 1 yr, 2 mths ago (August 13, 2016). Know a better answer? Let me know!

Related categories [coloured].

Comment on this article (no HTML, max 1200 characters):