deadman36g
9/26/2017 - 2:01 AM

Comicvine Fetcher for 32p

Comicvine Fetcher Fill the upload form information with ComicVine api.

// ==UserScript==
// @name         Comicvine Fetcher for 32p
// @namespace    http://google.com
// @version      0.7
// @description  Basic script which fetches comic information from Comicvine
// @author       You
// @match        https://32pag.es/upload.php*
// @grant        GM_xmlhttpRequest
// @connect      comicvine.gamespot.com
// @connect      api.imgur.com
// @require      https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js
// ==/UserScript==

let inputAndButton = `<div id="comicVineFetcher">
                        <input type="text" id="comicVineInput" name="Comic Vine Input" value="">
                        <input type="checkbox" id="uploadImage">Upload Image?
                        <input type="checkbox" id="overrideFields">Override fields?<br>
                        <input type="button" value="Populate with Comic Vine" id="comicVineButton">
                        <br>
                        <p id="comicVineUrl">Comic Vine url will be shown here</p>
                      </div>
`;

let comicVineApiKey = "6b04ca1e70d1f2f5ca6d65d08791c788a5fda379";
let imgurClientId = "a8a7a482ed6c75f";

(function() {
    'use strict';
    $(document).ready(function() {

        // Add the comicVineFetcher div after the error
        $(inputAndButton).insertAfter($('#formerror'));

        // When pressing enter on the input, click the comicVine Button
        $("#comicVineInput").keypress(function(e) {
            if(e.which == 13) {
                $('#comicVineButton').click();
            }
        });

        $('#comicVineButton').click(submitClick);
    });

})();

function submitClick() {
    let query = $("#comicVineInput").val();
    let params = createSearchParams(query);

    // let's try to get information from the filename
    if ($("#file")[0].files.length == 1) {
        getInfoFromFilename($("#file")[0].files[0].name);
    }

    console.log("Doing search with params " + params);
    GM_xmlhttpRequest({
        method: "GET",
        url: `https://comicvine.gamespot.com/api/search?${params}`,
        onload: onSearchResult,
        onError: onHttpError
    });
}

// Just search for issues now with a limit of 1 since we will grab the first result.
// query is escaped with Jquery
function createSearchParams(query) {
    let params = {};
    params.api_key = comicVineApiKey;
    params.resources = "issue";
    params.format = "json";
    params.limit = "1";
    params.query = query;

    return $.param(params);
}

function onHttpError(res) {
    // TODO: Show additional information from the response.
    alert("Http Error. Check the console");
}

function onApiError(res) {
    // TODO: Show additional information from the response.
    alert("API Error. Check the console");
}

function onSearchResult(res) {
    // Show error if we don't get a http 200.
    if (res.status != 200) {
        onApiError(res);
        return;
    }

    // Parse the json with Jquery
    let json = $.parseJSON(res.responseText);

    // No results? Let the user know with a friendly alert :]
    if (json.number_of_page_results === 0) {
        alert("Nothing found. Search again?");
        return;
    }

    // Detail url contains a final "/". Remove it.
    var urlString = json.results[0].api_detail_url;
    urlString = urlString.substring(0, urlString.length - 1);

    // We got something, let's fetch the issue
    GM_xmlhttpRequest({
        method: "GET",
        url: `${urlString}?api_key=${comicVineApiKey}&format=json`,
        onload: onApiDetailResult,
        onError: onHttpError
    });
}

function onApiDetailResult(res) {
    // Show error if we don't get a http 200.
    if (res.status != 200) {
        onApiError(res);
        return;
    }

    // Parse the json with Jquery
    let json = $.parseJSON(res.responseText);

    // TODO:
    // From the issue we can fetch the volume and get additional information
    // like publisher. Which is not a field in the issue. Stupid API.
    let issue = json.results;
    populateFormWith(issue);
}

// Fill the form with the query data
function populateFormWith(issue) {
    // Checkbox to device if fields need to be overriden by this script
    let overrideFields = $('#overrideFields')[0].checked;
    console.log("overrideFields is " + overrideFields);

    // Can't populate publisher because the issue doesn't contain that information
    //$("#publisher").val(query);

    // I am testing with "Walking Dead 1" and issue.name is null
    // I am getting the franchise from the volume name.
    // This might not always be true.
    if (overrideFields && !$("#franchise").val()) {
        $("#franchise").val(issue.name === null ? issue.volume.name : issue.name);
    }

    // TODO: I don't quite understand the difference between franchise and series
    // They will be the same for now
    if (overrideFields && !$("#series").val()) {
        $("#series").val(issue.name === null ? issue.volume.name : issue.name);
    }

    // We just want the character names separated by commas
    if (overrideFields && !$("#character").val()) {
        let characters = issue.character_credits.map(character => character.name).join(", ");
        $("#character").val(characters);
    }

    // We just want the team names separated by commas
    if (overrideFields && !$("#team").val()) {
        let teams = issue.team_credits.map(team => team.name).join(", ");
        $("#team").val(teams);
    }

    // Another thing I am not sure.
    // My logic is: If the person is not a writter, then she/he is an artist.
    let persons = issue.person_credits.reduce( (persons, person) => {
        if (person.role.indexOf('writer') > -1) {
            persons.writers.push(person.name);

            // If he did something else, he is an artist, and a genius!
            if (person.role.length > 1) {
                persons.artists.push(person.name);
            }

        } else {
            persons.artists.push(person.name);
        }

        return persons;
    }, {'writers': [], 'artists': []});

    if (overrideFields && !$("#writer").val()) {
        $("#writer").val(persons.writers.join(", "));
    }

    if (overrideFields && !$("#artist").val()) {
        $("#artist").val(persons.artists.join(", "));
    }

    let uploadImage = $('#uploadImage')[0].checked;
    console.log("uploadImage is " + uploadImage);
    if (uploadImage && (overrideFields || !$("#image").val())) {
        downloadAndUpload(issue.image.super_url);
    }

    if (overrideFields && !$("#desc").val()) {
        $("#desc").val($(issue.description).text());
    }

    // Adding defaults
    if (overrideFields && !$("#language").val()) {
        $("#language").val("English");
    }

    $('#comicVineUrl').html(`Information populated from <a href="${issue.site_detail_url}">this link</a>`);
}

function getInfoFromFilename(filename) {
    console.log("using filename: " + filename);

    // Parse file extension
    let ext = filename.match(/(cb[rz])\.torrent$/i);
    if (ext.length > 1) {
        $("#format").val(ext[1].toLowerCase());
    }

}

// This will take care of downloading the image
// Uploading to imgur
// Updating the image input
function downloadAndUpload(imageUrl) {
    // Download the image into a blob
    GM_xmlhttpRequest({
        method: "GET",
        responseType: 'blob',
        url: imageUrl,
        onload: onImageDownloaded,
        onError: onHttpError
    });
}

function onImageDownloaded(res) {
    // Show error if we don't get a http 200.
    if (res.status != 200) {
        onApiError(res);
        return;
    }

    // Async way of reading blob
    var reader = new FileReader();
    reader.readAsDataURL(res.response);
    reader.onloadend = function() {

       // I had to remove the first part of the base64
       let encodedBase64Data = encodeURIComponent(reader.result.split(',')[1]);

        // Send the image in base64 to imgur
        GM_xmlhttpRequest({
            method: "POST",
            url: 'https://api.imgur.com/3/image',
            headers: {
                'authorization': `Client-ID ${imgurClientId}`,
                "Content-Type": "application/x-www-form-urlencoded",
            },
            data: `image=${encodedBase64Data}`,
            onload: onImageUploaded,
            onError: onHttpError
        });
    };
}

function onImageUploaded(res) {
    // Show error if we don't get a http 200.
    if (res.status != 200) {
        onApiError(res);
        return;
    }

    // Parse the json with Jquery
    let json = $.parseJSON(res.responseText);

    let httpsUrl = json.data.link.replace("http:","https:");
    $("#image").val(httpsUrl);
}