/
messages.sendMedia_handler.go
executable file
·386 lines (332 loc) · 16.1 KB
/
messages.sendMedia_handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
/*
* Copyright (c) 2018, https://github.com/airwide-code/airwide.datacenter
* All rights reserved.
*
*
*
*/
package rpc
import (
"github.com/golang/glog"
"github.com/airwide-code/airwide.datacenter/baselib/logger"
"github.com/airwide-code/airwide.datacenter/baselib/grpc_util"
"github.com/airwide-code/airwide.datacenter/mtproto"
"golang.org/x/net/context"
"github.com/airwide-code/airwide.datacenter/biz/base"
"time"
"github.com/airwide-code/airwide.datacenter/biz_server/sync_client"
message2 "github.com/airwide-code/airwide.datacenter/biz/core/message"
"github.com/airwide-code/airwide.datacenter/biz/core/user"
"github.com/airwide-code/airwide.datacenter/biz/nbfs_client"
"github.com/airwide-code/airwide.datacenter/biz/core/channel"
"github.com/airwide-code/airwide.datacenter/biz/core/update"
"github.com/gogo/protobuf/proto"
)
func makeGeoPointByInput(geoPoint *mtproto.InputGeoPoint) *mtproto.GeoPoint {
var geo = &mtproto.GeoPoint{Data2: &mtproto.GeoPoint_Data{}}
switch geoPoint.GetConstructor() {
case mtproto.TLConstructor_CRC32_inputGeoPointEmpty:
geo.Constructor = mtproto.TLConstructor_CRC32_geoPointEmpty
case mtproto.TLConstructor_CRC32_inputGeoPoint:
geo.Data2.Lat = geoPoint.GetData2().Lat
geo.Data2.Long = geoPoint.GetData2().Long
geo.Constructor = mtproto.TLConstructor_CRC32_geoPoint
}
return geo
}
func makeMediaByInputMedia(authKeyId int64, media *mtproto.InputMedia) *mtproto.MessageMedia {
var (
now = int32(time.Now().Unix())
// photoModel = model.GetPhotoModel()
// uuid = helper.NextSnowflakeId()
)
switch media.GetConstructor() {
case mtproto.TLConstructor_CRC32_inputMediaUploadedPhoto:
uploadedPhoto := media.To_InputMediaUploadedPhoto()
file := uploadedPhoto.GetFile()
result, err := nbfs_client.UploadPhotoFile(authKeyId, file)
// , file.GetData2().GetId(), file.GetData2().GetParts(), file.GetData2().GetName(), file.GetData2().GetMd5Checksum())
if err != nil {
glog.Errorf("UploadPhoto error: %v, by %s", err, logger.JsonDebugData(media))
}
// fileData := mediaData.GetFile().GetData2()
photo := &mtproto.TLPhoto{Data2: &mtproto.Photo_Data{
Id: result.PhotoId,
HasStickers: len(uploadedPhoto.GetStickers()) > 0,
AccessHash: result.AccessHash, // photo2.GetFileAccessHash(file.GetData2().GetId(), file.GetData2().GetParts()),
Date: now,
Sizes: result.SizeList,
}}
messageMedia := &mtproto.TLMessageMediaPhoto{Data2: &mtproto.MessageMedia_Data{
Photo_1: photo.To_Photo(),
Caption: uploadedPhoto.GetCaption(),
TtlSeconds: uploadedPhoto.GetTtlSeconds(),
}}
return messageMedia.To_MessageMedia()
case mtproto.TLConstructor_CRC32_inputMediaPhoto:
//inputPhotoEmpty#1cd7bf0d = InputPhoto;
// inputPhoto#fb95c6c4 id:long access_hash:long = InputPhoto;
//inputMediaPhoto#81fa373a flags:# id:InputPhoto caption:string ttl_seconds:flags.0?int = InputMedia;
mediaPhoto := media.To_InputMediaPhoto()
sizeList, _ := nbfs_client.GetPhotoSizeList(mediaPhoto.GetId().GetData2().GetId())
photo := &mtproto.TLPhoto{Data2: &mtproto.Photo_Data{
Id: mediaPhoto.GetId().GetData2().GetId(),
HasStickers: false,
AccessHash: mediaPhoto.GetId().GetData2().GetAccessHash(),
// result.AccessHash, // photo2.GetFileAccessHash(file.GetData2().GetId(), file.GetData2().GetParts()),
Date: now,
Sizes: sizeList,
}}
messageMedia := &mtproto.TLMessageMediaPhoto{Data2: &mtproto.MessageMedia_Data{
Photo_1: photo.To_Photo(),
Caption: mediaPhoto.GetCaption(),
TtlSeconds: mediaPhoto.GetTtlSeconds(),
}}
return messageMedia.To_MessageMedia()
case mtproto.TLConstructor_CRC32_inputMediaGeoPoint:
// messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia;
messageMedia := &mtproto.TLMessageMediaGeo{Data2: &mtproto.MessageMedia_Data{
Geo: makeGeoPointByInput(media.To_InputMediaGeoPoint().GetGeoPoint()),
}}
return messageMedia.To_MessageMedia()
case mtproto.TLConstructor_CRC32_inputMediaContact:
// messageMediaContact#5e7d2f39 phone_number:string first_name:string last_name:string user_id:int = MessageMedia;
contact := media.To_InputMediaContact()
messageMedia := &mtproto.TLMessageMediaContact{Data2: &mtproto.MessageMedia_Data{
PhoneNumber: contact.GetPhoneNumber(),
FirstName: contact.GetFirstName(),
LastName: contact.GetLastName(),
// UserId: user.GetMyUserByPhoneNumber(contact.GetPhoneNumber()).GetId(),
}}
phoneNumber, err := base.CheckAndGetPhoneNumber(contact.GetPhoneNumber())
if err == nil {
contactUser := user.GetMyUserByPhoneNumber(phoneNumber)
if contactUser != nil {
messageMedia.SetUserId(contactUser.GetId())
}
}
return messageMedia.To_MessageMedia()
case mtproto.TLConstructor_CRC32_inputMediaUploadedDocument:
// inputMediaUploadedDocument#e39621fd flags:# file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> caption:string stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
uploadedDocument := media.To_InputMediaUploadedDocument()
messageMedia, _ := nbfs_client.UploadedDocumentMedia(authKeyId, uploadedDocument)
return messageMedia.To_MessageMedia()
// id:InputDocument caption:string ttl_seconds:flags.0?int
case mtproto.TLConstructor_CRC32_inputMediaDocument:
// inputMediaDocument#5acb668e flags:# id:InputDocument caption:string ttl_seconds:flags.0?int = InputMedia;
// document := media.To_InputMediaDocument()
id := media.To_InputMediaDocument().GetId()
document3, _ := nbfs_client.GetDocumentById(id.GetData2().GetId(), id.GetData2().GetAccessHash())
// messageMediaDocument#7c4414d3 flags:# document:flags.0?Document caption:flags.1?string ttl_seconds:flags.2?int = MessageMedia;
messageMedia := &mtproto.TLMessageMediaDocument{Data2: &mtproto.MessageMedia_Data{
Document: document3,
Caption: media.To_InputMediaDocument().GetCaption(),
TtlSeconds: media.To_InputMediaDocument().GetTtlSeconds(),
}}
return messageMedia.To_MessageMedia()
case mtproto.TLConstructor_CRC32_inputMediaVenue:
// inputMediaVenue#c13d1c11 geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string = InputMedia;
venue := media.To_InputMediaVenue()
// messageMediaVenue#2ec0533f geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string = MessageMedia;
messageMedia := &mtproto.TLMessageMediaVenue{Data2: &mtproto.MessageMedia_Data{
Geo: makeGeoPointByInput(venue.GetGeoPoint()),
Title: venue.GetTitle(),
Address: venue.GetAddress(),
Provider: venue.GetProvider(),
VenueId: venue.GetVenueId(),
VenueType: venue.GetVenueType(),
}}
return messageMedia.To_MessageMedia()
case mtproto.TLConstructor_CRC32_inputMediaGifExternal:
// inputMediaGifExternal#4843b0fd url:string q:string = InputMedia;
// TODO(@benqi): MessageMedia???
return mtproto.NewTLMessageMediaUnsupported().To_MessageMedia()
case mtproto.TLConstructor_CRC32_inputMediaDocumentExternal:
// inputMediaDocumentExternal#b6f74335 flags:# url:string caption:string ttl_seconds:flags.0?int = InputMedia;
// TODO(@benqi): MessageMedia???
return mtproto.NewTLMessageMediaUnsupported().To_MessageMedia()
case mtproto.TLConstructor_CRC32_inputMediaPhotoExternal:
// inputMediaPhotoExternal#922aec1 flags:# url:string caption:string ttl_seconds:flags.0?int = InputMedia;
// TODO(@benqi): MessageMedia???
return mtproto.NewTLMessageMediaUnsupported().To_MessageMedia()
case mtproto.TLConstructor_CRC32_inputMediaGame:
// inputMediaGame#d33f43f3 id:InputGame = InputMedia;
// game#bdf9653b flags:# id:long access_hash:long short_name:string title:string description:string photo:Photo document:flags.0?Document = Game;
//
// inputGameID#32c3e77 id:long access_hash:long = InputGame;
// inputGameShortName#c331e80a bot_id:InputUser short_name:string = InputGame;
// TODO(@benqi): Not impl inputMediaGame
return mtproto.NewTLMessageMediaUnsupported().To_MessageMedia()
case mtproto.TLConstructor_CRC32_inputMediaInvoice:
// inputMediaInvoice#f4e096c3 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON start_param:string = InputMedia;
// TODO(@benqi): Not impl inputMediaGame
return mtproto.NewTLMessageMediaUnsupported().To_MessageMedia()
case mtproto.TLConstructor_CRC32_inputMediaGeoLive:
// inputMediaGeoLive#7b1a118f geo_point:InputGeoPoint period:int = InputMedia;
// inputMediaGeoLive#7b1a118f geo_point:InputGeoPoint period:int = InputMedia;
messageMedia := &mtproto.TLMessageMediaGeoLive{Data2: &mtproto.MessageMedia_Data{
Geo: makeGeoPointByInput(media.To_InputMediaGeoLive().GetGeoPoint()),
Period: media.To_InputMediaGeoLive().GetPeriod(),
}}
return messageMedia.To_MessageMedia()
}
return mtproto.NewTLMessageMediaEmpty().To_MessageMedia()
}
func makeOutboxMessageBySendMedia(authKeyId int64, fromId int32, peer *base.PeerUtil, request *mtproto.TLMessagesSendMedia) *mtproto.TLMessage {
message := &mtproto.TLMessage{ Data2: &mtproto.Message_Data{
Out: true,
Silent: request.GetSilent(),
FromId: fromId,
ToId: peer.ToPeer(),
ReplyToMsgId: request.GetReplyToMsgId(),
Media: makeMediaByInputMedia(authKeyId, request.GetMedia()),
ReplyMarkup: request.GetReplyMarkup(),
Date: int32(time.Now().Unix()),
}}
// TODO(@benqi): check channel or super chat
if peer.PeerType == base.PEER_CHANNEL {
message.SetPost(true)
}
return message
}
func makeUpdateNewMessageUpdates(selfUserId int32, message *mtproto.Message) *mtproto.TLUpdates {
userIdList, _, _ := message2.PickAllIDListByMessages([]*mtproto.Message{message})
userList := user.GetUsersBySelfAndIDList(selfUserId, userIdList)
updateNew := &mtproto.TLUpdateNewMessage{Data2: &mtproto.Update_Data{
Message_1: message,
}}
return &mtproto.TLUpdates{Data2: &mtproto.Updates_Data{
Updates: []*mtproto.Update{updateNew.To_Update()},
Users: userList,
Date: int32(time.Now().Unix()),
Seq: 0,
}}
}
// TODO(@benqi): check error
func SetupUpdatesState(state *mtproto.ClientUpdatesState, updates *mtproto.TLUpdates) *mtproto.TLUpdates {
pts := state.GetPts() - state.GetPtsCount() + 1
for _, update := range updates.GetUpdates() {
switch update.GetConstructor() {
case mtproto.TLConstructor_CRC32_updateNewMessage,
mtproto.TLConstructor_CRC32_updateDeleteMessages,
mtproto.TLConstructor_CRC32_updateReadHistoryOutbox,
mtproto.TLConstructor_CRC32_updateReadHistoryInbox,
mtproto.TLConstructor_CRC32_updateWebPage,
mtproto.TLConstructor_CRC32_updateReadMessagesContents,
mtproto.TLConstructor_CRC32_updateEditMessage:
//if pts >= state.GetPtsCount() {
// return false
//}
//
update.Data2.Pts = pts
update.Data2.PtsCount = 1
pts += 1
}
}
return updates
// return pts == state.GetPtsCount()
}
// messages.sendMedia#c8f16791 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia random_id:long reply_markup:flags.2?ReplyMarkup = Updates;
func (s *MessagesServiceImpl) MessagesSendMedia(ctx context.Context, request *mtproto.TLMessagesSendMedia) (*mtproto.Updates, error) {
md := grpc_util.RpcMetadataFromIncoming(ctx)
glog.Infof("messages.sendMedia#c8f16791 - metadata: %s, request: %s", logger.JsonDebugData(md), logger.JsonDebugData(request))
// TODO(@benqi): ???
// request.NoWebpage
// request.Background
// peer
var (
peer *base.PeerUtil
err error
)
if request.GetPeer().GetConstructor() == mtproto.TLConstructor_CRC32_inputPeerEmpty {
err = mtproto.NewRpcError2(mtproto.TLRpcErrorCodes_BAD_REQUEST)
glog.Error("messages.sendMedia#c8f16791 - invalid peer", err)
return nil, err
}
// TODO(@benqi): check user or channels's access_hash
// peer = helper.FromInputPeer2(md.UserId, request.GetPeer())
if request.GetPeer().GetConstructor() == mtproto.TLConstructor_CRC32_inputPeerSelf {
peer = &base.PeerUtil{
PeerType: base.PEER_USER,
PeerId: md.UserId,
}
} else {
peer = base.FromInputPeer(request.GetPeer())
}
/////////////////////////////////////////////////////////////////////////////////////
// 发件箱
// sendMessageToOutbox
outboxMessage := makeOutboxMessageBySendMedia(md.AuthId, md.UserId, peer, request)
if peer.PeerType == base.PEER_USER || peer.PeerType == base.PEER_CHAT {
// TODO(@benqi): set media_unread.
messageOutbox := message2.CreateMessageOutboxByNew(md.UserId, peer, request.GetRandomId(), outboxMessage.To_Message(), func(messageId int32) {
// 更新会话信息
user.CreateOrUpdateByOutbox(md.UserId, peer.PeerType, peer.PeerId, messageId, outboxMessage.GetMentioned(), request.GetClearDraft())
})
syncUpdates := makeUpdateNewMessageUpdates(md.UserId, messageOutbox.Message)
state, err := sync_client.GetSyncClient().SyncUpdatesData(md.AuthId, md.SessionId, md.UserId, syncUpdates.To_Updates())
if err != nil {
return nil, err
}
reply := SetupUpdatesState(state, syncUpdates)
updateMessageID := &mtproto.TLUpdateMessageID{Data2: &mtproto.Update_Data{
Id_4: messageOutbox.MessageId,
RandomId: request.GetRandomId(),
}}
updateList := []*mtproto.Update{updateMessageID.To_Update()}
updateList = append(updateList, reply.GetUpdates()...)
reply.SetUpdates(updateList)
/////////////////////////////////////////////////////////////////////////////////////
// 收件箱
if request.GetPeer().GetConstructor() != mtproto.TLConstructor_CRC32_inputPeerSelf {
inBoxes, _ := messageOutbox.InsertMessageToInbox(md.UserId, peer, func(inBoxUserId, messageId int32) {
// 更新会话信息
switch peer.PeerType {
case base.PEER_USER:
user.CreateOrUpdateByInbox(inBoxUserId, peer.PeerType, md.UserId, messageId, outboxMessage.GetMentioned())
case base.PEER_CHAT:
user.CreateOrUpdateByInbox(inBoxUserId, peer.PeerType, peer.PeerId, messageId, outboxMessage.GetMentioned())
}
})
for i := 0; i < len(inBoxes); i++ {
syncUpdates = makeUpdateNewMessageUpdates(inBoxes[i].UserId, inBoxes[i].Message)
sync_client.GetSyncClient().PushToUserUpdatesData(inBoxes[i].UserId, syncUpdates.To_Updates())
}
}
glog.Infof("messages.sendMedia#c8f16791 - reply: %s", logger.JsonDebugData(reply))
return reply.To_Updates(), nil
} else {
channelBox := message2.CreateChannelMessageBoxByNew(md.UserId, peer.PeerId, request.RandomId, outboxMessage.To_Message(), func(messageId int32) {
user.CreateOrUpdateByOutbox(md.UserId, peer.PeerType, peer.PeerId, messageId, false, false)
})
// updates.NewUpdatesLogic()
syncUpdates := updates.NewUpdatesLogic(md.UserId)
//updateChatParticipants := &mtproto.TLUpdateChatParticipants{Data2: &mtproto.Update_Data{
// Participants: channel.GetChannelParticipants().To_Channels_ChannelParticipants(),
//}}
//syncUpdates.AddUpdate(updateChatParticipants.To_Update())
syncUpdates.AddUpdateNewChannelMessage(outboxMessage.To_Message())
// syncUpdates.AddUsers(user.GetUsersBySelfAndIDList(md.UserId, chat.GetChatParticipantIdList()))
syncUpdates.AddChat(channel.GetChannelBySelfID(md.UserId, peer.PeerId))
state, _ := sync_client.GetSyncClient().SyncUpdatesData(md.AuthId, md.SessionId, md.UserId, syncUpdates.ToUpdates())
syncUpdates.PushTopUpdateMessageId(channelBox.ChannelMessageBoxId, request.RandomId)
//updateChannel := &mtproto.TLUpdateChannel{Data2: &mtproto.Update_Data{
// ChannelId: peer.PeerId,
//}}
//syncUpdates.AddUpdate(updateChannel.To_Update())
syncUpdates.SetupState(state)
idList := channel.GetChannelParticipantIdList(peer.PeerId)
inboxMessage := proto.Clone(outboxMessage).(*mtproto.TLMessage)
for _, id := range idList {
if id != md.UserId {
user.CreateOrUpdateByInbox(id, peer.PeerType, peer.PeerId, inboxMessage.GetId(), outboxMessage.GetMentioned())
pushUpdates := updates.NewUpdatesLogic(id)
pushUpdates.AddUpdateNewChannelMessage(inboxMessage.To_Message())
pushUpdates.AddChat(channel.GetChannelBySelfID(id, peer.PeerId))
sync_client.GetSyncClient().PushToUserUpdatesData(id, pushUpdates.ToUpdates())
}
}
glog.Infof("messages.sendMedia#c8f16791 - reply: %s", logger.JsonDebugData(syncUpdates.ToUpdates()))
return syncUpdates.ToUpdates(), nil
}
}