diff --git a/cmd/magneticow/api.go b/cmd/magneticow/api.go index f5a8119..538ca10 100644 --- a/cmd/magneticow/api.go +++ b/cmd/magneticow/api.go @@ -56,6 +56,7 @@ func apiTorrentsHandler(w http.ResponseWriter, r *http.Request) { return } + // TODO: use plain Marshal jm, err := json.MarshalIndent(torrents, "", " ") if err != nil { respondError(w, 500, "json marshalling error: %s", err.Error()) diff --git a/cmd/magneticow/data/static/scripts/naturalSort-v0.8.1.js b/cmd/magneticow/data/static/scripts/naturalSort-v0.8.1.js new file mode 100644 index 0000000..b2ae74e --- /dev/null +++ b/cmd/magneticow/data/static/scripts/naturalSort-v0.8.1.js @@ -0,0 +1,73 @@ +/* + * Natural Sort algorithm for Javascript - Version 0.8.1 - Released under MIT license + * Author: Jim Palmer (based on chunking idea from Dave Koelle) + * + * https://github.com/overset/javascript-natural-sort + * + * Modified by Mert Bora ALPER for magnetico. + */ +function naturalSort (a, b) { + /* The following modification makes sure that paths with less levels (i.e. less directories) are + * smaller than (or, "comes before") the directories with more levels (i.e. more directories). + * + * Without Bora's Modification: + * >>> ["/aaaa/aaa/aa.html", "/aaaa/bbb.txt"].sort(naturalSort) + * ["/aaaa/aaa/aa.html", "/aaaa/bbb.txt"] + * + * With Bora's Modification: + * >>> ["/aaaa/aaa/aa.html", "/aaaa/bbb.txt"].sort(naturalSort) + * ["/aaaa/bbb.txt", "/aaaa/aaa/aa.html"] + * + * + */ + let aSlashes = a.split("/").length, + bSlashes = b.split("/").length; + if (aSlashes !== bSlashes) + return aSlashes - bSlashes; + // + + var re = /(^([+\-]?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?(?=\D|\s|$))|^0x[\da-fA-F]+$|\d+)/g, + sre = /^\s+|\s+$/g, // trim pre-post whitespace + snre = /\s+/g, // normalize all whitespace to single ' ' character + dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/, + hre = /^0x[0-9a-f]+$/i, + ore = /^0/, + i = function(s) { + return (naturalSort.insensitive && ('' + s).toLowerCase() || '' + s).replace(sre, ''); + }, + // convert all to strings strip whitespace + x = i(a), + y = i(b), + // chunk/tokenize + xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), + yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'), + // numeric, hex or date detection + xD = parseInt(x.match(hre), 16) || (xN.length !== 1 && Date.parse(x)), + yD = parseInt(y.match(hre), 16) || xD && y.match(dre) && Date.parse(y) || null, + normChunk = function(s, l) { + // normalize spaces; find floats not starting with '0', string or 0 if not defined (Clint Priest) + return (!s.match(ore) || l == 1) && parseFloat(s) || s.replace(snre, ' ').replace(sre, '') || 0; + }, + oFxNcL, oFyNcL; + // first try and sort Hex codes or Dates + if (yD) { + if (xD < yD) { return -1; } + else if (xD > yD) { return 1; } + } + // natural sorting through split numeric strings and default strings + for(var cLoc = 0, xNl = xN.length, yNl = yN.length, numS = Math.max(xNl, yNl); cLoc < numS; cLoc++) { + oFxNcL = normChunk(xN[cLoc] || '', xNl); + oFyNcL = normChunk(yN[cLoc] || '', yNl); + // handle numeric vs string comparison - number < string - (Kyle Adams) + if (isNaN(oFxNcL) !== isNaN(oFyNcL)) { + return isNaN(oFxNcL) ? 1 : -1; + } + // if unicode use locale comparison + if (/[^\x00-\x80]/.test(oFxNcL + oFyNcL) && oFxNcL.localeCompare) { + var comp = oFxNcL.localeCompare(oFyNcL); + return comp / Math.abs(comp); + } + if (oFxNcL < oFyNcL) { return -1; } + else if (oFxNcL > oFyNcL) { return 1; } + } +} diff --git a/cmd/magneticow/data/static/scripts/torrent.js b/cmd/magneticow/data/static/scripts/torrent.js index 43578c3..1c9cbc9 100644 --- a/cmd/magneticow/data/static/scripts/torrent.js +++ b/cmd/magneticow/data/static/scripts/torrent.js @@ -11,6 +11,7 @@ window.onload = function() { var pre_element = document.getElementsByTagName("pre")[0]; var paths = pre_element.textContent.replace(/\s+$/, "").split("\n"); + paths.sort(naturalSort); paths = paths.map(function(path) { return path.split('/'); }); pre_element.textContent = stringify(structurise(paths)).join("\n"); }; diff --git a/cmd/magneticow/data/static/scripts/torrents.js b/cmd/magneticow/data/static/scripts/torrents.js index 51a4aa8..c9e1cda 100644 --- a/cmd/magneticow/data/static/scripts/torrents.js +++ b/cmd/magneticow/data/static/scripts/torrents.js @@ -122,7 +122,7 @@ function encodeQueryData(data) { // https://stackoverflow.com/q/10420352/4466589 function fileSize(fileSizeInBytes) { let i = -1; - let byteUnits = [' kB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB']; + let byteUnits = [' KiB', ' MiB', ' GiB', ' TiB', ' PiB', ' EiB', ' ZiB', ' YiB']; do { fileSizeInBytes = fileSizeInBytes / 1024; i++; diff --git a/cmd/magneticow/data/templates/torrent.html b/cmd/magneticow/data/templates/torrent.html index 58acc36..65458af 100644 --- a/cmd/magneticow/data/templates/torrent.html +++ b/cmd/magneticow/data/templates/torrent.html @@ -2,11 +2,12 @@ - {{ torrent.name }} - magnetico - - - - + {{ .T.Name }} - magnetico + + + + +
@@ -17,39 +18,32 @@
- + - + - +
Size{{ torrent.size }}{{ humanizeSize .T.Size }}
Discovered on{{ torrent.discovered_on }}{{ unixTimeToYearMonthDay .T.DiscoveredOn }}
Files{{ torrent.files|length }}{{ .T.NFiles }}

Contents

- -
{% for file in torrent.files -%}{{ file.path }}{{ "\t" + file.size }}{{ "\n" }}{%- endfor %}
+
{{ range .F }}{{ .Path }}{{ "\t" }}{{ humanizeSizeF .Size }}{{ "\n" }}{{ end }}
\ No newline at end of file diff --git a/cmd/magneticow/data/templates/torrents.html b/cmd/magneticow/data/templates/torrents.html index ef58ade..8807326 100644 --- a/cmd/magneticow/data/templates/torrents.html +++ b/cmd/magneticow/data/templates/torrents.html @@ -16,7 +16,7 @@ Magnet link - {{name}} + {{name}} {{size}} {{discoveredOn}} diff --git a/cmd/magneticow/main.go b/cmd/magneticow/main.go index 8bdb1a9..12fdc7a 100644 --- a/cmd/magneticow/main.go +++ b/cmd/magneticow/main.go @@ -126,6 +126,13 @@ func main() { return humanize.IBytes(s) }, + "humanizeSizeF": func(s int64) string { + if s < 0 { + return "" + } + return humanize.IBytes(uint64(s)) + }, + "comma": func(s uint) string { return humanize.Comma(int64(s)) }, @@ -135,7 +142,7 @@ func main() { // templates["feed"] = template.Must(template.New("feed").Parse(string(mustAsset("templates/feed.xml")))) templates["homepage"] = template.Must(template.New("homepage").Funcs(templateFunctions).Parse(string(mustAsset("templates/homepage.html")))) // templates["statistics"] = template.Must(template.New("statistics").Parse(string(mustAsset("templates/statistics.html")))) - // templates["torrent"] = template.Must(template.New("torrent").Funcs(templateFunctions).Parse(string(mustAsset("templates/torrent.html")))) + templates["torrent"] = template.Must(template.New("torrent").Funcs(templateFunctions).Parse(string(mustAsset("templates/torrent.html")))) // templates["torrents"] = template.Must(template.New("torrents").Funcs(templateFunctions).Parse(string(mustAsset("templates/torrents.html")))) var err error @@ -182,6 +189,7 @@ func torrentsHandler(w http.ResponseWriter, r *http.Request) { w.Write(data) } +// TODO: we might as well move torrent.html into static... func torrentsInfohashHandler(w http.ResponseWriter, r *http.Request) { // show torrents/{infohash} infoHash, err := hex.DecodeString(mux.Vars(r)["infohash"]) @@ -193,8 +201,32 @@ func torrentsInfohashHandler(w http.ResponseWriter, r *http.Request) { if err != nil { panic(err.Error()) } + if torrent == nil { + w.WriteHeader(404) + w.Write([]byte("torrent not found!")) + return + } - templates["torrent"].Execute(w, torrent) + files, err := database.GetFiles(infoHash) + if err != nil { + panic(err.Error()) + } + if files == nil { + w.WriteHeader(500) + w.Write([]byte("files not found what!!!")) + return + } + + err = templates["torrent"].Execute(w, struct { + T *persistence.TorrentMetadata + F []persistence.File + }{ + T: torrent, + F: files, + }) + if err != nil { + panic("error while executing template!") + } } func statisticsHandler(w http.ResponseWriter, r *http.Request) { diff --git a/pkg/persistence/sqlite3.go b/pkg/persistence/sqlite3.go index 603c853..6ebbcec 100644 --- a/pkg/persistence/sqlite3.go +++ b/pkg/persistence/sqlite3.go @@ -330,7 +330,9 @@ func (db *sqlite3Database) GetTorrent(infoHash []byte) (*TorrentMetadata, error) } func (db *sqlite3Database) GetFiles(infoHash []byte) ([]File, error) { - rows, err := db.conn.Query("SELECT size, path FROM files WHERE torrent_id = ?;", infoHash) + rows, err := db.conn.Query( + "SELECT size, path FROM files, torrents WHERE files.torrent_id = torrents.id AND torrents.info_hash = ?;", + infoHash) if err != nil { return nil, err }