// Marks a bid as placed. This is purely informational for the user. func PlaceBid(c appengine.Context, bidId string) error { var key *datastore.Key if k, err := datastore.DecodeKey(bidId); err != nil { return err } else { key = k } f := func(c appengine.Context) error { var bid Bid if err := datastore.Get(c, key, bidCodec{&bid}); err != nil { return err } if bid.State != InQueue { c.Infof("Not placing bid %v : State=%v", key, bid.State) return nil } bid.State = Placed if _, err := datastore.Put(c, key, bidCodec{&bid}); err != nil { return err } return nil } return datastore.RunInTransaction(c, f, nil) }
func ParseFeed(c appengine.Context, contentType, origUrl, fetchUrl string, body []byte) (*Feed, []*Story, error) { cr := defaultCharsetReader if !bytes.EqualFold(body[:len(xml.Header)], []byte(xml.Header)) { enc, err := encodingReader(body, contentType) if err != nil { return nil, nil, err } if enc != encoding.Nop { cr = nilCharsetReader body, err = ioutil.ReadAll(transform.NewReader(bytes.NewReader(body), enc.NewDecoder())) if err != nil { return nil, nil, err } } } var feed *Feed var stories []*Story var atomerr, rsserr, rdferr error feed, stories, atomerr = parseAtom(c, body, cr) if feed == nil { feed, stories, rsserr = parseRSS(c, body, cr) } if feed == nil { feed, stories, rdferr = parseRDF(c, body, cr) } if feed == nil { c.Warningf("atom parse error: %s", atomerr.Error()) c.Warningf("xml parse error: %s", rsserr.Error()) c.Warningf("rdf parse error: %s", rdferr.Error()) return nil, nil, fmt.Errorf("Could not parse feed data") } feed.Url = origUrl return parseFix(c, feed, stories, fetchUrl) }
func getTickets(c appengine.Context, status string, newStatus string, limit int) ([]Ticket, []*datastore.Key, error) { c.Debugf("getTickets: ", status) statusKey, err := getStatusByType(c, status) if err != nil { return nil, nil, err } c.Debugf("statusKey: ", statusKey) q := datastore.NewQuery(DATASTORE_TICKET). Filter("Status =", statusKey). //Filter("SellerUrl >", ""). Order("Modified"). Limit(limit) var tickets []Ticket ticket_keys, err := q.GetAll(c, &tickets) if err != nil { return nil, nil, err } if len(tickets) < 1 { return nil, nil, fmt.Errorf("getTickets: No new tickets found with status: %s", status) } if newStatus != "" { err = setTicketsStatus(c, tickets, ticket_keys, newStatus) if err != nil { return nil, nil, err } } return tickets, ticket_keys, nil }
func (e Event) GetHTMLView(c appengine.Context) string { buffer := new(bytes.Buffer) var tmpltxt = `<label>Event Title: </label><a href="https://orgreminders.appspot.com/editevent?id={{.Key}}">{{.Title}}</a> <br> <label>When Due: </label>{{.DueFormatted}} <br> <label>Organization(s): </label>{{range .Orgs}}{{.}},{{end}} <br> <label>Email enabled: </label>{{.Email}} <br> <label>Text Enabled: </label>{{.Text}} <br> <label>Email Message: </label><br><div class="msgbody">{{.EmailMessage}}</div> <br> <label>Text Message: </label><br><div class="msgbody"><pre>{{.TextMessage}}</pre></div> <br>` template, terr := template.New("foo").Parse(tmpltxt) if terr != nil { c.Infof("error parsing event html template: %v", terr) return "" } template.Execute(buffer, e) return buffer.String() }
func searchUser(instanceId string, c appengine.Context) (key *datastore.Key, user *User, err error) { var v []User // Initial variables key = nil user = nil err = nil // Query f := datastore.NewQuery(UserKind) f = f.Filter("InstanceId=", instanceId) k, err := f.GetAll(c, &v) if err != nil { c.Errorf("%s in getting data from datastore\n", err) err = errors.New("Datastore is temporary unavailable") return } if k == nil || len(k) == 0 { return } key = k[0] user = &v[0] return }
// Handler to find all questions with specific tags func tagHandler(w http.ResponseWriter, r *http.Request, c appengine.Context, user stackongo.User) { // Collect query tag := r.FormValue("tagSearch") // Create and fill in a new webData struct tempData := newWebData() data.CacheLock.Lock() // range through the question caches golang stackongoand add if the question contains the tag for cacheType, cache := range data.Caches { for _, question := range cache { if contains(question.Tags, tag) { tempData.Caches[cacheType] = append(tempData.Caches[cacheType], question) } } } tempData.Qns = data.Qns data.CacheLock.Unlock() page := template.Must(template.ParseFiles("public/template.html")) var tagQuery = []string{ "tag", tag, } if err := page.Execute(w, writeResponse(user, tempData, c, tagQuery)); err != nil { c.Criticalf("%v", err.Error()) } }
//This is the main tags page //Should display a list of tags that are logged in the database //User can either click on a tag to view any questions containing that tag or search by a specific tag func viewTagsHandler(w http.ResponseWriter, r *http.Request, c appengine.Context, user stackongo.User) { //Read all tags and their counts from the db, and execute the page query := readTagsFromDb() //Format array of tags into another array, to be easier formatted on the page into a table //An array of tagData arrays of size 4 var tagArray [][]tagData var tempTagArray []tagData i := 0 for _, t := range query { tempTagArray = append(tempTagArray, t) i++ if i == 4 { tagArray = append(tagArray, tempTagArray) i = 0 //clear the temp array. tempTagArray = nil } } tagArray = append(tagArray, tempTagArray) page := template.Must(template.ParseFiles("public/viewTags.html")) if err := page.Execute(w, queryReply{user, tagArray}); err != nil { c.Criticalf("%v", err.Error()) } }
func read(c appengine.Context, name string) (fi *FileInfo, data []byte, err error) { name, _, _ = mangle(c, name) fi1, err := stat(c, name) if err != nil { return nil, nil, err } if fi1.IsDir { dt, err := readdir(c, name) if err != nil { return nil, nil, err } fi = fi1 data = dt return fi, data, nil } root := datastore.NewKey(c, "RootKey", "v2:", 0, nil) dkey := datastore.NewKey(c, "FileData", "", fi1.Qid, root) var fd FileData c.Infof("DATASTORE Read %q", name) if err := datastore.Get(c, dkey, &fd); err != nil { return nil, nil, err } fi = fi1 data = fd.Data return fi, data, nil }
func createPostKeyID(postID string, c appengine.Context) string { if postID == "" { c.Errorf("Creating a post entity key with no postID!") } return "post:" + postID }
func HandleEvent(tags *event.EventHeaderTags, ev event.Event, ctx appengine.Context, sender EventSendService) error { res, err := handleRecvEvent(tags, ev, ctx) if nil != err { ctx.Errorf("Failed to handle event[%d:%d] for reason:%v", ev.GetType(), ev.GetVersion(), err) return err } if nil == res { var empty bytes.Buffer sender.Send(&empty) return nil } res.SetHash(ev.GetHash()) compressType := Cfg.CompressType if httpres, ok := res.(*event.HTTPResponseEvent); ok { v := httpres.GetHeader("Content-Type") if len(v) > 0 && Cfg.CompressType != event.COMPRESSOR_NONE { if isContentTypeInCompressFilter(v) { compressType = event.COMPRESSOR_NONE } } } x := new(event.CompressEvent) x.SetHash(ev.GetHash()) x.CompressType = compressType x.Ev = res y := new(event.EncryptEvent) y.SetHash(ev.GetHash()) y.EncryptType = Cfg.EncryptType y.Ev = x var buf bytes.Buffer tags.Encode(&buf) event.EncodeEvent(&buf, y) sender.Send(&buf) return nil }
func RetrieveActDetails(c appengine.Context, actId int) (res *ActDetail, err os.Error) { var d DSActDetail if itm, err := memcache.Get(c, "actId__"+strconv.Itoa(actId)); err != nil && err != memcache.ErrCacheMiss { return nil, err } else if err == nil { // Cache hit buf := bytes.NewBuffer(itm.Value) dec := gob.NewDecoder(buf) dec.Decode(&d) } else { // Cache miss key := datastore.NewKey(c, "DSActDetail", "", int64(actId), nil) if err := datastore.Get(c, key, &d); err == datastore.ErrNoSuchEntity { return &ActDetail{ActId: actId}, nil } else if err != nil { return nil, err } buf := bytes.NewBufferString("") enc := gob.NewEncoder(buf) enc.Encode(d) itm := &memcache.Item{ Key: "actId__" + strconv.Itoa(actId), Value: buf.Bytes(), } err = memcache.Set(c, itm) c.Debugf("Request cache to memcache") } return d.fromDS(), nil }
// AllocateIDs returns a range of n integer IDs with the given kind and parent // combination. kind cannot be empty; parent may be nil. The IDs in the range // returned will not be used by the datastore's automatic ID sequence generator // and may be used with NewKey without conflict. // // The range is inclusive at the low end and exclusive at the high end. In // other words, valid intIDs x satisfy low <= x && x < high. // // If no error is returned, low + n == high. func AllocateIDs(c appengine.Context, kind string, parent *Key, n int) (low, high int64, err error) { if kind == "" { return 0, 0, errors.New("datastore: AllocateIDs given an empty kind") } if n < 0 { return 0, 0, fmt.Errorf("datastore: AllocateIDs given a negative count: %d", n) } if n == 0 { return 0, 0, nil } req := &pb.AllocateIdsRequest{ ModelKey: keyToProto("", NewIncompleteKey(c, kind, parent)), Size: proto.Int64(int64(n)), } res := &pb.AllocateIdsResponse{} if err := c.Call("datastore_v3", "AllocateIds", req, res, nil); err != nil { return 0, 0, err } // The protobuf is inclusive at both ends. Idiomatic Go (e.g. slices, for loops) // is inclusive at the low end and exclusive at the high end, so we add 1. low = res.GetStart() high = res.GetEnd() + 1 if low+int64(n) != high { return 0, 0, fmt.Errorf("datastore: internal error: could not allocate %d IDs", n) } return low, high, nil }
// Purge removes all tasks from a queue. func Purge(c appengine.Context, queueName string) error { req := &taskqueue_proto.TaskQueuePurgeQueueRequest{ QueueName: []byte(queueName), } res := &taskqueue_proto.TaskQueuePurgeQueueResponse{} return c.Call("taskqueue", "PurgeQueue", req, res, nil) }
func createUserKeyID(userID string, c appengine.Context) string { if userID == "" { c.Errorf("Creating an appUser entity key with no userID!") } return "user:" + userID }
func count_uv_pv(c appengine.Context, mins int) (uv int, pv int) { count := 0 uniq := make(map[string]bool) query := &log.Query{ AppLogs: true, StartTime: time.Now().Add(time.Duration(-1*mins) * time.Minute), Versions: []string{"1"}, } for results := query.Run(c); ; { record, err := results.Next() if err == log.Done { break } if err != nil { c.Errorf("Failed to retrieve next log: %v", err) } if len(record.AppLogs) > 0 && strings.Index(record.Combined, "GET "+config.URL_BEACON) > 0 { zcookie := record.AppLogs[0].Message if zcookie != "" { count++ uniq[zcookie] = true } } } uv = len(uniq) pv = count return }
// DeleteMulti is a batch version of Delete. // If any keys cannot be found, an appengine.MultiError is returned. // Each key must be at most 250 bytes in length. func DeleteMulti(c appengine.Context, key []string) error { req := &pb.MemcacheDeleteRequest{ Item: make([]*pb.MemcacheDeleteRequest_Item, len(key)), } for i, k := range key { req.Item[i] = &pb.MemcacheDeleteRequest_Item{Key: []byte(k)} } res := &pb.MemcacheDeleteResponse{} if err := c.Call("memcache", "Delete", req, res, nil); err != nil { return err } if len(res.DeleteStatus) != len(key) { return ErrServerError } me, any := make(appengine.MultiError, len(key)), false for i, s := range res.DeleteStatus { switch s { case pb.MemcacheDeleteResponse_DELETED: // OK case pb.MemcacheDeleteResponse_NOT_FOUND: me[i] = ErrCacheMiss any = true default: me[i] = ErrServerError any = true } } if any { return me } return nil }
// Sends an email to the author of part with a link to continue. func sendMail(c appengine.Context, story Story) { if story.Complete { return } var subject, text string part := story.LastPart() url := fmt.Sprintf(serverUrl, story.Id, story.NextId) if part != nil { subject = "Please write the next part of this story." text = fmt.Sprintf("%s, %s wrote:\n> %s\n\nPlease visit %s to write the next part.", capital(fuzzyTime(part.Written)), getFullEmail(c, part.Author), part.Visible, url) } else { subject = "Please write the first part of this story." text = fmt.Sprintf("%s, %s initiated a new story.\n\nPlease visit %s to write the beginning.", capital(fuzzyTime(story.Created)), getFullEmail(c, story.Creator), url) } msg := &mail.Message{ Sender: sender, To: []string{story.NextAuthor}, Subject: subject, Body: text, } if err := mail.Send(c, msg); err != nil { c.Errorf("Couldn't send email: %v", err) panic(err) } }
func load(c appengine.Context, id string) (*Group, error) { group := &Group{} _, err := memcache.JSON.Get(c, id, group) if err == nil { return group, nil } if err != memcache.ErrCacheMiss { c.Errorf("memcache get %q: %v", id, err) } group, err = fetch(c, id) if err != nil { return nil, err } item := &memcache.Item{ Key: id, Object: group, Expiration: time.Hour, } err = memcache.JSON.Set(c, item) if err != nil { c.Errorf("memcache set %q: %v", id, err) } return group, nil }
// Handler to find all questions answered/being answered by the user in URL func userHandler(w http.ResponseWriter, r *http.Request, c appengine.Context, user stackongo.User) { userID, _ := strconv.Atoi(r.FormValue("id")) query := userData{} // Create and fill in a new webData struct tempData := newWebData() data.CacheLock.Lock() // range through the question caches golang stackongo and add if the question contains the tag tempData.Caches["unanswered"] = data.Caches["unanswered"] if userQuery, ok := data.Users[userID]; ok { query = userQuery for cacheType, cache := range data.Users[userID].Caches { if cacheType != "unanswered" { tempData.Caches[cacheType] = cache } } tempData.Qns = data.Qns } data.CacheLock.Unlock() page := template.Must(template.ParseFiles("public/template.html")) var userQuery = []string{ "user", query.User_info.Display_name, } if err := page.Execute(w, writeResponse(user, tempData, c, userQuery)); err != nil { c.Criticalf("%v", err.Error()) } }
// DeleteMulti is a batch version of Delete. // The returned slice will have the same length as the input slice. // If a given key cannot be found, its corresponding value in the // returned error slice is set to ErrCacheMiss. // Each key must be at most 250 bytes in length. func DeleteMulti(c appengine.Context, key []string) []error { req := &pb.MemcacheDeleteRequest{ Item: make([]*pb.MemcacheDeleteRequest_Item, len(key)), } for i, k := range key { req.Item[i] = &pb.MemcacheDeleteRequest_Item{Key: []byte(k)} } res := &pb.MemcacheDeleteResponse{} e := make([]error, len(key)) err := c.Call("memcache", "Delete", req, res, nil) if err == nil && len(e) != len(res.DeleteStatus) { err = ErrServerError } if err != nil { for i := range e { e[i] = err } return e } for i, s := range res.DeleteStatus { switch s { case pb.MemcacheDeleteResponse_DELETED: e[i] = nil case pb.MemcacheDeleteResponse_NOT_FOUND: e[i] = ErrCacheMiss default: e[i] = ErrServerError } } return e }
func userPageHandler(w http.ResponseWriter, r *http.Request, c appengine.Context, user stackongo.User) { page := template.Must(template.ParseFiles("public/userPage.html")) usr, _ := strconv.Atoi(r.FormValue("userId")) currentUser := data.Users[usr] query := userData{User_info: currentUser.User_info} var n int query.Caches = make(map[string][]stackongo.Question) n = Min(3, len(currentUser.Caches["unanswered"])) if n > 0 { query.Caches["answered"] = currentUser.Caches["answered"][0:n] } n = Min(3, len(currentUser.Caches["pending"])) if n > 0 { query.Caches["pending"] = currentUser.Caches["pending"][0:n] } n = Min(3, len(currentUser.Caches["updating"])) if n > 0 { query.Caches["updating"] = currentUser.Caches["updating"][0:n] } if err := page.Execute(w, queryReply{user, query}); err != nil { c.Criticalf("%v", err.Error()) } }
func writeEncoded(c appengine.Context, w http.ResponseWriter, data interface{}) { newEncoder := bencode.NewEncoder(w) if err := newEncoder.Encode(data); err != nil { c.Errorf("Failed to encode data: %s", err) writeInternalError(w) } }
func searchGroup(name string, c appengine.Context) (key *datastore.Key, group *Group, err error) { var v []Group // Initial variables key = nil group = nil err = nil // Query f := datastore.NewQuery(GroupKind) f = f.Filter("Name=", name) k, err := f.GetAll(c, &v) if err != nil { c.Errorf("%s in getting data from datastore\n", err) err = errors.New("Datastore is temporary unavailable") return } if k == nil || len(k) == 0 { return } key = k[0] group = &v[0] return }
func GetAllAccounts(c appengine.Context) ([]string, error) { accounts := []string{} _, err := memcache.Gob.Get(c, "AccountsArray", &accounts) if err == nil { return accounts, nil } var accountsDS []AccountDS query := datastore.NewQuery("Account") _, err = query.GetAll(c, &accountsDS) if err != nil { return []string{}, err } for _, account := range accountsDS { accounts = append(accounts, account.UserID) } cacheItem := &memcache.Item{ Key: "AccountsArray", Object: accounts, } err = memcache.Gob.Set(c, cacheItem) if err != nil { c.Infof("Accounts array not cached (%v)", err) } return accounts, err }
// Send sends a message. // If any failures occur with specific recipients, the error will be an appengine.MultiError. func (m *Message) Send(c appengine.Context) error { req := &pb.XmppMessageRequest{ Jid: m.To, Body: &m.Body, RawXml: &m.RawXML, } if m.Type != "" && m.Type != "chat" { req.Type = &m.Type } if m.Sender != "" { req.FromJid = &m.Sender } res := &pb.XmppMessageResponse{} if err := c.Call("xmpp", "SendMessage", req, res, nil); err != nil { return err } if len(res.Status) != len(req.Jid) { return fmt.Errorf("xmpp: sent message to %d JIDs, but only got %d statuses back", len(req.Jid), len(res.Status)) } me, any := make(appengine.MultiError, len(req.Jid)), false for i, st := range res.Status { if st != pb.XmppMessageResponse_NO_ERROR { me[i] = errors.New(st.String()) any = true } } if any { return me } return nil }
// extracts the URL from an Feed. If the feed has publication date, we only // add the URL since the last feed update func getLinksFromFeed(dsFeed *data.Feed, r *http.Request, c appengine.Context) ([]string, error) { c.Infof("DS Feed @ importer: %v", dsFeed) _, body, err := extract.GetURL(dsFeed.URL, r) if err != nil { return nil, err } rss, err := parseFeedContent(body) if err != nil { return nil, err } var urls []string stopURL := dsFeed.LastURL for index, i := range rss.ItemList { if index == 0 { dsFeed.LastURL = i.Link } if i.Link == stopURL { break } urls = append(urls, i.Link) } return urls, nil }
func addLogo(profilePtr *image.Image, logo string, context appengine.Context) []byte { profileImage := *profilePtr destImage := image.NewRGBA(profileImage.Bounds()) draw.Draw(destImage, destImage.Bounds(), profileImage, image.ZP, draw.Src) if logoImages, ok := THELOGOIMAGES[logo]; ok { randi := rand.Intn(len(logoImages)) logoImage := logoImages[randi] offset := image.Pt(5, 5) if strings.HasPrefix(logo, "NLD-") { offset = image.Pt(0, 0) } start := profileImage.Bounds().Size() start = start.Sub(offset) start = start.Sub(logoImage.Bounds().Size()) bounds := image.Rectangle{start, start.Add(logoImage.Bounds().Size())} draw.Draw(destImage, bounds, logoImage, image.ZP, draw.Over) } else { context.Errorf("Cannot load logoimage for %s", logo) } buffer := new(bytes.Buffer) err := png.Encode(buffer, destImage) check(err, context) return buffer.Bytes() }
func dumpMessage(c appengine.Context, msg *mail.Message) { iw := InfoWriter{c} c.Infof("--BEGIN MESSAGE") io.Copy(iw, msg.Body) c.Infof("END MESSAGE--") }
// NewPage returns a new Page initialized embedding the template with the // given name and data, the current user for the given context, and the // latest announcement. func NewPage(ctx appengine.Context, name string, data interface{}) (*Page, error) { p := &Page{ Content: name, Data: data, Topics: topicList, Cities: cityList, } a, err := conf.LatestAnnouncement(ctx) if err != nil { ctx.Errorf("latest announcement: %v", err) } if a != nil { p.Announcement = a.Message } if u := user.Current(ctx); u != nil { p.User = u p.LogoutURL, err = user.LogoutURL(ctx, "/") } else { p.LoginURL, err = user.LoginURL(ctx, "/") } return p, err }
// This will reimburse the bid's price and fee to the buyer. func RetireBid(c appengine.Context, key *datastore.Key) error { f := func(c appengine.Context) error { now := time.Now() dao := NewGaeAccountingDao(c, true) var bid Bid if err := datastore.Get(c, key, bidCodec{&bid}); err != nil { return err } if bid.State == Matched { c.Infof("Not retiring matched bid %v", key) return nil } if err := bid.Retire(dao, key.Encode(), now); err != nil { return err } if _, err := datastore.Put(c, key, bidCodec{&bid}); err != nil { return err } return dao.Flush() } if err := datastore.RunInTransaction(c, f, &datastore.TransactionOptions{XG: true}); err != nil { return err } return nil }