ДЗ4 начато
parent
4b6be61eea
commit
f766c1dd6e
|
@ -25,7 +25,7 @@ func init() {
|
||||||
func main() {
|
func main() {
|
||||||
log.Println("Starting...")
|
log.Println("Starting...")
|
||||||
m := martini.Classic()
|
m := martini.Classic()
|
||||||
app, err := application.New("", "APP")
|
app, err := application.New("application.conf", "APP")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(fmt.Errorf("can't build app: %w", err).Error())
|
log.Fatal(fmt.Errorf("can't build app: %w", err).Error())
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,11 @@ func main() {
|
||||||
m.Get("/search", handlers.GetUserList)
|
m.Get("/search", handlers.GetUserList)
|
||||||
m.Post("/search", handlers.PostUserSearch)
|
m.Post("/search", handlers.PostUserSearch)
|
||||||
|
|
||||||
|
m.Get("/addPost", auth.LoginRequired, handlers.GetAddPost)
|
||||||
|
m.Post("/addPost", auth.LoginRequired, handlers.PostAddPost)
|
||||||
|
|
||||||
|
m.Get("/feed", auth.LoginRequired, handlers.GetFeed)
|
||||||
|
|
||||||
m.NotFound(func(r render.Render) {
|
m.NotFound(func(r render.Render) {
|
||||||
r.HTML(404, "404", nil)
|
r.HTML(404, "404", nil)
|
||||||
})
|
})
|
||||||
|
|
|
@ -84,6 +84,18 @@ func dbInit(db *sql.DB) error {
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8`); err != nil {
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8`); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS posts (
|
||||||
|
Id INT(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
Author INT(11) NULL DEFAULT NULL,
|
||||||
|
Created TIMESTAMP NULL DEFAULT NULL,
|
||||||
|
Subject VARCHAR(50) NULL DEFAULT NULL,
|
||||||
|
Body MEDIUMTEXT NULL DEFAULT NULL,
|
||||||
|
PRIMARY KEY (Id) USING BTREE,
|
||||||
|
INDEX AuthorID (author) USING BTREE,
|
||||||
|
CONSTRAINT AuthorID FOREIGN KEY (author) REFERENCES app.users (Id) ON UPDATE RESTRICT ON DELETE RESTRICT
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_unicode_ci`); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
log.Println("All tables exists")
|
log.Println("All tables exists")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/codegangsta/martini-contrib/render"
|
||||||
|
"github.com/tiburon-777/OTUS_HighLoad/internal/application"
|
||||||
|
"github.com/tiburon-777/OTUS_HighLoad/internal/auth"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetFeed(app application.App, r render.Render, user auth.User) {
|
||||||
|
h := user.(*auth.UserModel).BirthDate
|
||||||
|
user.(*auth.UserModel).YearsOld = int(time.Since(h).Hours() / 8760)
|
||||||
|
doc := make(map[string]interface{})
|
||||||
|
doc["user"] = user.(*auth.UserModel)
|
||||||
|
var tmpTime string
|
||||||
|
var post Post
|
||||||
|
var posts []Post
|
||||||
|
var results, err = app.DBMaster.Query(`SELECT
|
||||||
|
posts.Id AS Id,
|
||||||
|
users.Username AS Author,
|
||||||
|
posts.Created AS Created,
|
||||||
|
posts.Subject AS Subject,
|
||||||
|
posts.Body AS Body
|
||||||
|
FROM
|
||||||
|
users JOIN relations JOIN posts
|
||||||
|
WHERE
|
||||||
|
relations.friendId=users.Id
|
||||||
|
AND posts.Author=relations.friendId
|
||||||
|
AND relations.userId=?
|
||||||
|
ORDER by Created DESC`,
|
||||||
|
user.(*auth.UserModel).Id)
|
||||||
|
if err != nil || results == nil {
|
||||||
|
err500("can't get feed from DB: ", err, r)
|
||||||
|
}
|
||||||
|
defer results.Close()
|
||||||
|
for results.Next() {
|
||||||
|
err = results.Scan(&post.Id, &post.Author, &tmpTime, &post.Subject, &post.Body)
|
||||||
|
if err != nil {
|
||||||
|
err500("can't scan result from DB: ", err, r)
|
||||||
|
}
|
||||||
|
post.Created = str2Time(tmpTime, r)
|
||||||
|
posts = append(posts, post)
|
||||||
|
}
|
||||||
|
doc["posts"] = posts
|
||||||
|
|
||||||
|
r.HTML(200, "feed", doc)
|
||||||
|
}
|
||||||
|
|
|
@ -10,10 +10,17 @@ import (
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Post struct{
|
||||||
|
Id int `db:"Id"`
|
||||||
|
Author string `db:"Author"`
|
||||||
|
Created time.Time `db:"Created"`
|
||||||
|
Subject string `db:"Subject"`
|
||||||
|
Body string `db:"Body"`
|
||||||
|
}
|
||||||
|
|
||||||
func GetHome(app application.App, r render.Render, user auth.User) {
|
func GetHome(app application.App, r render.Render, user auth.User) {
|
||||||
h := user.(*auth.UserModel).BirthDate
|
h := user.(*auth.UserModel).BirthDate
|
||||||
user.(*auth.UserModel).YearsOld = int(time.Since(h).Hours() / 8760)
|
user.(*auth.UserModel).YearsOld = int(time.Since(h).Hours() / 8760)
|
||||||
|
@ -51,6 +58,23 @@ func GetHome(app application.App, r render.Render, user auth.User) {
|
||||||
}
|
}
|
||||||
doc["table"] = users
|
doc["table"] = users
|
||||||
|
|
||||||
|
var post Post
|
||||||
|
var posts []Post
|
||||||
|
results, err = app.DBMaster.Query(`SELECT Id, Created, Subject, Body FROM posts WHERE Author=? ORDER BY Created DESC;`, user.(*auth.UserModel).Id)
|
||||||
|
if err != nil || results == nil {
|
||||||
|
err500("can't get user list from DB: ", err, r)
|
||||||
|
}
|
||||||
|
defer results.Close()
|
||||||
|
for results.Next() {
|
||||||
|
err = results.Scan(&post.Id, &tmpTime, &post.Subject, &post.Body)
|
||||||
|
if err != nil {
|
||||||
|
err500("can't scan result from DB: ", err, r)
|
||||||
|
}
|
||||||
|
post.Created = str2Time(tmpTime, r)
|
||||||
|
posts = append(posts, post)
|
||||||
|
}
|
||||||
|
doc["posts"] = posts
|
||||||
|
|
||||||
r.HTML(200, "index", doc)
|
r.HTML(200, "index", doc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,129 +120,6 @@ func PostSignup(app application.App, postedUser auth.UserModel, r render.Render)
|
||||||
r.Redirect("/login")
|
r.Redirect("/login")
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserList(app application.App, r render.Render) {
|
|
||||||
doc := make(map[string]interface{})
|
|
||||||
doc["UsersFound"] = 0
|
|
||||||
var tmp int
|
|
||||||
if err := app.DBMaster.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&tmp); err != nil {
|
|
||||||
err500("can't get total of user profiles from DB: ", err, r)
|
|
||||||
}
|
|
||||||
doc["UsersTotal"] = tmp
|
|
||||||
r.HTML(200, "list", doc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func PostUserList(app application.App, user auth.User, r render.Render, req *http.Request) {
|
|
||||||
postName := req.FormValue("name")
|
|
||||||
postSurname := req.FormValue("surname")
|
|
||||||
doc := make(map[string]interface{})
|
|
||||||
doc["user"] = user.(*auth.UserModel)
|
|
||||||
var users []auth.UserModel
|
|
||||||
var tmp auth.UserModel
|
|
||||||
var tmpTime string
|
|
||||||
var results, err = app.DBMaster.Query(`SELECT
|
|
||||||
users.id as id,
|
|
||||||
users.name as name,
|
|
||||||
users.surname as surname,
|
|
||||||
users.birthdate as birthdate,
|
|
||||||
users.gender as gender,
|
|
||||||
users.city as city
|
|
||||||
FROM
|
|
||||||
users
|
|
||||||
WHERE
|
|
||||||
NOT users.id=?
|
|
||||||
AND users.id NOT IN (
|
|
||||||
SELECT
|
|
||||||
relations.friendId
|
|
||||||
FROM
|
|
||||||
relations
|
|
||||||
WHERE
|
|
||||||
relations.userId=?)
|
|
||||||
AND ( users.Name LIKE concat(?, '%') AND users.Surname LIKE concat(?, '%') )`,
|
|
||||||
user.(*auth.UserModel).Id,
|
|
||||||
user.(*auth.UserModel).Id,
|
|
||||||
postName,
|
|
||||||
postSurname,
|
|
||||||
)
|
|
||||||
if err != nil || results == nil {
|
|
||||||
err500("can't get user list from DB: ", err, r)
|
|
||||||
}
|
|
||||||
defer results.Close()
|
|
||||||
for results.Next() {
|
|
||||||
err = results.Scan(&tmp.Id, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City)
|
|
||||||
if err != nil {
|
|
||||||
err500("can't scan result from DB: ", err, r)
|
|
||||||
}
|
|
||||||
tmp.BirthDate = str2Time(tmpTime, r)
|
|
||||||
tmp.YearsOld = int(time.Since(tmp.BirthDate).Hours() / 8760)
|
|
||||||
users = append(users, tmp)
|
|
||||||
if len(users) >= 100 {
|
|
||||||
doc["msg"] = "( Too much rows in result. We will display only the first 100. )"
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doc["table"] = users
|
|
||||||
doc["UsersFound"] = len(users)
|
|
||||||
var uTotal int
|
|
||||||
if err := app.DBMaster.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&uTotal); err != nil {
|
|
||||||
err500("can't get total of user profiles from DB: ", err, r)
|
|
||||||
}
|
|
||||||
doc["UsersTotal"] = uTotal
|
|
||||||
r.HTML(200, "list", doc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func PostUserSearch(app application.App, r render.Render, req *http.Request) {
|
|
||||||
db := app.DBMaster
|
|
||||||
if app.Config.DSN.Slave1!="" {
|
|
||||||
db = app.DBSlave1
|
|
||||||
}
|
|
||||||
|
|
||||||
postName := req.FormValue("name")
|
|
||||||
postSurname := req.FormValue("surname")
|
|
||||||
doc := make(map[string]interface{})
|
|
||||||
var users []auth.UserModel
|
|
||||||
var tmp auth.UserModel
|
|
||||||
var tmpTime string
|
|
||||||
var results, err = db.Query(`SELECT
|
|
||||||
users.id as id,
|
|
||||||
users.name as name,
|
|
||||||
users.surname as surname,
|
|
||||||
users.birthdate as birthdate,
|
|
||||||
users.gender as gender,
|
|
||||||
users.city as city
|
|
||||||
FROM
|
|
||||||
users
|
|
||||||
WHERE
|
|
||||||
( users.Name LIKE concat(?, '%') AND users.Surname LIKE concat(?, '%') )`,
|
|
||||||
postName,
|
|
||||||
postSurname,
|
|
||||||
)
|
|
||||||
if err != nil || results == nil {
|
|
||||||
err500("can't get user list from DB: ", err, r)
|
|
||||||
}
|
|
||||||
defer results.Close()
|
|
||||||
for results.Next() {
|
|
||||||
err = results.Scan(&tmp.Id, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City)
|
|
||||||
if err != nil {
|
|
||||||
err500("can't scan result from DB: ", err, r)
|
|
||||||
}
|
|
||||||
tmp.BirthDate = str2Time(tmpTime, r)
|
|
||||||
tmp.YearsOld = int(time.Since(tmp.BirthDate).Hours() / 8760)
|
|
||||||
users = append(users, tmp)
|
|
||||||
if len(users) >= 100 {
|
|
||||||
doc["msg"] = "( Too much rows in result. We will display only the first 100. )"
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doc["table"] = users
|
|
||||||
doc["UsersFound"] = len(users)
|
|
||||||
var uTotal int
|
|
||||||
if err := db.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&uTotal); err != nil {
|
|
||||||
err500("can't get total of user profiles from DB: ", err, r)
|
|
||||||
}
|
|
||||||
doc["UsersTotal"] = uTotal
|
|
||||||
r.HTML(200, "list", doc)
|
|
||||||
}
|
|
||||||
|
|
||||||
func PostLogin(app application.App, session sessions.Session, postedUser auth.UserModel, r render.Render, req *http.Request) {
|
func PostLogin(app application.App, session sessions.Session, postedUser auth.UserModel, r render.Render, req *http.Request) {
|
||||||
user := auth.UserModel{}
|
user := auth.UserModel{}
|
||||||
err1 := app.DBMaster.QueryRow("SELECT id, password FROM users WHERE username=?", postedUser.Username).Scan(&user.Id, &user.Password)
|
err1 := app.DBMaster.QueryRow("SELECT id, password FROM users WHERE username=?", postedUser.Username).Scan(&user.Id, &user.Password)
|
||||||
|
@ -242,43 +143,6 @@ func PostLogin(app application.App, session sessions.Session, postedUser auth.Us
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetSubscribe(app application.App, r render.Render, user auth.User, req *http.Request) {
|
|
||||||
sid, ok := req.URL.Query()["id"]
|
|
||||||
if !ok {
|
|
||||||
err500("can't parce URL query", nil, r)
|
|
||||||
}
|
|
||||||
did, err := strconv.Atoi(sid[0])
|
|
||||||
if err != nil {
|
|
||||||
err500("can't convert URL query value: ", err, r)
|
|
||||||
}
|
|
||||||
_, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, user.(*auth.UserModel).Id, did)
|
|
||||||
if err != nil {
|
|
||||||
err500("can't create relation in DB: ", err, r)
|
|
||||||
}
|
|
||||||
_, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, did, user.(*auth.UserModel).Id)
|
|
||||||
if err != nil {
|
|
||||||
err500("can't create relation in DB: ", err, r)
|
|
||||||
}
|
|
||||||
r.Redirect("/list")
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUnSubscribe(app application.App, r render.Render, user auth.User, req *http.Request) {
|
|
||||||
sid, ok := req.URL.Query()["id"]
|
|
||||||
if !ok {
|
|
||||||
err500("can't parce URL query", nil, r)
|
|
||||||
}
|
|
||||||
did, err := strconv.Atoi(sid[0])
|
|
||||||
if err != nil {
|
|
||||||
err500("can't convert URL query value: ", err, r)
|
|
||||||
}
|
|
||||||
_, err = app.DBMaster.Exec(`DELETE FROM relations WHERE (userId,friendId) IN ((?, ?),(?, ?))`, user.(*auth.UserModel).Id, did, did, user.(*auth.UserModel).Id)
|
|
||||||
if err != nil {
|
|
||||||
err500("can't remove relation from DB: ", err, r)
|
|
||||||
}
|
|
||||||
r.Redirect("/")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func str2Time(s string, r render.Render) time.Time {
|
func str2Time(s string, r render.Render) time.Time {
|
||||||
t, err := time.Parse("2006-01-02 15:04:05", s)
|
t, err := time.Parse("2006-01-02 15:04:05", s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/codegangsta/martini-contrib/render"
|
||||||
|
"github.com/tiburon-777/OTUS_HighLoad/internal/application"
|
||||||
|
"github.com/tiburon-777/OTUS_HighLoad/internal/auth"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetAddPost(app application.App, r render.Render) {
|
||||||
|
r.HTML(200, "postadd", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostAddPost(app application.App, user auth.User, r render.Render, req *http.Request) {
|
||||||
|
postSubj := req.FormValue("subj")
|
||||||
|
postBody := req.FormValue("body")
|
||||||
|
var results, err = app.DBMaster.Query(`INSERT INTO posts (Author, Created, Subject, Body) VALUES (
|
||||||
|
?, ?, ?, ?)`,
|
||||||
|
user.(*auth.UserModel).Id,
|
||||||
|
time.Now().Format("2006-01-02 15:04:05"),
|
||||||
|
postSubj,
|
||||||
|
postBody,
|
||||||
|
)
|
||||||
|
if err != nil || results == nil {
|
||||||
|
err500("can't add new post: ", err, r)
|
||||||
|
}
|
||||||
|
r.Redirect("/",302)
|
||||||
|
}
|
|
@ -0,0 +1,133 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/codegangsta/martini-contrib/render"
|
||||||
|
"github.com/tiburon-777/OTUS_HighLoad/internal/application"
|
||||||
|
"github.com/tiburon-777/OTUS_HighLoad/internal/auth"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetUserList(app application.App, r render.Render) {
|
||||||
|
doc := make(map[string]interface{})
|
||||||
|
doc["UsersFound"] = 0
|
||||||
|
var tmp int
|
||||||
|
if err := app.DBMaster.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&tmp); err != nil {
|
||||||
|
err500("can't get total of user profiles from DB: ", err, r)
|
||||||
|
}
|
||||||
|
doc["UsersTotal"] = tmp
|
||||||
|
r.HTML(200, "list", doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostUserList(app application.App, user auth.User, r render.Render, req *http.Request) {
|
||||||
|
postName := req.FormValue("name")
|
||||||
|
postSurname := req.FormValue("surname")
|
||||||
|
doc := make(map[string]interface{})
|
||||||
|
doc["user"] = user.(*auth.UserModel)
|
||||||
|
var users []auth.UserModel
|
||||||
|
var tmp auth.UserModel
|
||||||
|
var tmpTime string
|
||||||
|
var results, err = app.DBMaster.Query(`SELECT
|
||||||
|
users.id as id,
|
||||||
|
users.name as name,
|
||||||
|
users.surname as surname,
|
||||||
|
users.birthdate as birthdate,
|
||||||
|
users.gender as gender,
|
||||||
|
users.city as city
|
||||||
|
FROM
|
||||||
|
users
|
||||||
|
WHERE
|
||||||
|
NOT users.id=?
|
||||||
|
AND users.id NOT IN (
|
||||||
|
SELECT
|
||||||
|
relations.friendId
|
||||||
|
FROM
|
||||||
|
relations
|
||||||
|
WHERE
|
||||||
|
relations.userId=?)
|
||||||
|
AND ( users.Name LIKE concat(?, '%') AND users.Surname LIKE concat(?, '%') )`,
|
||||||
|
user.(*auth.UserModel).Id,
|
||||||
|
user.(*auth.UserModel).Id,
|
||||||
|
postName,
|
||||||
|
postSurname,
|
||||||
|
)
|
||||||
|
if err != nil || results == nil {
|
||||||
|
err500("can't get user list from DB: ", err, r)
|
||||||
|
}
|
||||||
|
defer results.Close()
|
||||||
|
for results.Next() {
|
||||||
|
err = results.Scan(&tmp.Id, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City)
|
||||||
|
if err != nil {
|
||||||
|
err500("can't scan result from DB: ", err, r)
|
||||||
|
}
|
||||||
|
tmp.BirthDate = str2Time(tmpTime, r)
|
||||||
|
tmp.YearsOld = int(time.Since(tmp.BirthDate).Hours() / 8760)
|
||||||
|
users = append(users, tmp)
|
||||||
|
if len(users) >= 100 {
|
||||||
|
doc["msg"] = "( Too much rows in result. We will display only the first 100. )"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doc["table"] = users
|
||||||
|
doc["UsersFound"] = len(users)
|
||||||
|
var uTotal int
|
||||||
|
if err := app.DBMaster.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&uTotal); err != nil {
|
||||||
|
err500("can't get total of user profiles from DB: ", err, r)
|
||||||
|
}
|
||||||
|
doc["UsersTotal"] = uTotal
|
||||||
|
r.HTML(200, "list", doc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostUserSearch(app application.App, r render.Render, req *http.Request) {
|
||||||
|
db := app.DBMaster
|
||||||
|
if app.Config.DSN.Slave1!="" {
|
||||||
|
db = app.DBSlave1
|
||||||
|
}
|
||||||
|
|
||||||
|
postName := req.FormValue("name")
|
||||||
|
postSurname := req.FormValue("surname")
|
||||||
|
doc := make(map[string]interface{})
|
||||||
|
var users []auth.UserModel
|
||||||
|
var tmp auth.UserModel
|
||||||
|
var tmpTime string
|
||||||
|
var results, err = db.Query(`SELECT
|
||||||
|
users.id as id,
|
||||||
|
users.name as name,
|
||||||
|
users.surname as surname,
|
||||||
|
users.birthdate as birthdate,
|
||||||
|
users.gender as gender,
|
||||||
|
users.city as city
|
||||||
|
FROM
|
||||||
|
users
|
||||||
|
WHERE
|
||||||
|
( users.Name LIKE concat(?, '%') AND users.Surname LIKE concat(?, '%') )`,
|
||||||
|
postName,
|
||||||
|
postSurname,
|
||||||
|
)
|
||||||
|
if err != nil || results == nil {
|
||||||
|
err500("can't get user list from DB: ", err, r)
|
||||||
|
}
|
||||||
|
defer results.Close()
|
||||||
|
for results.Next() {
|
||||||
|
err = results.Scan(&tmp.Id, &tmp.Name, &tmp.Surname, &tmpTime, &tmp.Gender, &tmp.City)
|
||||||
|
if err != nil {
|
||||||
|
err500("can't scan result from DB: ", err, r)
|
||||||
|
}
|
||||||
|
tmp.BirthDate = str2Time(tmpTime, r)
|
||||||
|
tmp.YearsOld = int(time.Since(tmp.BirthDate).Hours() / 8760)
|
||||||
|
users = append(users, tmp)
|
||||||
|
if len(users) >= 100 {
|
||||||
|
doc["msg"] = "( Too much rows in result. We will display only the first 100. )"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doc["table"] = users
|
||||||
|
doc["UsersFound"] = len(users)
|
||||||
|
var uTotal int
|
||||||
|
if err := db.QueryRow(`SELECT COUNT(*) FROM users`).Scan(&uTotal); err != nil {
|
||||||
|
err500("can't get total of user profiles from DB: ", err, r)
|
||||||
|
}
|
||||||
|
doc["UsersTotal"] = uTotal
|
||||||
|
r.HTML(200, "list", doc)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/codegangsta/martini-contrib/render"
|
||||||
|
"github.com/tiburon-777/OTUS_HighLoad/internal/application"
|
||||||
|
"github.com/tiburon-777/OTUS_HighLoad/internal/auth"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetSubscribe(app application.App, r render.Render, user auth.User, req *http.Request) {
|
||||||
|
sid, ok := req.URL.Query()["id"]
|
||||||
|
if !ok {
|
||||||
|
err500("can't parce URL query", nil, r)
|
||||||
|
}
|
||||||
|
did, err := strconv.Atoi(sid[0])
|
||||||
|
if err != nil {
|
||||||
|
err500("can't convert URL query value: ", err, r)
|
||||||
|
}
|
||||||
|
_, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, user.(*auth.UserModel).Id, did)
|
||||||
|
if err != nil {
|
||||||
|
err500("can't create relation in DB: ", err, r)
|
||||||
|
}
|
||||||
|
_, err = app.DBMaster.Exec(`REPLACE INTO relations (userId, friendId) values (?, ?)`, did, user.(*auth.UserModel).Id)
|
||||||
|
if err != nil {
|
||||||
|
err500("can't create relation in DB: ", err, r)
|
||||||
|
}
|
||||||
|
r.Redirect("/list")
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUnSubscribe(app application.App, r render.Render, user auth.User, req *http.Request) {
|
||||||
|
sid, ok := req.URL.Query()["id"]
|
||||||
|
if !ok {
|
||||||
|
err500("can't parce URL query", nil, r)
|
||||||
|
}
|
||||||
|
did, err := strconv.Atoi(sid[0])
|
||||||
|
if err != nil {
|
||||||
|
err500("can't convert URL query value: ", err, r)
|
||||||
|
}
|
||||||
|
_, err = app.DBMaster.Exec(`DELETE FROM relations WHERE (userId,friendId) IN ((?, ?),(?, ?))`, user.(*auth.UserModel).Id, did, did, user.(*auth.UserModel).Id)
|
||||||
|
if err != nil {
|
||||||
|
err500("can't remove relation from DB: ", err, r)
|
||||||
|
}
|
||||||
|
r.Redirect("/")
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border: 1px solid black;
|
||||||
|
width: 100%;
|
||||||
|
background-color: azure;
|
||||||
|
}
|
||||||
|
table th {
|
||||||
|
border: 1px solid black;
|
||||||
|
background-color: aquamarine;
|
||||||
|
}
|
||||||
|
table td {
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Feed of your friend's news</h2>
|
||||||
|
{{ range $post:=.posts }}
|
||||||
|
<a><b>{{ $post.Author }} wrote at {{ $post.Created }}:</b></a><br/>
|
||||||
|
<a><b>{{ $post.Subject }}</b><br/><a>{{ $post.Body }}</a>
|
||||||
|
<br/><br/>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
<h2>Available actions:</h2>
|
||||||
|
<input type="button" onclick="location.href='/';" value="Home" />
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -25,6 +25,12 @@
|
||||||
<p>You now live in <b>{{ .user.City }}</b></p>
|
<p>You now live in <b>{{ .user.City }}</b></p>
|
||||||
<p>You interests is: <b>{{ .user.Interests }}</b></p>
|
<p>You interests is: <b>{{ .user.Interests }}</b></p>
|
||||||
|
|
||||||
|
<h2>Available actions:</h2>
|
||||||
|
<input type="button" onclick="location.href='/addPost';" value="Create Post" />
|
||||||
|
<input type="button" onclick="location.href='/feed';" value="Friend Feed" />
|
||||||
|
<input type="button" onclick="location.href='/list';" value="User list" />
|
||||||
|
<input type="button" onclick="location.href='/logout';" value="Logout" /><br />
|
||||||
|
|
||||||
<h2> You have friends:</h2>
|
<h2> You have friends:</h2>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -49,8 +55,11 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h2>Available actions:</h2>
|
<h2> Your posts:</h2>
|
||||||
<input type="button" onclick="location.href='/list';" value="User list" />
|
{{ range $post:=.posts }}
|
||||||
<input type="button" onclick="location.href='/logout';" value="Logout" /><br />
|
<a><b>{{ $post.Subject }}</b><br/><a>{{ $post.Body }}</a>
|
||||||
|
<br/><br/>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -0,0 +1,23 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.3/moment.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h2>Create post</h2>
|
||||||
|
<p style="color: red;"><b>{{ .msg }}</b></p>
|
||||||
|
<form method="POST">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>Тема</td>
|
||||||
|
<td><input type="text" name="subj" /></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Текст</td>
|
||||||
|
<td><textarea rows="10" cols="45" name="body"></textarea></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<button>Отправить</button>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -7,7 +7,14 @@
|
||||||
- работа с очередями;
|
- работа с очередями;
|
||||||
- проектирование масштабируемых архитектур.
|
- проектирование масштабируемых архитектур.
|
||||||
|
|
||||||
Разработать ленту новостей. Создается отдельная страница, куда пишутся все обновления друзей. Для этого нужно хранить подписчиков. Лента формируется на уровне кешей. Формирование ленты производить через постановку задачи в очередь на часть подписчиков, чтобы избежать эффекта леди Гаги. В ленте держать последние 1000 обновлений друзей. Лента должна кешироваться.
|
# План выполнения:
|
||||||
|
1) Разработать страницу добавления поста.
|
||||||
|
2) Разработать ленту новостей, содержащую посты пользователей на которых подписан текущий пользователь.
|
||||||
|
- Создается отдельная страница, куда пишутся все обновления друзей. Для этого нужно хранить подписчиков.
|
||||||
|
- Лента формируется на уровне кешей.
|
||||||
|
- Формирование ленты производить через постановку задачи в очередь на часть подписчиков, чтобы избежать эффекта леди Гаги.
|
||||||
|
- В ленте держать последние 1000 обновлений друзей.
|
||||||
|
- Лента должна кешироваться.
|
||||||
|
|
||||||
ДЗ сдается в виде ссылки на гитлаб и демонстрации работающего проекта, развернутого в интернете.
|
ДЗ сдается в виде ссылки на гитлаб и демонстрации работающего проекта, развернутого в интернете.
|
||||||
Критерии оценки: Оценка происходит по принципу зачет/незачет.
|
Критерии оценки: Оценка происходит по принципу зачет/незачет.
|
||||||
|
|
Loading…
Reference in New Issue