// Should return the user with the given username, or throw an Entity not found error
func TestGetUser(t *testing.T) {
	ctx, done, err := aetest.NewContext()
	if err != nil {
		t.Fatal(err)
	}
	defer done()
	key := datastore.NewKey(ctx, "User", "testertim", 0, nil)
	if _, err := datastore.Put(ctx, key, &models.User{FirstName: "Tim"}); err != nil {
		t.Fatal(err)
	}

	user := &models.User{Username: "******"}
	if err = repositories.GetUser(ctx, user); err == nil || err.Error() != "datastore: no such entity" {
		t.Errorf("Error: %v; want datastore: no such entity", err)
	}

	user.Username = "******"
	err = repositories.GetUser(ctx, user)
	if err != nil {
		t.Fatal(err)
	}

	if firstName, want := user.FirstName, "Tim"; firstName != want {
		t.Errorf("User First Name %d, want %d", firstName, want)
	}

	if username, want := user.Username, "testertim"; username != want {
		t.Errorf("Username %d, want %d", username, want)
	}
}
Example #2
0
func example6() {
	type Photo struct {
		URL string
	}
	var ctx context.Context

	// [START ancestor_query_example]
	// Create two Photo entities in the datastore with a Person as their ancestor.
	tomKey := datastore.NewKey(ctx, "Person", "Tom", 0, nil)

	wPhoto := Photo{URL: "http://example.com/some/path/to/wedding_photo.jpg"}
	wKey := datastore.NewKey(ctx, "Photo", "", 0, tomKey)
	_, err := datastore.Put(ctx, wKey, wPhoto)
	// check err

	bPhoto := Photo{URL: "http://example.com/some/path/to/baby_photo.jpg"}
	bKey := datastore.NewKey(ctx, "Photo", "", 0, tomKey)
	_, err = datastore.Put(ctx, bKey, bPhoto)
	// check err

	// Now fetch all Photos that have tomKey as an ancestor.
	// This will populate the photos slice with wPhoto and bPhoto.
	q := datastore.NewQuery("Photo").Ancestor(tomKey)
	var photos []Photo
	_, err = q.GetAll(ctx, &photos)
	// check err
	// do something with photos
	// [END ancestor_query_example]
	_ = err
	_ = photos
}
Example #3
0
// Increment increments the named counter.
func Increment(ctx context.Context, name string) error {
	// Get counter config.
	var cfg counterConfig
	ckey := datastore.NewKey(ctx, configKind, name, 0, nil)
	err := datastore.RunInTransaction(ctx, func(ctx context.Context) error {
		err := datastore.Get(ctx, ckey, &cfg)
		if err == datastore.ErrNoSuchEntity {
			cfg.Shards = defaultShards
			_, err = datastore.Put(ctx, ckey, &cfg)
		}
		return err
	}, nil)
	if err != nil {
		return err
	}
	var s shard
	err = datastore.RunInTransaction(ctx, func(ctx context.Context) error {
		shardName := fmt.Sprintf("%s-shard%d", name, rand.Intn(cfg.Shards))
		key := datastore.NewKey(ctx, shardKind, shardName, 0, nil)
		err := datastore.Get(ctx, key, &s)
		// A missing entity and a present entity will both work.
		if err != nil && err != datastore.ErrNoSuchEntity {
			return err
		}
		s.Name = name
		s.Count++
		_, err = datastore.Put(ctx, key, &s)
		return err
	}, nil)
	if err != nil {
		return err
	}
	memcache.IncrementExisting(ctx, memcacheKey(name), 1)
	return nil
}
Example #4
0
// Put will put this JunitTestResult into Datastore using the given key.
func (ƨ JunitTestResult) Put(ctx context.Context, key *datastore.Key) (*datastore.Key, error) {
	if key != nil {
		return datastore.Put(ctx, key, &ƨ)
	}

	return datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "JunitTestResult", nil), &ƨ)
}
Example #5
0
// Put will put this Challenge into Datastore using the given key.
func (ƨ Challenge) Put(ctx context.Context, key *datastore.Key) (*datastore.Key, error) {
	if key != nil {
		return datastore.Put(ctx, key, &ƨ)
	}

	return datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Challenge", nil), &ƨ)
}
Example #6
0
// Put will put this Submission into Datastore using the given key.
func (ƨ Submission) Put(ctx context.Context, key *datastore.Key) (*datastore.Key, error) {
	if key != nil {
		return datastore.Put(ctx, key, &ƨ)
	}

	return datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Submission", nil), &ƨ)
}
Example #7
0
// Increment increments the named counter.
func Increment(c context.Context, valName string) error {

	// Get counter config.
	shardsTotal := dsu.WrapInt{}
	dsu.McacheGet(c, mcKeyShardsTotal(valName), &shardsTotal)
	if shardsTotal.I < 1 {
		ckey := datastore.NewKey(c, dsKindNumShards, mcKeyShardsTotal(valName), 0, nil)
		errTx := datastore.RunInTransaction(c,
			func(c context.Context) error {
				err := datastore.Get(c, ckey, &shardsTotal)
				if err == datastore.ErrNoSuchEntity {
					shardsTotal.I = defaultNumShards
					_, err = datastore.Put(c, ckey, &shardsTotal)
				}
				return err
			}, nil)
		if errTx != nil {
			return errTx
		}
		dsu.McacheSet(c, mcKeyShardsTotal(valName), dsu.WrapInt{shardsTotal.I})
	}

	// pick random counter and increment it
	errTx := datastore.RunInTransaction(c,
		func(c context.Context) error {
			shardId := rand.Intn(shardsTotal.I)
			dsKey := datastore.NewKey(c, dsKindShard, keySingleShard(valName, shardId), 0, nil)
			var sd WrapShardData
			err := datastore.Get(c, dsKey, &sd)
			// A missing entity and a present entity will both work.
			if err != nil && err != datastore.ErrNoSuchEntity {
				return err
			}
			sd.Name = valName
			sd.ShardId = shardId
			sd.I++
			_, err = datastore.Put(c, dsKey, &sd)
			if ll > 2 {
				aelog.Infof(c, "ds put %v %v", dsKey, sd)
			}
			return err
		}, nil)
	if errTx != nil {
		return errTx
	}

	memcache.Increment(c, mcKey(valName), 1, 0)

	// collect number of updates
	//    per valName per instance in memory
	//    for every interval of 10 minutes
	//
	//  a batch job checks if the number of shards should be increased or decreased
	//    and truncates this map
	updateSamplingFrequency[valName+util.TimeMarker()[:len("2006-01-02 15:0")]] += 1

	return nil
}
Example #8
0
// SaveBoardState commits the state to the datastore
func SaveBoardState(c context.Context, state *BoardState) (*BoardState, error) {
	sessionKey, err := datastore.DecodeKey(state.SessionID)
	if err != nil {
		return nil, err
	}
	stateModel := &boardStateModel{}
	stateModel.parentKey = sessionKey
	stateModel.lastModified = time.Now()
	stateModel.key, err = datastore.Put(c, datastore.NewIncompleteKey(c, "BoardState", stateModel.parentKey), stateModel)
	if err != nil {
		return nil, err
	}

	// Initialize the result
	result := &BoardState{
		ID:           stateModel.key.Encode(),
		SessionID:    stateModel.parentKey.Encode(),
		LastModified: time.Now(),
		Players:      make(map[string]*Player),
	}

	// Save the players
	for k, v := range state.Players {
		p := &playerModel{
			Name:     k,
			Location: v.Location,
		}
		p.parentKey = stateModel.key
		p.key, err = datastore.Put(c, datastore.NewIncompleteKey(c, "PlayerState", p.parentKey), p)
		if err != nil {
			return nil, err
		}

		for _, card := range v.Hand {
			cardModel := &cardModel{
				Name:  card.Name,
				Color: card.Color,
			}
			cardModel.parentKey = p.key
			cardModel.key, err = datastore.Put(c, datastore.NewIncompleteKey(c, "PlayerCard", p.parentKey), cardModel)
			if err != nil {
				return nil, err
			}

		}

		// Added player to result
		result.Players[k] = &Player{
			Location: p.Location,
			Hand:     v.Hand,
		}
	}

	return result, nil
}
// Save will put this JunitSubmission into Datastore using the given key.
func (ƨ JunitSubmission) Save(ctx context.Context, key ...*datastore.Key) (*datastore.Key, error) {
	if len(key) > 1 {
		panic("zero or one key expected")
	}

	if len(key) == 1 && key[0] != nil {
		return datastore.Put(ctx, key[0], &ƨ)
	}

	return datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "JunitSubmission", nil), &ƨ)
}
Example #10
0
// Save will put this AccessToken into Datastore using the given key.
func (x AccessToken) Save(ctx context.Context, key ...*datastore.Key) (*datastore.Key, error) {
	if len(key) > 1 {
		panic("zero or one key expected")
	}

	if len(key) == 1 && key[0] != nil {
		return datastore.Put(ctx, key[0], &x)
	}

	return datastore.Put(ctx, datastore.NewIncompleteKey(ctx, AccessTokenKind, nil), &x)
}
func example6() {
	// [START parent]
	// Create Employee entity
	employee := &Employee{ /* ... */ }
	employeeKey, err := datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Employee", nil), employee)

	// Use Employee as Address entity's parent
	// and save Address entity to datastore
	address := &Address{ /* ... */ }
	addressKey := datastore.NewIncompleteKey(ctx, "Address", employeeKey)
	_, err = datastore.Put(ctx, addressKey, address)
	// [END parent]
	_ = err
}
Example #12
0
func uploadHandler(w http.ResponseWriter, r *http.Request) {

	//ducapple name

	name := r.FormValue("fileName")
	file, _, err := r.FormFile("uploadFile")
	if err != nil {
		//add error handling
		return
	}
	defer file.Close()
	b, err := ioutil.ReadAll(file)
	if err != nil {
	}

	c := appengine.NewContext(r)
	// get user data
	u, err := getUser(r)
	if err != nil {
	}

	key := datastore.NewKey(c, "File", u.UserKey+"/"+name, 0, nil)
	rtn := File{}
	if err = datastore.Get(c, key, &rtn); err != nil {
		if err != datastore.ErrNoSuchEntity {
			return
		}
	} else {
		u.Size -= int64(len(rtn.Data))
	}

	f := File{
		UserKey: u.UserKey,
		Data:    b,
	}
	u.Size += int64(len(b))
	lu := user.Current(c)

	_, err = datastore.Put(c, datastore.NewKey(c, "User", lu.ID, 0, nil), u)
	if err != nil {
	}

	// add empty slide data
	_, err = datastore.Put(c, key, &f)
	if err != nil {
	}

	http.Redirect(w, r, "/me/file/view", 301)
}
Example #13
0
func newPlayer(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r)

	id := r.FormValue("id")
	if id == "" {
		http.Error(w, "need a non-blank id from the form data", http.StatusBadRequest)
		return
	}

	k := datastore.NewKey(ctx, "Player", id, 0, nil)
	err := datastore.RunInTransaction(ctx, func(ctx context.Context) error {
		var p *Player
		if err := datastore.Get(ctx, k, p); err != datastore.ErrNoSuchEntity {
			return codeErr{fmt.Errorf("player(%s) already exists", id), http.StatusConflict}
		}

		// TODO(jaguilar): Add another system. Add a system Registry. Leagues
		// can have ratings.
		p = &Player{Rating: eloSys.InitialRating(), key: k}
		if _, err := datastore.Put(ctx, p.key, p); err != nil {
			return err
		}
		return nil
	}, nil)
	if err != nil {
		httpError(w, err)
		return
	}
	fmt.Fprintf(
		w,
		`<html><head><meta http-equiv="refresh" content="5,/"></head>
		<body>Successfully added %s. Redirecting you in five seconds.</body></html>`,
		id)
}
func Get(c context.Context, key, def string, values ...interface{}) string {
	configLock.Lock()
	defer configLock.Unlock()
	val, ok := configCache[key]
	if ok {
		return fmt.Sprintf(val, values...)
	}
	value := Value{}
	dskey := datastore.NewKey(c, ConfigName, key, 0, nil)
	err := datastore.Get(c, dskey, &value)
	if err == datastore.ErrNoSuchEntity {
		value.Val = def
		log.Infof(c, "Creating default config for key - %s - default value is - %s", key, value.Val)
		_, err = datastore.Put(c, dskey, &value)
		if err != nil {
			log.Errorf(c, "Error creating default config for key - %s - error is - %v", key, err)
		}
		return fmt.Sprintf(def, values...) // return default, totally new config setting
	}
	if err != nil {
		log.Errorf(c, "Error fetching config for key - %s - error is - %v", key, err)
		return def // error, return the default
	}
	configCache[key] = value.Val
	return fmt.Sprintf(value.Val, values...)
}
Example #15
0
func (s *UserService) Create(ctx context.Context, u *User) error {
	span := trace.FromContext(ctx).NewChild("trythings.user.Create")
	defer span.Finish()

	// TODO Make sure u.GoogleID == user.Current(ctx).ID

	if u.ID != "" {
		return fmt.Errorf("u already has id %q", u.ID)
	}

	if u.CreatedAt.IsZero() {
		u.CreatedAt = time.Now()
	}

	id, _, err := datastore.AllocateIDs(ctx, "User", nil, 1)
	if err != nil {
		return err
	}
	u.ID = fmt.Sprintf("%x", id)

	rootKey := datastore.NewKey(ctx, "Root", "root", 0, nil)
	k := datastore.NewKey(ctx, "User", u.ID, 0, rootKey)
	k, err = datastore.Put(ctx, k, u)
	if err != nil {
		return err
	}

	return nil
}
Example #16
0
func registerHandler(w http.ResponseWriter, r *http.Request) {

	c := appengine.NewContext(r)

	log.Infof(c, "Register")

	u := user.Current(c)
	r.ParseForm()

	userKey := r.FormValue("UserKey")
	log.Infof(c, "UserKey:%s", userKey)
	if existUser(r, userKey) {
		log.Infof(c, "Exists")
		return
	}

	rtn := User{
		UserKey: userKey,
		Size:    0,
	}

	_, err := datastore.Put(c, datastore.NewKey(c, "User", u.ID, 0, nil), &rtn)
	if err != nil {
		panic(err)
	}

	//Profile Page
	meRender(w, "./templates/me/profile.tmpl", rtn)
}
Example #17
0
func createUser(res http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	ctx := appengine.NewContext(req)
	hashedPass, err := bcrypt.GenerateFromPassword([]byte(req.FormValue("password")), bcrypt.DefaultCost)
	if err != nil {
		log.Errorf(ctx, "error creating password: %v", err)
		http.Error(res, err.Error(), 500)
		return
	}
	user := User{
		Email:    req.FormValue("email"),
		UserName: req.FormValue("userName"),
		Password: string(hashedPass),
	}
	key := datastore.NewKey(ctx, "Users", user.UserName, 0, nil)
	key, err = datastore.Put(ctx, key, &user)
	if err != nil {
		log.Errorf(ctx, "error adding todo: %v", err)
		http.Error(res, err.Error(), 500)
		return
	}

	createSession(res, req, user)
	// redirect
	http.Redirect(res, req, "/", 302)
}
func handleListForm(res http.ResponseWriter, req *http.Request) {
	ctx := appengine.NewContext(req)
	session := getSession(ctx, req)
	username := session.Username
	if username == "" {
		http.Redirect(res, req, "/loginform", 302)
		return
	}
	list := &List{
		Username: username,
	}
	key := datastore.NewKey(ctx, "List", username, 0, nil)
	datastore.Get(ctx, key, list)
	if req.Method == "POST" {
		list.List = req.FormValue("list")
		_, err := datastore.Put(ctx, key, list)
		if err != nil {
			http.Error(res, err.Error(), 500)
			return
		}
		http.Redirect(res, req, "/user/"+username, 302)
		return
	}
	model := &listModel{
		Session: session,
		List:    list.List,
	}
	err := tpls.ExecuteTemplate(res, "listform", model)
	if err != nil {
		http.Error(res, err.Error(), 500)
		return
	}
}
Example #19
0
func newStoryProcess(res http.ResponseWriter, req *http.Request, _ httprouter.Params) {
	ctx := appengine.NewContext(req)
	sd := sessionInfo(req)

	t := time.Now()
	// y, m, d := t.Date()
	time := t.UTC()
	s := fmt.Sprintf("%v", time)

	story := Story{
		Owner:       sd.Username,
		Title:       req.FormValue("story"),
		Description: req.FormValue("description"),
		Link:        strings.Replace(req.FormValue("story"), " ", "-", -1),
		CreatedDate: s,
	}

	userkey := datastore.NewKey(ctx, "Users", sd.Username, 0, nil)
	key := datastore.NewKey(ctx, "Stories", story.Title, 0, userkey) //owner is ancestor - eliminates need for owner-story table
	key, err := datastore.Put(ctx, key, &story)
	if err != nil {
		log.Errorf(ctx, "error adding todo: %v", err)
		http.Error(res, err.Error(), 500)
		return
	}

	// redirect
	http.Redirect(res, req, "/browse", 302)
}
Example #20
0
func (s *MigrationService) run(ctx context.Context, m *Migration) error {
	if m.RunAt.IsZero() {
		m.RunAt = time.Now()
	}

	if m.Version.IsZero() {
		return errors.New("cannot run migration without version")
	}

	// TODO: Pipe rootKey through with context.
	rootKey := datastore.NewKey(ctx, "Root", "root", 0, nil)
	k := datastore.NewIncompleteKey(ctx, "Migration", rootKey)

	err := m.Run(ctx, s)
	if err != nil {
		return err
	}

	_, err = datastore.Put(ctx, k, m)
	if err != nil {
		return err
	}

	return nil
}
Example #21
0
func incrementSoldCounter(c context.Context) error {
	_, err := memcache.IncrementExisting(c, "sold", 1)
	if err != nil {
		if err == datastore.ErrNoSuchEntity {
			log.Infof(c, "[counter] Cache miss when incrementing")
		} else {
			return err
		}
	}

	sold := new(Counter)
	err = datastore.RunInTransaction(c, func(c context.Context) error {
		key := datastore.NewKey(c, "Counter", "sold", 0, nil)
		err := datastore.Get(c, key, sold)
		if err != nil && err != datastore.ErrNoSuchEntity {
			return err
		}
		sold.Value++
		_, err = datastore.Put(c, key, sold)
		if err != nil {
			sold.Value--
			return err
		}
		return nil
	}, nil)

	return err
}
Example #22
0
// create profile
func createProfile(req *http.Request, profile *Profile) error {
	ctx := appengine.NewContext(req)
	key := datastore.NewKey(ctx, "Profile", profile.Email, 0, nil)
	_, err := datastore.Put(ctx, key, profile)
	return err
	// you can use memcache also to improve your consistency
}
Example #23
0
func handleIndex(res http.ResponseWriter, req *http.Request) {
	if req.Method == "POST" {
		term := req.FormValue("term")
		def := req.FormValue("def")

		ctx := appengine.NewContext(req)
		key := datastore.NewKey(ctx, "Word", term, 0, nil)

		entity := &Word{
			Term: term,
			Def:  def,
		}

		_, err := datastore.Put(ctx, key, entity)
		if err != nil {
			http.Error(res, err.Error(), 500)
			return
		}
	}

	res.Header().Set("Content-Type", "text/html")
	fmt.Fprintln(res, `
	<form method="POST" action="/words/">
		Enter a term <input type="text" name="term">
		Enter its definition <textarea name="def"></textarea>
		<input type="submit">
	</form>`)
}
Example #24
0
func index(res http.ResponseWriter, req *http.Request) {
	if req.Method == "POST" {
		name := req.FormValue("name")
		descrip := req.FormValue("descrip")

		ctx := appengine.NewContext(req)
		parentKey := datastore.NewKey(ctx, "House", "Garage", 0, nil)
		key := datastore.NewKey(ctx, "Tools", name, 0, parentKey)
		// 1 write / second
		// We will eventually use memcache to buffer our writes

		entity := &Tool{
			Name:        name,
			Description: descrip,
		}

		_, err := datastore.Put(ctx, key, entity)
		if err != nil {
			http.Error(res, err.Error(), 500)
			return
		}
	}
	res.Header().Set("Content-Type", "text/html")
	fmt.Fprintln(res, `
		<form method="POST">
			<h1>Tool</h1>
			<input type="text" name="name"><br>
			<h1>Descrip</h1>
			<textarea name="descrip"></textarea>
			<input type="submit">
		</form>`)
}
Example #25
0
func putTweet(req *http.Request, user *User, tweet *Tweet) error {
	ctx := appengine.NewContext(req)
	userKey := datastore.NewKey(ctx, "Users", user.UserName, 0, nil)
	key := datastore.NewIncompleteKey(ctx, "Tweets", userKey)
	_, err := datastore.Put(ctx, key, tweet)
	return err
}
Example #26
0
func TestBasicUsage2(t *testing.T) {
	c, closer, err := aetest.NewContext()
	if err != nil {
		t.Fatal(err)
	}
	defer closer()

	src := &a.Sample{"Foo!"}
	key := datastore.NewIncompleteKey(c, "Sample", nil)
	_, err = datastore.Put(c, key, src)
	if err != nil {
		t.Fatal(err)
	}

	builder := a.NewSampleQueryBuilder()
	builder.Foo.GreaterThan("Foo").KeysOnly().Limit(3)
	iter := builder.Query().Run(c)
	for {
		key, err = iter.Next(nil)
		if err == datastore.Done {
			break
		} else if err != nil {
			t.Fatal(err)
		}
		src := &a.Sample{}
		err = datastore.Get(c, key, src)
		if err != nil {
			t.Fatal(err)
		}

		t.Logf("key: %#v, entity: %#v", key, src)
	}
}
Example #27
0
func submitAddHandler(w http.ResponseWriter, r *http.Request) {
	ctx := appengine.NewContext(r)
	if err := r.ParseForm(); err != nil {
		serveErr(ctx, err, w)
		return
	}

	success, err := recaptchaCheck(ctx, r.FormValue("g-recaptcha-response"), r.RemoteAddr)
	if err != nil {
		serveErr(ctx, err, w)
		return
	}

	if !success {
		log.Warningf(ctx, "reCAPTCHA check failed")
		failedTmpl.ExecuteTemplate(w, "base", nil)
		return
	}

	sub := Submission{
		URL:       template.URL(strings.TrimSpace(r.FormValue("url"))),
		Submitted: time.Now(),
	}

	if _, err := datastore.Put(ctx, datastore.NewIncompleteKey(ctx, "Submission", nil), &sub); err != nil {
		serveErr(ctx, err, w)
		return
	}

	thanksTmpl.ExecuteTemplate(w, "base", nil)
}
Example #28
0
func follow(res http.ResponseWriter, req *http.Request, ps httprouter.Params) {
	ctx := appengine.NewContext(req)
	// get session
	memItem, err := getSession(req)
	if err != nil {
		log.Infof(ctx, "Attempt to follow from logged out user")
		http.Error(res, "You must be logged in", http.StatusForbidden)
		return
	}
	// declare a variable of type user
	// initialize user with values from memcache item
	var user User
	json.Unmarshal(memItem.Value, &user)
	// get the datastore key for the follower
	followerKey := datastore.NewKey(ctx, "Users", user.UserName, 0, nil)
	// get a datastore key for the followee
	followeeKey := datastore.NewKey(ctx, "Follows", ps.ByName("user"), 0, followerKey)
	// the follower is following the followee
	// put this into the datastore
	type F struct {
		Following string
	}
	//
	_, err = datastore.Put(ctx, followeeKey, &F{ps.ByName("user")})
	if err != nil {
		log.Errorf(ctx, "error adding followee: %v", err)
		http.Error(res, err.Error(), 500)
		return
	}
	http.Redirect(res, req, "/user/"+ps.ByName("user"), 302)
}
Example #29
0
func init() {
	delayedGetStats = delay.Func(
		"my-favorite-dog",
		func(ctx context.Context, accessToken, username string) error {
			log.Infof(ctx, "delayedGetStats CALLED")
			api := &GithubAPI{
				ctx:         ctx,
				accessToken: accessToken,
				username:    username,
			}
			since := time.Now().Add(-time.Hour * 24 * 30)
			stats, err := api.getCommitSummaryStats(since)
			if err != nil {
				return err
			}
			log.Infof(ctx, "STATS: %v", stats)

			key := datastore.NewKey(ctx, "Stats", username, 0, nil)
			_, err = datastore.Put(ctx, key, &stats)
			if err != nil {
				return err
			}
			return nil
		},
	)
}
Example #30
0
func buttonClickedPage(w http.ResponseWriter, r *http.Request) {
	click := &clickData{
		IPAddress: r.RemoteAddr,
	}

	c := appengine.NewContext(r)
	key := datastore.NewIncompleteKey(c, "Click", clickKey(c))
	_, err := datastore.Put(c, key, click)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	clickCount, err := datastore.NewQuery("Click").Count(c)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	stats := &buttonStats{
		Clicks: clickCount,
	}

	w.Header().Set("Content-Type", "application/json")
	w.Header().Set("Cache-Control", "no-cache")
	err = json.NewEncoder(w).Encode(stats)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}