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);
}