示例#1
0
func DeleteArticlesWithinScope(c appengine.Context, scope ArticleScope) error {
	ancestorKey, err := scope.key(c)
	if err != nil {
		return err
	}

	batchWriter := NewBatchWriter(c, BatchDelete)

	q := datastore.NewQuery("Article").Ancestor(ancestorKey).KeysOnly()
	for t := q.Run(c); ; {
		articleKey, err := t.Next(nil)

		if err == datastore.Done {
			break
		} else if err != nil {
			return err
		}

		if err := batchWriter.EnqueueKey(articleKey); err != nil {
			c.Errorf("Error queueing article for batch delete: %s", err)
			return err
		}
	}

	if err := batchWriter.Flush(); err != nil {
		c.Errorf("Error flushing batch queue: %s", err)
		return err
	}

	return nil
}
示例#2
0
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
}
示例#3
0
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()
}
示例#4
0
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)
	}
}
示例#5
0
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
}
示例#6
0
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
}
示例#7
0
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
}
示例#8
0
func GetAllClassesFromProds(c appengine.Context) []T {
	c.Infof("GetAllClassesFromProds: Enter")
	const cacheKey_product_classes = "product_classes"
	var item_list []T
	_, err := memcache.JSON.Get(c, cacheKey_product_classes, &item_list)
	if err != nil {
		//Memcache failed to extract the list.
		c.Infof("GetAllClassesFromProds: Unable to retrieve list from Memcache: %v", err)
		item_list = datastoreGetAllClassesFromProds(c)
		memcache_item := &memcache.Item{
			Key:        cacheKey_product_classes,
			Object:     item_list,
			Expiration: oneDay,
		}
		//Store into Memcache
		// Add the item to the memcache, if the key does not already exist
		if err := memcache.JSON.Set(c, memcache_item); err == memcache.ErrNotStored {
			c.Infof("item with key %q already exists", memcache_item.Key)
		} else if err != nil {
			c.Errorf("error adding item: %v", err)
		} else {

			c.Infof("got stored as json ")
		}
	}
	return item_list

}
示例#9
0
文件: data.go 项目: lambdaX/rsc.godev
func update(ctxt appengine.Context, kind string, data interface{}) error {
	updaters.RLock()
	up := updaters.m[kind]
	updaters.RUnlock()

	t := reflect.TypeOf(data)
	dv, _ := strconv.Atoi(t.Elem().Field(0).Tag.Get("dataversion"))
	if dv == 0 {
		return nil
	}
	v := reflect.ValueOf(data)
	v.Elem().Field(0).SetInt(int64(dv))
	for _, fv := range up {
		if fv.Type().In(0) != t {
			return fmt.Errorf("type mismatch for data kind %q: cannot apply updater %s to %T", kind, fv.Type(), data)
		}
		rv := fv.Call([]reflect.Value{v})
		if len(rv) > 0 {
			err := rv[0].Interface().(error)
			if err != nil {
				ctxt.Errorf("applying updater: %v", err)
				return fmt.Errorf("applying updater: %v", err)
			}
		}
	}
	return nil
}
示例#10
0
func (r *Room) Send(c appengine.Context, message string) error {
	var clients []Client

	_, err := memcache.JSON.Get(c, r.Name, &clients)
	if err != nil && err != memcache.ErrCacheMiss {
		return err
	}

	if err == memcache.ErrCacheMiss {
		q := datastore.NewQuery("Client").Ancestor(r.Key(c))
		_, err = q.GetAll(c, &clients)
		if err != nil {
			return err
		}
		err = memcache.JSON.Set(c, &memcache.Item{
			Key: r.Name, Object: clients,
		})
		if err != nil {
			return err
		}
	}

	for _, client := range clients {
		err = channel.Send(c, client.ClientID, message)
		if err != nil {
			c.Errorf("sending %q: %v", message, err)
		}
	}

	return nil
}
func PutInBlobstore(c appengine.Context, toStore interface{}) (appengine.BlobKey, error) {
	//TODO: check capabilities
	var k appengine.BlobKey
	var data bytes.Buffer
	enc := gob.NewEncoder(&data)
	err := enc.Encode(toStore)
	if err != nil {
		c.Errorf("Datastore - PutInBlobstore - error 1 - %s", err)
		return k, err
	}

	w, err := blobstore.Create(c, "application/octet-stream")
	if err != nil {
		c.Errorf("Datastore - PutInBlobstore - error 2 - %s", err)
		return k, err
	}
	_, err = w.Write(data.Bytes())
	if err != nil {
		c.Errorf("Datastore - PutInBlobstore - error 3 - %s", err)
		return k, err
	}
	err = w.Close()
	if err != nil {
		c.Errorf("Datastore - PutInBlobstore - error 4 - %s", err)
		return k, err
	}
	k, err = w.Key()
	if err != nil {
		c.Errorf("Datastore - PutInBlobstore - error 5 - %s", err)
	}
	return k, err
}
示例#12
0
func unregisterUser(addr string, c appengine.Context) {
	q := datastore.NewQuery(USER_MODEL).
		Filter("Email =", addr).
		KeysOnly()
	keys, err := q.GetAll(c, nil)
	if err != nil {
		c.Errorf("Cound not query the model for %s: %v", addr, err)
		return
	}
	if len(keys) == 0 {
		c.Infof("No such user to unregister: %s", addr)
		return
	}
	for i := range keys {
		datastore.Delete(c, keys[i])
	}
	c.Infof("Removed user %s", addr)

	msg := &gaeMail.Message{
		Sender:  "*****@*****.**",
		To:      []string{addr},
		Subject: "Email unregistered",
		Body:    "user " + addr + " has been unregistered",
	}
	gaeMail.Send(c, msg)
}
示例#13
0
func sendSubscription(addr string, c appengine.Context) {
	code := getSubCode()
	msg := &gaeMail.Message{
		Sender:  "*****@*****.**",
		To:      []string{addr},
		Subject: "confirm " + code,
		Body:    "Reply without changing subject",
	}
	if err := gaeMail.Send(c, msg); err != nil {
		c.Errorf("Couldn't send email to %s for %s: %v", addr, code, err)
	}

	// XXXX if successful, register the code as (email, code, 0 (retry)) tuple.
	confirmation := Confirmation{
		Email: addr,
		Code:  code,
		Retry: 0,
	}

	_, err := datastore.Put(c,
		datastore.NewIncompleteKey(c, CONFIRM_MODEL, nil),
		&confirmation)
	if err != nil {
		c.Errorf("Couldn't write confirmation code for %s, %s: %v", addr, code, err)
		return
	}
	c.Infof("Wrote confirmation successfully for %s, %s", addr, code)
}
示例#14
0
// send uses the Channel API to send the provided message in JSON-encoded form
// to the client identified by clientID.
//
// Channels created with one version of an app (eg, the default frontend)
// cannot be sent on from another version (eg, a backend). This is a limitation
// of the Channel API that should be fixed at some point.
// The send function creates a task that runs on the frontend (where the
// channel was created). The task handler makes the channel.Send API call.
func send(c appengine.Context, clientID string, m Message) {
	if clientID == "" {
		c.Debugf("no channel; skipping message send")
		return
	}
	switch {
	case m.TilesDone:
		c.Debugf("tiles done")
	case m.ZipDone:
		c.Debugf("zip done")
	default:
		c.Debugf("%d tiles", len(m.IDs))
	}
	b, err := json.Marshal(m)
	if err != nil {
		panic(err)
	}
	task := taskqueue.NewPOSTTask("/send", url.Values{
		"clientID": {clientID},
		"msg":      {string(b)},
	})
	host := appengine.DefaultVersionHostname(c)
	task.Header.Set("Host", host)
	if _, err := taskqueue.Add(c, task, sendQueue); err != nil {
		c.Errorf("add send task failed: %v", err)
	}
}
示例#15
0
func TriggerBatchProcessing(c appengine.Context, article ArticleId) error {
	// Instead of submitting a task to match incoming bids, resulting in one task per bid,
	// we collect bids for up to two seconds and batch-process them afterwards.
	semaphoreKey := "semaphore-" + string(article)
	if semaphore, err := memcache.Increment(c, semaphoreKey, 1, 0); err != nil {
		return err
	} else if semaphore >= 2 {
		c.Infof("Batch processing already triggered for article %v", article)
		memcache.IncrementExisting(c, semaphoreKey, -1)
		return nil
	} else {
		time.Sleep(1 * time.Second)
		c.Infof("Starting batch processing...")
		memcache.IncrementExisting(c, semaphoreKey, -1)
		time_before := time.Now()
		matchingErr := MatchIncomingBids(c, article)
		time_after := time.Now()
		duration := time_after.Sub(time_before)
		if duration > 1000*time.Millisecond {
			c.Errorf("Batch processing finished after %v. Limit exceeded!", duration)
		} else if duration > 500*time.Millisecond {
			c.Warningf("Batch processing finished after %v. Limit in danger.", duration)
		} else {
			c.Infof("Batch processing finished after %v.", duration)
		}
		return matchingErr
	}
}
示例#16
0
文件: fetch.go 项目: qtse/go_fetch
func fetchNomRoll(c appengine.Context, skey string, actId int) os.Error {
	///  req,err := http.NewRequest("GET", fmt.Sprintf("https://cadetone.aafc.org.au/activities/nominalroll.php?ActID=%d",actId), nil)
	///  if err != nil {
	///    c.Errorf("Fetch Roll - actId:%d - %s", actId, err.String())
	///    return err
	///  }
	///  session := c1SessionCookie(skey)
	///  injectSession(req,session)
	///  resp, err := GetClient(c).Do(req)
	///  if err != nil {
	///    c.Errorf("Fetch Roll - actId:%d - %s", actId, err.String())
	///    return err
	///  }
	///  defer resp.Body.Close()

	///  c.Infof("Fetch Roll OK - actId:%d", actId)

	///  res,err := parseNomRoll(c, &resp.Body)
	res, err := parseNomRoll(c)
	if err != nil {
		c.Errorf("Fetch Roll - actId:%d - %s", actId, err.String())
		return err
	}
	res.ActId = actId

	c.Infof(fmt.Sprint(res.ActId))
	for _, r := range res.Roll {
		c.Infof(fmt.Sprint(*r))
	}

	return err
}
示例#17
0
文件: user.go 项目: reedperry/gogram
func createUserKeyID(userID string, c appengine.Context) string {
	if userID == "" {
		c.Errorf("Creating an appUser entity key with no userID!")
	}

	return "user:" + userID
}
示例#18
0
文件: fetch.go 项目: qtse/go_fetch
///func parsePSearch(c appengine.Context, r *io.ReadCloser) (string, os.Error) {
func parsePSearch(c appengine.Context) (string, os.Error) {
	tmp := strings.NewReader(samplePSearchHtml)
	r := &tmp
	n, err := html.Parse(*r)
	if err != nil {
		c.Errorf("%s", err.String())
		return "", err
	}

	nc := NewCursor(n)
	nc = nc.FindById("main1")
	if !nc.Valid {
		printNode(c, n, 0)
		return "", os.NewError("Can't find main1")
	}
	nc.Prune()

	curr := nc.FindChildElement("table").NextSiblingElement("table")
	curr = curr.FindChildElement("tr").NextSiblingElement("tr")
	curr = curr.FindChildElement("input")
	if !curr.Valid {
		return "", os.NewError("Person not found")
	}

	for _, a := range curr.Attr() {
		if a.Key == "onclick" {
			l := strings.Split(a.Val, "'")
			return l[1], nil
		}
	}
	return "", os.NewError("No onclick attribute")
}
示例#19
0
文件: post.go 项目: reedperry/gogram
func createPostKeyID(postID string, c appengine.Context) string {
	if postID == "" {
		c.Errorf("Creating a post entity key with no postID!")
	}

	return "post:" + postID
}
示例#20
0
func fooHandler(c appengine.Context, w http.ResponseWriter, r *http.Request) (interface{}, error) {
	id := r.URL.Path[len(FOOS_API):]
	c.Errorf("Received foo id %v", id)
	if len(id) > 0 {
		switch r.Method {
		case "GET":
			id64, err := strconv.ParseInt(id, 10, 64)
			if err != nil {
				return nil, err
			}
			foo := new(Foo)
			foo.Id = FooId(id64)
			return foo.get(c)
		default:
			return nil, fmt.Errorf(r.Method + " on " + r.URL.Path + " not implemented")
		}
	} else {
		switch r.Method {
		case "POST":
			foo, err := decodeFoo(r.Body)
			if err != nil {
				return nil, err
			}
			return foo.save(c)
		case "GET":
			return getAllFoos(c)
		default:
			return nil, fmt.Errorf(r.Method + " on " + r.URL.Path + " not implemented")
		}
	}
	return nil, nil
}
示例#21
0
文件: web.go 项目: jimhopp/frederic
func webuserOK(c appengine.Context, w http.ResponseWriter, r *http.Request) bool {
	if !userauthenticated(c) {
		url, err := user.LoginURL(c, r.URL.String())
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return false
		}
		w.Header().Set("Location", url)
		w.WriteHeader(http.StatusFound)
		return false
	}
	u := user.Current(c)
	authzed, err := userauthorized(c, u.Email)
	if err != nil {
		c.Errorf("authorization error: %v", err)
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return false
	}
	if !authzed {
		c.Warningf("authorization failure: %v", u.Email)
		w.WriteHeader(http.StatusForbidden)
		err = templates.ExecuteTemplate(w, "unauthorized.html", nil)
		if err != nil {
			c.Errorf("unauthorized user and got err on template: %v", err)
		}
		return false
	}
	return true
}
func loadFullFeed(domain string, ctx appengine.Context, r *http.Request) (buf *bytes.Buffer) {
	newctx := newappengine.NewContext(r)

	tok, err := config.Exchange(newctx, r.FormValue("code"))
	if err != nil {
		ctx.Errorf("exchange error: %v", err)
		return
	}

	ctx.Infof("tok: %v", tok)

	client := config.Client(newctx, tok)
	expFeedUrl := fmt.Sprintf(feedUrl, domain)
	expFeedUrl = expFeedUrl + "&max-results=50000"
	res, err := client.Get(expFeedUrl)
	if err != nil {
		ctx.Errorf("get: %v", err)
		return
	}

	defer res.Body.Close()

	buf = new(bytes.Buffer)
	io.Copy(buf, res.Body)
	return
}
示例#23
0
// AppEngineLogHandler sends logs to AppEngine.
// The record must contain the appengine request context.
func AppEngineLogHandler() log15.Handler {
	logFormat := log15.JsonFormat()
	return log15.FuncHandler(func(r *log15.Record) error {
		var c appengine.Context
		index := 0
		for i, e := range r.Ctx {
			if ct, ok := e.(appengine.Context); ok {
				c = ct
				index = i
				break
			}
		}
		if c == nil {
			// not in the context of a request
			return nil
		}
		r.Ctx = append(r.Ctx[:index-1], r.Ctx[index+1:]...)
		log := string(logFormat.Format(r))
		switch r.Lvl {
		case log15.LvlCrit:
			c.Criticalf(log)
		case log15.LvlError:
			c.Errorf(log)
		case log15.LvlWarn:
			c.Warningf(log)
		case log15.LvlInfo:
			c.Infof(log)
		case log15.LvlDebug:
			c.Debugf(log)
		}
		return nil
	})
}
示例#24
0
// [END func_sign]
func GetAllProds(c appengine.Context) []models.Product {

	const cacheKey = "products"

	var item_list []models.Product
	_, err := memcache.JSON.Get(c, cacheKey, &item_list)
	if err != nil {
		//Memcache failed to extract the list.
		c.Infof("Unable to retrieve list from Memcache: %v", err)

		q := datastore.NewQuery("Product").Ancestor(productKey(c)).Limit(1000)
		item_list = make([]models.Product, 0, 1000)
		if _, err := q.GetAll(c, &item_list); err != nil {
			return nil
		}

		c.Infof("got products")
		memcache_item := &memcache.Item{
			Key:        cacheKey,
			Object:     item_list,
			Expiration: oneDay,
		}
		//Store into Memcache
		// Add the item to the memcache, if the key does not already exist
		if err := memcache.JSON.Set(c, memcache_item); err == memcache.ErrNotStored {
			c.Infof("item with key %q already exists", memcache_item.Key)
		} else if err != nil {
			c.Errorf("error adding item: %v", err)
		} else {

			c.Infof("got stored as json ")
		}
	}
	return item_list
}
示例#25
0
文件: mail.go 项目: shicks/storytime
// 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)
	}
}
示例#26
0
文件: log.go 项目: icub3d/gorca
// Log is a helper function that logs the given message to appenging
// with the given priority. Accepted priorities are "debug", "info",
// "warn", "error", and "crit". Other values default to "error".
func Log(c appengine.Context, r *http.Request, priority string,
	message string, params ...interface{}) {

	message = fmt.Sprintf("[%s] [%s] [%s]: %s", r.RemoteAddr, r.Method,
		r.URL, message)

	switch priority {
	case "debug":
		c.Debugf(message, params...)

	case "info":
		c.Infof(message, params...)

	case "warn":
		c.Warningf(message, params...)

	case "error":
		c.Errorf(message, params...)

	case "crit":
		c.Criticalf(message, params...)

	default:
		c.Errorf(message, params...)
	}
}
示例#27
0
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
}
示例#28
0
// Object usually too big (1MB limit), so shard.
// http://stackoverflow.com/questions/9127982/
func BytesToShardedMemcache(c appengine.Context, key string, b []byte) {
	/*
		var buf bytes.Buffer
		if err := gob.NewEncoder(&buf).Encode(f); err != nil {
			db.C.Errorf("fdb error encoding item: %v", err)
			return
		}
		b := buf.Bytes()
	*/

	items := []*memcache.Item{}
	for i := 0; i < len(b); i += chunksize {
		k := fmt.Sprintf("=%d=%s", i, key)
		s, e := i, i+chunksize-1
		if e >= len(b) {
			e = len(b) - 1
		}
		c.Infof(" #=== [%7d, %7d] (%d) %s", s, e, len(b), k)
		items = append(items, &memcache.Item{Key: k, Value: b[s : e+1]}) // slice sytax is [s,e)
	}

	if err := memcache.SetMulti(c, items); err != nil {
		c.Errorf(" #=== cdb sharded store fail: %v", err)
	}

	c.Infof(" #=== Stored '%s' (len=%d)!", key, len(b))
}
示例#29
0
文件: page.go 项目: javier/goconf
// 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
}
示例#30
0
func DeleteFolder(c appengine.Context, ref FolderRef) error {
	folderKey, err := ref.key(c)
	if err != nil {
		return err
	}

	// Get a list of relevant subscriptions
	q := datastore.NewQuery("Subscription").Ancestor(folderKey).KeysOnly().Limit(defaultBatchSize)
	subscriptionKeys, err := q.GetAll(c, nil)

	if err != nil {
		return err
	}

	// Delete folder & subscriptions
	if err := datastore.Delete(c, folderKey); err != nil {
		c.Errorf("Error deleting folder: %s", err)
		return err
	}

	if subscriptionKeys == nil {
		// No subscriptions; nothing more to do
		return nil
	}

	if err := datastore.DeleteMulti(c, subscriptionKeys); err != nil {
		c.Errorf("Error deleting subscriptions: %s", err)
		return err
	}

	return nil
}