Created
May 12, 2017 17:32
-
-
Save nmccready/aae3fb86ee16a83f60c0e2df65f31335 to your computer and use it in GitHub Desktop.
Browser userscripts to delete all Google Voice history
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Delete Google Voice (Legacy) History | |
// @description Deletes all Google Voice (Legacy) history | |
// @version 1.1.0 | |
// @license MIT | |
// @namespace gavinhungry.io | |
// @author Gavin Lloyd <gavinhungry@gmail.com> | |
// | |
// @include https://www.google.tld/voice | |
// @include https://www.google.tld/voice/* | |
// @include https://www.google.tld/voice#* | |
// @include https://www.google.tld/voice?* | |
// | |
// @require https://cdn.jsdelivr.net/jquery/2/jquery.min.js | |
// @grant none | |
// ==/UserScript== | |
(function($) { | |
'use strict'; | |
var voice = (function() { | |
var GV_KEY = '_rnr_se'; | |
/** | |
* Remove a message id | |
* | |
* @param {String} url | |
* @param {String} message - message id | |
* @return {Promise} | |
*/ | |
var remove = function(url, message) { | |
var d = $.Deferred(); | |
var data = { | |
messages: message, | |
trash: 1 | |
}; | |
data[GV_KEY] = $('input[name="'+ GV_KEY +'"]').first().val(); | |
$.ajax({ | |
type: 'POST', | |
url: url, | |
data: data | |
}).always(d.resolve); | |
return d.promise(); | |
}; | |
/** | |
* Remove a collection of message ids | |
* | |
* @param {String} url | |
* @param {Array} messages - message ids | |
* @return {Promise} | |
*/ | |
var batch = function(url, messages) { | |
var d = $.Deferred(); | |
var complete = 0; | |
var pending = messages.map(function(message) { | |
return remove(url, message).then(function() { | |
d.notify(++complete); | |
}); | |
}); | |
$.when.apply(null, pending).then(d.resolve); | |
return d.promise(); | |
}; | |
return { | |
/** | |
* Get all message ids from a URL | |
* | |
* @param {String} url | |
* @return {Promise} | |
*/ | |
get: function(url) { | |
var page = 1; | |
var messages = []; | |
return (function next() { | |
return $.ajax({ | |
url: url, | |
data: { page: 'p' + page++ } | |
}).then(function(data) { | |
var json = $(data).find('json').text(); | |
var results = Object.keys(JSON.parse(json).messages); | |
messages = messages.concat(results); | |
return results.length ? next() : messages; | |
}, function() { | |
return messages; | |
}); | |
})(); | |
}, | |
/** | |
* Trash a collection of messages | |
* | |
* @param {Promise|Array} messages | |
* @return {Promise} | |
*/ | |
trash: function(messages) { | |
return $.when(messages).then(function(messages) { | |
return batch('/voice/inbox/deleteMessages/', messages); | |
}); | |
}, | |
/** | |
* Delete a collection of messages forever | |
* | |
* @param {Promise|Array} messages | |
* @return {Promise} | |
*/ | |
forever: function(messages) { | |
return $.when(messages).then(function(messages) { | |
return batch('/voice/inbox/deleteForeverMessages/', messages); | |
}); | |
} | |
}; | |
})(); | |
var _handler = function(url, method) { | |
return function(e) { | |
if (!confirm('Are you sure?')) { return; } | |
$(this).addClass('jfk-button-disabled').off('click'); | |
var $span = $(this).find('span').text('(...)'); | |
voice.get(url).done(function(messages) { | |
method(messages).progress(function(complete) { | |
$span.text('(' + complete + '/' + messages.length + ')'); | |
}).done(function() { | |
window.location.reload(); | |
}); | |
}); | |
}; | |
}; | |
var $history = $('<div class="goog-inline-block jfk-button jfk-button-standard jfk-button-collapse-right" style="margin-left: 16px;">Delete ALL <span></span></div>'); | |
var $empty = $('<div class="goog-inline-block jfk-button jfk-button-standard jfk-button-collapse-left">Empty Trash <span></span></div>'); | |
$history.on('click', _handler('/voice/b/0/inbox/recent/all', voice.trash)); | |
$empty.on('click', _handler('/voice/inbox/recent/trash/', voice.forever)); | |
var i = setInterval(function() { | |
var $parent = $('.gc-appbar-buttons-left'); | |
if ($parent.length) { | |
clearInterval(i); | |
$parent.append($history, $empty); | |
} | |
}, 5); | |
})(jQuery); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Delete Google Voice History (WORK IN PROGRESS) | |
// @description Deletes all Google Voice history | |
// @version 2.0.0 | |
// @license MIT | |
// @namespace gavinhungry.io | |
// @author Gavin Lloyd <gavinhungry@gmail.com> | |
// | |
// @include https://voice.google.tld/* | |
// | |
// @require https://cdn.jsdelivr.net/jquery/2/jquery.min.js | |
// @grant none | |
// ==/UserScript== | |
(function($) { | |
'use strict'; | |
// allow us to examine Angular scopes - will refresh the page | |
if (!angular.element(document.body).scope()) { | |
angular.reloadWithDebugInfo(); | |
} | |
// Adds hidden "Delete" option for entire thread - does not seem to work yet | |
_gv.soyProto.ClientFlags[11].push('deleteThread'); | |
var deleteMessage = function(message) { | |
console.log('Deleting message'); | |
message.dispatchEvent(new Event('contextmenu')); | |
return new Promise(function(res, rej) { | |
setTimeout(function() { | |
// click the delete button | |
$('.md-open-menu-container button[aria-label=Delete]:visible').trigger('click'); | |
setTimeout(function() { | |
// this probably is not necessary - we just need to click the damned button | |
var $dialogActions = $('button[gv-test-id="message-delete-ok"]').closest('md-dialog-actions'); | |
angular.element($dialogActions).scope().ctrl.onConfirmClick(); | |
setTimeout(res, 250); | |
}, 250); | |
}, 250); // FIXME: we are waiting for the context menu to open | |
}); | |
}; | |
var deleteMessages = function(messages) { | |
var message = messages.shift(); | |
if (!message) { | |
return Promise.resolve(); | |
} | |
deleteMessage(message).then(function() { | |
deleteMessages(messages); | |
}); | |
}; | |
$(function() { | |
var $voicemailButton = $('gv-mini-nav gv-nav-button[icon=voicemail]'); | |
var $deleteButton = $('gv-mini-nav gv-nav-button [role=button][aria-selected!=true]').first().clone(); | |
$deleteButton.find('md-icon').html('delete'); | |
$deleteButton.css('user-select', 'none'); | |
$deleteButton.insertAfter($voicemailButton); | |
// FIXME: This sucks. Uses the UI, is slow and unreliable and only works on the active thread. | |
$deleteButton.on('click', function() { | |
if (!confirm('Are you sure?')) { | |
return; | |
} | |
var messages = $('gv-message-item [gv-test-id]').toArray(); | |
console.log('Deleting', messages.length, 'messages ...'); | |
deleteMessages(messages).then(function() { | |
console.log('Done deleting messages!'); | |
}); | |
}); | |
}); | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment