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:
Las Zenow 2012-09-12 00:19:19 +02:00
parent a9749e7136
commit 840fd3ed47
7 changed files with 366 additions and 346 deletions

261
admin.go
View file

@ -1,7 +1,6 @@
package main package main
import ( import (
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson" "labix.org/v2/mgo/bson"
"net/http" "net/http"
"os" "os"
@ -10,55 +9,51 @@ import (
"strings" "strings"
) )
func deleteHandler(coll *mgo.Collection, url string) func(http.ResponseWriter, *http.Request) { func deleteHandler(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { sess := GetSession(r)
sess := GetSession(r) if sess.User == "" {
if sess.User == "" { http.NotFound(w, r)
http.NotFound(w, r) return
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)
} }
// 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) { func editHandler(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { sess := GetSession(r)
sess := GetSession(r) if sess.User == "" {
if sess.User == "" { http.NotFound(w, r)
http.NotFound(w, r) return
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)
} }
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 { func cleanEmptyStr(s []string) []string {
@ -71,45 +66,43 @@ func cleanEmptyStr(s []string) []string {
return res return res
} }
func saveHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) { func saveHandler(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" {
if r.Method != "POST" { http.NotFound(w, r)
http.NotFound(w, r) return
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)
} }
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 { type newBook struct {
@ -123,31 +116,29 @@ type newData struct {
Books []newBook Books []newBook
} }
func newHandler(coll *mgo.Collection, booksColl *mgo.Collection) func(http.ResponseWriter, *http.Request) { func newHandler(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { sess := GetSession(r)
if len(r.URL.Path) > len("/new/") { if sess.User == "" {
http.ServeFile(w, r, r.URL.Path[1:]) http.NotFound(w, r)
return 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)
} }
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 { func ValidFileName(path string, title string, extension string) string {
@ -162,34 +153,30 @@ func ValidFileName(path string, title string, extension string) string {
return file return file
} }
func storeHandler(newColl, coll *mgo.Collection) func(http.ResponseWriter, *http.Request) { func storeHandler(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { sess := GetSession(r)
sess := GetSession(r) if sess.User == "" {
if sess.User == "" { http.NotFound(w, r)
http.NotFound(w, r) return
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)
} }
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)
} }

View file

@ -1,11 +1,15 @@
package main package main
import ( import (
"crypto/md5"
"labix.org/v2/mgo" "labix.org/v2/mgo"
"labix.org/v2/mgo/bson" "labix.org/v2/mgo/bson"
"sort" "sort"
) )
var db *DB
type Book struct { type Book struct {
Id string `bson:"_id"` Id string `bson:"_id"`
Title string Title string
@ -26,14 +30,60 @@ type Book struct {
Path string Path string
Cover string Cover string
CoverSmall string CoverSmall string
Active bool
Keywords []string 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 /* optional parameters: length and start index
* *
* Returns: list of books, number found and err * 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 var start, length int
if len(r) > 0 { if len(r) > 0 {
length = 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] start = r[1]
} }
} }
q := coll.Find(query).Sort("-_id") q := d.books.Find(query).Sort("-_id")
num, err = q.Count() num, err = q.Count()
if err != nil { if err != nil {
return 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() books[i].Id = bson.ObjectId(b.Id).Hex()
} }
return 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 { type tagsList []struct {
@ -78,11 +144,11 @@ func (t tagsList) Swap(i, j int) {
t[j] = aux t[j] = aux
} }
func GetTags(coll *mgo.Collection) (tagsList, error) { func (d *DB) GetTags() (tagsList, error) {
// TODO: cache the tags // TODO: cache the tags
var mr mgo.MapReduce var mr mgo.MapReduce
mr.Map = "function() { " + 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) { " + mr.Reduce = "function(tag, vals) { " +
"var count = 0;" + "var count = 0;" +
@ -90,7 +156,7 @@ func GetTags(coll *mgo.Collection) (tagsList, error) {
"return count;" + "return count;" +
"}" "}"
var result tagsList var result tagsList
_, err := coll.Find(nil).MapReduce(&mr, &result) _, err := d.books.Find(nil).MapReduce(&mr, &result)
if err == nil { if err == nil {
sort.Sort(result) sort.Sort(result)
} }

113
reader.go
View file

@ -2,7 +2,6 @@ package main
import ( import (
"git.gitorious.org/go-pkg/epub.git" "git.gitorious.org/go-pkg/epub.git"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson" "labix.org/v2/mgo/bson"
"net/http" "net/http"
"regexp" "regexp"
@ -116,72 +115,62 @@ func chapterList(e *epub.Epub, file string, id string, base string) (string, str
return next, prev, chapters return next, prev, chapters
} }
func readHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) { func readHandler(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { base, id, file := parseUrl(r.URL.Path)
base, id, file := parseUrl(r.URL.Path) books, _, err := db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)})
if base == "/readnew/" { if err != nil || len(books) == 0 {
sess := GetSession(r) http.NotFound(w, r)
if sess.User == "" { return
http.NotFound(w, r) }
return
} var data readData
} data.Book = books[0]
books, _, err := GetBook(coll, bson.M{"_id": bson.ObjectIdHex(id)}) if ! data.Book.Active {
if err != nil || len(books) == 0 { sess := GetSession(r)
if sess.User == "" {
http.NotFound(w, r) http.NotFound(w, r)
return return
} }
book := books[0] data.Back = "/new/"
e, _ := epub.Open(book.Path, 0) } else {
defer e.Close() data.Back = "/book/" + id
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)
} }
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) { func contentHandler(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { _, id, file := parseUrl(r.URL.Path)
base, id, file := parseUrl(r.URL.Path) books, _, err := db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)})
if base == "/contentnew/" { if err != nil || len(books) == 0 {
sess := GetSession(r) http.NotFound(w, r)
if sess.User == "" { return
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))
} }
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))
} }

View file

@ -1,7 +1,6 @@
package main package main
import ( import (
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson" "labix.org/v2/mgo/bson"
"net/http" "net/http"
"strconv" "strconv"
@ -10,7 +9,7 @@ import (
func buildQuery(q string) bson.M { func buildQuery(q string) bson.M {
var reg []bson.RegEx var reg []bson.RegEx
query := bson.M{} query := bson.M{"active": true}
words := strings.Split(q, " ") words := strings.Split(q, " ")
for _, w := range words { for _, w := range words {
tag := strings.SplitN(w, ":", 2) tag := strings.SplitN(w, ":", 2)
@ -35,35 +34,33 @@ type searchData struct {
Prev string Prev string
} }
func searchHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) { func searchHandler(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { err := r.ParseForm()
err := r.ParseForm() if err != nil {
if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError)
http.Error(w, err.Error(), http.StatusInternalServerError) return
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)
} }
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)
} }

View file

@ -21,14 +21,15 @@
</p> </p>
</div> </div>
<div class="span2"> <div class="span2">
<div class="row"> <div class="row btn-group pull-right">
<p><a href="/readnew/{{.Id}}" class="btn btn-warning pull-right"><i class="icon-eye-open icon-white"></i> read it!</a> <a href="/store/{{.Id}}" class="btn btn-success"><i class="icon-ok"></i> Save</a>
<a href="/{{.Path}}" class="btn btn-inverse pull-right"><i class="icon-download-alt icon-white"></i> download</a></p> <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>
<div class="row"><p></p></div> <div class="row"><p></p></div>
<div class="row btn-group pull-right"> <div class="row btn-group pull-right">
<a href="/store/{{.Id}}" class="btn btn-success"><i class="icon-ok"></i> Save</a> <a href="/{{.Path}}" class="btn btn-inverse"><i class="icon-download-alt icon-white"></i> download</a>
<a href="/delnew/{{.Id}}" class="btn btn-danger"><i class="icon-remove"></i> Delete</a> <a href="/read/{{.Id}}" class="btn btn-warning"><i class="icon-eye-open icon-white"></i> read it!</a>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,8 +1,6 @@
package main package main
import ( import (
"crypto/md5"
"labix.org/v2/mgo"
"labix.org/v2/mgo/bson" "labix.org/v2/mgo/bson"
"net/http" "net/http"
"os" "os"
@ -27,25 +25,20 @@ func logoutHandler(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/", 307) http.Redirect(w, r, "/", 307)
} }
func loginHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) { func loginHandler(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" {
if r.Method == "POST" { user := r.FormValue("user")
user := r.FormValue("user") pass := r.FormValue("pass")
pass := r.FormValue("pass") sess := GetSession(r)
h := md5.New() if db.UserValid(user, pass) {
hash := h.Sum(([]byte)(PASS_SALT + pass)) sess.LogIn(user)
n, _ := coll.Find(bson.M{"user": user, "pass": hash}).Count() sess.Notify("Successful login!", "Welcome "+user, "success")
sess := GetSession(r) } else {
if n != 0 { sess.Notify("Invalid login!", "user or password invalid", "error")
sess.LogIn(user)
sess.Notify("Successful login!", "Welcome "+user, "success")
} else {
sess.Notify("Invalid login!", "user or password invalid", "error")
}
sess.Save(w, r)
} }
http.Redirect(w, r, r.Referer(), 307) sess.Save(w, r)
} }
http.Redirect(w, r, r.Referer(), 307)
} }
type bookData struct { type bookData struct {
@ -53,19 +46,17 @@ type bookData struct {
Book Book Book Book
} }
func bookHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) { func bookHandler(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { var data bookData
var data bookData data.S = GetStatus(w, r)
data.S = GetStatus(w, r) id := bson.ObjectIdHex(r.URL.Path[len("/book/"):])
id := bson.ObjectIdHex(r.URL.Path[len("/book/"):]) books, _, err := db.GetBooks(bson.M{"_id": id})
books, _, err := GetBook(coll, bson.M{"_id": id}) if err != nil || len(books) == 0 {
if err != nil || len(books) == 0 { http.NotFound(w, r)
http.NotFound(w, r) return
return
}
data.Book = books[0]
loadTemplate(w, "book", data)
} }
data.Book = books[0]
loadTemplate(w, "book", data)
} }
func fileHandler(path string) { func fileHandler(path string) {
@ -80,45 +71,39 @@ type indexData struct {
Tags []string Tags []string
} }
func indexHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) { func indexHandler(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { var data indexData
var data indexData
/* get the tags */ /* get the tags */
tags, err := GetTags(coll) tags, err := db.GetTags()
if err == nil { if err == nil {
length := len(tags) length := len(tags)
if length > TAGS_DISPLAY { if length > TAGS_DISPLAY {
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) if tag.Subject != "" {
for i, tag := range tags { data.Tags[i] = tag.Subject
if i == TAGS_DISPLAY {
break /* display only 50 */
}
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() { func main() {
session, err := mgo.Dial(DB_IP) db = initDB()
if err != nil { defer db.Close()
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)
/* create the needed folders */
var err error
_, err = os.Stat(BOOKS_PATH) _, err = os.Stat(BOOKS_PATH)
if err != nil { if err != nil {
os.Mkdir(BOOKS_PATH, os.ModePerm) os.Mkdir(BOOKS_PATH, os.ModePerm)
@ -132,27 +117,25 @@ func main() {
os.Mkdir(NEW_PATH, os.ModePerm) os.Mkdir(NEW_PATH, os.ModePerm)
} }
http.HandleFunc("/book/", bookHandler(coll)) /* set up web handlers */
http.HandleFunc("/search/", searchHandler(coll)) http.HandleFunc("/book/", bookHandler)
http.HandleFunc("/upload/", uploadHandler(newColl)) http.HandleFunc("/search/", searchHandler)
http.HandleFunc("/login/", loginHandler(userColl)) http.HandleFunc("/upload/", uploadHandler)
http.HandleFunc("/login/", loginHandler)
http.HandleFunc("/logout/", logoutHandler) http.HandleFunc("/logout/", logoutHandler)
http.HandleFunc("/new/", newHandler(newColl, coll)) http.HandleFunc("/new/", newHandler)
http.HandleFunc("/delnew/", deleteHandler(newColl, "/new/")) http.HandleFunc("/store/", storeHandler)
http.HandleFunc("/store/", storeHandler(newColl, coll)) http.HandleFunc("/read/", readHandler)
http.HandleFunc("/read/", readHandler(coll)) http.HandleFunc("/content/", contentHandler)
http.HandleFunc("/content/", contentHandler(coll)) http.HandleFunc("/edit/", editHandler)
http.HandleFunc("/readnew/", readHandler(newColl)) http.HandleFunc("/save/", saveHandler)
http.HandleFunc("/contentnew/", contentHandler(newColl)) http.HandleFunc("/delete/", deleteHandler)
http.HandleFunc("/edit/", editHandler(coll))
http.HandleFunc("/save/", saveHandler(coll))
http.HandleFunc("/delete/", deleteHandler(coll, "/"))
http.HandleFunc("/about/", aboutHandler) http.HandleFunc("/about/", aboutHandler)
fileHandler("/img/") fileHandler("/img/")
fileHandler("/cover/") fileHandler("/cover/")
fileHandler("/books/") fileHandler("/books/")
fileHandler("/css/") fileHandler("/css/")
fileHandler("/js/") fileHandler("/js/")
http.HandleFunc("/", indexHandler(coll)) http.HandleFunc("/", indexHandler)
panic(http.ListenAndServe(":"+PORT, nil)) panic(http.ListenAndServe(":"+PORT, nil))
} }

View file

@ -2,7 +2,6 @@ package main
import ( import (
"git.gitorious.org/go-pkg/epub.git" "git.gitorious.org/go-pkg/epub.git"
"labix.org/v2/mgo"
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
@ -198,7 +197,7 @@ func keywords(b map[string]interface{}) (k []string) {
return return
} }
func parseFile(coll *mgo.Collection, path string) (string, error) { func parseFile(path string) (string, error) {
book := map[string]interface{}{} book := map[string]interface{}{}
e, err := epub.Open(path, 0) e, err := epub.Open(path, 0)
@ -229,7 +228,7 @@ func parseFile(coll *mgo.Collection, path string) (string, error) {
book["coversmall"] = coverSmall book["coversmall"] = coverSmall
book["keywords"] = keywords(book) book["keywords"] = keywords(book)
coll.Insert(book) db.InsertBook(book)
return title, nil return title, nil
} }
@ -237,33 +236,31 @@ type uploadData struct {
S Status S Status
} }
func uploadHandler(coll *mgo.Collection) func(http.ResponseWriter, *http.Request) { func uploadHandler(w http.ResponseWriter, r *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" {
if r.Method == "POST" { sess := GetSession(r)
sess := GetSession(r) paths, err := storeFiles(r)
paths, err := storeFiles(r) if err != nil {
if err != nil { sess.Notify("Problem uploading!", "Some files were not stored. Try again or contact us if it keeps happening", "error")
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")
}
} }
var data uploadData uploaded := ""
data.S = GetStatus(w, r) for _, path := range paths {
data.S.Upload = true title, err := parseFile(path)
loadTemplate(w, "upload", data) 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)
} }