func (s *ApiServer) TestJob() error { profile, _ := store.GetProfile(s.mdb, "yinhm") feedinfo, _ := store.GetFeedinfo(s.rdb, profile.Uuid) // only sync twitter service graph := BuildGraph(feedinfo) if _, ok := graph.Services["twitter"]; !ok { return nil } service := graph.Services["twitter"] if service.Oauth == nil { return nil } job := &pb.FeedJob{ Uuid: feedinfo.Uuid, Id: feedinfo.Id, Profile: profile, Service: service, Start: 0, Created: time.Now().Unix(), Updated: time.Now().Unix(), } _, err := s.EnqueJob(context.Background(), job) return err }
// TODO: build graph if it not exists func (s *ApiServer) FetchGraph(ctx context.Context, req *pb.ProfileRequest) (*pb.Graph, error) { if req.Uuid == "" { return nil, fmt.Errorf("bad request") } feedinfo, err := store.GetFeedinfo(s.rdb, req.Uuid) if err != nil { return nil, err } return BuildGraph(feedinfo), nil }
func (s *ApiServer) DeleteService(ctx context.Context, req *pb.ServiceRequest) (*pb.Feedinfo, error) { feedinfo, err := store.GetFeedinfo(s.rdb, req.User) if err != nil { return nil, err } for i, item := range feedinfo.Services { if item.Id == req.Service { feedinfo.Services = append(feedinfo.Services[:i], feedinfo.Services[i+1:]...) } } if err := store.SaveFeedinfo(s.rdb, feedinfo.Uuid, feedinfo); err != nil { return nil, err } return feedinfo, nil }
func (s *ApiServer) PutOAuth(ctx context.Context, authinfo *pb.OAuthUser) (*pb.Profile, error) { // TODO: create profile on oauth? user, err := store.PutOAuthUser(s.mdb, authinfo) if err != nil { return nil, err } // exists user if user.Uuid != "" { uuid1, err := uuid.FromString(user.Uuid) if err != nil { return nil, err } profile, err := store.GetProfileFromUuid(s.mdb, uuid1) if err != nil { return nil, err } // build services if profile present if authinfo.Provider == "twitter" { feedinfo, err := store.GetFeedinfo(s.rdb, profile.Uuid) if err != nil { return nil, err } // WARN: goth user.NickName == screen_name which is twitter id service := &pb.Service{ Id: "twitter", Name: "Twitter", Icon: "/static/images/icons/twitter.png", Profile: "https://twitter.com/" + user.NickName, Username: user.Name, Oauth: user, Created: time.Now().Unix(), Updated: time.Now().Unix(), } feedinfo.Services = append(feedinfo.Services, service) err = store.SaveFeedinfo(s.rdb, profile.Uuid, feedinfo) if err != nil { return nil, err } } return profile, nil } return new(pb.Profile), nil }
func (s *ApiServer) RefetchUserFeed() error { prefix := store.TableProfile j := 0 n, err := store.ForwardTableScan(s.mdb, prefix, func(i int, k, v []byte) error { profile := &pb.Profile{} if err := proto.Unmarshal(v, profile); err != nil { return err } feedinfo, _ := store.GetFeedinfo(s.rdb, profile.Uuid) // only sync twitter service graph := BuildGraph(feedinfo) if _, ok := graph.Services["twitter"]; !ok { return nil } service := graph.Services["twitter"] if service.Oauth == nil { return nil } job := &pb.FeedJob{ Uuid: feedinfo.Uuid, Id: feedinfo.Id, Profile: profile, Service: service, Start: 0, Created: time.Now().Unix(), Updated: time.Now().Unix(), } _, err := s.EnqueJob(context.Background(), job) j++ return err }) if err != nil { log.Println("Error on scanning user profiles:", err) } log.Printf("Jobs pulled: %d scanned, %d user feeds scheduled.", n, j) return err }
func TestPostProfile(t *testing.T) { setup() defer teardown() Convey("Given ApiServer, post profile then get profile", t, func() { ctx := context.Background() p1 := &pb.Profile{ Uuid: "c6f8dca854f011ddb489003048343a40", Id: "yinhm", Name: "yinhm", Type: "user", Private: false, SupId: "4566789", Description: "desc", RemoteKey: "xxx", } feedinfo := &pb.Feedinfo{ Uuid: "c6f8dca854f011ddb489003048343a40", Id: "yinhm", Name: "Heming Friend", Type: "user", Private: false, SupId: "123456-1234", Description: "Friendfeed land", Subscriptions: []*pb.Profile{p1}, } got, err := srv.PostFeedinfo(ctx, feedinfo) So(err, ShouldBeNil) So(got.Uuid, ShouldEqual, feedinfo.Uuid) So(got.RemoteKey, ShouldEqual, feedinfo.RemoteKey) profile, err := store.GetProfile(srv.mdb, feedinfo.Id) So(err, ShouldBeNil) So(profile.Uuid, ShouldEqual, feedinfo.Uuid) So(profile.RemoteKey, ShouldEqual, feedinfo.RemoteKey) newinfo, err := store.GetFeedinfo(srv.rdb, feedinfo.Uuid) So(err, ShouldBeNil) So(newinfo.Uuid, ShouldEqual, feedinfo.Uuid) So(newinfo.RemoteKey, ShouldEqual, feedinfo.RemoteKey) So(len(newinfo.Subscriptions), ShouldEqual, 1) Convey("post entry", func() { from := &pb.Feed{ Id: "yinhm", Name: "yinhm", Type: "user", } entry := &pb.Entry{ Body: "张无忌对张三丰说:“太师父,武当山的生活太寂寞了,只有清风和明月两个朋友能陪我玩。”张三丰叹了口气:“已经很不错啦,至少还有清风明月呢。想当年我在少林寺的时候,也是只有两个朋友,其中一个也叫清风……”“那另一个呢?”“叫心相印。”…", Id: "e/2b43a9066074d120ed2e45494eea1797", Date: "2012-09-07T07:40:22Z", Url: "http://friendfeed.com/yinhm/2b43a906/rt-trojansj", From: from, ProfileUuid: "c6f8dca854f011ddb489003048343a40", } _, err := store.PutEntry(srv.rdb, entry, false) So(err, ShouldBeNil) req := &pb.FeedRequest{ Id: "yinhm", Start: 0, PageSize: 50, } feed, err := srv.FetchFeed(context.Background(), req) So(err, ShouldBeNil) So(feed.Id, ShouldEqual, "yinhm") So(len(feed.Entries), ShouldEqual, 1) // prefix stripped So(feed.Entries[0].Id, ShouldEqual, "2b43a9066074d120ed2e45494eea1797") Convey("comment on the entry", func() { cmt := &pb.Comment{ Id: "2b43a9066074d120ed2e45494eea1797", Date: "2012-09-07T07:40:22Z", From: from, Body: "this is a comment", RawBody: "this is a comment", } cReq := &pb.CommentRequest{ Entry: entry.Id, Comment: cmt, } entry, err := srv.CommentEntry(context.Background(), cReq) So(err, ShouldBeNil) So(entry.Id, ShouldEqual, "2b43a9066074d120ed2e45494eea1797") // BUG: duplicated entry when comment feed, err := srv.FetchFeed(context.Background(), req) So(err, ShouldBeNil) So(feed.Id, ShouldEqual, "yinhm") So(len(feed.Entries), ShouldEqual, 1) }) }) }) }
func (s *ApiServer) FetchFeedinfo(ctx context.Context, req *pb.ProfileRequest) (*pb.Feedinfo, error) { if req.Uuid == "" { return nil, fmt.Errorf("bad request") } return store.GetFeedinfo(s.rdb, req.Uuid) }