Exemple #1
0
func ProcessRescue(from Source, msgid uint32, req *proto.RescueRequest, t Transport) {
	a, err := models.FindAccount(models.DBM(), req.Account)
	if err != nil {
		SendError(from, msgid, &proto.Err{Type: proto.Error_Rescue_DatabaseError})
		return
	}
	if !a.VerifySign(req.Sign, req.Walltime) {
		SendError(from, msgid, &proto.Err{Type: proto.Error_Rescue_InvalidAuth})
		return
	}
	res, err := models.NewRescue(models.DBM(), req.Account)
	if err != nil {
		SendError(from, msgid, &proto.Err{Type: proto.Error_Rescue_DatabaseError})
		return
	}
	//send post notification to all member in this Topic
	log.Printf("id:%v url:%v", req.Account, res.URL())
	from.Send(&proto.Payload{
		Type:  proto.Payload_RescueResponse,
		Msgid: msgid,
		RescueResponse: &proto.RescueResponse{
			Url:    res.URL(),
			Remain: res.RemainTime(),
		},
	})
}
Exemple #2
0
func ProcessChannelCreate(from Source, msgid uint32, req *proto.ChannelCreateRequest, t Transport) {
	ch, err := models.NewChannel(models.DBM(), from.Account(), req)
	if err != nil {
		log.Printf("err: %v", err)
		SendError(from, msgid, err)
		return
	}
	//send post notification to all member in this Topic
	from.Send(&proto.Payload{
		Type:  proto.Payload_ChannelCreateResponse,
		Msgid: msgid,
		ChannelCreateResponse: &proto.ChannelCreateResponse{
			Channel: &ch.Model_Channel,
		},
	})
}
Exemple #3
0
func ProcessChannelList(from Source, msgid uint32, req *proto.ChannelListRequest, t Transport) {
	chs, err := models.ListChannel(models.DBM(), req)
	if err != nil {
		log.Printf("err: %v", err)
		SendError(from, msgid, err)
		return
	}
	//send post notification to all member in this Topic
	from.Send(&proto.Payload{
		Type:  proto.Payload_ChannelListResponse,
		Msgid: msgid,
		ChannelListResponse: &proto.ChannelListResponse{
			List: chs,
		},
	})
}
Exemple #4
0
func ProcessTopicCreate(from Source, msgid uint32, req *proto.TopicCreateRequest, t Transport) {
	tp, err := models.NewTopic(models.DBM(), from.Account(), req)
	if err != nil {
		log.Printf("err: %v", err)
		SendError(from, msgid, err)
		return
	}
	//send post notification to all member in this Topic
	from.Send(&proto.Payload{
		Type:  proto.Payload_TopicCreateResponse,
		Msgid: msgid,
		TopicCreateResponse: &proto.TopicCreateResponse{
			Created: &tp.Model_Topic,
		},
	})
}
Exemple #5
0
func ProcessPostList(from Source, msgid uint32, req *proto.PostListRequest, t Transport) {
	ps, err := models.ListPost(models.DBM(), req)
	if err != nil {
		log.Printf("err: %v", err)
		SendError(from, msgid, err)
		return
	}

	from.Send(&proto.Payload{
		Type:  proto.Payload_PostListResponse,
		Msgid: msgid,
		PostListResponse: &proto.PostListResponse{
			List: ps,
		},
	})
}
Exemple #6
0
func topicFetcher(btyp proto.TopicListRequest_BucketType, start, end time.Time, locale string) ([]FetchResult, error) {
	entries := make([]FetchResult, DEFAULT_HOTBUCKET_SIZE)
	dbm := models.DBM()
	var rows *sql.Rows
	var err error
	locale_clause := ""
	if len(locale) > 0 {
		locale_clause = fmt.Sprintf(" and locale = '%s'", locale)
	}
	switch btyp {
	case proto.TopicListRequest_Rising:
		where_clause := fmt.Sprintf("created >= %v and created < %v%s", yue.UUIDAt(start), yue.UUIDAt(end), locale_clause)
		rows, err = dbm.Query(
			dbm.Stmt(
				`select id,max(parent) as channel,sum(param) as point,count(persona) as vote from %s.reactions where %s and type = $1 group by id`,
				where_clause),
			proto.Model_Reaction_Topic_Vote)
	case proto.TopicListRequest_Hot:
		where_clause := fmt.Sprintf("id >= %v and id < %v%s", yue.UUIDAt(start), yue.UUIDAt(end), locale_clause)
		rows, err = dbm.Query(
			dbm.Stmt(
				`select id,channel,point,vote from %s.topics where %s order by point desc limit %v`,
				where_clause, len(entries)))
	case proto.TopicListRequest_Flame:
		/*
			u: upvote, d: downvote, v: vote, p: point
			u + d = v
			u - d = p

			u = (v + p) / 2
			d = (v - p) / 2

			u / v => (1 + p / v) / 2

			abs(u / v - 0.5) = abs(p / (2 * v)) < threshold => abs(p / v) < 2 * threshold
		*/
		where_clause := fmt.Sprintf("id >= %v and id < %v%s", yue.UUIDAt(start), yue.UUIDAt(end), locale_clause)
		rows, err = dbm.Query(
			dbm.Stmt(
				`select id,channel,point,vote from %s.topics where %s and vote >= %v and abs(point / vote) < %v order by vote desc limit %v`,
				where_clause, FLAME_VOTE_THRESHOLD, FLAME_THRESHOLD*2, len(entries)))
	default:
		return nil, fmt.Errorf("invalid btyp: %v", btyp)
	}

	if err != nil {
		return nil, err
	}
	i := 0
	for rows.Next() {
		if cap(entries) <= len(entries) {
			tmp := make([]FetchResult, 2*len(entries))
			entries = append(tmp, entries...)
		}
		if err := rows.Scan(&entries[i].id, &entries[i].parent, &entries[i].score, &entries[i].vote); err != nil {
			return nil, err
		}
		i++
	}
	return entries, nil
}
Exemple #7
0
func ProcessLogin(from Source, msgid uint32, req *proto.LoginRequest, t Transport) {
	user := req.User
	version := req.Version
	if AssetsConfig().App.ClientVersion != version {
		log.Printf("login user:%v client outdated %v:%v", user, AssetsConfig().App.ClientVersion, version)
		SendError(from, msgid, &proto.Err{Type: proto.Error_Login_OutdatedVersion})
		return
	}
	rescue := req.Rescue
	if rescue != nil {
		a, err := models.FindRescueAccount(*rescue)
		if err != nil {
			SendError(from, msgid, &proto.Err{Type: proto.Error_Rescue_CannotRescue})
			return
		}
		req.User = a.User
		req.Mail = a.Mail
		req.Id = &a.Id
		req.Pass = &a.Pass
		log.Printf("account %v rescue is enabled %v, force override secret", a.Id, *rescue)
	}
	walltime := req.Walltime
	//update account database
	a, created, err := models.NewAccount(models.DBM(), req.Id, proto.Model_Account_User, user, req.Mail)
	if err != nil {
		log.Printf("login create account database error: %v", err)
		SendError(from, msgid, &proto.Err{Type: proto.Error_Login_DatabaseError})
		return
	}
	if pass := req.Pass; pass != nil {
		if !created {
			if *pass != a.Pass {
				SendError(from, msgid, &proto.Err{Type: proto.Error_Login_UserAlreadyExists})
				return
			}
		}
		secret := a.ComputeSecret(*pass, walltime)
		a.Secret = secret
		a.Pass = *pass
		log.Printf("login database %v %v", a.User, a.Secret)
		if _, err := a.Save(models.DBM(), []string{"Secret", "Pass"}); err != nil {
			log.Printf("login update account database error: %v", err)
			SendError(from, msgid, &proto.Err{Type: proto.Error_Login_DatabaseError})
			return
		}
	} else {
		if created {
			SendError(from, msgid, &proto.Err{Type: proto.Error_Login_UserNotFound})
			return
		}
		sign := req.Sign
		log.Printf("sign:%v", *sign)
		if sign == nil || !a.VerifySign(*sign, walltime) {
			SendError(from, msgid, &proto.Err{Type: proto.Error_Login_InvalidAuth})
			return
		}
		//TODO: with some duration, update hash
	}

	//set device information
	device_type := req.DeviceType
	device_id := req.DeviceId
	if device_id == nil {
		//TODO: get unique identifier of browser and use it as device_id.
		//(especially, if user uses mobile browser, how we identify it as same mobile device)
		tmp_device_id := "browser:" + a.StringId()
		tmp_device_type := "browser"
		device_id = &tmp_device_id
		device_type = &tmp_device_type
	}
	if _, _, err := models.NewDevice(models.DBM(), *device_id, *device_type, from.String(), a.Id); err != nil {
		log.Printf("register device fails %v:%v:%v:%v", *device_id, *device_type, a.Id, err)
		//continue
	}
	//compute response
	resp := &proto.LoginResponse{
		Id:     a.Id,
		Secret: a.Secret,
	}
	if rescue != nil {
		resp.Pass = req.Pass
		resp.Mail = &req.Mail
		resp.User = &req.User
	}
	//send post notification to all member in this Topic
	log.Printf("secret:%v, id:%v", a.Secret, a.Id)
	from.SetAccount(a)
	from.Send(&proto.Payload{
		Type:          proto.Payload_LoginResponse,
		Msgid:         msgid,
		LoginResponse: resp,
	})
}