Rearranged Files
Configurations are separated in files in the folder config Connection to database by a package to import when needed Models will be in a model package for better maintenance Services access to the models Utils are tools or functions that can be used anywhere main.go cleaned a bit and other files modifications are there for the above modifications
Cette révision appartient à :
Parent
a50d218504
révision
9586f1e731
14 fichiers modifiés avec 426 ajouts et 329 suppressions
5
config/database.go
Fichier normal
5
config/database.go
Fichier normal
|
@ -0,0 +1,5 @@
|
|||
package config
|
||||
|
||||
const (
|
||||
DbName = "./nyaa.db"
|
||||
)
|
8
config/env.go
Fichier normal
8
config/env.go
Fichier normal
|
@ -0,0 +1,8 @@
|
|||
package config
|
||||
|
||||
// Constants for environment.
|
||||
const (
|
||||
// DEVELOPMENT | TEST | PRODUCTION
|
||||
Environment = "DEVELOPMENT"
|
||||
// Environment = "PRODUCTION"
|
||||
)
|
6
config/navigation.go
Fichier normal
6
config/navigation.go
Fichier normal
|
@ -0,0 +1,6 @@
|
|||
package config
|
||||
|
||||
// Constants for pagination.
|
||||
const (
|
||||
TorrentsPerPage = 50
|
||||
)
|
7
config/sorting.go
Fichier normal
7
config/sorting.go
Fichier normal
|
@ -0,0 +1,7 @@
|
|||
package config
|
||||
|
||||
// Constants for ordering models.
|
||||
const (
|
||||
TorrentOrder = "torrent_id"
|
||||
TorrentSort = "DESC"
|
||||
)
|
5
config/trackers.go
Fichier normal
5
config/trackers.go
Fichier normal
|
@ -0,0 +1,5 @@
|
|||
package config
|
||||
|
||||
const (
|
||||
Trackers = "&tr=udp://zer0day.to:1337/announce&tr=udp://tracker.leechers-paradise.org:6969&tr=udp://explodie.org:6969&tr=udp://tracker.opentrackr.org:1337&tr=udp://tracker.coppersurfer.tk:6969&tr=http://tracker.baka-sub.cf/announce"
|
||||
)
|
57
db/gorm.go
Fichier normal
57
db/gorm.go
Fichier normal
|
@ -0,0 +1,57 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"github.com/ewhal/nyaa/config"
|
||||
"github.com/ewhal/nyaa/util/log"
|
||||
"github.com/ewhal/nyaa/model"
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
// _ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
var ORM, Errs = GormInit()
|
||||
|
||||
// GormInit init gorm ORM.
|
||||
func GormInit() (*gorm.DB, error) {
|
||||
db, err := gorm.Open("sqlite3", config.DbName)
|
||||
// db, err := gorm.Open("mysql", config.MysqlDSL())
|
||||
//db, err := gorm.Open("sqlite3", "/tmp/gorm.db")
|
||||
|
||||
// Get database connection handle [*sql.DB](http://golang.org/pkg/database/sql/#DB)
|
||||
db.DB()
|
||||
|
||||
// Then you could invoke `*sql.DB`'s functions with it
|
||||
db.DB().Ping()
|
||||
db.DB().SetMaxIdleConns(10)
|
||||
db.DB().SetMaxOpenConns(100)
|
||||
|
||||
// Disable table name's pluralization
|
||||
// db.SingularTable(true)
|
||||
if config.Environment == "DEVELOPMENT" {
|
||||
db.LogMode(true)
|
||||
// db.DropTable(&model.User{}, "UserFollower")
|
||||
db.AutoMigrate(&model.Torrents{}, &model.Categories{}, &model.Sub_Categories{}, &model.Statuses{})
|
||||
// db.AutoMigrate(&model.User{}, &model.Role{}, &model.Connection{}, &model.Language{}, &model.Article{}, &model.Location{}, &model.Comment{}, &model.File{})
|
||||
// db.Model(&model.User{}).AddIndex("idx_user_token", "token")
|
||||
|
||||
}
|
||||
log.CheckError(err)
|
||||
|
||||
// relation := gorm.Relationship{}
|
||||
// relation.Kind = "many2many"
|
||||
// relation.ForeignFieldNames = []string{"id"} //(M1 pkey)
|
||||
// relation.ForeignDBNames = []string{"user_id"} //(M1 fkey in m1m2join)
|
||||
// relation.AssociationForeignFieldNames = []string{"id"} //(M2 pkey)
|
||||
// // relation.AssociationForeignStructFieldNames = []string{"id", "ID"} //(m2 pkey name in m2 struct?)
|
||||
// relation.AssociationForeignDBNames = []string{"follower_id"} //(m2 fkey in m1m2join)
|
||||
// m1Type := reflect.TypeOf(model.User{})
|
||||
// m2Type := reflect.TypeOf(model.User{})
|
||||
// handler := gorm.JoinTableHandler{}
|
||||
// // ORDER BELOW MATTERS
|
||||
// // Install handler
|
||||
// db.SetJoinTableHandler(&model.User{}, "Likings", &handler)
|
||||
// // Configure handler to use the relation that we've defined
|
||||
// handler.Setup(&relation, "users_followers", m1Type, m2Type)
|
||||
|
||||
return db, err
|
||||
}
|
115
main.go
115
main.go
|
@ -1,57 +1,23 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"encoding/json"
|
||||
"github.com/gorilla/feeds"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/jinzhu/gorm/dialects/sqlite"
|
||||
|
||||
"github.com/ewhal/nyaa/model"
|
||||
"github.com/ewhal/nyaa/service/torrent"
|
||||
"github.com/ewhal/nyaa/util/log"
|
||||
|
||||
"html"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var db *gorm.DB
|
||||
var router *mux.Router
|
||||
var debugLogger *log.Logger
|
||||
var trackers = "&tr=udp://zer0day.to:1337/announce&tr=udp://tracker.leechers-paradise.org:6969&tr=udp://explodie.org:6969&tr=udp://tracker.opentrackr.org:1337&tr=udp://tracker.coppersurfer.tk:6969&tr=http://tracker.baka-sub.cf/announce"
|
||||
|
||||
func getDBHandle() *gorm.DB {
|
||||
dbInit, err := gorm.Open("sqlite3", "./nyaa.db")
|
||||
|
||||
// Migrate the schema of Torrents
|
||||
dbInit.AutoMigrate(&Torrents{}, &Categories{}, &Sub_Categories{}, &Statuses{})
|
||||
|
||||
checkErr(err)
|
||||
return dbInit
|
||||
}
|
||||
|
||||
func checkErr(err error) {
|
||||
if err != nil {
|
||||
debugLogger.Println(" " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func unZlib(description []byte) string {
|
||||
if len(description) > 0 {
|
||||
b := bytes.NewReader(description)
|
||||
//log.Println(b)
|
||||
z, err := zlib.NewReader(b)
|
||||
checkErr(err)
|
||||
defer z.Close()
|
||||
p, err := ioutil.ReadAll(z)
|
||||
checkErr(err)
|
||||
return string(p)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func apiHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
|
@ -59,13 +25,13 @@ func apiHandler(w http.ResponseWriter, r *http.Request) {
|
|||
page := vars["page"]
|
||||
pagenum, _ := strconv.Atoi(html.EscapeString(page))
|
||||
|
||||
b := CategoryJson{Torrents: []TorrentsJson{}}
|
||||
b := model.CategoryJson{Torrents: []model.TorrentsJson{}}
|
||||
maxPerPage := 50
|
||||
nbTorrents := 0
|
||||
|
||||
torrents, nbTorrents := getAllTorrents(maxPerPage, maxPerPage*(pagenum-1))
|
||||
torrents, nbTorrents := torrentService.GetAllTorrents(maxPerPage, maxPerPage*(pagenum-1))
|
||||
for i, _ := range torrents {
|
||||
res := torrents[i].toJson()
|
||||
res := torrents[i].ToJson()
|
||||
b.Torrents = append(b.Torrents, res)
|
||||
}
|
||||
|
||||
|
@ -84,10 +50,10 @@ func apiViewHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
b := CategoryJson{Torrents: []TorrentsJson{}}
|
||||
b := model.CategoryJson{Torrents: []model.TorrentsJson{}}
|
||||
|
||||
torrent, err := getTorrentById(id)
|
||||
res := torrent.toJson()
|
||||
torrent, err := torrentService.GetTorrentById(id)
|
||||
res := torrent.ToJson()
|
||||
b.Torrents = append(b.Torrents, res)
|
||||
|
||||
b.QueryRecordCount = 1
|
||||
|
@ -103,7 +69,6 @@ func apiViewHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func searchHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var templates = template.Must(template.New("home").Funcs(funcMap).ParseFiles("templates/index.html", "templates/home.html"))
|
||||
templates.ParseGlob("templates/_*.html") // common
|
||||
vars := mux.Vars(r)
|
||||
page := vars["page"]
|
||||
|
||||
|
@ -126,6 +91,7 @@ func searchHandler(w http.ResponseWriter, r *http.Request) {
|
|||
// need this to prevent out of index panics
|
||||
var searchCatId, searchSubCatId string
|
||||
if len(catsSplit) == 2 {
|
||||
|
||||
searchCatId = html.EscapeString(catsSplit[0])
|
||||
searchSubCatId = html.EscapeString(catsSplit[1])
|
||||
}
|
||||
|
@ -139,53 +105,29 @@ func searchHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
nbTorrents := 0
|
||||
|
||||
b := []TorrentsJson{}
|
||||
b := []model.TorrentsJson{}
|
||||
|
||||
parameters := WhereParams{}
|
||||
conditions := []string{}
|
||||
if searchCatId != "" {
|
||||
conditions = append(conditions, "category_id = ?")
|
||||
parameters.params = append(parameters.params, searchCatId)
|
||||
}
|
||||
if searchSubCatId != "" {
|
||||
conditions = append(conditions, "sub_category_id = ?")
|
||||
parameters.params = append(parameters.params, searchSubCatId)
|
||||
}
|
||||
if stat != "" {
|
||||
conditions = append(conditions, "status_id = ?")
|
||||
parameters.params = append(parameters.params, stat)
|
||||
}
|
||||
searchQuerySplit := strings.Split(searchQuery, " ")
|
||||
for i, _ := range searchQuerySplit {
|
||||
conditions = append(conditions, "torrent_name LIKE ?")
|
||||
parameters.params = append(parameters.params, "%"+searchQuerySplit[i]+"%")
|
||||
}
|
||||
|
||||
parameters.conditions = strings.Join(conditions[:], " AND ")
|
||||
log.Printf("SQL query is :: %s\n", parameters.conditions)
|
||||
torrents, nbTorrents := getTorrentsOrderBy(¶meters, order_by, maxPerPage, maxPerPage*(pagenum-1))
|
||||
parameters := torrentService.CreateWhereParams("torrent_name LIKE ? AND status_id LIKE ? AND category_id LIKE ? AND sub_category_id LIKE ?",
|
||||
"%"+searchQuery+"%", stat+"%", searchCatId+"%", searchSubCatId+"%")
|
||||
torrents, nbTorrents := torrentService.GetTorrentsOrderBy(¶meters, order_by, maxPerPage, maxPerPage*(pagenum-1))
|
||||
|
||||
for i, _ := range torrents {
|
||||
res := torrents[i].toJson()
|
||||
res := torrents[i].ToJson()
|
||||
b = append(b, res)
|
||||
}
|
||||
|
||||
navigationTorrents := Navigation{nbTorrents, maxPerPage, pagenum, "search_page"}
|
||||
searchForm := SearchForm{searchQuery, stat, cat, sort, order}
|
||||
htv := HomeTemplateVariables{b, getAllCategories(false), searchForm, navigationTorrents, r.URL, mux.CurrentRoute(r)}
|
||||
htv := HomeTemplateVariables{b, torrentService.GetAllCategories(false), searchForm, navigationTorrents, r.URL, mux.CurrentRoute(r)}
|
||||
|
||||
err := templates.ExecuteTemplate(w, "index.html", htv)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
}
|
||||
func safe(s string) template.URL {
|
||||
return template.URL(s)
|
||||
}
|
||||
|
||||
func faqHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var templates = template.Must(template.New("FAQ").Funcs(funcMap).ParseFiles("templates/index.html", "templates/FAQ.html"))
|
||||
templates.ParseGlob("templates/_*.html") // common
|
||||
err := templates.ExecuteTemplate(w, "index.html", FaqTemplateVariables{Navigation{}, NewSearchForm(), r.URL, mux.CurrentRoute(r)})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
|
@ -199,7 +141,7 @@ func rssHandler(w http.ResponseWriter, r *http.Request) {
|
|||
// db params url
|
||||
//maxPerPage := 50 // default Value maxPerPage
|
||||
|
||||
torrents := getFeeds()
|
||||
torrents := torrentService.GetFeeds()
|
||||
created := time.Now().String()
|
||||
if len(torrents) > 0 {
|
||||
created = torrents[0].Timestamp
|
||||
|
@ -240,12 +182,11 @@ func rssHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
func viewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var templates = template.Must(template.ParseFiles("templates/index.html", "templates/view.html"))
|
||||
templates.ParseGlob("templates/_*.html") // common
|
||||
vars := mux.Vars(r)
|
||||
id := vars["id"]
|
||||
|
||||
torrent, err := getTorrentById(id)
|
||||
b := torrent.toJson()
|
||||
torrent, err := torrentService.GetTorrentById(id)
|
||||
b := torrent.ToJson()
|
||||
|
||||
htv := ViewTemplateVariables{b, NewSearchForm(), Navigation{}, r.URL, mux.CurrentRoute(r)}
|
||||
|
||||
|
@ -257,7 +198,6 @@ func viewHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func rootHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var templates = template.Must(template.New("home").Funcs(funcMap).ParseFiles("templates/index.html", "templates/home.html"))
|
||||
templates.ParseGlob("templates/_*.html") // common
|
||||
vars := mux.Vars(r)
|
||||
page := vars["page"]
|
||||
|
||||
|
@ -273,16 +213,16 @@ func rootHandler(w http.ResponseWriter, r *http.Request) {
|
|||
pagenum = 1
|
||||
}
|
||||
|
||||
b := []TorrentsJson{}
|
||||
torrents, nbTorrents := getAllTorrents(maxPerPage, maxPerPage*(pagenum-1))
|
||||
b := []model.TorrentsJson{}
|
||||
torrents, nbTorrents := torrentService.GetAllTorrents(maxPerPage, maxPerPage*(pagenum-1))
|
||||
|
||||
for i, _ := range torrents {
|
||||
res := torrents[i].toJson()
|
||||
res := torrents[i].ToJson()
|
||||
b = append(b, res)
|
||||
}
|
||||
|
||||
navigationTorrents := Navigation{nbTorrents, maxPerPage, pagenum, "search_page"}
|
||||
htv := HomeTemplateVariables{b, getAllCategories(false), NewSearchForm(), navigationTorrents, r.URL, mux.CurrentRoute(r)}
|
||||
htv := HomeTemplateVariables{b, torrentService.GetAllCategories(false), NewSearchForm(), navigationTorrents, r.URL, mux.CurrentRoute(r)}
|
||||
|
||||
err := templates.ExecuteTemplate(w, "index.html", htv)
|
||||
if err != nil {
|
||||
|
@ -293,7 +233,6 @@ func rootHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
func main() {
|
||||
|
||||
db = getDBHandle()
|
||||
router = mux.NewRouter()
|
||||
|
||||
cssHandler := http.FileServer(http.Dir("./css/"))
|
||||
|
@ -324,5 +263,5 @@ func main() {
|
|||
}
|
||||
|
||||
err := srv.ListenAndServe()
|
||||
checkErr(err)
|
||||
}
|
||||
log.CheckError(err)
|
||||
}
|
122
model/torrent.go
Fichier normal
122
model/torrent.go
Fichier normal
|
@ -0,0 +1,122 @@
|
|||
package model
|
||||
|
||||
import (
|
||||
"github.com/ewhal/nyaa/util"
|
||||
"github.com/ewhal/nyaa/config"
|
||||
|
||||
"html"
|
||||
"html/template"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Feed struct {
|
||||
Id int
|
||||
Name string
|
||||
Hash string
|
||||
Magnet string
|
||||
Timestamp string
|
||||
}
|
||||
|
||||
type Categories struct {
|
||||
Id int `gorm:"column:category_id"`
|
||||
Name string `gorm:"column:category_name"`
|
||||
Torrents []Torrents `gorm:"ForeignKey:category_id;AssociationForeignKey:category_id"`
|
||||
Sub_Categories []Sub_Categories `gorm:"ForeignKey:parent_id;AssociationForeignKey:category_id"`
|
||||
}
|
||||
|
||||
type Sub_Categories struct {
|
||||
Id int `gorm:"column:sub_category_id"`
|
||||
Name string `gorm:"column:Sub_category_name"`
|
||||
Parent_id int `gorm:"column:parent_id"`
|
||||
Torrents []Torrents `gorm:"ForeignKey:sub_category_id;AssociationForeignKey:sub_category_id"`
|
||||
}
|
||||
|
||||
type Statuses struct {
|
||||
Status_id int
|
||||
Status_name string
|
||||
Torrents []Torrents `gorm:"ForeignKey:status_id;AssociationForeignKey:status_id"`
|
||||
}
|
||||
|
||||
type Torrents struct {
|
||||
Id int `gorm:"column:torrent_id"`
|
||||
Name string `gorm:"column:torrent_name"`
|
||||
Category_id int `gorm:"column:category_id"`
|
||||
Sub_category_id int `gorm:"column:sub_category_id"`
|
||||
Status int `gorm:"column:status_id"`
|
||||
Hash string `gorm:"column:torrent_hash"`
|
||||
Date int64 `gorm:"column:date"`
|
||||
Downloads int `gorm:"column:downloads"`
|
||||
Filesize string `gorm:"column:filesize"`
|
||||
Description []byte `gorm:"column:description"`
|
||||
Statuses Statuses `gorm:"ForeignKey:status_id;AssociationForeignKey:status_id"`
|
||||
Categories Categories `gorm:"ForeignKey:category_id;AssociationForeignKey:category_id"`
|
||||
Sub_Categories Sub_Categories `gorm:"ForeignKey:sub_category_id;AssociationForeignKey:sub_category_id"`
|
||||
}
|
||||
|
||||
/* We need JSON Object instead because of Magnet URL that is not in the database but generated dynamically
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
JSON Models Oject
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
type CategoryJson struct {
|
||||
Id string `json: "id"`
|
||||
Name string `json: "category"`
|
||||
Torrents []TorrentsJson `json: "torrents"`
|
||||
QueryRecordCount int `json: "queryRecordCount"`
|
||||
TotalRecordCount int `json: "totalRecordCount"`
|
||||
}
|
||||
|
||||
type SubCategoryJson struct {
|
||||
Id string `json: "id"`
|
||||
Name string `json: "category"`
|
||||
}
|
||||
|
||||
type TorrentsJson struct {
|
||||
Id string `json: "id"` // Is there a need to put the ID?
|
||||
Name string `json: "name"`
|
||||
Status int `json: "status"`
|
||||
Hash string `json: "hash"`
|
||||
Date string `json: "date"`
|
||||
Filesize string `json: "filesize"`
|
||||
Description template.HTML `json: "description"`
|
||||
Sub_Category SubCategoryJson `json: "sub_category"`
|
||||
Category CategoryJson `json: "category"`
|
||||
Magnet template.URL `json: "magnet"`
|
||||
}
|
||||
|
||||
|
||||
/* Model Conversion to Json */
|
||||
|
||||
func (t *Torrents) ToJson() TorrentsJson {
|
||||
magnet := "magnet:?xt=urn:btih:" + strings.TrimSpace(t.Hash) + "&dn=" + t.Name + config.Trackers
|
||||
res := TorrentsJson{
|
||||
Id: strconv.Itoa(t.Id),
|
||||
Name: html.UnescapeString(t.Name),
|
||||
Status: t.Status,
|
||||
Hash: t.Hash,
|
||||
Date: time.Unix(t.Date, 0).Format(time.RFC3339),
|
||||
Filesize: t.Filesize,
|
||||
Description: template.HTML(util.UnZlib(t.Description)),
|
||||
Sub_Category: t.Sub_Categories.ToJson(),
|
||||
Category: t.Categories.ToJson(),
|
||||
Magnet: util.Safe(magnet)}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *Sub_Categories) ToJson() SubCategoryJson {
|
||||
return SubCategoryJson{
|
||||
Id: strconv.Itoa(c.Id),
|
||||
Name: html.UnescapeString(c.Name)}
|
||||
}
|
||||
|
||||
func (c *Categories) ToJson() CategoryJson {
|
||||
return CategoryJson{
|
||||
Id: strconv.Itoa(c.Id),
|
||||
Name: html.UnescapeString(c.Name)}
|
||||
}
|
||||
|
||||
/* Complete the functions when necessary... */
|
238
models.go
238
models.go
|
@ -1,238 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/jinzhu/gorm"
|
||||
"html"
|
||||
"html/template"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Feed struct {
|
||||
Id int
|
||||
Name string
|
||||
Hash string
|
||||
Magnet string
|
||||
Timestamp string
|
||||
}
|
||||
|
||||
type Categories struct {
|
||||
Id int `gorm:"column:category_id"`
|
||||
Name string `gorm:"column:category_name"`
|
||||
Torrents []Torrents `gorm:"ForeignKey:category_id;AssociationForeignKey:category_id"`
|
||||
Sub_Categories []Sub_Categories `gorm:"ForeignKey:parent_id;AssociationForeignKey:category_id"`
|
||||
}
|
||||
|
||||
type Sub_Categories struct {
|
||||
Id int `gorm:"column:sub_category_id"`
|
||||
Name string `gorm:"column:Sub_category_name"`
|
||||
Parent_id int `gorm:"column:parent_id"`
|
||||
Torrents []Torrents `gorm:"ForeignKey:sub_category_id;AssociationForeignKey:sub_category_id"`
|
||||
}
|
||||
|
||||
type Statuses struct {
|
||||
Status_id int
|
||||
Status_name string
|
||||
Torrents []Torrents `gorm:"ForeignKey:status_id;AssociationForeignKey:status_id"`
|
||||
}
|
||||
|
||||
type Torrents struct {
|
||||
Id int `gorm:"column:torrent_id"`
|
||||
Name string `gorm:"column:torrent_name"`
|
||||
Category_id int `gorm:"column:category_id"`
|
||||
Sub_category_id int `gorm:"column:sub_category_id"`
|
||||
Status int `gorm:"column:status_id"`
|
||||
Hash string `gorm:"column:torrent_hash"`
|
||||
Date int64 `gorm:"column:date"`
|
||||
Downloads int `gorm:"column:downloads"`
|
||||
Filesize string `gorm:"column:filesize"`
|
||||
Description []byte `gorm:"column:description"`
|
||||
Statuses Statuses `gorm:"ForeignKey:status_id;AssociationForeignKey:status_id"`
|
||||
Categories Categories `gorm:"ForeignKey:category_id;AssociationForeignKey:category_id"`
|
||||
Sub_Categories Sub_Categories `gorm:"ForeignKey:sub_category_id;AssociationForeignKey:sub_category_id"`
|
||||
}
|
||||
|
||||
/* We need JSON Object instead because of Magnet URL that is not in the database but generated dynamically
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
JSON Models Oject
|
||||
--------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
type CategoryJson struct {
|
||||
Id string `json: "id"`
|
||||
Name string `json: "category"`
|
||||
Torrents []TorrentsJson `json: "torrents"`
|
||||
QueryRecordCount int `json: "queryRecordCount"`
|
||||
TotalRecordCount int `json: "totalRecordCount"`
|
||||
}
|
||||
|
||||
type SubCategoryJson struct {
|
||||
Id string `json: "id"`
|
||||
Name string `json: "category"`
|
||||
}
|
||||
|
||||
type TorrentsJson struct {
|
||||
Id string `json: "id"` // Is there a need to put the ID?
|
||||
Name string `json: "name"`
|
||||
Status int `json: "status"`
|
||||
Hash string `json: "hash"`
|
||||
Date string `json: "date"`
|
||||
Filesize string `json: "filesize"`
|
||||
Description template.HTML `json: "description"`
|
||||
Sub_Category SubCategoryJson `json: "sub_category"`
|
||||
Category CategoryJson `json: "category"`
|
||||
Magnet template.URL `json: "magnet"`
|
||||
}
|
||||
|
||||
type WhereParams struct {
|
||||
conditions string // Ex : name LIKE ? AND category_id LIKE ?
|
||||
params []interface{}
|
||||
}
|
||||
|
||||
/* Function to interact with Models
|
||||
*
|
||||
* Get the torrents with where clause
|
||||
*
|
||||
*/
|
||||
|
||||
// don't need raw SQL once we get MySQL
|
||||
func getFeeds() []Feed {
|
||||
var result []Feed
|
||||
rows, err := db.DB().
|
||||
Query(
|
||||
"SELECT `torrent_id` AS `id`, `torrent_name` AS `name`, `torrent_hash` AS `hash`, `timestamp` FROM `torrents` " +
|
||||
"ORDER BY `timestamp` desc LIMIT 50")
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
item := Feed{}
|
||||
rows.Scan(&item.Id, &item.Name, &item.Hash, &item.Timestamp)
|
||||
magnet := "magnet:?xt=urn:btih:" + strings.TrimSpace(item.Hash) + "&dn=" + item.Name + trackers
|
||||
item.Magnet = magnet
|
||||
// memory hog
|
||||
result = append(result, item)
|
||||
}
|
||||
rows.Close()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func getTorrentById(id string) (Torrents, error) {
|
||||
var torrent Torrents
|
||||
|
||||
if db.Where("torrent_id = ?", id).Find(&torrent).RecordNotFound() {
|
||||
return torrent, errors.New("Article is not found.")
|
||||
}
|
||||
|
||||
return torrent, nil
|
||||
}
|
||||
|
||||
func getTorrentsOrderBy(parameters *WhereParams, orderBy string, limit int, offset int) ([]Torrents, int) {
|
||||
var torrents []Torrents
|
||||
var dbQuery *gorm.DB
|
||||
var count int
|
||||
conditions := "torrent_hash is not null" //filter out broken entries
|
||||
var params []interface{}
|
||||
if parameters != nil { // if there is where parameters
|
||||
conditions += " AND " + parameters.conditions
|
||||
params = parameters.params
|
||||
}
|
||||
db.Model(&torrents).Where(conditions, params...).Count(&count)
|
||||
dbQuery = db.Model(&torrents).Where(conditions, params...)
|
||||
|
||||
if orderBy == "" {
|
||||
orderBy = "torrent_id DESC"
|
||||
} // Default OrderBy
|
||||
if limit != 0 || offset != 0 { // if limits provided
|
||||
dbQuery = dbQuery.Limit(limit).Offset(offset)
|
||||
}
|
||||
dbQuery.Order(orderBy).Preload("Categories").Preload("Sub_Categories").Find(&torrents)
|
||||
return torrents, count
|
||||
|
||||
}
|
||||
|
||||
/* Functions to simplify the get parameters of the main function
|
||||
*
|
||||
* Get Torrents with where parameters and limits, order by default
|
||||
*/
|
||||
func getTorrents(parameters WhereParams, limit int, offset int) ([]Torrents, int) {
|
||||
return getTorrentsOrderBy(¶meters, "", limit, offset)
|
||||
}
|
||||
|
||||
/* Get Torrents with where parameters but no limit and order by default (get all the torrents corresponding in the db)
|
||||
*/
|
||||
func getTorrentsDB(parameters WhereParams) ([]Torrents, int) {
|
||||
return getTorrentsOrderBy(¶meters, "", 0, 0)
|
||||
}
|
||||
|
||||
/* Function to get all torrents
|
||||
*/
|
||||
|
||||
func getAllTorrentsOrderBy(orderBy string, limit int, offset int) ([]Torrents, int) {
|
||||
|
||||
return getTorrentsOrderBy(nil, orderBy, limit, offset)
|
||||
}
|
||||
|
||||
func getAllTorrents(limit int, offset int) ([]Torrents, int) {
|
||||
return getTorrentsOrderBy(nil, "", limit, offset)
|
||||
}
|
||||
|
||||
func getAllTorrentsDB() ([]Torrents, int) {
|
||||
return getTorrentsOrderBy(nil, "", 0, 0)
|
||||
}
|
||||
|
||||
/* Function to get all categories with/without torrents (bool)
|
||||
*/
|
||||
func getAllCategories(populatedWithTorrents bool) []Categories {
|
||||
var categories []Categories
|
||||
if populatedWithTorrents {
|
||||
db.Preload("Torrents").Preload("Sub_Categories").Find(&categories)
|
||||
} else {
|
||||
db.Preload("Sub_Categories").Find(&categories)
|
||||
}
|
||||
return categories
|
||||
}
|
||||
|
||||
func createWhereParams(conditions string, params ...string) WhereParams {
|
||||
whereParams := WhereParams{}
|
||||
whereParams.conditions = conditions
|
||||
for i, _ := range params {
|
||||
whereParams.params = append(whereParams.params, params[i])
|
||||
}
|
||||
|
||||
return whereParams
|
||||
}
|
||||
|
||||
/* Model Conversion to Json */
|
||||
|
||||
func (t *Torrents) toJson() TorrentsJson {
|
||||
magnet := "magnet:?xt=urn:btih:" + strings.TrimSpace(t.Hash) + "&dn=" + t.Name + trackers
|
||||
res := TorrentsJson{
|
||||
Id: strconv.Itoa(t.Id),
|
||||
Name: html.UnescapeString(t.Name),
|
||||
Status: t.Status,
|
||||
Hash: t.Hash,
|
||||
Date: time.Unix(t.Date, 0).Format(time.RFC3339),
|
||||
Filesize: t.Filesize,
|
||||
Description: template.HTML(unZlib(t.Description)),
|
||||
Sub_Category: t.Sub_Categories.toJson(),
|
||||
Category: t.Categories.toJson(),
|
||||
Magnet: safe(magnet)}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (c *Sub_Categories) toJson() SubCategoryJson {
|
||||
return SubCategoryJson{
|
||||
Id: strconv.Itoa(c.Id),
|
||||
Name: html.UnescapeString(c.Name)}
|
||||
}
|
||||
|
||||
func (c *Categories) toJson() CategoryJson {
|
||||
return CategoryJson{
|
||||
Id: strconv.Itoa(c.Id),
|
||||
Name: html.UnescapeString(c.Name)}
|
||||
}
|
||||
|
||||
/* Complete the functions when necessary... */
|
127
service/torrent/torrent.go
Fichier normal
127
service/torrent/torrent.go
Fichier normal
|
@ -0,0 +1,127 @@
|
|||
package torrentService
|
||||
import (
|
||||
"github.com/ewhal/nyaa/db"
|
||||
"github.com/ewhal/nyaa/model"
|
||||
"github.com/ewhal/nyaa/config"
|
||||
"github.com/jinzhu/gorm"
|
||||
"errors"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type WhereParams struct {
|
||||
conditions string // Ex : name LIKE ? AND category_id LIKE ?
|
||||
params []interface{}
|
||||
}
|
||||
|
||||
/* Function to interact with Models
|
||||
*
|
||||
* Get the torrents with where clause
|
||||
*
|
||||
*/
|
||||
|
||||
// don't need raw SQL once we get MySQL
|
||||
func GetFeeds() []model.Feed {
|
||||
var result []model.Feed
|
||||
rows, err := db.ORM.DB().
|
||||
Query(
|
||||
"SELECT `torrent_id` AS `id`, `torrent_name` AS `name`, `torrent_hash` AS `hash`, `timestamp` FROM `torrents` " +
|
||||
"ORDER BY `timestamp` desc LIMIT 50")
|
||||
if err == nil {
|
||||
for rows.Next() {
|
||||
item := model.Feed{}
|
||||
rows.Scan(&item.Id, &item.Name, &item.Hash, &item.Timestamp)
|
||||
magnet := "magnet:?xt=urn:btih:" + strings.TrimSpace(item.Hash) + "&dn=" + item.Name + config.Trackers
|
||||
item.Magnet = magnet
|
||||
// memory hog
|
||||
result = append(result, item)
|
||||
}
|
||||
rows.Close()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func GetTorrentById(id string) (model.Torrents, error) {
|
||||
var torrent model.Torrents
|
||||
|
||||
if db.ORM.Where("torrent_id = ?", id).Find(&torrent).RecordNotFound() {
|
||||
return torrent, errors.New("Article is not found.")
|
||||
}
|
||||
|
||||
return torrent, nil
|
||||
}
|
||||
|
||||
func GetTorrentsOrderBy(parameters *WhereParams, orderBy string, limit int, offset int) ([]model.Torrents, int) {
|
||||
var torrents []model.Torrents
|
||||
var dbQuery *gorm.DB
|
||||
var count int
|
||||
conditions := "torrent_hash is not null" //filter out broken entries
|
||||
var params []interface{}
|
||||
if parameters != nil { // if there is where parameters
|
||||
conditions += " AND " + parameters.conditions
|
||||
params = parameters.params
|
||||
}
|
||||
db.ORM.Model(&torrents).Where(conditions, params...).Count(&count)
|
||||
dbQuery = db.ORM.Model(&torrents).Where(conditions, params...)
|
||||
|
||||
if orderBy == "" {
|
||||
orderBy = "torrent_id DESC"
|
||||
} // Default OrderBy
|
||||
if limit != 0 || offset != 0 { // if limits provided
|
||||
dbQuery = dbQuery.Limit(limit).Offset(offset)
|
||||
}
|
||||
dbQuery.Order(orderBy).Preload("Categories").Preload("Sub_Categories").Find(&torrents)
|
||||
return torrents, count
|
||||
|
||||
}
|
||||
|
||||
/* Functions to simplify the get parameters of the main function
|
||||
*
|
||||
* Get Torrents with where parameters and limits, order by default
|
||||
*/
|
||||
func GetTorrents(parameters WhereParams, limit int, offset int) ([]model.Torrents, int) {
|
||||
return GetTorrentsOrderBy(¶meters, "", limit, offset)
|
||||
}
|
||||
|
||||
/* Get Torrents with where parameters but no limit and order by default (get all the torrents corresponding in the db)
|
||||
*/
|
||||
func GetTorrentsDB(parameters WhereParams) ([]model.Torrents, int) {
|
||||
return GetTorrentsOrderBy(¶meters, "", 0, 0)
|
||||
}
|
||||
|
||||
/* Function to get all torrents
|
||||
*/
|
||||
|
||||
func GetAllTorrentsOrderBy(orderBy string, limit int, offset int) ([]model.Torrents, int) {
|
||||
|
||||
return GetTorrentsOrderBy(nil, orderBy, limit, offset)
|
||||
}
|
||||
|
||||
func GetAllTorrents(limit int, offset int) ([]model.Torrents, int) {
|
||||
return GetTorrentsOrderBy(nil, "", limit, offset)
|
||||
}
|
||||
|
||||
func GetAllTorrentsDB() ([]model.Torrents, int) {
|
||||
return GetTorrentsOrderBy(nil, "", 0, 0)
|
||||
}
|
||||
|
||||
/* Function to get all categories with/without torrents (bool)
|
||||
*/
|
||||
func GetAllCategories(populatedWithTorrents bool) []model.Categories {
|
||||
var categories []model.Categories
|
||||
if populatedWithTorrents {
|
||||
db.ORM.Preload("Torrents").Preload("Sub_Categories").Find(&categories)
|
||||
} else {
|
||||
db.ORM.Preload("Sub_Categories").Find(&categories)
|
||||
}
|
||||
return categories
|
||||
}
|
||||
|
||||
func CreateWhereParams(conditions string, params ...string) WhereParams {
|
||||
whereParams := WhereParams{}
|
||||
whereParams.conditions = conditions
|
||||
for i, _ := range params {
|
||||
whereParams.params = append(whereParams.params, params[i])
|
||||
}
|
||||
|
||||
return whereParams
|
||||
}
|
|
@ -2,6 +2,7 @@ package main
|
|||
|
||||
import (
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/ewhal/nyaa/model"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
|
@ -19,7 +20,7 @@ type FaqTemplateVariables struct {
|
|||
}
|
||||
|
||||
type ViewTemplateVariables struct {
|
||||
Torrent TorrentsJson
|
||||
Torrent model.TorrentsJson
|
||||
Search SearchForm
|
||||
Navigation Navigation
|
||||
URL *url.URL // For parsing Url in templates
|
||||
|
@ -27,8 +28,8 @@ type ViewTemplateVariables struct {
|
|||
}
|
||||
|
||||
type HomeTemplateVariables struct {
|
||||
ListTorrents []TorrentsJson
|
||||
ListCategories []Categories
|
||||
ListTorrents []model.TorrentsJson
|
||||
ListCategories []model.Categories
|
||||
Search SearchForm
|
||||
Navigation Navigation
|
||||
URL *url.URL // For parsing Url in templates
|
||||
|
|
29
util/log/error.go
Fichier normal
29
util/log/error.go
Fichier normal
|
@ -0,0 +1,29 @@
|
|||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/Sirupsen/logrus"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// CheckError check error and return true if error is nil and return false if error is not nil.
|
||||
func CheckError(err error) bool {
|
||||
return CheckErrorWithMessage(err, "")
|
||||
}
|
||||
|
||||
// CheckErrorWithMessage check error with message and log messages with stack. And then return true if error is nil and return false if error is not nil.
|
||||
func CheckErrorWithMessage(err error, msg string, args ...interface{}) bool {
|
||||
if err != nil {
|
||||
var stack [4096]byte
|
||||
runtime.Stack(stack[:], false)
|
||||
// logrus.Errorf(msg, args)
|
||||
if len(args) == 0 {
|
||||
logrus.Error(msg + fmt.Sprintf("%q\n%s\n", err, stack[:]))
|
||||
} else {
|
||||
logrus.Error(fmt.Sprintf(msg, args...) + fmt.Sprintf("%q\n%s\n", err, stack[:]))
|
||||
}
|
||||
// logrus.Printf(msg+"\n%q\n%s\n",args, err, stack[:])
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
7
util/safe.go
Fichier normal
7
util/safe.go
Fichier normal
|
@ -0,0 +1,7 @@
|
|||
package util
|
||||
|
||||
import "html/template"
|
||||
|
||||
func Safe(s string) template.URL {
|
||||
return template.URL(s)
|
||||
}
|
22
util/unzlib.go
Fichier normal
22
util/unzlib.go
Fichier normal
|
@ -0,0 +1,22 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"github.com/ewhal/nyaa/util/log"
|
||||
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
func UnZlib(description []byte) string {
|
||||
if len(description) > 0 {
|
||||
b := bytes.NewReader(description)
|
||||
z, err := zlib.NewReader(b)
|
||||
log.CheckError(err)
|
||||
defer z.Close()
|
||||
p, err := ioutil.ReadAll(z)
|
||||
log.CheckError(err)
|
||||
return string(p)
|
||||
}
|
||||
return ""
|
||||
}
|
Référencer dans un nouveau ticket