From ebc7da1d0591b6d9a58364cbb942fa7b8c88bd41 Mon Sep 17 00:00:00 2001 From: sqozz Date: Sat, 21 Feb 2015 03:01:47 +0100 Subject: [PATCH] modified create dialog to display torrent infos detected from files --- indexer.py | 22 ++-- static/css/create.css | 9 ++ static/js/create.js | 234 +++++++++++++++++++++++++++++++++++++----- strings.json | 6 +- templates/create.html | 36 ++++++- 5 files changed, 270 insertions(+), 37 deletions(-) diff --git a/indexer.py b/indexer.py index 4128399..b3a63d0 100644 --- a/indexer.py +++ b/indexer.py @@ -43,8 +43,7 @@ def init(): def initDb(): connection = sqlite3.connect("torrentdb.sqlite") c = connection.cursor() - c.execute('CREATE TABLE IF NOT EXISTS torrents (fileid TEXT PRIMARY KEY NOT NULL, name TEXT NOT NULL, category TEXT NOT NULL, subcategory TEXT NOT NULL, description TEXT NOT NULL);') - c.execute('CREATE TABLE IF NOT EXISTS language_mapping (fileid TEXT NOT NULL, language TEXT NOT NULL);') + c.execute('CREATE TABLE IF NOT EXISTS torrents (fileid TEXT PRIMARY KEY NOT NULL, name TEXT NOT NULL, category TEXT NOT NULL, subcategory TEXT NOT NULL, description TEXT NOT NULL, audioquality_description TEXT NOT NULL, videoquality_description TEXT NOT NULL);') connection.commit() connection.close() @@ -78,8 +77,9 @@ def createNewTorrent(reuqest): category = request.form["category"] subcategory = request.form["subcategory"] description = request.form["description"] - languages = [] - newTFile = TorrentFile(safeFilename, name, category, subcategory, description, languages) + audioquality_description = request.form["audioquality_description"] + videoquality_description = request.form["videoquality_description"] + newTFile = TorrentFile(safeFilename, name, category, subcategory, description, audioquality_description, videoquality_description) connection = sqlite3.connect("torrentdb.sqlite") newTFile.writeToDb(connection.cursor()) connection.commit() @@ -92,21 +92,23 @@ class TorrentFile(): category = None subcategory = None description = None - languages = [] - def __init__(self, fileid=fileid, name=name, category=category, subcategory=subcategory, description=description, languages=languages): + audioquality_description = None + videoquality_description = None + def __init__(self, fileid=fileid, name=name, category=category, subcategory=subcategory, description=description, audioquality_description=audioquality_description, videoquality_description=videoquality_description): self.fileid = fileid self.name = name self.category = category self.subcategory = subcategory self.description = description - self.languages = languages + self.audioquality_description = audioquality_description + self.videoquality_description = videoquality_description def writeToDb(self, cursor): c = cursor b64description = base64.b64encode(self.description.encode()) - c.execute("INSERT INTO torrents(fileid, name, category, subcategory, description) VALUES(:fileid, :name, :category, :subcategory, :description)", { 'fileid' : self.fileid, 'name' : self.name, 'category' : self.category, 'subcategory' : self.subcategory, 'description' : b64description }) - for language in self.languages: - c.execute("INSERT INTO language_mapping(fileid, language)", { "fileid" : self.fileid, "language" : language }) + b64audioquality_description = base64.b64encode(self.audioquality_description.encode()) + b64videoquality_description = base64.b64encode(self.videoquality_description.encode()) + c.execute("INSERT INTO torrents(fileid, name, category, subcategory, description, audioquality_description, videoquality_description) VALUES(:fileid, :name, :category, :subcategory, :description, :audioquality_description, :videoquality_description)", { 'fileid' : self.fileid, 'name' : self.name, 'category' : self.category, 'subcategory' : self.subcategory, 'description' : b64description , 'audioquality_description' : b64audioquality_description, 'videoquality_description' : b64videoquality_description}) if __name__ == "__main__": init() diff --git a/static/css/create.css b/static/css/create.css index 843fc81..36bd5d3 100644 --- a/static/css/create.css +++ b/static/css/create.css @@ -108,6 +108,15 @@ body { content: ":"; } +.detectedFiles { + max-height: 100px; + overflow: auto; +} + +.detectedInfos h5,p { + display: inline; +} + .row { margin-bottom: 10px; } diff --git a/static/js/create.js b/static/js/create.js index 56ad603..28ef678 100644 --- a/static/js/create.js +++ b/static/js/create.js @@ -2,34 +2,13 @@ window.onload = function () { $('.dropdown li > a').click(function(e){ setDropdownButtonText(this.innerHTML, this.parentElement.parentElement.parentElement) //set the display-text to the selected value fillDropdownByValue(this.innerHTML, $(".dropdown")["1"]) + this.parentElement.parentElement.parentElement.classList.remove("open"); + return false; }); customizeUploadButton() } -//function fillDropdownByValue(value, dropdownToFill) { -// dropdownToFill.getElementsByClassName("text")[0].innerHTML = "Subcategory" -// var dropdownToFillUl = dropdownToFill.getElementsByClassName("dropdown-menu")[0] -// dropdownToFillUl.innerHTML = "" -// -// subCategory = getDescriptorByLocalString("english", value) -// catList = document.getElementById("subcategory_list") -// catList.innerHTML = "" -// categories = global_categories[subCategory].sort() -// for(var key in categories) { -// var newEntry = document.createElement("li") -// var newEntryLink = document.createElement("a") -// newEntry.setAttribute("role", "presentation") -// newEntryLink.setAttribute("role", "menuitem") -// newEntryLink.tabIndex = -1 -// newEntryLink.href = "#" -// newEntryLink.innerHTML = getLocalString("english", categories[key]) -// newEntryLink.onclick = function(){ setDropdownButtonText(this.innerHTML, this.parentElement.parentElement.parentElement) } -// newEntry.appendChild(newEntryLink) -// dropdownToFillUl.appendChild(newEntry) -// } -//} - function setDropdownButtonText(text, dropdownButton) { var dropdownTextSpan = dropdownButton.getElementsByClassName("text")[0] dropdownTextSpan.innerHTML = text @@ -44,6 +23,40 @@ function sortCategories(categories) { return sortedCategories } +function fillDetectedFilelist(file) { + var reader = new FileReader(); + fileList = document.querySelectorAll(".detectedFiles ul")[0] + fileList.innerHTML = "" + reader.onload = function() { + b = new bencode() + torrentObject = b.decode(reader.result) + for(var fileIndex = 0; fileIndex < torrentObject.info.files.length; fileIndex++){ + newListElement = document.createElement("li") + newListElement.innerHTML = torrentObject.info.files[fileIndex].path[0] + fileList.appendChild(newListElement) + } + + document.querySelectorAll("input.name")[0].value = torrentObject.info.name + + sizeGroup = document.querySelectorAll(".sizeGroup")[0] + if(torrentObject.info.pieces.length && torrentObject.info["piece length"]){ + sizeGroup.style.display = "" + document.querySelectorAll(".detectedSize")[0].innerHTML = ((Math.round((torrentObject.info.pieces.length / 20) * torrentObject.info["piece length"]) / 1024 / 1024 * 100) / 100) + " MB" + } else { + sizeGroup.style.display = "none" + } + + trackerGroup = document.querySelectorAll(".trackerGroup")[0] + if(torrentObject.announce){ + trackerGroup.style.display = "" + document.querySelectorAll(".detectedTracker")[0].innerHTML = torrentObject.announce + } else { + trackerGroup.style.display = "none" + } + } + reader.readAsArrayBuffer(file) +} + // Fill a defined dropdown with values. // These values will be generated out of the categories.json function fillDropdownByValue(value, dropdownToFill) { @@ -63,7 +76,11 @@ function fillDropdownByValue(value, dropdownToFill) { newEntryLink.tabIndex = -1 newEntryLink.href = "#" newEntryLink.innerHTML = subcategoryLocalString - newEntryLink.onclick = function(){ setDropdownButtonText(this.innerHTML, this.parentElement.parentElement.parentElement) } + newEntryLink.onclick = function(e){ + setDropdownButtonText(this.innerHTML, this.parentElement.parentElement.parentElement) + this.parentElement.parentElement.parentElement.classList.remove("open"); + return false; + } newEntry.appendChild(newEntryLink) dropdownToFillUl.appendChild(newEntry) } @@ -85,6 +102,7 @@ function setButtonToFilename(event) { targetInput = event["target"] button = targetInput.previousSibling.getElementsByClassName("text")[0] button.innerHTML = chunk(fileName, 40) + fillDetectedFilelist(this.files[0]) }); } @@ -162,3 +180,171 @@ function chunk(string, n) { } return ret }; + + +// Bencode Library +// Copyright 2014 Steven Goodwin +// Released under the GPL, version 2 + +// For format details, please see: +// http://en.wikipedia.org/wiki/Bencode + +bencode = function() { + this.STATE_NULL = 0; + this.STATE_INTEGER = 1; // i-?[0-9]e + this.STATE_STRING_LENGTH = 2; // [0-9]+:\a+ + this.STATE_STRING_CONTENT = 3; // [0-9]+:\a+ + this.STATE_LIST = 4; // le + this.STATE_DICTIONARY = 5; // de +} + +// Parse accepts an array of characters to process, and the index of the +// first character to parse. +// It returns an object containing the parsed result (in result.o), and the index +// of the next character to parse in result.idx +bencode.prototype.parse = function(dataArray, fromIndex) { + var length = dataArray.byteLength; + var idx = fromIndex; + var state = this.STATE_NULL; + + // State data + var current = ""; + var currentObject = null;; + // String-specific state data + var stringLength; + + while(idx < length) { + var c = String.fromCharCode(dataArray[idx]) ; + + switch(state) { + case this.STATE_NULL: + switch(c) { + case 'i': + state = this.STATE_INTEGER; + current = ""; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + state = this.STATE_STRING_LENGTH; + current = c; + break; + case 'l': + currentObject = new Array(); + state = this.STATE_LIST; + break; + + case 'd': + currentObject = new Object(); + state = this.STATE_DICTIONARY; + break; + + default: + return null; + } + // + ++idx; + break; + + case this.STATE_INTEGER: + switch(c) { + case '-': // we assume that negative numbers start with - + current = "-"; + break; + case 'e': + return { o : current, idx : idx+1 }; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + current += c; + break; + } + ++idx; + break; + + case this.STATE_STRING_LENGTH: + switch(c) { + case ':': // the separator between length and content + stringLength = parseInt(current, 10); + state = this.STATE_STRING_CONTENT; + current = ""; // We now parse the string content + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + current += c; + break; + default: + return null; + + } + ++idx; + break; + + case this.STATE_STRING_CONTENT: + current += c; + if (--stringLength == 0) { + return { o : current, idx : idx+1 }; + } + + ++idx; + break; + + case this.STATE_DICTIONARY: + + if (c == 'e') { + return { o : currentObject, idx : idx+1 }; + } else { + var objKey = this.parse(dataArray, idx); + var objValue = this.parse(dataArray, objKey.idx); + + currentObject[objKey.o] = objValue.o; + idx = objValue.idx; + } + break; + + case this.STATE_LIST: + + if (c == 'e') { + return { o : currentObject, idx : idx+1 }; + } else { + var obj = this.parse(dataArray, idx); + + currentObject.push(obj.o); + idx = obj.idx; + } + break; + + } + } + + return null; +} + +bencode.prototype.decode = function(byteArray) { + var dataArray = new Uint8Array(byteArray); + var result = this.parse(dataArray, 0); + + return result.o; +} diff --git a/strings.json b/strings.json index d142a42..4bf4af9 100644 --- a/strings.json +++ b/strings.json @@ -35,7 +35,9 @@ "create" : "Create", "torrent_file" : "Torrent file", "name" : "Name", - "create_new_torrent" : "Create new torrent", - "description" : "Description" + "create_new_torrent" : "Create a new torrent", + "description" : "Description", + "audio_quality" : "Audio quality", + "video_quality" : "Video quality" } } diff --git a/templates/create.html b/templates/create.html index 5c87bee..b524b9f 100644 --- a/templates/create.html +++ b/templates/create.html @@ -24,6 +24,26 @@ vim: ts=2 noexpandtab +
+ +
+
+
Size:
+

123MB

+
+
+
Tracker:
+

http://foo.bar/tracker

+
+
+
Detected files:
+
+
    +
+
+
+
+
@@ -62,6 +82,19 @@ vim: ts=2 noexpandtab
+
+ +
+ +
+
+
+ +
+ +
+
+
- +