Albirew/nyaa-pantsu
Albirew
/
nyaa-pantsu
Archivé
1
0
Bifurcation 0

Merge pull request #842 from NyaaPantsu/xhr-torrent-refresh

Xhr torrent refresh
Cette révision appartient à :
akuma06 2017-05-30 17:04:25 +02:00 révisé par GitHub
révision efe00f1f61
9 fichiers modifiés avec 248 ajouts et 50 suppressions

Voir le fichier

@ -156,13 +156,15 @@ func (c *Category) Parse(s string) (ok bool) {
// deprecated for TorrentParam
type SearchParam struct {
Order bool // True means acsending
Status Status
Sort SortMode
Category Category
Page int
UserID uint
Max uint
NotNull string
Query string
TorrentID uint
FromID uint // Search for torrentID > FromID
Order bool // True means acsending
Status Status
Sort SortMode
Category Category
Page int
UserID uint
Max uint
NotNull string
Query string
}

Voir le fichier

@ -3,11 +3,12 @@ package common
import (
"context"
"encoding/json"
"github.com/gorilla/mux"
elastic "gopkg.in/olivere/elastic.v5"
"net/http"
"strconv"
"github.com/gorilla/mux"
elastic "gopkg.in/olivere/elastic.v5"
"github.com/NyaaPantsu/nyaa/config"
"github.com/NyaaPantsu/nyaa/db"
"github.com/NyaaPantsu/nyaa/model"
@ -26,11 +27,13 @@ type TorrentParam struct {
Offset uint32
UserID uint32
TorrentID uint32
FromID uint32
NotNull string // csv
Null string // csv
NameLike string // csv
}
// FromRequest : parse a request in torrent param
// TODO Should probably return an error ?
func (p *TorrentParam) FromRequest(r *http.Request) {
var err error
@ -54,9 +57,15 @@ func (p *TorrentParam) FromRequest(r *http.Request) {
}
// FIXME 0 means no userId defined
userId, err := strconv.ParseUint(r.URL.Query().Get("userID"), 10, 32)
userID, err := strconv.ParseUint(r.URL.Query().Get("userID"), 10, 32)
if err != nil {
userId = 0
userID = 0
}
// FIXME 0 means no userId defined
fromID, err := strconv.ParseUint(r.URL.Query().Get("fromID"), 10, 32)
if err != nil {
fromID = 0
}
var status Status
@ -76,7 +85,7 @@ func (p *TorrentParam) FromRequest(r *http.Request) {
p.NameLike = nameLike
p.Offset = uint32(pagenum)
p.Max = uint32(max)
p.UserID = uint32(userId)
p.UserID = uint32(userID)
// TODO Use All
p.All = false
// TODO Use Full
@ -88,9 +97,11 @@ func (p *TorrentParam) FromRequest(r *http.Request) {
// FIXME 0 means no TorrentId defined
// Do we even need that ?
p.TorrentID = 0
// Needed to display result after a certain torrentID
p.FromID = uint32(fromID)
}
// Builds a query string with for es query string query defined here
// ToFilterQuery : Builds a query string with for es query string query defined here
// https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html
func (p *TorrentParam) ToFilterQuery() string {
// Don't set sub category unless main category is set
@ -116,9 +127,14 @@ func (p *TorrentParam) ToFilterQuery() string {
query += " !status:" + p.Status.ToString()
}
}
if p.FromID != 0 {
query += " id:>" + strconv.FormatInt(int64(p.FromID), 10)
}
return query
}
// Find :
/* Uses elasticsearch to find the torrents based on TorrentParam
* We decided to fetch only the ids from ES and then query these ids to the
* database
@ -143,7 +159,7 @@ func (p *TorrentParam) Find(client *elastic.Client) (int64, []model.Torrent, err
From(int((p.Offset-1)*p.Max)).
Size(int(p.Max)).
Sort(p.Sort.ToESField(), p.Order).
Sort("_score", false). // Don't put _score before the field sort, it messes with the sorting
Sort("_score", false). // Don't put _score before the field sort, it messes with the sorting
FetchSourceContext(fsc)
filterQueryString := p.ToFilterQuery()
@ -198,6 +214,7 @@ func (p *TorrentParam) Find(client *elastic.Client) (int64, []model.Torrent, err
}
// Clone : To clone a torrent params
func (p *TorrentParam) Clone() TorrentParam {
return TorrentParam{
Order: p.Order,
@ -208,6 +225,7 @@ func (p *TorrentParam) Clone() TorrentParam {
Offset: p.Offset,
UserID: p.UserID,
TorrentID: p.TorrentID,
FromID: p.FromID,
NotNull: p.NotNull,
Null: p.Null,
NameLike: p.NameLike,

Voir le fichier

@ -52,25 +52,27 @@ function toggleLayer(elem) {
else
elem.classList.add("hide");
}
function parseAllDates() {
// Date formatting
var lang = document.getElementsByTagName("html")[0].getAttribute("lang");
var ymdOpt = { year: "numeric", month: "short", day: "numeric" };
var hmOpt = { hour: "numeric", minute: "numeric" };
// Date formatting
var lang = document.getElementsByTagName("html")[0].getAttribute("lang");
var ymdOpt = { year: "numeric", month: "short", day: "numeric" };
var hmOpt = { hour: "numeric", minute: "numeric" };
var list = document.getElementsByClassName("date-short");
for(var i in list) {
var e = list[i];
e.title = e.innerText;
e.innerText = new Date(e.innerText).toLocaleString(lang, ymdOpt);
}
var list = document.getElementsByClassName("date-short");
for(var i in list) {
var e = list[i];
e.title = e.innerText;
e.innerText = new Date(e.innerText).toLocaleString(lang, ymdOpt);
}
var list = document.getElementsByClassName("date-full");
for(var i in list) {
var e = list[i];
e.title = e.innerText;
e.innerText = new Date(e.innerText).toLocaleString(lang);
var list = document.getElementsByClassName("date-full");
for(var i in list) {
var e = list[i];
e.title = e.innerText;
e.innerText = new Date(e.innerText).toLocaleString(lang);
}
}
parseAllDates();
/*Fixed-Navbar offset fix*/
document.addEventListener("DOMContentLoaded", function(event) {
var shiftWindow = function() { scrollBy(0, -70) };

15
public/js/query.js Fichier normal
Voir le fichier

@ -0,0 +1,15 @@
var Query = {
Get: function(url, renderer, callback) {
var xhr = new XMLHttpRequest();
console.log(url)
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onload = function(e) {
if (this.status == 200) {
renderer(this.response);
callback(this.response)
}
};
xhr.send();
}
}

36
public/js/template.js Fichier normal
Voir le fichier

@ -0,0 +1,36 @@
// Templates variable
var Templates = {
tmpl: [],
Add: function(templateName, template) {
this.tmpl[templateName] = template
},
Render: function(templateName, model) {
return this.tmpl[templateName](model)
},
ApplyItemListRenderer: function(params) {
return function(models) {
for (var i=models.length-1; i >= 0; i--) {
var object = Templates.Render(params.templateName, models[i]);
if (params.method == "append") {
params.element.innerHTML = params.element.innerHTML + object
} else if (params.method == "prepend") {
params.element.innerHTML = object + params.element.innerHTML
}
}
};
},
EncodeEntities: function(value) {
return value.
replace(/&/g, '&').
replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, function(value) {
var hi = value.charCodeAt(0);
var low = value.charCodeAt(1);
return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
}).
replace(/([^\#-~| |!])/g, function(value) {
return '&#' + value.charCodeAt(0) + ';';
}).
replace(/</g, '&lt;').
replace(/>/g, '&gt;');
}
};

58
public/js/torrents.js Fichier normal
Voir le fichier

@ -0,0 +1,58 @@
var Torrents = {
CanRefresh: false,
timeout: undefined,
Seconds: 300, // Every five minutes, can be overridden directly in home.html (not here is better)
SearchURL: "/api/search",
Method: "prepend",
LastID: 0,
StopRefresh: function() {
clearTimeout(this.timeout)
this.timeout = undefined
this.CanRefresh = false
},
Refresh: function() {
if (this.CanRefresh) {
console.log("Start Refresh...")
this.timeout = setTimeout(function() {
var searchArgs = (window.location.search != "") ? window.location.search.substr(1) : ""
searchArgs = (Torrents.LastID > 0) ? "?fromID="+Torrents.LastID+"&"+searchArgs : "?"+searchArgs
Query.Get(Torrents.SearchURL+searchArgs,
Templates.ApplyItemListRenderer({
templateName: "torrents.item", method: "prepend", element: document.getElementById("torrentListResults")
}), function(torrents) {
for (var i =0; i < torrents.length; i++) { if (Torrents.LastID < torrents[i].id) Torrents.LastID = torrents[i].id; }
parseAllDates();
Torrents.Refresh()
});
}, this.Seconds*1000);
}
},
StartRefresh: function() {
this.CanRefresh = true;
this.Refresh()
}
}
document.addEventListener("DOMContentLoaded", function() { // if Torrents.CanRefresh is enabled, refresh is automatically done (no need to start it anually)
if (Torrents.CanRefresh) {
Torrents.StartRefresh()
}
})
// Credits to mpen (StackOverflow)
function humanFileSize(bytes, si) {
var thresh = si ? 1000 : 1024;
if(Math.abs(bytes) < thresh) {
return bytes + ' B';
}
var units = si
? ['kB','MB','GB','TB','PB','EB','ZB','YB']
: ['KiB','MiB','GiB','TiB','PiB','EiB','ZiB','YiB'];
var u = -1;
do {
bytes /= thresh;
++u;
} while(Math.abs(bytes) >= thresh && u < units.length - 1);
return bytes.toFixed(1)+' '+units[u];
}

Voir le fichier

@ -8,6 +8,7 @@ import (
"time"
"github.com/NyaaPantsu/nyaa/config"
"github.com/NyaaPantsu/nyaa/model"
"github.com/NyaaPantsu/nyaa/service/user/permission"
"github.com/NyaaPantsu/nyaa/util"
"github.com/NyaaPantsu/nyaa/util/categories"
@ -193,11 +194,33 @@ var FuncMap = template.FuncMap{
return config.DefaultUserSettings[s]
},
"makeTreeViewData": func(f *filelist.FileListFolder, nestLevel int, T publicSettings.TemplateTfunc, identifierChain string) interface{} {
return struct{
Folder *filelist.FileListFolder
NestLevel int
T publicSettings.TemplateTfunc
return struct {
Folder *filelist.FileListFolder
NestLevel int
T publicSettings.TemplateTfunc
IdentifierChain string
}{ f, nestLevel, T, identifierChain }
}{f, nestLevel, T, identifierChain}
},
"lastID": func(currentUrl url.URL, torrents []model.TorrentJSON) int {
values := currentUrl.Query()
order := false
sort := "2"
if _, ok := values["order"]; ok {
order, _ = strconv.ParseBool(values["order"][0])
}
if _, ok := values["sort"]; ok {
sort = values["sort"][0]
}
lastID := 0
if sort == "2" || sort == "" {
if order {
lastID = int(torrents[len(torrents)-1].ID)
} else {
lastID = int(torrents[0].ID)
}
}
return lastID
},
}

Voir le fichier

@ -37,6 +37,7 @@ Your browser does not support the audio element.
<th class="tr-date hide-xs"><a href="{{ genSearchWithOrdering .URL "2" }}">{{call $.T "date"}}<span class="sort-arrows">{{ genSortArrows .URL "2" }}</span></a></th>
</tr>
</thead>
<tbody id="torrentListResults">
{{ range .Models}}
<tr class="torrent-info
{{if eq .Status 2}}remake{{end}}
@ -84,6 +85,41 @@ Your browser does not support the audio element.
<td class="tr-date home-td date-short hide-xs">{{.Date}}</td>
</tr>
{{end}}
</tbody>
</table>
</div>
{{end}}
{{ define "footer_js"}}
<script type="text/javascript" src="{{ $.URL.Parse "/js/template.js" }}"></script>
<script type="text/javascript" src="{{ $.URL.Parse "/js/query.js" }}"></script>
<script type="text/javascript" src="{{ $.URL.Parse "/js/torrents.js" }}"></script>
<!-- JS Template -->
<script type="text/javascript">
Templates.Add("torrents.item", function(torrent) {
return "<tr class=\"torrent-info"+ ((torrent.status == 2) ? " remake" : ((torrent.status == 3) ? " trusted" : ((torrent.status == 3) ? " aplus" : "" )))+"\">"+
"<td class=\"tr-cat home-td\">"+
"<a href=\"{{$.URL.Parse "/search?c=" }}"+ torrent.category + "_" + torrent.sub_category +"\">"+
{{ if Sukebei }}
"<img src=\"{{ $.URL.Parse "/img/torrents/sukebei/" }}"+ torrent.category + torrent.sub_category+".png\" title=\""+ torrent.CategoryName +"\">"+
{{ else }}
"<img src=\"{{ $.URL.Parse "/img/torrents/" }}"+ torrent.sub_category +".png\" title=\""+ torrent.CategoryName +"\">"+
{{ end }}
"</a>"+
"</td>"+
"<td class=\"tr-name home-td\"><a href=\"/view/"+torrent.id+"\">"+Templates.EncodeEntities(torrent.name) +"</a></td>"+
"<td class=\"tr-links home-td\">"+
"<a href=\""+torrent.magnet +"\" title=\"{{ call $.T "magnet_link" }}\">"+
"<div class=\"magnet-icon\"></div>"+
"</a>"+(torrent.torrent != "" ? " <a href=\""+torrent.torrent+"\" title=\"{{ call $.T "torrent_file" }}\"><div class=\"download-icon\"></div></a>" : "") +
"</td>"+
"<td class=\"tr-size home-td hide-xs\">"+humanFileSize(torrent.filesize)+"</td>"+
"<td class=\"tr-se home-td hide-xs\">"+torrent.seeders+"</td>"+
"<td class=\"tr-le home-td hide-xs\">"+torrent.leechers+"</td>"+
"<td class=\"tr-dl home-td hide-xs\">"+torrent.completed+"</td>"+
"<td class=\"tr-date home-td date-short hide-xs\">"+torrent.date+"</td>"+
"</tr>";
});
Torrents.LastID = {{ lastID .URL .Models }};
if (Torrents.LastID > 0) Torrents.CanRefresh = true;
</script>
{{end}}

Voir le fichier

@ -6,6 +6,7 @@ import (
"strings"
"unicode"
"unicode/utf8"
elastic "gopkg.in/olivere/elastic.v5"
"github.com/NyaaPantsu/nyaa/cache"
@ -83,23 +84,24 @@ func searchByQuery(r *http.Request, pagenum int, countAll bool, withUser bool, d
torrentParam.FromRequest(r)
totalHits, torrents, err := torrentParam.Find(client)
searchParam := common.SearchParam{
Order: torrentParam.Order,
Status: torrentParam.Status,
Sort: torrentParam.Sort,
Category: torrentParam.Category,
Page: int(torrentParam.Offset),
UserID: uint(torrentParam.UserID),
Max: uint(torrentParam.Max),
NotNull: torrentParam.NotNull,
Query: torrentParam.NameLike,
TorrentID: uint(torrentParam.TorrentID),
FromID: uint(torrentParam.FromID),
Order: torrentParam.Order,
Status: torrentParam.Status,
Sort: torrentParam.Sort,
Category: torrentParam.Category,
Page: int(torrentParam.Offset),
UserID: uint(torrentParam.UserID),
Max: uint(torrentParam.Max),
NotNull: torrentParam.NotNull,
Query: torrentParam.NameLike,
}
// Convert back to non-json torrents
return searchParam, torrents, int(totalHits), err
} else {
log.Errorf("Unable to create elasticsearch client: %s", err)
log.Errorf("Falling back to postgresql query")
return searchByQueryPostgres(r, pagenum, countAll, withUser, deleted)
}
log.Errorf("Unable to create elasticsearch client: %s", err)
log.Errorf("Falling back to postgresql query")
return searchByQueryPostgres(r, pagenum, countAll, withUser, deleted)
}
func searchByQueryPostgres(r *http.Request, pagenum int, countAll bool, withUser bool, deleted bool) (
@ -117,6 +119,8 @@ func searchByQueryPostgres(r *http.Request, pagenum int, countAll bool, withUser
search.Query = r.URL.Query().Get("q")
userID, _ := strconv.Atoi(r.URL.Query().Get("userID"))
search.UserID = uint(userID)
fromID, _ := strconv.Atoi(r.URL.Query().Get("fromID"))
search.FromID = uint(fromID)
switch s := r.URL.Query().Get("s"); s {
case "1":
@ -216,6 +220,10 @@ func searchByQueryPostgres(r *http.Request, pagenum int, countAll bool, withUser
conditions = append(conditions, "uploader = ?")
parameters.Params = append(parameters.Params, search.UserID)
}
if search.FromID != 0 {
conditions = append(conditions, "torrent_id > ?")
parameters.Params = append(parameters.Params, search.FromID)
}
if search.Category.Sub != 0 {
conditions = append(conditions, "sub_category = ?")
parameters.Params = append(parameters.Params, search.Category.Sub)