Example #1
0
// A helper function to produce information about inbox items
func fillInboxItem(s *store, perma_blobref string, lastSeq int64, entry map[string]interface{}) (err os.Error) {
	followers := []string{}
	authors := []string{}
	latestauthors := []string{}
	data, err := s.GetPermaNode(perma_blobref)
	if err != nil {
		log.Printf("ERR: Failed reading permanode")
		return err
	}
	perma := grapher.NewPermaNode(nil)
	perma.FromMap(perma_blobref, data)
	updates := perma.Updates()
	for _, user := range perma.Followers() {
		if seq, ok := updates[user]; ok {
			if seq > lastSeq {
				latestauthors = append(latestauthors, userShortName(user))
			} else if seq >= 0 {
				authors = append(authors, userShortName(user))
			} else {
				followers = append(followers, userShortName(user))
			}
		} else {
			followers = append(followers, userShortName(user))
		}
	}
	entry["followers"] = followers
	entry["authors"] = authors
	entry["latestauthors"] = latestauthors
	entry["digest"] = "Untitled Page" // TODO
	entry["latestseq"] = perma.SequenceNumber() - 1
	return nil
}
Example #2
0
func handleDelayedNotify(w http.ResponseWriter, r *http.Request) {
	log.Printf("Task started")
	c := appengine.NewContext(r)
	// Read the form data
	perma_blobref := r.FormValue("perma")
	// Allow for further notification tasks to be enqueued
	memcache.Delete(c, "notify-"+perma_blobref)
	// Find out about the users of this permanode
	s := newStore(c)
	data, err := s.GetPermaNode(perma_blobref)
	if err != nil {
		http.Error(w, "Err: Failed reading permanode", http.StatusInternalServerError)
		return
	}
	perma := grapher.NewPermaNode(nil)
	perma.FromMap(perma_blobref, data)
	message := fmt.Sprintf(`{"type":"notification", "perma":"%v", "lastseq":%v}`, perma_blobref, perma.SequenceNumber()-1)
	// For all users find all channels on which they are listening
	for _, user := range perma.Users() {
		// Do we know this user?
		userid, err := isLocalUser(c, user)
		if err != nil {
			// TODO: In the case of federation this is not really an error?
			log.Printf("Err: Unknown user %v", user)
			continue
		}
		// Mark that there is an unread file
		err = addUnread(c, userid, perma_blobref)
		if err != nil {
			log.Printf("Err writing unread: %v", err)
		}
		// Notify browser instances where this user is logged in
		var channels []channelStruct
		query := datastore.NewQuery("channel").Filter("UserEmail =", user)
		for it := query.Run(c); ; {
			var data channelStruct
			_, e := it.Next(&data)
			if e == datastore.Done {
				break
			}
			if e != nil {
				log.Printf("Err: in query: %v", e)
				break
			}
			channels = append(channels, data)
		}
		for _, ch := range channels {
			log.Printf("Sending to %v", ch.UserID+"/"+ch.SessionID)
			err := channel.Send(c, ch.UserID+"/"+ch.SessionID, message)
			if err != nil {
				log.Printf("Failed sending to channel %v", ch.UserID+"/"+ch.SessionID)
			}
		}
	}
}
Example #3
0
func handleListUnread(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	userid, _, err := getSession(c, r)
	if err != nil {
		sendError(w, r, "No session cookie")
		return
	}

	s := newStore(c)
	inbox, err := s.ListInbox(userid, true)
	if err != nil {
		sendError(w, r, err.String())
		return
	}

	// Read the bloom filter
	parent := datastore.NewKey("user", userid, 0, nil)
	key := datastore.NewKey("unread", "unread", 0, parent)
	filter := NewBloomFilter(sha256.New())
	var b UnreadStruct
	err = datastore.Get(c, key, &b)
	if err == datastore.ErrNoSuchEntity {
		log.Printf("No filter found")
		// Do nothing
	} else if err != nil {
		sendError(w, r, "Failed reading unread-bloom-filter")
		return
	} else {
		filter.Load(b.BloomFilter)
	}

	// Read the updates for all items in the inbox
	unread := map[string]interface{}{}
	for _, entry := range inbox {
		perma_blobref := entry["perma"].(string)
		lastSeq := entry["seq"].(int64)
		log.Printf("Testing %v for unread", perma_blobref)
		if !filter.Has([]byte(perma_blobref)) {
			log.Printf("   not in filter")
			continue
		}
		data, err := s.GetPermaNode(perma_blobref)
		if err != nil {
			log.Printf("ERR: Failed reading permanode")
			continue
		}
		perma := grapher.NewPermaNode(nil)
		perma.FromMap(perma_blobref, data)
		updates := perma.Updates()
		var authors int64 = 0
		for _, user := range perma.Users() {
			if seq, ok := updates[user]; ok {
				if seq > lastSeq {
					authors++
				}
			}
		}
		if authors > 0 {
			unread[perma_blobref] = lastSeq
		}
	}

	j := map[string]interface{}{"ok": true, "unread": unread}
	msg, err := json.Marshal(j)
	if err != nil {
		panic("Cannot serialize")
	}
	fmt.Fprint(w, string(msg))
}
Example #4
0
func handleOpen(w http.ResponseWriter, r *http.Request) {
	c := appengine.NewContext(r)
	userid, sessionid, err := getSession(c, r)
	if err != nil {
		sendError(w, r, "No session cookie")
		return
	}
	// Read the request body
	jreq, err := ioutil.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "Error reading request body", http.StatusInternalServerError)
		return
	}
	r.Body.Close()
	// Parse request
	var req openCloseRequest
	err = json.Unmarshal(jreq, &req)
	if err != nil {
		sendError(w, r, "Malformed JSON")
		return
	}
	// Load the channel infos
	var ch channelStruct
	if err = datastore.Get(c, datastore.NewKey("channel", userid+"/"+sessionid, 0, nil), &ch); err != nil {
		sendError(w, r, "Unknown channel: "+userid+"/"+sessionid)
		return
	}
	// Check
	if len(ch.OpenPermas) >= 10 {
		sendError(w, r, "Too many open channels")
		return
	}
	is_open := false
	for _, p := range ch.OpenPermas {
		if p == req.Perma {
			is_open = true
			break
		}
	}
	var perma grapher.PermaNode
	if !is_open {
		// Update channel infos
		ch.OpenPermas = append(ch.OpenPermas, req.Perma)
		_, err = datastore.Put(c, datastore.NewKey("channel", userid+"/"+sessionid, 0, nil), &ch)
		if err != nil {
			sendError(w, r, "Internal server error")
			return
		}
		// Repeat all blobs from this document.
		s := newStore(c)
		g := grapher.NewGrapher(userid, schema, s, s, nil)
		s.SetGrapher(g)
		ch := newChannelAPI(c, s, userid, sessionid, true, g)
		perma, err = g.Repeat(req.Perma, req.From)
		if err != nil {
			sendError(w, r, "Failed opening")
			return
		}
		fmt.Fprintf(w, `{"ok":true, "blobs":[%v]}`, strings.Join(ch.messageBuffer, ","))
	} else {
		fmt.Fprint(w, `{"ok":true, "blobs":[]}`)
	}

	if req.MarkAsRead {
		if perma == nil {
			s := newStore(c)
			data, err := s.GetPermaNode(req.Perma)
			if err != nil {
				log.Printf("Err: Failed reading permanode")
				return
			}
			perma = grapher.NewPermaNode(nil)
			perma.FromMap(req.Perma, data)
		}
		markAsRead(c, userid, perma.BlobRef(), perma.SequenceNumber()-1)
	}
}