IMDB List Importer

Import list of titles or people in the imdb list

Από την 22/05/2020. Δείτε την τελευταία έκδοση.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==UserScript==
// @name         IMDB List Importer
// @namespace    Neinei0k_imdb
// @include      https://www.imdb.com/list/*
// @version	 7.2
// @license      GNU General Public License v3.0 or later
// @grant        GM.xmlHttpRequest
// @description  Import list of titles or people 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]; // DOM element with messages for the user.
	var checkboxes = e.querySelectorAll('input[type="checkbox"]');
	this.source = checkboxes[0];
	this.csv = checkboxes[1];
	this.unique = checkboxes[2];
  
  var hidden_element =  document.querySelector('#main > input'); // Unknown hidden element. Data needs to be send with all requests.
  if (hidden_element === null) {
   	this.log('e','Hidden element not found');
  } else {
  	this.hidden_data = hidden_element.id + "=" + hidden_element.value;
  }
},

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 = "";
  switch (level) {
    case 'i': l = "Info: "; break;
    case 'w': l = "Warning: "; break;
    case 'e': l = "Error: "; break;
  }
	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.querySelector('[data-type="Characters"]') !== null) {
		this.log("i", "List type: characters");
		re = "ch";
	} else*/
  if (document.querySelector('[data-type="People"]') !== null) {
		this.log("i", "List type: people");
		re = "nm";
	} else if (document.querySelector('[data-type="Titles"]') !== null) {
		this.log("i", "List type: titles");
		re = "tt";
	} else {
		this.log("e","Could not determine type of the list");
		return [];
	}
	re += "[0-9]{7,8}";

	if (this.csv.checked) {
		return this.read_csv(re);
	} else {
		re = new RegExp(re);
		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) {
	re = new RegExp("^" + re + "$");
	var list = [];
  
  // Parse csv
  var text = this.text.split('\n'); // Separate by lines
  this.text = null; // Variable may have lots of data which is no longer needed
  var parsed_text = [];
  for (var i in text) { // For each line
    if (text[i].trim().length === 0) { // Ignore empty lines including lines with only white space characters
      continue;
    }
    var state = 0; // 0 - outside of double quotes (comma character is the separator), 1 - inside double quotes (comma character is part of a field)
    var parsed_line = [""];
    for (var j in text[i]) {
      if (state === 0 && text[i][j] == ',') {
        parsed_line.push("");
      } else if (text[i][j] == '"') {
        state = (state + 1) % 2;
      } else {
        parsed_line[parsed_line.length-1] += text[i][j];
      }
    }
    parsed_text.push(parsed_line);
  }
  text = parsed_text;
  
  // console.log(text); // print parsed data

  var fl = "";
  var fll = "";
  var const_field = "";
  // Find const and description field numbers.
    try {
    if (text.length < 2) { // There must be at least 2 rows in the data
    	throw "No data";
    }
		fl = text[0];
		fll = fl.length;
		const_field = fl.indexOf('const');
		if (const_field === -1) {
      const_field = fl.indexOf('Const');
      if (const_field === -1) {
      	throw "Field 'const' not found.";
      }
    }
	} catch (err) {
		this.log("e","Input line 1: " + err);
		return [];
	}
  var desc_field = fl.indexOf('description');
		if (desc_field === -1) {
      desc_field = fl.indexOf('Description');
    }
  
	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++) {
		if (text[i].length === 0)
			continue;
		try {
			fl = text[i];
			if (fll !== fl.length) throw "Invalid number of fields.";
			if (re.exec(fl[const_field]) === null) throw "Invalid 'const' field.";
		} catch (err) {
			this.log("e","Input line " + (i+2) + ": " + err);
			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: (desc_field == -1 ? "" : fl[desc_field])});
	}
 
  // console.log(list); // Print final list
  
	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, 'https://www.imdb.com/list/' + l.list_id + '/' + l.list[l.ready].const + '/add', this.hidden_data);
},

send_request: function(f,l,u,d) {
  GM.xmlHttpRequest({
  	method: "POST",
    url: u,
    data: d,
    headers: {
      "Content-Type": "application/x-www-form-urlencoded"
    },
    onreadystatechange: f.bind(this,l)
  });
	/*var x = new XMLHttpRequest();
	x.onreadystatechange = f.bind(this,l);
	x.open('POST', u, true);
	x.setRequestHeader('Content-Type',
	  'application/x-www-form-urlencoded');
	x.send(d);*/
},

check_item: function(l, e) {
	this.log("i","Add element(" + l.list[l.ready].const +
	             ") request: readyState(" + e.readyState +
	             "), status(" + e.status + ")");
	if (e.readyState == 4 && e.status == 200) {
		if (l.list[l.ready].description.length !== 0) {
			this.send_request(this.check_item_desc, l, 'https://www.imdb.com/list/' + l.list_id + '/edit/itemdescription',
			                  'newDescription=' + l.list[l.ready].description +
			                  '&listItem=' + JSON.parse(e.responseText).list_item_id + '&' + this.hidden_data);
		} else {
			this.showReady(l);
		}
	}
},

check_item_desc: function(l,e) {
	this.log("i","Add element(" + l.list[l.ready].const +
	             ") description request: readyState(" + e.readyState +
	             "), status(" + e.status + ")");
	if (e.readyState == 4 && e.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; // Check support of File API
var div = document.createElement('div');
div.setAttribute('class', 'search-bar');
div.style.height = "initial";
var s = '<textarea style="background-color: white; width: 100%; height: 100px; overflow: initial"></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>';
} else {
	s += '<span style="font-weight: normal;">';
	s += 'Looks like your browser does not support File API for reading local files.';
	s += '</span><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>Set-up parameters. Insert text or choose file. Press \'Import List\' button.</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('.lister-search');
list_edit.appendChild(div);