New database squema
The collection new is removed, now the books have a field "active" set to true if the book was aproved. For update the database: db.books.update({}, {$set: {active: true}}, true, true)
This commit is contained in:
parent
a9749e7136
commit
840fd3ed47
7 changed files with 366 additions and 346 deletions
261
admin.go
261
admin.go
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"labix.org/v2/mgo"
|
||||
"labix.org/v2/mgo/bson"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -10,55 +9,51 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
func deleteHandler(coll *mgo.Collection, url string) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// cutre hack: /delete/ and /delnew/ have the same lenght:
|
||||
id := bson.ObjectIdHex(r.URL.Path[len("/delete/"):])
|
||||
books, _, err := GetBook(coll, bson.M{"_id": id})
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
book := books[0]
|
||||
if book.Cover != "" {
|
||||
os.RemoveAll(book.Cover[1:])
|
||||
}
|
||||
if book.CoverSmall != "" {
|
||||
os.RemoveAll(book.CoverSmall[1:])
|
||||
}
|
||||
os.RemoveAll(book.Path)
|
||||
coll.Remove(bson.M{"_id": id})
|
||||
sess.Notify("Removed book!", "The book '"+book.Title+"' it's completly removed", "success")
|
||||
sess.Save(w, r)
|
||||
http.Redirect(w, r, url, 307)
|
||||
func deleteHandler(w http.ResponseWriter, r *http.Request) {
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// cutre hack: /delete/ and /delnew/ have the same lenght:
|
||||
id := bson.ObjectIdHex(r.URL.Path[len("/delete/"):])
|
||||
books, _, err := db.GetBooks(bson.M{"_id": id})
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
book := books[0]
|
||||
if book.Cover != "" {
|
||||
os.RemoveAll(book.Cover[1:])
|
||||
}
|
||||
if book.CoverSmall != "" {
|
||||
os.RemoveAll(book.CoverSmall[1:])
|
||||
}
|
||||
os.RemoveAll(book.Path)
|
||||
db.RemoveBook(id)
|
||||
sess.Notify("Removed book!", "The book '"+book.Title+"' it's completly removed", "success")
|
||||
sess.Save(w, r)
|
||||
http.Redirect(w, r, "/", 307) //FIXME: if new return to /new/
|
||||
}
|
||||
|
||||
func editHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
id := bson.ObjectIdHex(r.URL.Path[len("/edit/"):])
|
||||
books, _, err := GetBook(coll, bson.M{"_id": id})
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
var data bookData
|
||||
data.Book = books[0]
|
||||
data.S = GetStatus(w, r)
|
||||
loadTemplate(w, "edit", data)
|
||||
func editHandler(w http.ResponseWriter, r *http.Request) {
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
id := bson.ObjectIdHex(r.URL.Path[len("/edit/"):])
|
||||
books, _, err := db.GetBooks(bson.M{"_id": id})
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
var data bookData
|
||||
data.Book = books[0]
|
||||
data.S = GetStatus(w, r)
|
||||
loadTemplate(w, "edit", data)
|
||||
}
|
||||
|
||||
func cleanEmptyStr(s []string) []string {
|
||||
|
@ -71,45 +66,43 @@ func cleanEmptyStr(s []string) []string {
|
|||
return res
|
||||
}
|
||||
|
||||
func saveHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
idStr := r.URL.Path[len("/save/"):]
|
||||
id := bson.ObjectIdHex(idStr)
|
||||
title := r.FormValue("title")
|
||||
publisher := r.FormValue("publisher")
|
||||
date := r.FormValue("date")
|
||||
description := r.FormValue("description")
|
||||
author := cleanEmptyStr(r.Form["author"])
|
||||
subject := cleanEmptyStr(r.Form["subject"])
|
||||
lang := cleanEmptyStr(r.Form["lang"])
|
||||
book := map[string]interface{}{"title": title,
|
||||
"publisher": publisher,
|
||||
"date": date,
|
||||
"description": description,
|
||||
"author": author,
|
||||
"subject": subject,
|
||||
"lang": lang}
|
||||
book["keywords"] = keywords(book)
|
||||
err := coll.Update(bson.M{"_id": id}, bson.M{"$set": book})
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
sess.Notify("Book Modified!", "", "success")
|
||||
sess.Save(w, r)
|
||||
http.Redirect(w, r, "/book/"+idStr, 307)
|
||||
func saveHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "POST" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
idStr := r.URL.Path[len("/save/"):]
|
||||
id := bson.ObjectIdHex(idStr)
|
||||
title := r.FormValue("title")
|
||||
publisher := r.FormValue("publisher")
|
||||
date := r.FormValue("date")
|
||||
description := r.FormValue("description")
|
||||
author := cleanEmptyStr(r.Form["author"])
|
||||
subject := cleanEmptyStr(r.Form["subject"])
|
||||
lang := cleanEmptyStr(r.Form["lang"])
|
||||
book := map[string]interface{}{"title": title,
|
||||
"publisher": publisher,
|
||||
"date": date,
|
||||
"description": description,
|
||||
"author": author,
|
||||
"subject": subject,
|
||||
"lang": lang}
|
||||
book["keywords"] = keywords(book)
|
||||
err := db.UpdateBook(id, book)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
sess.Notify("Book Modified!", "", "success")
|
||||
sess.Save(w, r)
|
||||
http.Redirect(w, r, "/book/"+idStr, 307)
|
||||
}
|
||||
|
||||
type newBook struct {
|
||||
|
@ -123,31 +116,29 @@ type newData struct {
|
|||
Books []newBook
|
||||
}
|
||||
|
||||
func newHandler(coll *mgo.Collection, booksColl *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if len(r.URL.Path) > len("/new/") {
|
||||
http.ServeFile(w, r, r.URL.Path[1:])
|
||||
return
|
||||
}
|
||||
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
res, num, _ := GetBook(coll, bson.M{})
|
||||
var data newData
|
||||
data.S = GetStatus(w, r)
|
||||
data.Found = num
|
||||
data.Books = make([]newBook, num)
|
||||
for i, b := range res {
|
||||
data.Books[i].B = b
|
||||
_, data.Books[i].TitleFound, _ = GetBook(booksColl, buildQuery("title:" + b.Title), 1)
|
||||
_, data.Books[i].AuthorFound, _ = GetBook(booksColl, buildQuery("author:" + strings.Join(b.Author, " author:")), 1)
|
||||
}
|
||||
loadTemplate(w, "new", data)
|
||||
func newHandler(w http.ResponseWriter, r *http.Request) {
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if len(r.URL.Path) > len("/new/") {
|
||||
http.ServeFile(w, r, r.URL.Path[1:])
|
||||
return
|
||||
}
|
||||
|
||||
res, num, _ := db.GetNewBooks()
|
||||
var data newData
|
||||
data.S = GetStatus(w, r)
|
||||
data.Found = num
|
||||
data.Books = make([]newBook, num)
|
||||
for i, b := range res {
|
||||
data.Books[i].B = b
|
||||
_, data.Books[i].TitleFound, _ = db.GetBooks(buildQuery("title:" + b.Title), 1)
|
||||
_, data.Books[i].AuthorFound, _ = db.GetBooks(buildQuery("author:" + strings.Join(b.Author, " author:")), 1)
|
||||
}
|
||||
loadTemplate(w, "new", data)
|
||||
}
|
||||
|
||||
func ValidFileName(path string, title string, extension string) string {
|
||||
|
@ -162,34 +153,30 @@ func ValidFileName(path string, title string, extension string) string {
|
|||
return file
|
||||
}
|
||||
|
||||
func storeHandler(newColl, coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
id := bson.ObjectIdHex(r.URL.Path[len("/store/"):])
|
||||
var book bson.M
|
||||
err := newColl.Find(bson.M{"_id": id}).One(&book)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
title, _ := book["title"].(string)
|
||||
path := ValidFileName(BOOKS_PATH + title[:1], title, ".epub")
|
||||
|
||||
oldPath, _ := book["path"].(string)
|
||||
os.Mkdir(BOOKS_PATH+title[:1], os.ModePerm)
|
||||
cmd := exec.Command("mv", oldPath, path)
|
||||
cmd.Run()
|
||||
book["path"] = path
|
||||
coll.Insert(book)
|
||||
newColl.Remove(bson.M{"_id": id})
|
||||
sess.Notify("Store book!", "The book '"+title+"' it's stored for public download", "success")
|
||||
sess.Save(w, r)
|
||||
http.Redirect(w, r, "/new/", 307)
|
||||
func storeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
id := bson.ObjectIdHex(r.URL.Path[len("/store/"):])
|
||||
books, _, err := db.GetBooks(bson.M{"_id": id})
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
book := books[0]
|
||||
|
||||
title := book.Title
|
||||
path := ValidFileName(BOOKS_PATH + title[:1], title, ".epub")
|
||||
|
||||
oldPath := book.Path
|
||||
os.Mkdir(BOOKS_PATH+title[:1], os.ModePerm)
|
||||
cmd := exec.Command("mv", oldPath, path)
|
||||
cmd.Run()
|
||||
db.UpdateBook(id, bson.M{"active": true, "path": path})
|
||||
sess.Notify("Store book!", "The book '"+title+"' it's stored for public download", "success")
|
||||
sess.Save(w, r)
|
||||
http.Redirect(w, r, "/new/", 307)
|
||||
}
|
||||
|
|
76
database.go
76
database.go
|
@ -1,11 +1,15 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"labix.org/v2/mgo"
|
||||
"labix.org/v2/mgo/bson"
|
||||
"sort"
|
||||
)
|
||||
|
||||
var db *DB
|
||||
|
||||
|
||||
type Book struct {
|
||||
Id string `bson:"_id"`
|
||||
Title string
|
||||
|
@ -26,14 +30,60 @@ type Book struct {
|
|||
Path string
|
||||
Cover string
|
||||
CoverSmall string
|
||||
Active bool
|
||||
Keywords []string
|
||||
}
|
||||
|
||||
type DB struct {
|
||||
session *mgo.Session
|
||||
books *mgo.Collection
|
||||
user *mgo.Collection
|
||||
}
|
||||
|
||||
func initDB() *DB {
|
||||
var err error
|
||||
d := new(DB)
|
||||
d.session, err = mgo.Dial(DB_IP)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
d.books = d.session.DB(DB_NAME).C(BOOKS_COLL)
|
||||
d.user = d.session.DB(DB_NAME).C(USERS_COLL)
|
||||
return d
|
||||
}
|
||||
|
||||
func (d *DB) Close() {
|
||||
d.session.Close()
|
||||
}
|
||||
|
||||
func (d *DB) UserValid(user string, pass string) bool {
|
||||
h := md5.New()
|
||||
hash := h.Sum(([]byte)(PASS_SALT + pass))
|
||||
n, err := d.user.Find(bson.M{"user": user, "pass": hash}).Count()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n != 0
|
||||
}
|
||||
|
||||
func (d *DB) InsertBook(book interface{}) error {
|
||||
return d.books.Insert(book)
|
||||
}
|
||||
|
||||
func (d *DB) RemoveBook(id bson.ObjectId) error {
|
||||
return d.books.Remove(bson.M{"_id": id})
|
||||
}
|
||||
|
||||
func (d *DB) UpdateBook(id bson.ObjectId, book interface{}) error {
|
||||
return d.books.Update(bson.M{"_id": id}, bson.M{"$set": book})
|
||||
}
|
||||
|
||||
/* optional parameters: length and start index
|
||||
*
|
||||
* Returns: list of books, number found and err
|
||||
*/
|
||||
func GetBook(coll *mgo.Collection, query bson.M, r ...int) (books []Book, num int, err error) {
|
||||
func (d *DB) GetBooks(query bson.M, r ...int) (books []Book, num int, err error) {
|
||||
var start, length int
|
||||
if len(r) > 0 {
|
||||
length = r[0]
|
||||
|
@ -41,7 +91,7 @@ func GetBook(coll *mgo.Collection, query bson.M, r ...int) (books []Book, num in
|
|||
start = r[1]
|
||||
}
|
||||
}
|
||||
q := coll.Find(query).Sort("-_id")
|
||||
q := d.books.Find(query).Sort("-_id")
|
||||
num, err = q.Count()
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -58,7 +108,23 @@ func GetBook(coll *mgo.Collection, query bson.M, r ...int) (books []Book, num in
|
|||
books[i].Id = bson.ObjectId(b.Id).Hex()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/* Returns: list of books, number found and err
|
||||
*/
|
||||
func (d *DB) GetNewBooks()(books []Book, num int, err error) {
|
||||
var q *mgo.Query
|
||||
q = d.books.Find(bson.M{"$nor": []bson.M{{"active": true}}}).Sort("-_id")
|
||||
num, err = q.Count()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = q.All(&books)
|
||||
for i, b := range books {
|
||||
books[i].Id = bson.ObjectId(b.Id).Hex()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type tagsList []struct {
|
||||
|
@ -78,11 +144,11 @@ func (t tagsList) Swap(i, j int) {
|
|||
t[j] = aux
|
||||
}
|
||||
|
||||
func GetTags(coll *mgo.Collection) (tagsList, error) {
|
||||
func (d *DB) GetTags() (tagsList, error) {
|
||||
// TODO: cache the tags
|
||||
var mr mgo.MapReduce
|
||||
mr.Map = "function() { " +
|
||||
"this.subject.forEach(function(s) { emit(s, 1); });" +
|
||||
"if (this.active) { this.subject.forEach(function(s) { emit(s, 1); }); }" +
|
||||
"}"
|
||||
mr.Reduce = "function(tag, vals) { " +
|
||||
"var count = 0;" +
|
||||
|
@ -90,7 +156,7 @@ func GetTags(coll *mgo.Collection) (tagsList, error) {
|
|||
"return count;" +
|
||||
"}"
|
||||
var result tagsList
|
||||
_, err := coll.Find(nil).MapReduce(&mr, &result)
|
||||
_, err := d.books.Find(nil).MapReduce(&mr, &result)
|
||||
if err == nil {
|
||||
sort.Sort(result)
|
||||
}
|
||||
|
|
113
reader.go
113
reader.go
|
@ -2,7 +2,6 @@ package main
|
|||
|
||||
import (
|
||||
"git.gitorious.org/go-pkg/epub.git"
|
||||
"labix.org/v2/mgo"
|
||||
"labix.org/v2/mgo/bson"
|
||||
"net/http"
|
||||
"regexp"
|
||||
|
@ -116,72 +115,62 @@ func chapterList(e *epub.Epub, file string, id string, base string) (string, str
|
|||
return next, prev, chapters
|
||||
}
|
||||
|
||||
func readHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
base, id, file := parseUrl(r.URL.Path)
|
||||
if base == "/readnew/" {
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
books, _, err := GetBook(coll, bson.M{"_id": bson.ObjectIdHex(id)})
|
||||
if err != nil || len(books) == 0 {
|
||||
func readHandler(w http.ResponseWriter, r *http.Request) {
|
||||
base, id, file := parseUrl(r.URL.Path)
|
||||
books, _, err := db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)})
|
||||
if err != nil || len(books) == 0 {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
var data readData
|
||||
data.Book = books[0]
|
||||
if ! data.Book.Active {
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
book := books[0]
|
||||
e, _ := epub.Open(book.Path, 0)
|
||||
defer e.Close()
|
||||
if file == "" {
|
||||
it := e.Iterator(epub.EITERATOR_LINEAR)
|
||||
defer it.Close()
|
||||
http.Redirect(w, r, base+id+"/"+it.CurrUrl(), 307)
|
||||
return
|
||||
}
|
||||
|
||||
var data readData
|
||||
data.S = GetStatus(w, r)
|
||||
data.Book = book
|
||||
data.Next, data.Prev, data.Chapters = chapterList(e, file, id, base)
|
||||
if base == "/readnew/" {
|
||||
data.Back = "/new/"
|
||||
} else {
|
||||
data.Back = "/book/" + id
|
||||
}
|
||||
baseContent := "/content/"
|
||||
if base == "/readnew/" {
|
||||
baseContent = "/contentnew/"
|
||||
}
|
||||
data.Content = genLink(id, baseContent, file)
|
||||
loadTemplate(w, "read", data)
|
||||
data.Back = "/new/"
|
||||
} else {
|
||||
data.Back = "/book/" + id
|
||||
}
|
||||
e, _ := epub.Open(data.Book.Path, 0)
|
||||
defer e.Close()
|
||||
if file == "" {
|
||||
it := e.Iterator(epub.EITERATOR_LINEAR)
|
||||
defer it.Close()
|
||||
http.Redirect(w, r, base+id+"/"+it.CurrUrl(), 307)
|
||||
return
|
||||
}
|
||||
|
||||
data.S = GetStatus(w, r)
|
||||
data.Next, data.Prev, data.Chapters = chapterList(e, file, id, base)
|
||||
data.Content = genLink(id, "/content/", file)
|
||||
loadTemplate(w, "read", data)
|
||||
}
|
||||
|
||||
func contentHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
base, id, file := parseUrl(r.URL.Path)
|
||||
if base == "/contentnew/" {
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
books, _, err := GetBook(coll, bson.M{"_id": bson.ObjectIdHex(id)})
|
||||
if err != nil || len(books) == 0 {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
book := books[0]
|
||||
e, _ := epub.Open(book.Path, 0)
|
||||
defer e.Close()
|
||||
if file == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(e.Data(file))
|
||||
func contentHandler(w http.ResponseWriter, r *http.Request) {
|
||||
_, id, file := parseUrl(r.URL.Path)
|
||||
books, _, err := db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)})
|
||||
if err != nil || len(books) == 0 {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
book := books[0]
|
||||
if ! book.Active {
|
||||
sess := GetSession(r)
|
||||
if sess.User == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
e, _ := epub.Open(book.Path, 0)
|
||||
defer e.Close()
|
||||
if file == "" {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(e.Data(file))
|
||||
}
|
||||
|
|
61
search.go
61
search.go
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"labix.org/v2/mgo"
|
||||
"labix.org/v2/mgo/bson"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -10,7 +9,7 @@ import (
|
|||
|
||||
func buildQuery(q string) bson.M {
|
||||
var reg []bson.RegEx
|
||||
query := bson.M{}
|
||||
query := bson.M{"active": true}
|
||||
words := strings.Split(q, " ")
|
||||
for _, w := range words {
|
||||
tag := strings.SplitN(w, ":", 2)
|
||||
|
@ -35,35 +34,33 @@ type searchData struct {
|
|||
Prev string
|
||||
}
|
||||
|
||||
func searchHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
req := strings.Join(r.Form["q"], " ")
|
||||
page := 0
|
||||
if len(r.Form["p"]) != 0 {
|
||||
page, err = strconv.Atoi(r.Form["p"][0])
|
||||
if err != nil {
|
||||
page = 0
|
||||
}
|
||||
}
|
||||
res, num, _ := GetBook(coll, buildQuery(req), SEARCH_ITEMS_PAGE, page*SEARCH_ITEMS_PAGE)
|
||||
|
||||
var data searchData
|
||||
data.S = GetStatus(w, r)
|
||||
data.S.Search = req
|
||||
data.Books = res
|
||||
data.Found = num
|
||||
data.Page = page + 1
|
||||
if num > (page+1)*SEARCH_ITEMS_PAGE {
|
||||
data.Next = "/search/?q=" + req + "&p=" + strconv.Itoa(page+1)
|
||||
}
|
||||
if page > 0 {
|
||||
data.Prev = "/search/?q=" + req + "&p=" + strconv.Itoa(page-1)
|
||||
}
|
||||
loadTemplate(w, "search", data)
|
||||
func searchHandler(w http.ResponseWriter, r *http.Request) {
|
||||
err := r.ParseForm()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
req := strings.Join(r.Form["q"], " ")
|
||||
page := 0
|
||||
if len(r.Form["p"]) != 0 {
|
||||
page, err = strconv.Atoi(r.Form["p"][0])
|
||||
if err != nil {
|
||||
page = 0
|
||||
}
|
||||
}
|
||||
res, num, _ := db.GetBooks(buildQuery(req), SEARCH_ITEMS_PAGE, page*SEARCH_ITEMS_PAGE)
|
||||
|
||||
var data searchData
|
||||
data.S = GetStatus(w, r)
|
||||
data.S.Search = req
|
||||
data.Books = res
|
||||
data.Found = num
|
||||
data.Page = page + 1
|
||||
if num > (page+1)*SEARCH_ITEMS_PAGE {
|
||||
data.Next = "/search/?q=" + req + "&p=" + strconv.Itoa(page+1)
|
||||
}
|
||||
if page > 0 {
|
||||
data.Prev = "/search/?q=" + req + "&p=" + strconv.Itoa(page-1)
|
||||
}
|
||||
loadTemplate(w, "search", data)
|
||||
}
|
||||
|
|
|
@ -21,14 +21,15 @@
|
|||
</p>
|
||||
</div>
|
||||
<div class="span2">
|
||||
<div class="row">
|
||||
<p><a href="/readnew/{{.Id}}" class="btn btn-warning pull-right"><i class="icon-eye-open icon-white"></i> read it!</a>
|
||||
<a href="/{{.Path}}" class="btn btn-inverse pull-right"><i class="icon-download-alt icon-white"></i> download</a></p>
|
||||
<div class="row btn-group pull-right">
|
||||
<a href="/store/{{.Id}}" class="btn btn-success"><i class="icon-ok"></i> Save</a>
|
||||
<a href="/edit/{{.Id}}" class="btn btn-primary"><i class="icon-pencil"></i> Edit</a>
|
||||
<a href="/delete/{{.Id}}" class="btn btn-danger"><i class="icon-remove"></i> Delete</a>
|
||||
</div>
|
||||
<div class="row"><p></p></div>
|
||||
<div class="row btn-group pull-right">
|
||||
<a href="/store/{{.Id}}" class="btn btn-success"><i class="icon-ok"></i> Save</a>
|
||||
<a href="/delnew/{{.Id}}" class="btn btn-danger"><i class="icon-remove"></i> Delete</a>
|
||||
<a href="/{{.Path}}" class="btn btn-inverse"><i class="icon-download-alt icon-white"></i> download</a>
|
||||
<a href="/read/{{.Id}}" class="btn btn-warning"><i class="icon-eye-open icon-white"></i> read it!</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
135
trantor.go
135
trantor.go
|
@ -1,8 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"labix.org/v2/mgo"
|
||||
"labix.org/v2/mgo/bson"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -27,25 +25,20 @@ func logoutHandler(w http.ResponseWriter, r *http.Request) {
|
|||
http.Redirect(w, r, "/", 307)
|
||||
}
|
||||
|
||||
func loginHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "POST" {
|
||||
user := r.FormValue("user")
|
||||
pass := r.FormValue("pass")
|
||||
h := md5.New()
|
||||
hash := h.Sum(([]byte)(PASS_SALT + pass))
|
||||
n, _ := coll.Find(bson.M{"user": user, "pass": hash}).Count()
|
||||
sess := GetSession(r)
|
||||
if n != 0 {
|
||||
sess.LogIn(user)
|
||||
sess.Notify("Successful login!", "Welcome "+user, "success")
|
||||
} else {
|
||||
sess.Notify("Invalid login!", "user or password invalid", "error")
|
||||
}
|
||||
sess.Save(w, r)
|
||||
func loginHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "POST" {
|
||||
user := r.FormValue("user")
|
||||
pass := r.FormValue("pass")
|
||||
sess := GetSession(r)
|
||||
if db.UserValid(user, pass) {
|
||||
sess.LogIn(user)
|
||||
sess.Notify("Successful login!", "Welcome "+user, "success")
|
||||
} else {
|
||||
sess.Notify("Invalid login!", "user or password invalid", "error")
|
||||
}
|
||||
http.Redirect(w, r, r.Referer(), 307)
|
||||
sess.Save(w, r)
|
||||
}
|
||||
http.Redirect(w, r, r.Referer(), 307)
|
||||
}
|
||||
|
||||
type bookData struct {
|
||||
|
@ -53,19 +46,17 @@ type bookData struct {
|
|||
Book Book
|
||||
}
|
||||
|
||||
func bookHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var data bookData
|
||||
data.S = GetStatus(w, r)
|
||||
id := bson.ObjectIdHex(r.URL.Path[len("/book/"):])
|
||||
books, _, err := GetBook(coll, bson.M{"_id": id})
|
||||
if err != nil || len(books) == 0 {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
data.Book = books[0]
|
||||
loadTemplate(w, "book", data)
|
||||
func bookHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var data bookData
|
||||
data.S = GetStatus(w, r)
|
||||
id := bson.ObjectIdHex(r.URL.Path[len("/book/"):])
|
||||
books, _, err := db.GetBooks(bson.M{"_id": id})
|
||||
if err != nil || len(books) == 0 {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
data.Book = books[0]
|
||||
loadTemplate(w, "book", data)
|
||||
}
|
||||
|
||||
func fileHandler(path string) {
|
||||
|
@ -80,45 +71,39 @@ type indexData struct {
|
|||
Tags []string
|
||||
}
|
||||
|
||||
func indexHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var data indexData
|
||||
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var data indexData
|
||||
|
||||
/* get the tags */
|
||||
tags, err := GetTags(coll)
|
||||
if err == nil {
|
||||
length := len(tags)
|
||||
if length > TAGS_DISPLAY {
|
||||
length = TAGS_DISPLAY
|
||||
/* get the tags */
|
||||
tags, err := db.GetTags()
|
||||
if err == nil {
|
||||
length := len(tags)
|
||||
if length > TAGS_DISPLAY {
|
||||
length = TAGS_DISPLAY
|
||||
}
|
||||
data.Tags = make([]string, length)
|
||||
for i, tag := range tags {
|
||||
if i == TAGS_DISPLAY {
|
||||
break /* display only 50 */
|
||||
}
|
||||
data.Tags = make([]string, length)
|
||||
for i, tag := range tags {
|
||||
if i == TAGS_DISPLAY {
|
||||
break /* display only 50 */
|
||||
}
|
||||
if tag.Subject != "" {
|
||||
data.Tags[i] = tag.Subject
|
||||
}
|
||||
if tag.Subject != "" {
|
||||
data.Tags[i] = tag.Subject
|
||||
}
|
||||
}
|
||||
|
||||
data.S = GetStatus(w, r)
|
||||
data.S.Home = true
|
||||
data.Books, data.Count, _ = GetBook(coll, bson.M{}, 6)
|
||||
loadTemplate(w, "index", data)
|
||||
}
|
||||
|
||||
data.S = GetStatus(w, r)
|
||||
data.S.Home = true
|
||||
data.Books, data.Count, _ = db.GetBooks(bson.M{"active": true}, 6)
|
||||
loadTemplate(w, "index", data)
|
||||
}
|
||||
|
||||
func main() {
|
||||
session, err := mgo.Dial(DB_IP)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer session.Close()
|
||||
coll := session.DB(DB_NAME).C(BOOKS_COLL)
|
||||
userColl := session.DB(DB_NAME).C(USERS_COLL)
|
||||
newColl := session.DB(DB_NAME).C(NEW_BOOKS_COLL)
|
||||
db = initDB()
|
||||
defer db.Close()
|
||||
|
||||
/* create the needed folders */
|
||||
var err error
|
||||
_, err = os.Stat(BOOKS_PATH)
|
||||
if err != nil {
|
||||
os.Mkdir(BOOKS_PATH, os.ModePerm)
|
||||
|
@ -132,27 +117,25 @@ func main() {
|
|||
os.Mkdir(NEW_PATH, os.ModePerm)
|
||||
}
|
||||
|
||||
http.HandleFunc("/book/", bookHandler(coll))
|
||||
http.HandleFunc("/search/", searchHandler(coll))
|
||||
http.HandleFunc("/upload/", uploadHandler(newColl))
|
||||
http.HandleFunc("/login/", loginHandler(userColl))
|
||||
/* set up web handlers */
|
||||
http.HandleFunc("/book/", bookHandler)
|
||||
http.HandleFunc("/search/", searchHandler)
|
||||
http.HandleFunc("/upload/", uploadHandler)
|
||||
http.HandleFunc("/login/", loginHandler)
|
||||
http.HandleFunc("/logout/", logoutHandler)
|
||||
http.HandleFunc("/new/", newHandler(newColl, coll))
|
||||
http.HandleFunc("/delnew/", deleteHandler(newColl, "/new/"))
|
||||
http.HandleFunc("/store/", storeHandler(newColl, coll))
|
||||
http.HandleFunc("/read/", readHandler(coll))
|
||||
http.HandleFunc("/content/", contentHandler(coll))
|
||||
http.HandleFunc("/readnew/", readHandler(newColl))
|
||||
http.HandleFunc("/contentnew/", contentHandler(newColl))
|
||||
http.HandleFunc("/edit/", editHandler(coll))
|
||||
http.HandleFunc("/save/", saveHandler(coll))
|
||||
http.HandleFunc("/delete/", deleteHandler(coll, "/"))
|
||||
http.HandleFunc("/new/", newHandler)
|
||||
http.HandleFunc("/store/", storeHandler)
|
||||
http.HandleFunc("/read/", readHandler)
|
||||
http.HandleFunc("/content/", contentHandler)
|
||||
http.HandleFunc("/edit/", editHandler)
|
||||
http.HandleFunc("/save/", saveHandler)
|
||||
http.HandleFunc("/delete/", deleteHandler)
|
||||
http.HandleFunc("/about/", aboutHandler)
|
||||
fileHandler("/img/")
|
||||
fileHandler("/cover/")
|
||||
fileHandler("/books/")
|
||||
fileHandler("/css/")
|
||||
fileHandler("/js/")
|
||||
http.HandleFunc("/", indexHandler(coll))
|
||||
http.HandleFunc("/", indexHandler)
|
||||
panic(http.ListenAndServe(":"+PORT, nil))
|
||||
}
|
||||
|
|
55
upload.go
55
upload.go
|
@ -2,7 +2,6 @@ package main
|
|||
|
||||
import (
|
||||
"git.gitorious.org/go-pkg/epub.git"
|
||||
"labix.org/v2/mgo"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
@ -198,7 +197,7 @@ func keywords(b map[string]interface{}) (k []string) {
|
|||
return
|
||||
}
|
||||
|
||||
func parseFile(coll *mgo.Collection, path string) (string, error) {
|
||||
func parseFile(path string) (string, error) {
|
||||
book := map[string]interface{}{}
|
||||
|
||||
e, err := epub.Open(path, 0)
|
||||
|
@ -229,7 +228,7 @@ func parseFile(coll *mgo.Collection, path string) (string, error) {
|
|||
book["coversmall"] = coverSmall
|
||||
book["keywords"] = keywords(book)
|
||||
|
||||
coll.Insert(book)
|
||||
db.InsertBook(book)
|
||||
return title, nil
|
||||
}
|
||||
|
||||
|
@ -237,33 +236,31 @@ type uploadData struct {
|
|||
S Status
|
||||
}
|
||||
|
||||
func uploadHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "POST" {
|
||||
sess := GetSession(r)
|
||||
paths, err := storeFiles(r)
|
||||
if err != nil {
|
||||
sess.Notify("Problem uploading!", "Some files were not stored. Try again or contact us if it keeps happening", "error")
|
||||
}
|
||||
|
||||
uploaded := ""
|
||||
for _, path := range paths {
|
||||
title, err := parseFile(coll, path)
|
||||
if err != nil {
|
||||
os.Remove(path)
|
||||
sess.Notify("Problem uploading!", "The file '"+path[len("new/"):]+"' is not a well formed epub", "error")
|
||||
} else {
|
||||
uploaded = uploaded + " '" + title + "'"
|
||||
}
|
||||
}
|
||||
if uploaded != "" {
|
||||
sess.Notify("Upload successful!", "Added the books:"+uploaded+". Thank you for your contribution", "success")
|
||||
}
|
||||
func uploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == "POST" {
|
||||
sess := GetSession(r)
|
||||
paths, err := storeFiles(r)
|
||||
if err != nil {
|
||||
sess.Notify("Problem uploading!", "Some files were not stored. Try again or contact us if it keeps happening", "error")
|
||||
}
|
||||
|
||||
var data uploadData
|
||||
data.S = GetStatus(w, r)
|
||||
data.S.Upload = true
|
||||
loadTemplate(w, "upload", data)
|
||||
uploaded := ""
|
||||
for _, path := range paths {
|
||||
title, err := parseFile(path)
|
||||
if err != nil {
|
||||
os.Remove(path)
|
||||
sess.Notify("Problem uploading!", "The file '"+path[len("new/"):]+"' is not a well formed epub", "error")
|
||||
} else {
|
||||
uploaded = uploaded + " '" + title + "'"
|
||||
}
|
||||
}
|
||||
if uploaded != "" {
|
||||
sess.Notify("Upload successful!", "Added the books:"+uploaded+". Thank you for your contribution", "success")
|
||||
}
|
||||
}
|
||||
|
||||
var data uploadData
|
||||
data.S = GetStatus(w, r)
|
||||
data.S.Upload = true
|
||||
loadTemplate(w, "upload", data)
|
||||
}
|
||||
|
|
Reference in a new issue