javascriptgoogle-voice

Constructing a JavaScript form without creating hidden page elements


I am trying to automatie bulk deleting my Google Voice history. So far, I have:

// Code to be run at Legacy Google Voice: https://www.google.com/voice/b/0#history
function sleep(ms) { // courtesy: https://stackoverflow.com/a/39914235/1429450
    return new Promise(resolve => setTimeout(resolve, ms));
}
async function deleteMessages() {
    do {
        var msgs = document.getElementsByClassName('gc-message'),
            msgids = [];
        itemcount = msgs.length;
        for (var i = 0; i < itemcount; ++i) {
            msgids.push(msgs[i].id);
        };
        // the following based off https://stackoverflow.com/a/133997/1429450
        var form = document.createElement("form");
        form.setAttribute("method", "post");
        form.setAttribute("action", "https://www.google.com/voice/b/0/inbox/deleteMessages/");
        for (var i in msgids) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", "messages");
            hiddenField.setAttribute("value", msgids[i]);
            form.appendChild(hiddenField);
        }
        var hiddenField = document.createElement("input");
        hiddenField.setAttribute("type", "hidden");
        hiddenField.setAttribute("name", "trash");
        hiddenField.setAttribute("value", 1);
        form.appendChild(hiddenField);
        var hiddenField = document.createElement("input");
        hiddenField.setAttribute("type", "hidden");
        hiddenField.setAttribute("name", "_rnr_se");
        hiddenField.setAttribute("value", _gcData['_rnr_se']);
        form.appendChild(hiddenField);
        document.body.appendChild(form);
        form.submit();
        await sleep(1000);
        document.getElementById('gc-inbox-next').click();
    } while (itemcount != 0);
}
deleteMessages();

How do I do this without actually creating hidden page elements (such as by using FormData?)?

Also, another issue with my code is that my browser downloads the response to the POST request as a file. Is there a way to make it ignore the response?


Solution

  • Using FormData objects is much conciser and also now the browser doesn't download the POST response as a file:

    // Code to be run at Legacy Google Voice
    //  Run at: https://www.google.com/voice/b/0#history
    //          https://www.google.com/voice/b/0#spam
    //          https://www.google.com/voice/b/0#trash
    function sleep(ms) { // courtesy: https://stackoverflow.com/a/39914235/1429450
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    async function deleteMessages() {
        do {
            // Get message IDs.
            var msgs = document.getElementsByClassName("gc-message"),
                msgids = [];
            itemcount = msgs.length;
            for (var i = 0; i < itemcount; ++i) {
                msgids.push(msgs[i].id);
            };
            // Construct form. courtesy: https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects#Creating_a_FormData_object_from_scratch
            try {
                var formData = new FormData();
                for (var i in msgids) {
                    formData.append("messages", msgids[i]);
                }
                formData.append("_rnr_se", _gcData["_rnr_se"]);
                var request = new XMLHttpRequest();
                request.open("POST", "https://www.google.com/voice/b/0/inbox/deleteForeverMessages/");
                request.send(formData);
            } catch (a) {
                return;
            }
            await sleep(1000);
            try {
                document.getElementById("gc-inbox-next").click();
            } catch (b) {
                try {
                    document.getElementById("gc-inbox-prev").click();
                } catch (c) {
                    continue;
                }
            }
            await sleep(1000);
        } while (itemcount != 0);
    }
    deleteMessages();