// ==UserScript==
// @name IMDB List Importer
// @namespace Neinei0k_imdb
// @include http://www.imdb.com/list/edit*
// @version 5.0
// @grant none
// @description Import list of titles, people or characters in the imdb list
// ==/UserScript==
var o = {
init: function(e) {
this.etext = e.querySelector('textarea');
this.efile = e.querySelector('input[type="file"]');
this.eready = e.children[10];
var checkboxes = e.querySelectorAll('input[type="checkbox"]');
this.source = checkboxes[0];
this.csv = checkboxes[1];
this.unique = checkboxes[2];
},
run: function(event) {
this.text = this.etext.value;
if (this.source.checked) { // read data from file
var file = this.efile.files[0];
if (file !== undefined) {
this.log("i","Reading file " + file.name);
var r = new FileReader();
r.onload = this.file_onload.bind(this);
r.readAsText(file);
} else {
this.log("e","File is undefined");
}
} else { // read data from input element
this.add_list(this.create_list());
}
},
file_onload: function(e) {
if (e.target.error === null) {
this.text = e.target.result;
this.add_list(this.create_list());
} else {
this.log("e","File reading error: " + e.target.error);
}
},
log: function(level,msg) {
var l = "";
if (level === "i") l = "Info: ";
else if (level === "e") l = "Error: ";
if (l.length !== 0)
console.log("IMDB List Importer: " + l + msg);
if (level == "n" || level == "e")
this.eready.innerText = msg;
},
create_list: function() {
var re;
// Find type of the list
if (document.getElementsByClassName('list_characters').length !== 0) {
this.log("i", "List type: characters");
re = /ch[0-9]{7}/;
} else if (document.getElementsByClassName('list_people').length !== 0) {
this.log("i", "List type: people");
re = /nm[0-9]{7}/;
} else if (document.getElementsByClassName('list_titles').length !== 0) {
this.log("i", "List type: titles");
re = /tt[0-9]{7}/;
} else {
this.log("e","Could not determine type of the list");
return [];
}
if (this.csv.checked) {
return this.read_csv(re);
} else {
var list = [];
var e;
var text = this.text;
while ((e = re.exec(text)) !== null) {
var flag = '';
if (this.unique.checked) flag = 'g';
text = text.replace(new RegExp(e[0], flag), '');
list.push({const: e[0], description: ""});
}
return list;
}
},
read_csv: function(re) {
var list = [];
text = this.text.split('\n');
// Remove empty strings from the end
var i = text.length-1;
for (;i >= 0 && text[i].trim().length === 0; i--);
i++;
text.splice(i,text.length - i);
// Find const and description field numbers.
var fl = JSON.parse('[' + text[0] + ']');
var fll = fl.length
var const_field = fl.indexOf('const')
var desc_field = fl.indexOf('description');
if (const_field === -1 || desc_field === -1) {
this.log("e","File line 1: fields 'const' or/and 'description'" +
"are not found.");
return [];
}
this.log("i","Found csv file fields const(" + const_field +
") and description(" + desc_field + ")");
text.shift();
// Add elements to the list
for (i = 0; i < text.length; i++) {
fl = JSON.parse('[' + text[i] + ']');
if (fll !== fl.length || re.exec(text) === null) {
this.log("e","File line " + (i+2) +
": invalid data structure");
return [];
}
if (this.unique.checked) {
var exists = list.findIndex(function(v){
return v.const === fl[const_field];
});
if (exists !== -1) continue;
}
list.push({const: fl[const_field],description: fl[desc_field]});
}
return list;
},
add_list: function(list) {
if (list.length === 0)
return;
var msg = "Elements to add: ";
for (var i in list)
msg += list[i].const + ",";
this.log("i",msg);
var l = {};
l.list = list;
l.ready = 0;
l.list_id = /ls[0-9]{1,}/.exec(location.href)[0];
this.sendNext(l);
},
sendNext: function(l) {
this.log("i",'Add element ' + l.ready + ': ' + l.list[l.ready].const);
this.send_request(this.check_item, l, 'const=' + l.list[l.ready].const +
'&list_id=' + l.list_id);
},
send_request: function(f,l,d) {
var x = new XMLHttpRequest();
x.onreadystatechange = f.bind(this,l);
x.open('POST', '/list/_ajax/edit', true);
x.setRequestHeader('Content-Type',
'application/x-www-form-urlencoded; charset=UTF-8');
x.send(d);
},
check_item: function(l, e) {
this.log("i","Add element(" + l.list[l.ready].const +
") request: readyState(" + e.target.readyState +
"), status(" + e.target.status + ")");
if (e.target.readyState == 4 && e.target.status == 200) {
if (l.list[l.ready].description.length !== 0) {
this.send_request(this.check_item_desc, l,
'description=' + l.list[l.ready].description +
'&list_id=' + l.list_id + '&list_item_id=' +
JSON.parse(e.target.responseText).list_item_id);
} else {
this.showReady(l);
}
}
},
check_item_desc: function(l,e) {
this.log("i","Add element(" + l.list[l.ready].const +
") description request: readyState(" + e.target.readyState +
"), status(" + e.target.status + ")");
if (e.target.readyState == 4 && e.target.status == 200) {
this.showReady(l);
}
},
showReady: function(l) {
l.ready += 1;
this.log("n",'Ready ' + l.ready + ' of ' + l.list.length + '.');
if (l.ready == l.list.length) {
location.reload();
} else {
this.sendNext(l);
}
},
change: function(e) {
var s = e.target.checked;
this.etext.disabled = s;
this.efile.disabled = !s;
},
};
var c = window.File && window.FileReader && window.FileList && window.Blob;
var div = document.createElement('div');
div.setAttribute('class', 'add');
var s = '<textarea style="background-color: white"></textarea><br>';
if (c) {
s += '<input type="file" disabled><br>';
s += '<label>';
s += '<input type="checkbox" style="width: initial;">';
s += '<span style="font-weight: normal;">';
s += 'Import from file (otherwise import from text)';
s += '</span>';
s += '</label><br>';
}
s += '<label>';
s += '<input type="checkbox" checked style="width: initial;">';
s += '<span style="font-weight: normal;">Data from .csv file</span>';
s += '</label><br>';
s += '<label>';
s += '<input type="checkbox" style="width: initial;">';
s += '<span style="font-weight: normal;">Add only unique elements</span>';
s += '</label><br>';
s += '<div>Insert text with id\'s in the field above and press button "Import list"</div>';
s += '<button class="btn">Import List</button>';
div.innerHTML = s;
o.init(div);
div.querySelector('button').addEventListener('click',o.run.bind(o),false);
if (c) {
o.source.addEventListener('change',o.change.bind(o),false);
}
var list_edit = document.querySelector('.list_edit');
var footer = document.querySelector('.footer');
list_edit.insertBefore(div, footer);