func publish(c appengine.Context, roomId string, email string, message string) error { room := newRoom() _, err := memcache.JSON.Get(c, roomId, room) if err != nil { return err } errs := make([]error, 0, len(room.Users)) for user, _ := range room.Users { if user == email { continue } if message == "" { channel.SendJSON(c, user+roomId, command{"join", email, message}) } else { channel.SendJSON(c, user+roomId, command{"msg", email, message}) } } if len(errs) > 0 { return errors.New("Publishing message failed!") } return nil }
func submitWord(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) tableKey := r.FormValue("g") user := r.FormValue("u") word := r.FormValue("word") points, _ := strconv.Atoi(r.FormValue("points")) hasWord := false totalPoints := 0 gameChanger := func(g *MyGame) bool { // In our current model, users can only submit valid words since their // clients have the solutions. hasWord = g.HasWord(word) if g.HasWord(word) { return false } totalPoints = g.AddWord(user, word, points) // user found a word congrats, store it. return true } g := ChangeGame(c, tableKey, gameChanger) if hasWord { wordUpdate := &WordUpdate{ User: user, Word: word, TotalPoints: -1, } resp := &Resp{ Action: "wordUpdate", Payload: wordUpdate, } myToken := r.FormValue("t") channel.SendJSON(c, myToken, resp) return } wordUpdate := &WordUpdate{ User: user, Word: word, TotalPoints: totalPoints, } resp := &Resp{ Action: "wordUpdate", Payload: wordUpdate, } // Send table information to everyone in the room about what the result // was. for _, token := range g.GetUserTokens() { err := channel.SendJSON(c, token, resp) if err != nil { c.Errorf("Err with sendTables response: %v", err) } } }
// What to do when a user leaves (send a notification to everyone and // reset the game if everyone left the table). func leaving(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) cid := ClientId{ clientId: r.FormValue("from"), } c.Infof("Client id leaving: %v", cid.clientId) tableKey := cid.table() c.Infof("User %v has left table %v.", cid.user(), tableKey) gameChanger := func(g *MyGame) bool { g.RemoveUser(cid.user()) if len(g.Users) == 0 { c.Infof("There are no more users left in this game. Deleting game.") g.Clear() // Clear the game when everyone has left. } return true } g := ChangeGame(c, tableKey, gameChanger) // Just need to read the game. resp := &Resp{ Action: "join", Payload: g, } c.Infof("Notifying these tokens that a user left: %v", g.GetUserTokens()) // Let everyone know that they joined the game! for _, token := range g.GetUserTokens() { err := channel.SendJSON(c, token, resp) if err != nil { c.Errorf("sending Start game updates: %v", err) } } }
// Reset the state of the game and let all users know about that. func gameOver(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) tableKey := r.FormValue("g") justEnded := false gameChanger := func(g *MyGame) bool { justEnded = g.HadState("justEnded") if justEnded { return false } g.Clear() g.AddState("justEnded") return true } g := ChangeGame(c, tableKey, gameChanger) if justEnded { return } resp := &Resp{ Action: "gameEnded", Payload: g, } // Send update to people letting them know the game is over. for _, token := range g.GetUserTokens() { err := channel.SendJSON(c, token, resp) if err != nil { c.Errorf("Err with gameOver response: %v", err) } } }
func client_callback(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) itsStatus, _ := strconv.Atob(r.FormValue("Status")) msg := MSG{itsStatus, r.FormValue("Nickname"), r.FormValue("Message")} for _, value := range map_clients { channel.SendJSON(c, value, msg) } }
func sendResponseToChannel(w http.ResponseWriter, message string, r *http.Request, uuid string) { c := appengine.NewContext(r) err := channel.SendJSON(c, uuid, message) c.Infof("json") if err != nil { c.Errorf("sending Game: %v", err) } }
func RenderPost(blog_config map[string]interface{}) func(w http.ResponseWriter, req *http.Request) { l := func(w http.ResponseWriter, req *http.Request) { appcontext := appengine.NewContext(req) err := req.ParseMultipartForm(1024 * 1024) if err != nil { appcontext.Errorf("sending markdown payload: %v", err) http.Error(w, err.Error(), http.StatusBadRequest) return } dataFile, _, err := req.FormFile("data") if err != nil { http.Error(w, "did not specify data as a param", http.StatusBadRequest) return } data, err := ioutil.ReadAll(dataFile) if err != nil { appcontext.Errorf("ioutil.ReadAll(): %v", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } if len(data) < 1 { appcontext.Errorf("len(data): %v", len(data)) http.Error(w, "did not specify data as a param", http.StatusBadRequest) return } key := req.FormValue("g") if key == "" { http.Error(w, "did not specify a key!", http.StatusBadRequest) return } var decoded interface{} err = json.Unmarshal(data, &decoded) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } q := decoded.(map[string]interface{}) str, ok := q["data"] if !ok { http.Error(w, "error: must supply JSON with 'data' specified!", http.StatusBadRequest) return } con := map[string]interface{}{"markdown": bytes.NewBuffer(blackfriday.MarkdownCommon(bytes.NewBufferString(fmt.Sprintf("%v", str)).Bytes())).String()} err = channel.SendJSON(appcontext, key, con) if err != nil { appcontext.Errorf("sending markdown payload: %v", err) http.Error(w, err.Error(), http.StatusInternalServerError) return } } return l }
// 発言時の処理 // Javascriptのクライアントから // /submit?chatkey=(chatkey)[&msg=(msg)] というクエリでリクエストがくる // msgの内容をデータストアに保存し、発言内容リストをchannelを経由して // 部屋にいるすべてのJavascriptクライアントにSendJSONする func submit(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) u := user.Current(c) tkey := r.FormValue("chatkey") // 発言内容をデータストアに保存する stm := Message{ Date: time.Now(), Name: u.String(), Content: r.FormValue("msg"), } log.Printf("tkey: %v, msg: %v\n", tkey, stm.Content) // データストアへ発言内容をPut stmkey := datastore.NewIncompleteKey(c, "message", tinychatKey(c, tkey)) _, err := datastore.Put(c, stmkey, &stm) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // データストアから現在の部屋にいるユーザ全員を取得する q := datastore.NewQuery("Member").Ancestor(memberKey(c, tkey)) members := make([]Member, 0, 20) if _, err := q.GetAll(c, &members); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } log.Printf("member: %v\n", members) // 発言内容を20件取得 q = datastore.NewQuery("message").Ancestor(tinychatKey(c, tkey)).Order("-Date").Limit(20) messages := make([]Message, 0, 20) if _, err := q.GetAll(c, &messages); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } // すべてのユーザに対してSendJSONする d := Display{ Token: "", Me: u.ID, Chat_key: tkey, Messages: messages, } for _, member := range members { err := channel.SendJSON(c, member.ID+tkey, d) if err != nil { c.Errorf("sending data: %v", err) } } //log.Printf("hello") }
func rendezVous(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) id := r.FormValue("from") if waiting.Len() == 0 { waiting.PushBack(id) channel.SendJSON(c, id, map[string]int{"t": WAITING_PARTNER}) c.Infof("User %v added to the waiting list", id) } else { opponent := waiting.Front() opponentId, _ := opponent.Value.(string) waiting.Remove(opponent) channel.SendJSON(c, opponentId, map[string]int{"t": FOUND_PARTNER, "p": 0}) channel.SendJSON(c, id, map[string]int{"t": FOUND_PARTNER, "p": 1}) pairs[opponentId] = id pairs[id] = opponentId c.Infof("Matching user %v with %v", id, opponentId) } }
func messageHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") c := appengine.NewContext(r) if r.Method != "POST" { c.Errorf("messageHandler did not expect %s", r.Method) http.Error(w, "Method not allowed.", http.StatusInternalServerError) return } var patchSet map[string]interface{} defer r.Body.Close() if err := json.NewDecoder(r.Body).Decode(&patchSet); err != nil { c.Errorf("json.NewDecoder: %s", err) http.Error(w, "Error decoding json.", http.StatusInternalServerError) return } code := patchSet["key"].(string) repo := repository.NewRepo(c) candidate, interviewer, err := repo.GetSession(code) if err != nil { c.Errorf("repo.GetSession: %v", err) http.Redirect(w, r, "/", 301) return } if code == interviewer { err := channel.SendJSON(c, candidate, patchSet) if err != nil { c.Errorf("channel.SendJSON, problem sending: %s.", err) http.Error(w, "Error decoding json.", http.StatusInternalServerError) } } else { err := channel.SendJSON(c, interviewer, patchSet) if err != nil { c.Errorf("channel.SendJSON, problem sending: %s.", err) http.Error(w, "Error decoding json.", http.StatusInternalServerError) } } }
func move(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) id := r.FormValue("id") y, _ := strconv.Atoi(r.FormValue("y")) direction, _ := strconv.Atoi(r.FormValue("d")) c.Infof("Seding move msg from %v to %v", id, pairs[id]) err := channel.SendJSON(c, pairs[id], map[string]int{"t": PARTNER_MOVED, "y": y, "d": direction}) if err != nil { c.Errorf("%v", err) } }
func startGame(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) c.Infof("Got a message from a client that they want to start a game.") // Need to keep track of all users associated with the games, then // we must broadcast an update to all of them. tableKey := r.FormValue("g") isStarted := false g := defaultGame() err := datastore.RunInTransaction(c, func(c appengine.Context) error { k := datastore.NewKey(c, "WrGame", tableKey, 0, nil) if err := datastore.Get(c, k, g); err != nil { return err } isStarted = g.HadState("justStarted") if isStarted { return nil } g.AddState("justStarted") // Set to true when a user first starts the game. if _, err := datastore.Put(c, k, g); err != nil { return err } return nil }, nil) if err != nil { c.Errorf("Error in start game db call. %v", err) return } if isStarted { // Do nothing if the game is already started. // TODO(dlluncor): Update the user's UI that the game is already started. c.Infof("Game has already started!!!") return } resp := &Resp{ Action: "startGame", Payload: "start", } c.Infof("Tokens: %v", g.Tokens) for _, token := range g.GetUserTokens() { err := channel.SendJSON(c, token, resp) if err != nil { c.Errorf("sending Start game updates: %v", err) } } return }
func sendAll(c appengine.Context, h *hunt.Hunt, m Message) { var listeners []Listener _, err := datastore.NewQuery(listenerKind).Ancestor(h.Key).Filter("Open =", true).GetAll(c, &listeners) if err != nil { c.Errorf("Send: %v", err) return } for _, listener := range listeners { err := channel.SendJSON(c, listener.Channel, m) if err != nil { c.Errorf("Send(%s): %v", listener.Channel, err) } } }
func disconnect(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) id := r.FormValue("from") _, isPaired := pairs[id] if isPaired { partner := pairs[id] delete(pairs, id) delete(pairs, partner) channel.SendJSON(c, partner, map[string]int{"t": PARTNER_LEFT}) c.Infof("Removed Pair %v,%v", id, partner) } else { for e := waiting.Front(); e != nil; e = e.Next() { if e.Value == id { waiting.Remove(e) c.Infof("User %v removed from the waiting list", id) return } } } }
func handle(w http.ResponseWriter, r *http.Request) { switch r.Method { case "GET": Execute("get", w, nil) case "POST": wID := r.FormValue("ID") wToken, err := channel.Create(appengine.NewContext(r), wID) if err != nil { Execute("get", w, map[string]string{"Error": err.Error()}) } else { Execute( "post", w, map[string]string{ "ID": wID, "Token": wToken, }, ) } case "PUT": ctx := appengine.NewContext(r) keys, err := datastore.NewQuery("Channels").KeysOnly().GetAll(ctx, nil) if err != nil { panic(err) } for _, key := range keys { if err := channel.SendJSON( ctx, key.StringID(), map[string]interface{}{ "message": r.FormValue("Message"), "ID": r.FormValue("ID"), }, ); err != nil { panic(err) } } } }
// send data client callbacks. func SendCallBack(c appengine.Context, clientID int64, request string, args interface{}) error { // clientKey clientKey := datastore.NewKey(c, "ClientInfo", "", clientID, nil) // sent data handler := fmt.Sprintf("on%s", request) data := struct { Call string `json:"call"` Args interface{} `json:"args"` }{ handler, args, } q := datastore.NewQuery("CallBackInfo").Ancestor(clientKey).Filter("Request=", request) // callbacks var callbacks []CallBackInfo keys, err := q.GetAll(c, &callbacks) if err != nil { c.Errorf(err.Error()) return err } // send for i, callback := range callbacks { k := keys[i] client := callback.ClientID c.Infof("Send to %s", client) channel.SendJSON(c, client, data) // remove request err = datastore.Delete(c, k) if err != nil { return err } } return nil }
// When the first user starts the game and gives us tables that defines // this entire game. // // Notifies all users to start their timers for round 1. func sendTables(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) tableKey := r.FormValue("g") // Store all tables as part of the game state and send // a "startTimer" response. timerStarted := false gameChanger := func(g *MyGame) bool { timerStarted = g.HadState("timerStarted") if timerStarted { return false } g.AddState("timerStarted") tableStrKeys := []string{"table1", "table2", "table3", "table4"} for _, tableStrKey := range tableStrKeys { tableVal := r.FormValue(tableStrKey) g.SetTable(tableStrKey, tableVal) } return true } g := ChangeGame(c, tableKey, gameChanger) if timerStarted { return } resp := &Resp{ Action: "startTimers", Payload: "", } // Send an update to everyone. for _, token := range g.GetUserTokens() { err := channel.SendJSON(c, token, resp) if err != nil { c.Errorf("Err with sendTables response: %v", err) } } }
func messageReceived(w http.ResponseWriter, r *http.Request) { var clients []Client c := appengine.NewContext(r) message := r.FormValue("name") + ": " + r.FormValue("message") _, err := memcache.JSON.Get(c, "sut", &clients) if err != nil && err != memcache.ErrCacheMiss { http.Error(w, err.String(), http.StatusInternalServerError) return } if err == memcache.ErrCacheMiss { q := datastore.NewQuery("Client") _, err = q.GetAll(c, &clients) if err != nil { http.Error(w, err.String(), http.StatusInternalServerError) return } err = memcache.JSON.Set(c, &memcache.Item{ Key: "sut", Object: clients, }) if err != nil { http.Error(w, err.String(), http.StatusInternalServerError) return } } for _, client := range clients { channel.SendJSON(c, client.ClientID, map[string]string{ "reply_message": message, }) } }
// One user can request for the entire group all the information for // a round like the words to solve and the actual puzzle. // At this time there is 10 seconds left before the round starts. func getRoundInfo(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) tableKey := r.FormValue("g") round := r.FormValue("r") isRoundFetched := false gameChanger := func(g *MyGame) bool { val := "roundFetched" + round isRoundFetched = g.HadState(val) if isRoundFetched { return false } roundInt, _ := strconv.Atoi(round) g.CreateTableInfo(roundInt) g.AddState(val) g.SetRoundFetched() return true } g := ChangeGame(c, tableKey, gameChanger) // Just need to read the game. if isRoundFetched { // We can only fetch a round once... return } tableInfo := g.GetTableInfo() resp := &Resp{ Action: "aboutToStartRound", Payload: tableInfo, } // Send table information to everyone in the room (need a solution // for when someone randomly jumps into the game). for _, token := range g.GetUserTokens() { err := channel.SendJSON(c, token, resp) if err != nil { c.Errorf("Err with sendTables response: %v", err) } } }
func (handler taskRequestHandler) handleRequest(pfc *PFContext) { if userID := pfc.R.PostFormValue("userID"); userID != "" { pfc.UserID = storage.UserID(userID) if channelID := pfc.R.PostFormValue("channelID"); channelID != "" { pfc.ChannelID = channelID } if user, err := storage.UserByID(pfc.C, pfc.UserID); err != nil { pfc.C.Errorf("Error loading user: %s", err) http.Error(pfc.W, "Unexpected error", http.StatusInternalServerError) return } else { pfc.User = user } } var response interface{} taskMessage, err := handler.RouteHandler(pfc) if err != nil { pfc.C.Errorf("Task failed: %s", err.Error()) http.Error(pfc.W, err.Error(), http.StatusInternalServerError) response = map[string]string{"error": err.Error()} } else { response = taskMessage } if !taskMessage.Silent { if channelID := pfc.R.PostFormValue("channelID"); channelID != "" { if err := channel.SendJSON(pfc.C, channelID, response); err != nil { pfc.C.Criticalf("Error writing to channel: %s", err) } } else { pfc.C.Warningf("Channel ID is empty!") } } }
func Save(blog_config map[string]interface{}) func(w http.ResponseWriter, req *http.Request) { l := func(w http.ResponseWriter, req *http.Request) { appcontext := appengine.NewContext(req) blobs, _, err := blobstore.ParseUpload(req) if err != nil { appcontext.Errorf("error parsing blobstore! %v", err) http.Error(w, "error parsing blobstore!", http.StatusBadRequest) return } //key := "coolguys" key := req.FormValue("g") if key == "" { http.Error(w, "did not specify a key!", http.StatusBadRequest) return } send_message := func(stat string, color string) { con := map[string]interface{}{"status": stat, "color": color} err := channel.SendJSON(appcontext, key, con) if err != nil { appcontext.Errorf("sending update message: %v", err) http.Error(w, err.Error(), http.StatusInternalServerError) } } bdata, ok := blobs["data"] if !ok { http.Error(w, "did not specify data as a param", http.StatusBadRequest) send_message("internal error while saving!", "#AA0000") return } if len(bdata) != 1 { appcontext.Errorf("error parsing blobstore!", err) http.Error(w, "error parsing blobstore!", http.StatusBadRequest) return } jsonkey := bdata[0].BlobKey data, err := ioutil.ReadAll(blobstore.NewReader(appcontext, jsonkey)) if err != nil { appcontext.Errorf("error parsing blobstore!", err) http.Error(w, "error parsing blobstore!", http.StatusBadRequest) return } if len(data) <= 0 { http.Error(w, "did not specify data as a param", http.StatusBadRequest) send_message("internal error while saving!", "#AA0000") return } var decoded interface{} err = json.Unmarshal(data, &decoded) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) send_message("internal error while saving!", "#AA0000") return } q := decoded.(map[string]interface{}) _, ok = q["data"].(string) if !ok { http.Error(w, "error: must supply JSON with 'data' specified!", http.StatusBadRequest) send_message("internal error while saving!", "#AA0000") return } title, ok := q["title"].(string) if !ok { http.Error(w, "error: must supply JSON with 'title' specified!", http.StatusBadRequest) send_message("internal error while saving!", "#AA0000") return } labels, ok := q["labels"].(string) if !ok { http.Error(w, "error: must supply JSON with 'labels' specified!", http.StatusBadRequest) send_message("internal error while saving!", "#AA0000") return } individual_labels := strings.Split(labels, ",") real_labels := make([]string, len(individual_labels)) for i := range individual_labels { real_labels[i] = strings.ToLower(strings.Trim(individual_labels[i], " \t")) } _, err = post.SavePost(appcontext, title, jsonkey, real_labels, time.Now()) if err != nil { appcontext.Errorf("saving a post: %v", err) http.Error(w, err.Error(), http.StatusInternalServerError) send_message("internal error while saving!", "#AA0000") return } send_message("saved", "#00AA00") } return l }
func updateClients(c appengine.Context, game *m.Game) { for _, player := range game.Players { channel.SendJSON(c, player.PlayerId, "true") } }
func (m *Messages) roomEmit() { // sends messages to every user for _, key := range getUserList() { channel.SendJSON(c, key, m) } }
func opened(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) c.Infof("Got a message from a client that they connected to a table.") // Make sure the table is in the database here and provide the entire state // to the user of what is going on right now. // The user needs to know. // users and their points. // current puzzles associated with game. // current words found in the puzzle. g := defaultGame() tableKey := r.FormValue("g") token := r.FormValue("t") userExists := false err := datastore.RunInTransaction(c, func(c appengine.Context) error { k := datastore.NewKey(c, "WrGame", tableKey, 0, nil) if err := datastore.Get(c, k, g); err != nil { c.Infof("We have never entered this game into the database. Should have one already!!!") return err } // Now write this user to the list of connect users to this table. user := r.FormValue("u") userExists = g.AddUserToken(user, token) if userExists { c.Infof("User %v already exists, replacing their token.", user) } if _, err := datastore.Put(c, k, g); err != nil { return err } // Update user count for lounge. return nil }, nil) if !userExists { // Update the lounge with the number of current players for this table. // when a new player was added. lounge := r.FormValue("l") loungeChanger := func(l *MyLounge) bool { // TODO(dlluncor): In the middle of something will need to resolve this later... return true } ChangeLounge(c, lounge, loungeChanger) } if err != nil { c.Errorf("Error in db with connect to table. %v", err) } g.SetNow() // Let users who jump in randomly to figure out what time it is from // when the last round started. resp := &Resp{ Action: "join", Payload: g, } c.Infof("Notifying these tokens that a user entered: %v", g.GetUserTokens()) // Let everyone know that they joined the game! for _, token := range g.GetUserTokens() { err := channel.SendJSON(c, token, resp) if err != nil { c.Errorf("sending Start game updates: %v", err) } } }