func init() { var tokenFormValidator = v.NewFormValidator() tokenFormValidator.IntField("alert_on").Min(0) app.Api.Get("/api_tokens/", lib.Admin.Required( func(res *wcg.Response, req *wcg.Request) { d := lib.NewApiTokenDriver(lib.NewAppContextFromRequest(req)) tokens := make([]*models.ApiToken, 0) _, err := d.NewQuery().GetAll(&tokens) if err != nil { panic(err) } res.WriteJson(tokens) }, )) app.Api.Post("/api_tokens/", lib.Admin.Required( func(res *wcg.Response, req *wcg.Request) { d := lib.NewApiTokenDriver(lib.NewAppContextFromRequest(req)) t, err := d.Issue(req.Form("desc")) if err != nil { app.Api.InternalError(res, req, err) } app.Api.Created(res, req, t.Token) }, )) put_fn := lib.Admin.Required( func(res *wcg.Response, req *wcg.Request) { err := tokenFormValidator.Eval(req.HttpRequest().PostForm) if err != nil { app.Api.BadRequest(res, req, err) return } alertOn, _ := strconv.Atoi(req.Form("alert_on")) d := lib.NewApiTokenDriver(lib.NewAppContextFromRequest(req)) err = d.Update(req.Param("token"), req.Form("desc"), time.Duration(alertOn)) if err != nil { app.Api.InternalError(res, req, err) } app.Api.Ok(res, req) }, ) app.Api.Put("/api_tokens/:token/", put_fn) // TODO: remove this after client fixed. app.Api.Put("/api_tokens/:token.json", put_fn) delete_fn := lib.Admin.Required( func(res *wcg.Response, req *wcg.Request) { d := lib.NewApiTokenDriver(lib.NewAppContextFromRequest(req)) err := d.Revoke(req.Param("token")) if err != nil { app.Api.InternalError(res, req, err) } app.Api.Ok(res, req) }, ) app.Api.Delete("/api_tokens/:token/", delete_fn) // TODO: remove this after client fixed. app.Api.Delete("/api_tokens/:token.json", delete_fn) }
func setupYAuctionCron(app *App) { app.Cron.Get( "Crawl registered keywords and generate AuctionItem with Assoc.", "every 1 hours synchronized", "/yauction/keywords/", lib.Admin.Required(func(res *wcg.Response, req *wcg.Request) { err := crawlKeywords(lib.NewAppContextFromRequest(req)) if err != nil { lib.Error(res, req, err) return } app.Api.Ok(res, req) }), ) app.Cron.Get( "Crawl expired AuctionItems to finalize properties.", "every 1 hours from 02:00 to 22:00", "/yauction/auctions/", lib.Admin.Required(func(res *wcg.Response, req *wcg.Request) { err := crawlExpiredAuctions(lib.NewAppContextFromRequest(req)) if err != nil { lib.Error(res, req, err) return } app.Api.Ok(res, req) }), ) app.Cron.Get( "Crawl expired AuctionItems to finalize properties.", "every 10 minutes from 00:00 to 02:00", "/yauction/auctions/", lib.Admin.Required(func(res *wcg.Response, req *wcg.Request) { err := crawlExpiredAuctions(lib.NewAppContextFromRequest(req)) if err != nil { lib.Error(res, req, err) return } app.Api.Ok(res, req) }), ) app.Cron.Get( "Crawl expired AuctionItems to finalize properties.", "every 10 minutes from 22:00 to 23:59", "/yauction/auctions/", lib.Admin.Required(func(res *wcg.Response, req *wcg.Request) { err := crawlExpiredAuctions(lib.NewAppContextFromRequest(req)) if err != nil { lib.Error(res, req, err) return } app.Api.Ok(res, req) }), ) }
func setupPages(app *App) { app.Page.Page("/insights/:member.html", ""). AssetPath("/artistapp/insights.js"). Templates("./artistapp/insights.html"). Handler( func(res *wcg.Response, req *wcg.Request, p *lib.Page) { member, ok := app.Members[req.Param("member")] if !ok { app.Page.NotFound(res, req) return } // load the recent post var list []*ameblo.AmebloEntry d := NewAmebloEntryDriver(lib.NewAppContextFromRequest(req)) q := d.NewQuery().Filter("Owner =", member.Name).Order("-PostAt").Limit(1) if _, err := q.GetAll(&list); err != nil { app.Page.InternalError(res, req, err) return } if len(list) > 0 { list[0].Content, _ = list[0].GetDescription() res.SetLocal("RecentAmebloEntry", list[0]) } p.Ogp("type", "website"). Ogp("title", fmt.Sprintf("%s / %s", p.Title, p.App.Title)). Ogp("description", fmt.Sprintf("%sのSNSデータを可視化しています。", member.Name)). Ogp("image", member.PictureUrl) res.SetLocal("Member", member) }) }
func indexAllMembers(res *wcg.Response, req *wcg.Request, app *App) { var appCtx = lib.NewAppContextFromRequest(req) result := make(map[string][]string) crawler := ameblo.NewCrawler(appCtx.NewHttpClient()) for _, m := range app.Members { req.Logger.Debug("Crawling %s (%s)", m.BlogUrl, m.Name) entries, err := crawler.CrawlEntryList(m.BlogUrl) if err != nil { req.Logger.Error("An error occurred while crawling %s: %v", m.BlogUrl, err) continue } req.Logger.Debug("Found %d entries.", len(entries)) list := make([]string, 0) for _, e := range entries { e.Owner = m.Name list = append(list, e.Url) } if err := updateIndexes(appCtx, entries); err != nil { req.Logger.Error("Failed to update the entry: %v", err) } else { result[m.Name] = list } } // invalidate the cache time.Sleep(10 * time.Second) // TODO: wait for all indexes are updated on datastore. mc := appCtx.NewMemcacheDriver() for _, m := range app.Members { mckey := fmt.Sprintf(MC_KEY_HISTORY, app.Key, m.Name) mc.Delete(mckey) } res.WriteJson(result) }
func queryShows(res *wcg.Response, req *wcg.Request, q *datastore.Query) (*showQueryResult, error) { var appCtx = lib.NewAppContextFromRequest(req) var showList []event.Show var basePath = req.HttpRequest().URL.Path per_page := 12 // Restict to 12 due to view rendering. page := wcg.ParseInt(req.Query("page"), 0, 0, wcg.ParseIntMax) if _, err := q.Offset(page * per_page).Limit(per_page).GetAll(&showList); err != nil { return nil, err } if showList == nil { return &showQueryResult{ Shows: make([]EventShow, 0), }, nil } if list, err := NewEventShowList(appCtx, showList); err != nil { return nil, err } else { p := &showQueryResult{ Shows: list, Current: fmt.Sprintf("%s?page=%d&n=%d", basePath, page, per_page), } // prev url if page > 0 { p.Previous = fmt.Sprintf("%s?page=%d&n=%d", basePath, page-1, per_page) } // next url if len(p.Shows) == per_page { p.Next = fmt.Sprintf("%s?page=%d&n=%d", basePath, page+1, per_page) } return p, nil } }
func loadEvent(app *App, req *wcg.Request, key string) (*event.Event, error) { var e event.Event d := NewEventDriver(lib.NewAppContextFromRequest(req)) if err := d.Get(d.NewKey(req.Param(key), 0, nil), &e); err != nil { return nil, err } else { return &e, nil } }
func indexSpecifiedMember(res *wcg.Response, req *wcg.Request, app *App) { var appCtx = lib.NewAppContextFromRequest(req) member, ok := app.Members[req.Param("member")] if !ok { lib.NotFound(res, req) return } num := wcg.ParseInt(req.Param("n"), 0, 0, wcg.ParseIntMax) if num == 0 { num = wcg.ParseIntMax } // Crawling crawler := ameblo.NewCrawler(appCtx.NewHttpClient()) prefix := strings.TrimSuffix(member.BlogUrl, ".html") // xxxx.html => xxxx-{num}.html entries := make([]*ameblo.AmebloEntry, 0) for i := 1; i < num; i += 1 { url := fmt.Sprintf("%s-%d.html", prefix, i) req.Logger.Info("Indexing from %s ... ", url) newentries, err := crawler.CrawlEntryList(url) if err != nil { lib.InternalError(res, req, err) return } if len(newentries) > 20 { panic(fmt.Errorf("Unexpected number of entries (%d) are returned during indexing.", len(newentries))) } if len(newentries) == 0 { break } if len(newentries) < 20 { entries = append(entries, newentries...) break } if len(entries) > 0 && entries[len(entries)-1].Url == newentries[len(newentries)-1].Url { break } entries = append(entries, newentries...) } // Save and return resutls results := make([]string, 0) for _, ent := range entries { ent.Owner = member.Name results = append(results, ent.Url) } if err := updateIndexes(appCtx, entries); err != nil { req.Logger.Error("Failed to update the entry: %v", err) lib.InternalError(res, req, err) // stopped. } else { time.Sleep(10 * time.Second) // TODO: wait for all indexes are updated on datastore. mc := appCtx.NewMemcacheDriver() mckey := fmt.Sprintf(MC_KEY_HISTORY, app.Key, member.Name) mc.Delete(mckey) res.WriteJson(results) } }
func setupApi(app *App) { app.Api.Get("/ameblo/insights/:member/history.json", func(res *wcg.Response, req *wcg.Request) { historyInsights(res, req, app) }) app.Api.Get("/ameblo/indexes/", lib.Admin.Required(func(res *wcg.Response, req *wcg.Request) { indexAllMembers(res, req, app) })) app.Api.Get("/ameblo/indexes/:member.json", lib.Admin.Required(func(res *wcg.Response, req *wcg.Request) { indexSpecifiedMember(res, req, app) })) app.Api.Get("/ameblo/contents/", lib.Admin.Required(func(res *wcg.Response, req *wcg.Request) { crawlAllMembers(res, req, app) })) app.Api.Get("/ameblo/contents/:member.json", lib.Admin.Required(func(res *wcg.Response, req *wcg.Request) { crawlSpecifiedMembers(res, req, app) })) app.Api.Delete("/ameblo/contents/:member.json", lib.Admin.Required( func(res *wcg.Response, req *wcg.Request) { var appCtx = lib.NewAppContextFromRequest(req) member, ok := app.Members[req.Param("member")] if !ok { lib.NotFound(res, req) return } PER_ENT := 100 offset := 0 d := NewAmebloEntryDriver(appCtx) for { var list []*ameblo.AmebloEntry var q = d.NewQuery().Filter("Owner =", member.Name).Offset(offset).Limit(PER_ENT) if keys, err := q.GetAll(&list); err != nil { lib.InternalError(res, req, err) return } else { for _, ent := range list { ent.CrawledAt = time.Time{} } if _, err = d.PutMulti(keys, list); datastore.IsDatastoreError(err) { lib.InternalError(res, req, err) } offset = offset + len(list) if len(list) < PER_ENT { break } } } app.Api.Ok(res, req) }, )) }
func setupPages(app *App) { app.Page.Navi("/", "記事一覧"). AssetPath("/blogapp/index.js"). Templates("./blogapp/list.html", "./blogapp/post_part.html"). Handler( func(res *wcg.Response, req *wcg.Request, p *lib.Page) { result, err := queryPosts(res, req, 20) if err != nil { panic(err) } p.Ogp("type", "blog") res.SetLocal("Posts", result.Posts) res.SetLocal("Next", result.Next) res.SetLocal("Previous", result.Previous) }, ) app.Page.Navi("/admin/editor.html", "記事管理"). RequireAuth(lib.Admin). Templates("./blogapp/admin/editor.html"). AssetPath("/blogapp/admin/editor.js") app.Page.Page("/posts/:id.html", ""). Templates("./blogapp/show.html", "./blogapp/post_part.html"). AssetPath("/blogapp/posts/show.js"). Handler( func(res *wcg.Response, req *wcg.Request, p *lib.Page) { var post blog.Post driver := NewPostDriver(lib.NewAppContextFromRequest(req)) key := driver.NewKey(req.Param("id"), 0, nil) err := driver.Get(key, &post) if err != nil { lib.Error(res, req, err) return } p.Title = post.Title p.Canonical = wcg.AbsoluteUrl(req, app.Page.Path(fmt.Sprintf("/posts/%s.html", post.Id))) p.Ogp("title", fmt.Sprintf("%s: %s", p.App.Title, p.Title)) p.Ogp("url", p.Canonical) p.Ogp("type", "article") p.Ogp("description", post.Summary()) imageUrl := post.ExtractFirstImageUrl() if imageUrl != "" { p.Ogp("image", imageUrl) } res.SetLocal("Post", post) }) }
func setupEventCron(app *App) { app.Cron.Get( "Generate YAKeyword crawling metadata for registered event show entries.", "every 1 hours synchronized", "/event/yakeywords/", lib.Admin.Required(func(res *wcg.Response, req *wcg.Request) { updateKeys, err := generateYACrawlerKeywords(lib.NewAppContextFromRequest(req)) if err != nil { lib.Error(res, req, err) return } req.Logger.Info("Updating %d yauction keyword entries from event.", len(updateKeys)) app.Api.Ok(res, req) }), ) }
func init() { app.Cron.Get( "Monitor API tokens", "every 1 minutes", "/api_tokens/", lib.Admin.Required( func(res *wcg.Response, req *wcg.Request) { var tokens []*models.ApiToken d := lib.NewApiTokenDriver(lib.NewAppContextFromRequest(req)) _, err := d.NewQuery().GetAll(&tokens) if err != nil { panic(err) } m := 0 c := 0 for _, t := range tokens { if t.AlertOn > 0 { m += 1 if t.ShouldAlert() { c += 1 req.Logger.Fatal( "API Token '%s' losts access. The last access time was %s (Threshould: %d minutes).", t.Token, t.LastAccess, t.AlertOn, ) } } } if c > 0 { notifications.SendAlert( req, "API token(s) have not been accessed for a while.", fmt.Sprintf(TMPL_ALERT_BODY, c, wcg.AbsoluteUrl(req, "/admin/clients.html")), ) } res.WriteJson(map[string]interface{}{ "alerted_tokens": c, "monitored_tokens": m, "total_tokens": len(tokens), }) }, )) }
func crawl(res *wcg.Response, req *wcg.Request, member *ameblo.Member, app *App) { var appCtx = lib.NewAppContextFromRequest(req) var logger = appCtx.Logger var targets []*ameblo.AmebloEntry result := make([]string, 0) d := NewAmebloEntryDriver(appCtx) crawler := ameblo.NewCrawler(appCtx.NewHttpClient()) // prioritize the entries which are not crawled and are posted recently. q := d.NewQuery().Filter("CrawledAt =", time.Time{}).Order("PostAt").Limit(NUM_ENTRIES_TO_CRAWL_PER_CALL) if member != nil { q = q.Filter("Owner =", member.Name) } if _, err := q.GetAll(&targets); err != nil { lib.InternalError(res, req, err) return } // Crawl Contents for _, e := range targets { logger.Info("Crawling %s ... ", e.Url) if e1, err := crawler.CrawlEntry(e.Url); err != nil { logger.Warn("Failed to crawl %s, skipped: %v", e.Url, err) continue } else { if e1 == nil { logger.Warn("CrawlEntry returns nil entry for %s", e.Url) e.Content = "<No Content>" e.CrawledAt = time.Now() } else { logger.Debug("CrawlEntry scraped %d bytes.", len(e1.Content)) e.Content = e1.Content } result = append(result, e.Url) } } if err := updateContents(appCtx, targets, app.MemberList); err != nil { lib.InternalError(res, req, err) return } res.WriteJson(result) }
func queryPosts(res *wcg.Response, req *wcg.Request, per_page int) (*postQueryResult, error) { var list []blog.Post var basePath = req.HttpRequest().URL.Path is_admin := (lib.GetUserKind(req) == lib.Admin) && (req.Query("is_admin") == "true") if per_page == 0 { per_page = wcg.ParseInt(req.Query("n"), 5, 0, 20) // default 5, max 20 } page := wcg.ParseInt(req.Query("page"), 0, 0, wcg.ParseIntMax) q := NewPostDriver(lib.NewAppContextFromRequest(req)).NewQuery() q = q.Order("-PublishAt").Order("-CreatedAt") if !is_admin { q = q.Filter("PublishAt <=", time.Now()).Filter("IsDraft =", false).Filter("IsHidden =", false) } _, err := q.Offset(page * per_page).Limit(per_page).GetAll(&list) if err != nil { return nil, err } if list == nil { list = make([]blog.Post, 0) } p := &postQueryResult{ Posts: list, } // prev url if page > 0 { p.Previous = fmt.Sprintf("%s?page=%d&n=%d", basePath, page-1, per_page) if is_admin { p.Previous = fmt.Sprintf("%s&is_admin=true", p.Previous) } } // next url if len(list) == per_page { p.Next = fmt.Sprintf("%s?page=%d&n=%d", basePath, page+1, per_page) if is_admin { p.Next = fmt.Sprintf("%s&is_admin=true", p.Next) } } return p, nil }
func historyInsights(res *wcg.Response, req *wcg.Request, app *App) { var appCtx = lib.NewAppContextFromRequest(req) member, ok := app.Members[req.Param("member")] if !ok { lib.NotFound(res, req) return } var insights amebloHistoryInsights mckey := fmt.Sprintf(MC_KEY_HISTORY, app.Key, member.Name) dent := NewAmebloEntryDriver(appCtx) dref := NewAmebloRefDriver(appCtx) mc := appCtx.NewMemcacheDriver() err := mc.CachedObject(mckey, &insights, func() (interface{}, error) { return getAmebloHistoryInsights(member, dent, dref) }, req.Query("force") == "1") if err != nil { lib.Error(res, req, err) return } res.WriteJson(insights) }
func setupYAuctionPages(app *App) { app.Page.Page("/yauction/keywords/", "オークション状況"). AssetPath("/artistapp/yauction/keyword.js"). Templates("./artistapp/yauction/keyword.html"). Handler( func(res *wcg.Response, req *wcg.Request, p *lib.Page) { keyword := req.Query("q") var ckeyword yauction.CrawlerKeyword ckdriver := NewCrawlerKeywordDriver(lib.NewAppContextFromRequest(req)) if err := ckdriver.Get(ckdriver.NewKey(keyword, 0, nil), &ckeyword); err != nil { if err == ds.ErrNoSuchEntity { app.Page.NotFound(res, req) } else { app.Page.InternalError(res, req, err) } return } p.Title = fmt.Sprintf("ヤフオク: %q", keyword) p.Ogp("title", fmt.Sprintf("ヤフオク: %q", keyword)) res.SetLocal("Keyword", keyword) }) }
func setupYAuctionApi(app *App) { app.Api.Get("/yauction/admin/closed/", lib.Admin.Required(func(res *wcg.Response, req *wcg.Request) { var appCtx = lib.NewAppContextFromRequest(req) keyword := req.Query("q") if keyword == "" { app.Api.BadRequest(res, req, fmt.Errorf("Missing 'q' parameter.")) return } ids, err := crawlClosedKeyword(appCtx, keyword) if err != nil && ids == nil { lib.Error(res, req, err) return } if err != nil { res.WriteJson(map[string]interface{}{ "num_updates": len(ids), "auction_ids": ids, "error": err.Error(), }) } else { res.WriteJson(map[string]interface{}{ "num_updates": len(ids), "auction_ids": ids, }) } })) app.Api.Get("/yauction/keywords/", func(res *wcg.Response, req *wcg.Request) { keyword, _ := url.QueryUnescape(req.Query("q")) var appCtx = lib.NewAppContextFromRequest(req) var ckeyword yauction.CrawlerKeyword var assocs []yauction.AssocCrawlerKeywordAuctionItem ckdriver := NewCrawlerKeywordDriver(appCtx) assocdriver := NewAssocCrawlerKeywordAuctionItemDriver(appCtx) aidriver := NewAuctionItemDriver(appCtx) if err := ckdriver.Get(ckdriver.NewKey(keyword, 0, nil), &ckeyword); err != nil { if err == ds.ErrNoSuchEntity { app.Api.NotFound(res, req) } else { app.Api.InternalError(res, req, err) } return } if _, err := assocdriver.NewQuery().Filter("Keyword =", keyword).GetAll(&assocs); err != nil { app.Api.InternalError(res, req, err) return } itemKeys := make([]*datastore.Key, len(assocs)) items := make([]yauction.AuctionItem, len(assocs)) for i, assoc := range assocs { itemKeys[i] = aidriver.NewKey(assoc.AuctionId, 0, nil) } err := aidriver.GetMulti(itemKeys, items) if ds.IsDatastoreError(err) { app.Api.InternalError(res, req, err) return } res.WriteJson(map[string]interface{}{ "keyword": ckeyword, "auctions": items, }) }) }
func setupApi(app *App) { app.Api.Get("/posts/", func(res *wcg.Response, req *wcg.Request) { if result, err := queryPosts(res, req, 0); err != nil { lib.Error(res, req, err) } else { res.WriteJson(result) } }) app.Api.Get("/posts/:id.json", func(res *wcg.Response, req *wcg.Request) { var p blog.Post driver := NewPostDriver(lib.NewAppContextFromRequest(req)) key := driver.NewKey(req.Param("id"), 0, nil) if err := driver.Get(key, &p); err != nil { lib.Error(res, req, err) return } if p.IsDraft && lib.GetUserKind(req) != lib.Admin { app.Api.NotFound(res, req) } else { res.WriteJson(p) } }) app.Api.Post("/posts/", lib.Admin.Required( func(res *wcg.Response, req *wcg.Request) { driver := NewPostDriver(lib.NewAppContextFromRequest(req)) p := &blog.Post{} if err := updateAttributesFromForm(res, req, p); err != nil { lib.Error(res, req, err) return } if _, err := driver.Save(p); err != nil { lib.Error(res, req, err) } app.Api.Created(res, req, p.Id) }, )) app.Api.Put("/posts/:id.json", lib.Admin.Required( func(res *wcg.Response, req *wcg.Request) { var p blog.Post driver := NewPostDriver(lib.NewAppContextFromRequest(req)) key := driver.NewKey(req.Param("id"), 0, nil) if err := driver.Get(key, &p); err != nil { lib.Error(res, req, err) return } if err := updateAttributesFromForm(res, req, &p); err != nil { lib.Error(res, req, err) return } if _, err := driver.Save(&p); err != nil { lib.Error(res, req, err) return } else { app.Api.Ok(res, req) } }, )) app.Api.Delete("/posts/:id.json", lib.Admin.Required( func(res *wcg.Response, req *wcg.Request) { driver := NewPostDriver(lib.NewAppContextFromRequest(req)) key := driver.NewKey(req.Param("id"), 0, nil) if err := driver.Delete(key); err != nil { lib.Error(res, req, err) return } else { app.Api.Ok(res, req) } }, )) }
func setupEventApi(app *App) { app.Api.Get("/events/", func(res *wcg.Response, req *wcg.Request) { var events []event.Event d := NewEventDriver(lib.NewAppContextFromRequest(req)) if _, err := d.NewQuery().GetAll(&events); err != nil { lib.Error(res, req, err) } else { if events == nil { events = make([]event.Event, 0) } res.WriteJson(events) } }) app.Api.Get("/events/importer/", lib.Admin.Required( func(res *wcg.Response, req *wcg.Request) { var appCtx = lib.NewAppContextFromRequest(req) url := req.Query("url") if eventShowList, err := importer.Import(url, appCtx.NewHttpClient()); err != nil { lib.Error(res, req, err) } else { res.WriteJson(eventShowList) } }, )) app.Api.Post("/events/", lib.Admin.Required( func(res *wcg.Response, req *wcg.Request) { t := &event.Event{} d := NewEventDriver(lib.NewAppContextFromRequest(req)) if err := updateAttributesFromForm(res, req, t); err != nil { lib.Error(res, req, err) return } if t, err := d.Save(t); err != nil { lib.Error(res, req, err) } else { app.Api.Created(res, req, t.Id) } }, )) app.Api.Put("/events/:id.json", lib.Admin.Required( func(res *wcg.Response, req *wcg.Request) { if t, err := loadEvent(app, req, "id"); err != nil { lib.Error(res, req, err) return } else { if err := updateAttributesFromForm(res, req, t); err != nil { lib.Error(res, req, err) return } d := NewEventDriver(lib.NewAppContextFromRequest(req)) if _, err := d.Save(t); err != nil { lib.Error(res, req, err) } else { app.Api.Ok(res, req) } } }, )) app.Api.Delete("/events/:id.json", lib.Admin.Required( func(res *wcg.Response, req *wcg.Request) { d := NewEventDriver(lib.NewAppContextFromRequest(req)) if err := d.Delete(req.Param("id")); err != nil { lib.Error(res, req, err) } else { app.Api.Ok(res, req) } }, )) }
func setupEventPages(app *App) { app.Page.Navi("/events/", "イベント"). Templates("./artistapp/events.html", "./artistapp/show_part.html"). AssetPath("/artistapp/events.js"). Handler( func(res *wcg.Response, req *wcg.Request, p *lib.Page) { var appCtx = lib.NewAppContextFromRequest(req) var all = req.Query("all") == "1" q := NewShowDriver(appCtx).NewQuery() if all { q = q.Order("-StartAt") } else { q = q.Filter("StartAt >=", util.Date(now())).Order("StartAt") } if result, err := queryShows(res, req, q); err != nil { lib.Error(res, req, err) return } else { p.Ogp("type", "blog") res.SetLocal("Shows", result.Shows) if all { res.SetLocal("Future", result.Current) res.SetLocal("Next", fmt.Sprintf("%s&all=1", result.Next)) res.SetLocal("Previous", fmt.Sprintf("%s&all=1", result.Previous)) } else { res.SetLocal("All", fmt.Sprintf("%s&all=1", result.Current)) res.SetLocal("Next", result.Next) res.SetLocal("Previous", result.Previous) } } }) app.Page.Page("/events/:name.html", "イベント"). Templates("./artistapp/events.html"). Handler( func(res *wcg.Response, req *wcg.Request, p *lib.Page) { //d := NewShowDriver(app.Key, gae.NewContext(req), req.Logger) }) app.Page.Navi("/admin/events.html", "イベント管理"). Templates("./artistapp/admin/events.html"). AssetPath("/artistapp/admin/events.js"). RequireAuth(lib.Admin) app.Page.Page("/admin/events/:id.html", ""). Templates("./artistapp/admin/events.html"). AssetPath("/artistapp/admin/shows.js"). Handler( func(res *wcg.Response, req *wcg.Request, p *lib.Page) { var e event.Event d := NewEventDriver(lib.NewAppContextFromRequest(req)) key := d.NewKey(req.Param("id"), 0, nil) if err := d.Get(key, &e); err != nil { lib.Error(res, req, err) return } p.Title = fmt.Sprintf("公演一覧 - %s", e.Title) }) app.Page.Page("/venues/:id/", ""). AssetPath("/artistapp/venues.js"). Templates("./artistapp/venues.html"). Handler( func(res *wcg.Response, req *wcg.Request, p *lib.Page) { var appCtx = lib.NewAppContextFromRequest(req) var showList []event.Show q := NewShowDriver(appCtx).NewQuery() q = q.Filter("VenueId =", req.Param("id")) if _, err := q.Limit(1).GetAll(&showList); err != nil { lib.Error(res, req, err) return } if len(showList) == 0 { app.Page.NotFound(res, req) return } if list, err := NewEventShowList(appCtx, showList); err != nil { lib.Error(res, req, err) return } else { ev := list[0] p.Title = fmt.Sprintf("会場情報 - %s", ev.VenueName) res.SetLocal("VenueName", ev.VenueName) res.SetLocal("Latitude", ev.Latitude) res.SetLocal("Longitude", ev.Longitude) } }) }
func setupEventShowApi(app *App) { app.Api.Get("/events/:event_id/shows/", func(res *wcg.Response, req *wcg.Request) { if e, err := loadEvent(app, req, "event_id"); err != nil { lib.Error(res, req, err) return } else { var list []event.Show d := NewShowDriver(lib.NewAppContextFromRequest(req)) if _, err = d.NewQueryWithEventId(e.Id).GetAll(&list); err != nil { lib.Error(res, req, err) return } if list == nil { list = make([]event.Show, 0) } if req.Query("composit") == "1" { res.WriteJson(compositShowList{ Event: e, ShowList: list, }) } else { res.WriteJson(list) } } }) app.Api.Post("/events/:event_id/shows/", func(res *wcg.Response, req *wcg.Request) { if e, err := loadEvent(app, req, "event_id"); err != nil { lib.Error(res, req, err) return } else { if err := showFormValidator.Eval(req.HttpRequest().PostForm); err != nil { lib.Error(res, req, err) return } d := NewShowDriver(lib.NewAppContextFromRequest(req)) s := updateShowAttributes(req, &event.Show{ EventId: e.Id, }) if s, err := d.Save(s); err != nil { lib.Error(res, req, err) return } else { app.Api.Created(res, req, s.Id) } } }) app.Api.Put("/events/:event_id/shows/:id.json", func(res *wcg.Response, req *wcg.Request) { if _, err := loadEvent(app, req, "event_id"); err != nil { lib.Error(res, req, err) return } else { var show event.Show d := NewShowDriver(lib.NewAppContextFromRequest(req)) if _, err := d.Load(req.Param("id"), req.Param("event_id"), &show); err != nil { lib.Error(res, req, err) return } else { if _, err = d.Save(updateShowAttributes(req, &show)); err != nil { lib.Error(res, req, err) return } res.WriteJson(show) } } }) app.Api.Delete("/events/:event_id/shows/:id.json", func(res *wcg.Response, req *wcg.Request) { if e, err := loadEvent(app, req, "event_id"); err != nil { lib.Error(res, req, err) return } else { d := NewShowDriver(lib.NewAppContextFromRequest(req)) if err := d.Delete(req.Param("id"), e.Id); err != nil { lib.Error(res, req, err) return } else { app.Api.Ok(res, req) } } }) }