chore: refresh gramsrv public release
This commit is contained in:
parent
75cebe8dbf
commit
70b6820474
1274 changed files with 378751 additions and 59919 deletions
159
internal/rpc/messages_edit_geolive.go
Normal file
159
internal/rpc/messages_edit_geolive.go
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gotd/td/tg"
|
||||
|
||||
"telesrv/internal/domain"
|
||||
)
|
||||
|
||||
// 本文件实现 live location 的续报与停止:editMessage + InputMediaGeoLive。
|
||||
// DrKLO Android 用它周期性上报新坐标;stopped=true 表示停止共享。
|
||||
// 停止语义:把 Period 改写为「已逝时长」,所有客户端按 message.date + period
|
||||
// 判定立即过期,服务端不需要后台到点任务。
|
||||
|
||||
func (r *Router) onEditMessageLiveLocation(ctx context.Context, req *tg.MessagesEditMessageRequest, media *tg.InputMediaGeoLive) (tg.UpdatesClass, error) {
|
||||
if req.ID <= 0 || req.ID > domain.MaxMessageBoxID {
|
||||
return nil, messageIDInvalidErr()
|
||||
}
|
||||
userID, _, err := r.currentUserID(ctx)
|
||||
if err != nil {
|
||||
return nil, internalErr()
|
||||
}
|
||||
if userID == 0 {
|
||||
return nil, peerIDInvalidErr()
|
||||
}
|
||||
peer, err := r.checkedDomainPeerFromInputPeer(ctx, userID, req.Peer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
current, found := r.loadLiveLocationMessage(ctx, userID, peer, req.ID)
|
||||
if !found {
|
||||
return nil, messageIDInvalidErr()
|
||||
}
|
||||
now := int(r.clock.Now().Unix())
|
||||
next := *current.media.GeoLive
|
||||
if media.Stopped {
|
||||
// 立即过期:elapsed 至少 1 秒;forever 共享停止后同样按 elapsed 收口。
|
||||
elapsed := now - current.date
|
||||
if elapsed < 1 {
|
||||
elapsed = 1
|
||||
}
|
||||
next.Period = elapsed
|
||||
} else {
|
||||
geo, err := domainGeoPointFromInput(media.GeoPoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 保留首发 access_hash:客户端可能继续用旧 hash 拉地图缩略。
|
||||
geo.AccessHash = next.Geo.AccessHash
|
||||
next.Geo = *geo
|
||||
if heading, ok := media.GetHeading(); ok {
|
||||
if heading < 0 || heading > maxLiveLocationHeading {
|
||||
return nil, mediaInvalidErr()
|
||||
}
|
||||
next.Heading = heading
|
||||
}
|
||||
if period, ok := media.GetPeriod(); ok {
|
||||
if period != foreverLiveLocationPeriod && (period < minLiveLocationPeriod || period > maxLiveLocationPeriod) {
|
||||
return nil, mediaInvalidErr()
|
||||
}
|
||||
next.Period = period
|
||||
}
|
||||
if radius, ok := media.GetProximityNotificationRadius(); ok {
|
||||
if radius < 0 || radius > maxProximityRadiusMeters {
|
||||
return nil, mediaInvalidErr()
|
||||
}
|
||||
next.ProximityNotificationRadius = radius
|
||||
}
|
||||
}
|
||||
newMedia := &domain.MessageMedia{Kind: domain.MessageMediaKindGeoLive, GeoLive: &next}
|
||||
|
||||
if peer.Type == domain.PeerTypeChannel {
|
||||
if r.deps.Channels == nil {
|
||||
return nil, peerIDInvalidErr()
|
||||
}
|
||||
res, err := r.deps.Channels.EditMessage(ctx, userID, domain.EditChannelMessageRequest{
|
||||
UserID: userID,
|
||||
ChannelID: peer.ID,
|
||||
ID: req.ID,
|
||||
Message: current.body,
|
||||
Entities: current.entities,
|
||||
Media: newMedia,
|
||||
EditDate: now,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, channelEditErr(err)
|
||||
}
|
||||
updates := r.channelEditMessageUpdates(ctx, userID, res)
|
||||
r.enqueueChannelEditMessageFanout(ctx, userID, res)
|
||||
return updates, nil
|
||||
}
|
||||
if peer.Type != domain.PeerTypeUser || r.deps.Messages == nil {
|
||||
return nil, peerIDInvalidErr()
|
||||
}
|
||||
sessionID, _ := SessionIDFrom(ctx)
|
||||
authKeyID, _ := AuthKeyIDFrom(ctx)
|
||||
res, err := r.deps.Messages.EditMessage(ctx, userID, domain.EditMessageRequest{
|
||||
OwnerUserID: userID,
|
||||
Peer: peer,
|
||||
ID: req.ID,
|
||||
Message: current.body,
|
||||
Entities: current.entities,
|
||||
Media: newMedia,
|
||||
EditDate: now,
|
||||
OriginAuthKeyID: authKeyID,
|
||||
OriginSessionID: sessionID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, messageEditErr(err)
|
||||
}
|
||||
self := res.Self()
|
||||
if self.Event.Pts == 0 || self.Message.ID == 0 {
|
||||
return nil, messageIDInvalidErr()
|
||||
}
|
||||
users := r.usersForMessageUpdate(ctx, userID, self.Message)
|
||||
chats := r.chatsForMessageUpdate(ctx, userID, self.Message)
|
||||
return tgEditMessageUpdates(self.Event, self.Message, users, chats), nil
|
||||
}
|
||||
|
||||
type liveLocationTarget struct {
|
||||
media *domain.MessageMedia
|
||||
body string
|
||||
entities []domain.MessageEntity
|
||||
date int
|
||||
}
|
||||
|
||||
// loadLiveLocationMessage 加载目标消息并校验它是一条 live location。
|
||||
func (r *Router) loadLiveLocationMessage(ctx context.Context, userID int64, peer domain.Peer, msgID int) (liveLocationTarget, bool) {
|
||||
switch peer.Type {
|
||||
case domain.PeerTypeChannel:
|
||||
if r.deps.Channels == nil {
|
||||
return liveLocationTarget{}, false
|
||||
}
|
||||
history, err := r.deps.Channels.GetMessages(ctx, userID, peer.ID, []int{msgID})
|
||||
if err != nil {
|
||||
return liveLocationTarget{}, false
|
||||
}
|
||||
for _, msg := range history.Messages {
|
||||
if msg.ID == msgID && msg.Media != nil && msg.Media.Kind == domain.MessageMediaKindGeoLive && msg.Media.GeoLive != nil {
|
||||
return liveLocationTarget{media: msg.Media, body: msg.Body, entities: msg.Entities, date: msg.Date}, true
|
||||
}
|
||||
}
|
||||
case domain.PeerTypeUser:
|
||||
if r.deps.Messages == nil {
|
||||
return liveLocationTarget{}, false
|
||||
}
|
||||
list, err := r.deps.Messages.GetMessages(ctx, userID, []int{msgID})
|
||||
if err != nil {
|
||||
return liveLocationTarget{}, false
|
||||
}
|
||||
for _, msg := range list.Messages {
|
||||
if msg.ID == msgID && msg.Peer == peer && msg.Media != nil && msg.Media.Kind == domain.MessageMediaKindGeoLive && msg.Media.GeoLive != nil {
|
||||
return liveLocationTarget{media: msg.Media, body: msg.Body, entities: msg.Entities, date: msg.Date}, true
|
||||
}
|
||||
}
|
||||
}
|
||||
return liveLocationTarget{}, false
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue