IMDB List Importer

Import list of titles, people or characters in the imdb list

当前为 2017-07-14 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==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);