messageserver.py
贴代码
1
#
--coding:utf-8--
2
3
4 import os,os.path,sys,struct,time,traceback,signal,threading,copy
5 import base64
6
7 from datetime import datetime
8 from base import *
9 import tcelib as tce
10 from showbox import *
11 import utils.misc
12 import utils.config
13 # import django.showbox
14
15 # sys.path.insert(0,r'F:\projects\shoebox\database\showbox')
16 os.environ.setdefault( " DJANGO_SETTINGS_MODULE ", " database.showbox.showbox.settings ")
17
18 from django.db import connection
19 from django.db.models import Sum
20 from django.db import transaction
21 # import sns.core.models as cm
22 import database.showbox.core.models as core
23 import database.showbox.nosql.models as nosql
24 import msgentity
25 import utils
26
27
28 # sys.exit()
29
30 # def dumpMsg(m):
31 # '''
32 # from MimeMessage_t to mongo-json object {}
33 # '''
34 # r = {'sender_id':0,
35 # 'target_id':0,
36 # 'team_id':0,
37 # 'issue_time':datetime.now(),
38 # 'ack_time':None,
39 # 'status':SendMsgStatus.UNACKED,
40 # 'level':SendMsgLevel.DURABLE,
41 # 'type':m.type,
42 # 'text':m.text.text,
43 # 'im_type':m.image.type,
44 # 'im_width':m.image.width,
45 # 'im_height':m.image.height,
46 # 'im_data':base64.encodestring(m.image.data),
47 # 'au_type':m.audio.type,
48 # 'au_sample':0,
49 # 'au_channel':0,
50 # 'au_timelen':m.audio.timelen,
51 # 'au_data':base64.encodestring(m.audio.data)
52 # }
53 # return r
54 #
55 # def loadMsg(d):
56 # '''
57 # 从db对象还原为 MimeMessage_t()
58 # '''
59 # m = MimeMessage_t()
60 # m.type = d['type']
61 # m.text.type = 1
62 # m.text.text = d['text']
63 # m.timesec = time.mktime(d['issue_time'].timetuple())
64 # m.sender_id = d['sender_id']
65 #
66 # m.image.type = d['im_type']
67 # m.image.width = d['im_width']
68 # m.image.height = d['im_height']
69 # data = d['im_data']
70 # if data:
71 # m.image.data = base64.decodestring(data)
72 #
73 # m.audio.type = d['au_type']
74 # data = d['au_data']
75 # if data:
76 # m.audio.data = base64.decodestring(data)
77 # return m
78
79
80
81
82
83
84
85
86 # class MessagingServiceImpl(IMessageServer,IUserTeamServer,IUserEventListener):
87 class MessagingServiceImpl(IMessageServer,IUserEventListener):
88 def __init__(self,app):
89 IMessageServer. __init__(self)
90 # IUserTeamServer.__init__(self)
91 IUserEventListener. __init__(self)
92 self.app = app
93 self.serviceprxlist={} # 服务器代理对象缓存
94 self.usergws = {}
95
96
97 def onUserExitTeam(self,userid,teamid,ctx):
98 '''
99 将用户退出群的消息发送给群内其他用户
100 '''
101
102 ents = core.UserTeam.objects.get(id = int(teamid)).teamuser_set.exclude(user__id=int(userid) )
103 for en in ents:
104 nf = nosql.Notification()
105 nf.sid = utils.misc.genUUID()
106 nf.sender_id = userid
107 nf.target_id = str(en.user.id)
108 nf.type =NotifyMsgType.ExitTeam
109 nf.p1 = str(teamid)
110 nf.save()
111 prx = self. __getTerminalProxyByUserId(nf.target_id)
112 if prx:
113 prx.onTeamUserLeave_oneway(userid,teamid)
114
115
116
117 def onUserIntoTeam(self,userid,teamid,ctx):
118 '''
119 用户加入群之后通知群内其他用户
120 '''
121 ents = core.UserTeam.objects.get(id = int(teamid)).teamuser_set.exclude(user__id=int(userid) )
122 for en in ents:
123 nf = nosql.Notification()
124 nf.sid = utils.misc.genUUID()
125 nf.sender_id = userid
126 nf.target_id = str(en.user.id)
127 nf.type =NotifyMsgType.JoinTeam
128 nf.p1 = str(teamid)
129 nf.save()
130 prx = self. __getTerminalProxyByUserId(nf.target_id)
131 if prx:
132 prx.onTeamUserJoinin_oneway(userid,teamid)
133
134 def onUserDismissTeam(self,userid,team_id,ctx):
135 '''
136 用户群集散,通知群内所有用户
137 '''
138 ents = core.UserTeam.objects.get(id = int(team_id)).teamuser_set.exclude(user__id=int(userid) )
139 for en in ents:
140 nf = nosql.Notification()
141 nf.sid = utils.misc.genUUID()
142 nf.sender_id = userid
143 nf.target_id = str(en.user.id)
144 nf.type =NotifyMsgType.DestroyTeam
145 nf.p1 = str(team_id)
146 nf.save()
147 prx = self. __getTerminalProxyByUserId(nf.target_id)
148 if prx:
149 prx.onTeamDismiss_oneway(team_id)
150
151 def onUserOnline(self,userid,gws_id,device,ctx):
152 print ' onUserOnline.. ',userid,gws_id
153 userid = int(userid)
154 self.usergws[userid] = gws_id
155 # 保存用户状态到数据表
156 user = core.User.objects.get(id = int(userid))
157 user.status = UserStatus.Online
158 user.save()
159 # 传递未发送消息到前端用户
160 self._sendPendingMsgToUser(userid)
161 self._sendNotifications(userid)
162
163 self._sendPendingInvitationToInvitee(userid)
164 self._sendPendingInvitationActToInviter(userid)
165 self._notifyUserStatusChanged(userid,UserStatus.Online)
166
167
168 def onUserOffline(self,userid,gws_id,device,ctx):
169 print ' onUserOffline.. '
170 userid = int(userid)
171 gws = self.usergws.get(userid)
172 if gws != None:
173 del self.usergws[userid]
174 user = core.User.objects.get(id = int(userid))
175 user.status = UserStatus.Offline
176 user.save()
177 # 通知所有用户告知本人离线
178 self._notifyUserStatusChanged(userid,UserStatus.Offline)
179
180
181 def inviteUser(self,target_id,whisper,ctx):
182 '''
183 发送加入好友请求
184 '''
185 userid = USER_ID(ctx)
186 target_id = int(target_id)
187 res = CallReturn()
188 try:
189 target_id = int(target_id)
190 user = core.User.objects.get(id=userid)
191 if core.UserRelation.objects.filter(user__id=userid,friend__id=target_id):
192 return CallReturn(ErrorDefs.UserIsFriend)
193 if core.User.objects.filter(id=target_id).count() ==0:
194 return CallReturn(ErrorDefs.UserIdNotExisted)
195
196 # 1.write to invitation
197 inv = nosql.Invitation()
198 # inv.sid = utils.misc.genUUID()
199 inv.sender_id = userid
200 inv.target_id = target_id
201 inv.greeting = whisper
202 inv.sender_name = user.name
203 inv.send_type = InviteSendType.SysInternal
204 inv.confirm_result = InvitationResult.NO_ACK
205
206 if not inv.sender_name:
207 inv.sender_name = user.user # 替换合适的名称
208 inv.save()
209 # 2.send to PeerUser
210 prx = self. __getTerminalProxyByUserId(target_id)
211 if prx:
212 prx.onInviteRequest_oneway( str(inv.id),str(userid),whisper,CALL_USER_ID(target_id))
213 except :
214 print traceback.print_exc()
215 res = CallReturn(ErrorDefs.InternalException)
216 return res
217
218 def inviteReject(self,seq,reason,ctx):
219 try:
220 userid = USER_ID(ctx)
221 seq = int(seq)
222 inv = nosql.Invitation.objects.get(id=seq,target_id=userid)
223 inv.confirm_time = datetime.now()
224 inv.confirm_result = InvitationResult.REJECT
225 inv.save()
226 prx = self. __getTerminalProxyByUserId(inv.sender_id)
227 if prx:
228 prx.onInviteReject_oneway(seq,inv.target_id,CALL_USER_ID(inv.sender_id))
229 except:
230 traceback.print_exc()
231
232 def inviteAccept(self,seq,ctx):
233 '''
234 B 接收到邀请之后 发送接受加为好友的答复到服务器
235 '''
236 try:
237 userid = USER_ID(ctx)
238 inv = nosql.Invitation.objects.get(id=int(seq),target_id=userid)
239 inv.confirm_time = datetime.now()
240 inv.confirm_result = InvitationResult.ACCEPT
241 print inv,inv.id,inv.issue_time
242 inv.save()
243 # 接着记录两者的关系 ,表 UserRelation
244 user1 = core.User.objects.get(id=inv.sender_id)
245 user2 = core.User.objects.get(id=inv.target_id)
246 rel = core.UserRelation()
247 rel.user =user1
248 rel.friend = user2
249 rel.save()
250
251 rel = core.UserRelation()
252 rel.user =user2
253 rel.friend = user1
254 rel.save()
255
256 prx = self. __getTerminalProxyByUserId(inv.sender_id)
257 if prx:
258 prx.onInviteAccept_oneway(seq,inv.target_id,CALL_USER_ID(inv.sender_id))
259 except:
260 traceback.print_exc()
261
262 # def getMessageLogList(self,target_id,type,timerange,ctx):
263 # return QueryMessageLogResult_t()
264
265 def inviteResultConfirm(self,seq,ctx):
266 '''
267 A->S->B
268 B->S->A
269 A->S
270 '''
271 try:
272 userid = USER_ID(ctx)
273 inv = nosql.Invitation.objects.get(id=int(seq))
274 inv.issuer_confirm_time = datetime.now()
275 inv.save()
276 except:
277 traceback.print_exc()
278
279 def nofityConfirm(self,seq_id,ctx):
280 '''
281 除了消息发送、邀请之外的处理类型,需要确认接收到了,必须走此接口
282 '''
283 userid = USER_ID(ctx) # 当前用户编号
284 e = nosql.Notification.objects.get(id=int(seq_id),target_id=int(userid))
285 e.confirm_time = datetime.now()
286 e.save()
287
288 def _sendNotifications(self,userid):
289 userid = int(userid)
290 prx = self. __getTerminalProxyByUserId(userid)
291 # 提取未发送的通知消息
292 ents = nosql.Notification.objects.filter(target_id=int(userid),confirm_time=None).order_by( ' issue_time ')
293
294 for e in ents:
295 nm = NotifyMessage_t()
296 nm.seq = str(e.id)
297 nm.issuer = str(e.sender_id)
298 nm.type = e.type
299 nm.issue_time = utils.misc.maketimestamp(e.issue_time)
300 nm.p1 = e.p1
301 nm.p2 = e.p2
302 prx.onNotifyMessage_oneway( nm.issuer,nm,CALL_USER_ID(userid))
303
304
305 def _sendPendingMsgToUser(self,userid):
306 '''
307 发送未传送的消息到终端用户
308 '''
309 print ' _sendPendingMsgToUser.. ',userid
310 ents = nosql.SendMessage.objects.filter(target_id=userid,confirm_result=SendMsgStatus.UNACKED).order_by( ' issue_time ')
311 prx = self. __getTerminalProxyByUserId(userid)
312 if not prx:
313 return
314
315 for e in ents:
316
317 m = MimeText_t()
318 m.seq = e.id
319 m.text = e.content
320 m.issue_time = utils.misc.maketimestamp(e.issue_time)
321 m.type = e.type
322 m.entities = e.entities
323 if e.team_id ==0:
324 prx.onMessageText_oneway(str(e.sender_id),m,CALL_USER_ID(userid))
325 else: # 传递到用户组
326 prx.onTeamMessageText_oneway(str(e.sender_id),e.team_id,m,CALL_USER_ID(userid))
327
328
329 def _sendPendingInvitationToInvitee(self,invitee_id):
330 '''
331 发送邀请,传送到前端好友
332 '''
333 print ' _sendPendingInvitationToInvitee.. '
334 invitee_id = int(invitee_id)
335 ents = nosql.Invitation.objects.filter(target_id=invitee_id,
336 confirm_result = InvitationResult.NO_ACK,
337 send_type = InviteSendType.SysInternal)
338 prx = self. __getTerminalProxyByUserId(invitee_id)
339 if not prx: return
340 print ents
341 for e in ents:
342 prx.onInviteRequest_oneway( str(e.id),str(e.sender_id),str(e.greeting),CALL_USER_ID(invitee_id))
343
344 def _sendPendingInvitationActToInviter(self,userid):
345 '''
346 被邀请者接收到邀请,并提交到服务器。并将提交结果转发给邀请发送者
347 '''
348 userid = int(userid)
349 ents = nosql.Invitation.objects.filter(sender_id=userid,issuer_confirm_time = None,
350 send_type = InviteSendType.SysInternal).\
351 exclude(confirm_result=InvitationResult.NO_ACK)
352 prx = self. __getTerminalProxyByUserId(userid)
353 if not prx: return
354 for e in ents:
355 if e.confirm_result == InvitationResult.ACCEPT:
356 prx.onInviteAccept_oneway(e.id,e.target_id,CALL_USER_ID(userid))
357 if e.confirm_result == InvitationResult.REJECT:
358 prx.onInviteReject_oneway(e.id,e.target_id,CALL_USER_ID(userid))
359
360
361 def _sendPendingJoinTeamRequestToTeamOwner(self,userid):
362 '''
363 将请求加入隶属B的群的消息,发送给B
364 '''
365 userid = int(userid)
366 rs = nosql.JoinTeam.objects.filter(owner_id = userid,issuer_confirm_time = None,
367 confirm_result=JoinTeamResult.NO_ACK)
368
369
370
371 def _notifyUserStatusChanged(self,userid,status):
372 '''
373 通知user的好友或者加入群内的用户,本人状态改变
374 此消息不用持久化
375 '''
376 user = core.User.objects.get(id = userid)
377 entries = user.userfriend_set.all()
378 for en in entries:
379 target_id = en.friend.id
380 prx = self. __getTerminalProxyByUserId(target_id)
381 if not prx:
382 print ' prx is None ,user_id: %s not online! '%target_id
383 continue
384 nm = NotifyMessage_t()
385 nm.seq = str(0)
386 nm.issuer = str(userid)
387 nm.type_ = NotifyMsgType.UserStatusChanged
388 nm.p1 = status
389 nm.issue_time = int(time.time())
390 prx.onNotifyMessage_oneway(nm.issuer,nm,CALL_USER_ID(target_id))
391
392 # ------------- IUserTeamServer --------------------------------------
393
394 def sendTeamMessageText(self,team_id,text,ctx):
395 print ' sendTeamMessageText.. ',team_id
396
397 userid = USER_ID(ctx)
398 # 群内非本人所有朋友记录, 群主不在 teamrelation表哦,
399 users=[]
400 team_id = team_id
401
402 team = core.UserTeam.objects.get(id=team_id)
403 if team.user.id != userid: # 不是本人的team,把team的owner也加入群发数组
404 users.append(team.user)
405
406 rs = core.TeamRelation.objects.filter(team__id=int(team_id)).exclude(user__id=userid)
407 for r in rs:
408 users.append(r.user)
409
410 for r in users:
411 m = nosql.SendMessage()
412 m.sender_id = userid
413 m.target_id = r.id
414 m.team_id = int(team_id)
415 m.type = text.type_
416 m.level = SendMsgLevel.DURABLE
417 m.content = text.text # to see MineText_t
418 m.entities = text.entities
419 m.save()
420 text.seq = m.id
421 self._ripMessageContent(m,text)
422
423 # 查询目标用户是否接入到某个gws,并将消息传送过去
424 prx = self. __getTerminalProxyByUserId(m.target_id)
425 print ' prx is: ',prx
426 if prx :
427 prx.onTeamMessageText_oneway(str(userid),team_id,text,CALL_USER_ID(m.target_id))
428
429
430
431 # ---------------- IMessageServer -----------------------------------
432 def sendMessageText(self,target_id,text,ctx):
433 print ' sendMessageText: ', target_id,text.text
434 userid = USER_ID(ctx)
435 m = nosql.SendMessage()
436 # m.sid = utils.misc.genUUID()
437 m.sender_id = userid
438 m.target_id = int(target_id)
439 m.team_id = 0
440 m.type = text.type_
441 m.level = SendMsgLevel.DURABLE
442 m.content = text.text # to see MineText_t
443 m.entities = text.entities
444 m.save()
445 self._ripMessageContent(m,text)
446
447 text.seq = m.id
448 # 查询目标用户是否接入到某个gws,并将消息传送过去
449 prx = self. __getTerminalProxyByUserId(target_id)
450 print ' prx is: ',prx
451 if prx :
452 prx.onMessageText_oneway(str(userid),text,CALL_USER_ID(target_id))
453
454
455 def _ripMessageContent(self,dbobj,m):
456 '''
457 抽取消息文本中各个entities,并写入db
458 包括 图像、音频 适当调整和处理
459 图像等新记录会写到 Message的text字段,内包含指向资源编号
460 MimeText内的image和audio数据存放在 MimeText.datas数据内,一次摆放
461 '''
462 enset = msgentity.MessageEntitySet.parse(m.text)
463 if not enset:
464 print ' MessageEntitiySet parse failed. '
465 return
466 idx = 0
467 print repr(m.datas)
468 try:
469 for en in enset.entities:
470 if isinstance(en,msgentity.ImageEntity) or \
471 isinstance(en,msgentity.AudioEntity):
472 en.content = m.datas[idx]
473
474 if isinstance(en,msgentity.ImageEntity):
475 r = nosql.ImageEntity()
476 r.msg_id = dbobj.id
477 r.image_type = 0
478 r.width = en.width
479 r.height = en.height
480 r.content = utils.misc.encodeBase64( m.datas[idx] )
481 print r.content
482 r.save()
483 en.id = r.id # 记录image记录编号
484 en.content= ''
485
486 if isinstance(en,msgentity.AudioEntity):
487 r = nosql.AudioEntity()
488 r.msg_id = dbobj.id
489 r.duration = en.duration
490 r.content = utils.misc.encodeBase64(m.datas[idx])
491 r.save()
492 en.id = r.id
493 en.content = ''
494
495 if isinstance(en,msgentity.ImageEntity) or \
496 isinstance(en,msgentity.AudioEntity):
497 idx+=1
498
499 # 更新消息的文本内容
500 dbobj.content = enset.toJson()
501 dbobj.save()
502 except:
503 traceback.print_exc()
504
505 # def sendMessageImage(self,target_id,image,ctx):
506 # userid = USER_ID(ctx)
507 # m = nosql.SendMessage()
508 # m.sid = utils.misc.genUUID()
509 # m.sender_id = userid
510 # m.target_id = int(target_id)
511 # m.type = MimeMessageType.IMAGE
512 # m.level = SendMsgLevel.DURABLE
513 # m.im_type = image.type
514 # m.im_width = image.width
515 # m.im_height = image.height
516 # m.im_content = base64.encodestring(image.data)
517 # m.save()
518 # #查询目标用户是否接入到某个gws,并将消息传送过去
519 # prx = self.__getTerminalProxyByUserId(userid)
520 # if prx :
521 # prx.onMessageImage_oneway(str(userid),image,m.sid,CALL_USER_ID(target_id))
522 #
523 # def sendMessageAudioClip(self,target_id,clip,ctx):
524 # userid = USER_ID(ctx)
525 # m = nosql.SendMessage()
526 # m.sid = utils.misc.genUUID()
527 # m.sender_id = userid
528 # m.target_id = int(target_id)
529 # m.type = MimeMessageType.AUDIO
530 # m.level = SendMsgLevel.DURABLE
531 # m.au_channel = clip.channel
532 # m.au_duration = clip.timelen
533 # m.au_sample = clip.samples
534 # m.au_type = clip.type
535 # m.au_content = base64.encodestring(clip.data)
536 # m.save()
537 # #查询目标用户是否接入到某个gws,并将消息传送过去
538 # prx = self.__getTerminalProxyByUserId(userid)
539 # if prx :
540 # prx.onMessageAudioclip_oneway(str(userid),clip,m.sid,CALL_USER_ID(target_id))
541
542
543 def sendMessageConfirm(self,seq_id,ctx):
544 '''
545 B 接收到消息之后发送 确认消息,
546 否则系统将定时重发当初的消息或者当B再次在线online时被推送到B
547 '''
548 print ' sendMessageConfirm.. ', ' seq_id: ',seq_id
549 userid = USER_ID(ctx)
550 m = nosql.SendMessage.objects.get(id=int(seq_id),target_id=int(userid))
551 m.confirm_time = datetime.now()
552 m.confirm_result = SendMsgStatus.ACKED
553 m.save()
554
555 # def sendLocation(self,target_id,gps,ctx):
556 # '''
557 # 转发gps坐标到目标用户
558 # '''
559 # userid = USER_ID(ctx)
560 # prx = self.__getTerminalProxyByUserId(target_id)
561 # if prx:
562 # prx.onLocation_oneway(str(userid),gps,CALL_USER_ID(target_id))
563 #
564
565
566 def sendFilePrepare(self,type_,target_id,info,ctx):
567 return CallReturn_t()
568
569 def putFilePrepare(self,info,path,category,ctx):
570 return CallReturn_t()
571
572 def getFilePrepare(self,file_id,ctx):
573 return CallReturn_t()
574
575 def getFileServerUri(self,seq_id,ctx):
576 return ServiceURI_t()
577
578 def retrieveFileFinished(self,seq_id,ctx):
579 pass
580
581 def retrieveFileAccept(self,seq_id,ctx):
582 pass
583
584 def retrieveFileFileReject(self,seq_id,reason,ctx):
585 pass
586
587 def queryUserMessage(self,target_id,type_,timerange,limit,ctx):
588 return UserMessageQueryResult_t()
589
590 # ------------- TEAM operations ------------------
591 def requestJoinTeam(self, team_id, identity, ctx):
592 '''
593 用户请求加入指定的群
594 '''
595 userid = USER_ID(ctx)
596 cr = CallReturn()
597 try:
598 team_id = int(team_id)
599 team = core.UserTeam.objects.get(id = team_id)
600 ownerid = team.user.id
601 if ownerid == userid: # 自己加入自己的群,此操作非法
602 return CallReturn(ErrorDefs.TargetInvalid,msg= ' user_id equals team-owner! ')
603 jt = nosql.JoinTeam()
604 jt.sender_id = userid
605 jt.target_id = team_id
606 jt.owner_id = ownerid
607 jt.greeting = identity
608 jt.sender_name = team.user.name
609 jt.confirm_result = JoinTeamResult.NO_ACK
610 jt.save()
611 # 立马是发送给群拥有者
612 prx = self. __getTerminalProxyByUserId(ownerid)
613 if prx:
614 prx.onJoinTeamRequest_oneway( str(jt.id),team_id,str(userid),identity,CALL_USER_ID(ownerid))
615 except:
616 traceback.print_exc()
617 cr = CallReturn(ErrorDefs.InternalException)
618 return cr
619
620 def joinTeamResultConfirm(self, seq, ctx):
621 '''
622 请求加入群的用户收到 accept,reject之后发送确认信息
623 '''
624 try:
625 userid = USER_ID(ctx)
626 jt = nosql.JoinTeam.objects.get(id = int(seq))
627 jt.issuer_confirm_time = datetime.now()
628 jt.save()
629 except:
630 traceback.print_exc()
631
632
633 def removeTeamUser(self, team_id, friend_id, ctx):
634 '''
635 群创建者直接删除群内用户
636 '''
637 cr = CallReturn()
638 try:
639 userid = USER_ID(ctx)
640 team_id = int(team_id)
641 friend_id = int(friend_id)
642 if core.UserTeam.objects.filter(user__id=userid,id = team_id).count() ==0:
643 return CallReturn_Error(ErrorDefs.TargetObjectNotExisted,msg= ' team id invalid! ')
644 if core.TeamRelation.objects.filter(user__id=friend_id,team__id=team_id).count() == 0:
645 return CallReturn_Error(ErrorDefs.TargetObjectNotExisted,msg= ' friend or team unmatched! ')
646
647 # 通知群内用户 指定用户离开群
648 users = self._getUsersInTeam(team_id)
649 for user in users:
650 # 写入数据库
651 nf = nosql.Notification()
652 nf.sender_id = userid
653 nf.target_id = user.id
654 nf.type = NotifyMsgType.TeamUserLeave # 新成员加入
655 nf.p1 = team_id
656 nf.p2 = friend_id
657 nf.save()
658 # 发送到群用户
659 prx = self. __getTerminalProxyByUserId(user.id)
660 if prx:
661 prx.onNotifyMessage_oneway(userid,nf,CALL_USER_ID(user.id))
662 # 删除数据库记录
663 rs = core.TeamRelation.filter(user__id = friend_id,team__id=team_id)
664 rs.delete()
665 except:
666 traceback.print_exc()
667 cr = CallReturn_Error(ErrorDefs.InternalException)
668 return cr
669
670 def addTeamUser(self, team_id, friend_id, ctx):
671 '''
672 群创建者直接将好友加入指定的群
673
674 '''
675
676 cr = CallReturn()
677 try:
678 userid = USER_ID(ctx)
679 team_id = int(team_id)
680 friend_id = int(friend_id)
681 rs = core.UserTeam.objects.filter(id=team_id)
682 if not rs:
683 return CallReturn_Error(ErrorDefs.TargetInvalid,msg= ' team id do not existed! ')
684 team = rs[0]
685 rs = core.UserRelation.objects.filter(user__id=userid,friend__id=friend_id).count()
686 if not rs:
687 return CallReturn_Error(ErrorDefs.TargetInvalid,msg= ' team id or friend id not matched! ')
688 friend = rs[0].friend
689 rel = core.TeamRelation()
690 rel.user = friend
691 rel.team = team
692 rel.save()
693
694 users = self._getUsersInTeam(team_id)
695 # 发送通知到群成员
696 for user in users:
697 # 写入数据库
698 nf = nosql.Notification()
699 nf.sender_id = userid
700 nf.target_id = user.id
701 nf.type = NotifyMsgType.TeamUserEnter # 新成员加入
702 nf.p1 = team_id
703 nf.p2 = friend_id
704 nf.save()
705 # 发送到群用户
706 prx = self. __getTerminalProxyByUserId(user.id)
707 if prx:
708 prx.onNotifyMessage_oneway(userid,nf,CALL_USER_ID(user.id))
709
710 except:
711 traceback.print_exc()
712 cr = CallReturn_Error(ErrorDefs.InternalException)
713 return cr
714
715 def dismissTeam(self, team_id, ctx):
716 '''
717 群创建者解散群
718 '''
719 cr = CallReturn()
720 userid = USER_ID(ctx)
721 try:
722 team_id = int(team_id)
723 rs = core.UserTeam.objects.filter(id=team_id,user__id=userid)
724 if not rs:
725 return CallReturn_Error(ErrorDefs.TargetInvalid, ' team object not existed! ')
726 team = rs[0]
727 users = self._getUsersInTeam(team_id)
728
729 # 发送通知到群成员
730 for user in users:
731 # 写入数据库
732 nf = nosql.Notification()
733 nf.sender_id = userid
734 nf.target_id = user.id
735 nf.type = NotifyMsgType.DismissTeam
736 nf.p1 = team_id
737 nf.save()
738 # 发送到群用户
739 prx = self. __getTerminalProxyByUserId(user.id)
740 if prx:
741 prx.onNotifyMessage_oneway(userid,nf,CALL_USER_ID(user.id))
742
743 rs.delete() # 删除群内成员
744 team.delete() # 删除群记录
745 except:
746 traceback.print_exc()
747 cr = CallReturn_Error(ErrorDefs.InternalException)
748 return cr
749
750
751
752
753 def _getUsersInTeam(self,team_id,exclusive=0):
754 '''
755 获取群内所有成员用户,包含群主
756 '''
757 users=[]
758 try:
759 team =core.UserTeam.objects.get(id=int(team_id))
760 if exclusive != team.user.id:
761 users.append(team.user)
762 rs = core.TeamRelation.objects.filter(team__id=int(team_id))
763 for r in rs:
764 if exclusive != r.user.id:
765 users.append(r.user)
766 except:
767 traceback.print_exc()
768 return users
769
770 def exitTeam(self, team_id, ctx):
771 '''
772 群用户退出将通知群内其他用户(群创建者不允许)
773 '''
774 cr = CallReturn()
775 try:
776 userid = USER_ID(ctx)
777 team_id = int(team_id)
778 # 群主不能退出自己创建的群
779 if core.UserTeam.objects.filter(user__id= userid,id = team_id).count():
780 return CallReturn_Error(ErrorDefs.IllegalOperation,msg= ' the team belong to curernt user! ')
781 rs = core.TeamRelation.objects.filter(user__id=userid,team__id = team_id)
782 if not rs:
783 return CallReturn_Error(ErrorDefs.IllegalOperation,msg= ' user not in team ! ')
784 rs.delete()
785 # 通知群内其他人
786 users = self._getUsersInTeam(team_id)
787 for user in users:
788 nt = nosql.Notification()
789 nt.sender_id = userid
790 nt.target_id = user.id
791 nt.type = NotifyMsgType.TeamUserLeave
792 nt.p1 = team_id
793 nt.p2 = userid
794 nt.save() # 完成通知存储
795
796 # 发送通知前端客户
797 prx = self. __getTerminalProxyByUserId(user.id)
798 if prx:
799 prx.onNotifyMessage_oneway(userid,nt,CALL_USER_ID(user.id))
800 except:
801 traceback.print_exc()
802 cr = CallReturn_Error(ErrorDefs.InternalException)
803 return cr
804
805
806 def joinTeamAccept(self, seq, ctx):
807 try:
808 userid = USER_ID(ctx)
809 jt = nosql.JoinTeam.objects.get(id = int(seq))
810 jt.confirm_time = datetime.now()
811 jt.confirm_result = JoinTeamResult.ACCEPT
812 jt.save()
813 if core.TeamRelation.objects.filter(team__id=jt.target_id,user__id=jt.sender_id).count() ==0:
814 user = core.User.objects.get(id=jt.sender_id)
815 team = core.UserTeam.objects.get(id=jt.target_id)
816 rel = core.TeamRelation()
817 rel.user = user
818 rel.team = team
819 rel.save()
820 # 通知请求用户,加入群okay
821 prx = self. __getTerminalProxyByUserId(jt.sender_id)
822 if prx:
823 prx.onJoinTeamAccept_oneway(seq,jt.target_id,userid,CALL_USER_ID(jt.sender_id))
824
825 # 通知群内所有其他用户,告知新用户进入
826 users = self._getUsersInTeam(jt.target_id)
827
828 for user in users: # 群内的所有好友
829 # 1.写入通知表
830 nt = nosql.Notification()
831 nt.sender_id = jt.owner_id
832 nt.target_id = user.id
833 nt.type = NotifyMsgType.TeamUserEnter
834 nt.p1 = jt.target_id
835 nt.p2 = jt.sender_id
836 nt.save() # 完成通知存储
837
838 # 发送通知前端客户
839 prx = self. __getTerminalProxyByUserId(user.id)
840 if prx:
841 prx.onJoinTeamAccept_oneway(seq,jt.target_id,jt.owner_id,CALL_USER_ID(user.id))
842 except:
843 traceback.print_exc()
844
845
846 def joinTeamReject(self, seq, reason, ctx):
847 '''
848 用户请求加入群,群主拒绝
849 '''
850 try:
851 userid = USER_ID(ctx)
852 jt = nosql.JoinTeam.objects.get(id = int(seq))
853 jt.confirm_time = datetime.now()
854 jt.confirm_result = JoinTeamResult.REJECT
855 jt.save()
856 # 通知请求用户
857 prx = self. __getTerminalProxyByUserId(jt.sender_id)
858 if prx:
859 prx.onJoinTeamReject_oneway(seq,jt.target_id,userid,CALL_USER_ID(jt.sender_id))
860 except:
861 traceback.print_exc()
862
863
864 # ---------------- Others -----------------------------------
865
866
867 def __getTerminalProxyByUserId(self,user_id):
868 '''
869 server_eps.conf 记录gws对应的接收rpc消息的endpoint名称,
870 获取ep名称,通过RpcCommunicator.findEndpoints()得到ep
871 ep.impl就是对应服务器接收消息的连接
872 '''
873 prx = None
874 try:
875 user_id = int(user_id)
876 if not self.usergws.get(user_id):
877 return None # user没有上线
878 gws = self.usergws.get(user_id)
879 prx = self.serviceprxlist.get(gws)
880 if not prx:
881 cf = utils.config.SimpleConfig()
882 cf.load( ' server_eps.conf ')
883 epname = cf.getValue(gws)
884 ep = tce.RpcCommunicator.instance().currentServer().findEndPointByName(epname)
885 prx = ITerminalPrx(ep.impl)
886 self.serviceprxlist[gws] = prx
887 return prx
888 finally:
889 if not prx:
890 print ' user: %s is not online! '%user_id
891
892
893 # def sendMessage(self,targets,type,msg,ctx):
894 # '''
895 # 消息进入mongodb,待用户发送ack之后才删除,否则等用户再次连接进入时发送给用户
896 # targets - id list
897 # type - MsgTargetType
898 # msg - MimeMessage_t
899 # @deal :
900 # delivery msg to sender
901 # '''
902 # userid = USER_ID(ctx)
903 # # self.app.msgsync.sendMessage(targets,type,msg,userid)
904 # ids = map(int,targets)
905 # for id in ids:
906 # if type == MsgTargetType.USER:
907 # self.app.sendMsgToUser(id,msg,userid)
908 # elif type == MsgTargetType.TEAM:
909 # #发送到群
910 # self.app.sendMsgToTeam(id,msg,userid)
911 #
912 #
913 # def sendLocation(self,targets,type,loc,ctx):
914 # userid = USER_ID(ctx)
915 # ids = map(int,targets)
916 # x,y = geotools.point_g2m(loc.gps.loc.lon,loc.gps.loc.lat)
917 # loc.gps.loc.lon = x
918 # loc.gps.loc.lat = y
919 # for id in ids:
920 # if type == MsgTargetType.USER:
921 # self.app.sendLocationToUser(id,loc,userid)
922 # elif type == MsgTargetType.TEAM:
923 # #发送到群
924 # self.app.sendLocationToTeam(id,loc,userid)
925 # elif type == MsgTargetType.SYSTEM:
926 # pass
927 # self.app.sendLocationToReciever(loc,userid)
928 #
929 # def uploadLocation(self,loc,ctx):
930 # userid = USER_ID(ctx)
931 # pass
932 #
933 # def sendMsgAck(self,seqs,ctx):
934 # #用户发送消息确认消息
935 # db = self.app.getNosqlDb()
936 # for seq in seqs:
937 # try:
938 # #r = db.user_sendmessage.find_one({'_id':seq})
939 # #if r:
940 # db.user_sendmessage.update({'_id':ObjectId(seq)},
941 # {'$set':{'status':1,'ack_time':datetime.now()}},
942 # multi = True
943 # )
944 # # r['status'] = 1
945 # # r['ack_time']= datetime.now()
946 # # r.save()
947 # except:
948 # print traceback.format_exc()
949 #
950 #
951 # def createTalking(self,type,ctx):
952 # '''
953 # talkin建立发送talking创建到talkingserver
954 # 用户根据talkingid链接到talkingserver
955 # '''
956 # return TalkingResource_t()
957 #
958 # def inviteTalking(self,target_id,talking_id,ctx):
959 # pass
960 #
961 # def inviteTalkingAccept(self,talking_id,ctx):
962 # pass
963 #
964 # def inviteTalkingReject(self,talking_id,reason,ctx):
965 # pass
966 #
967 # def initOnlineUserList(self,gwaid,useridlist,ctx):
968 # for uid in useridlist:
969 # self.app.userOnline(uid,gwaid)
970 # #-------- above interface implements ---
971 # #----- local functions ----
972 #
973
974
975
976
977
978 class ServerApp:
979 def __init__(self):
980 pass
981
982 def getConfig(self):
983 # return self.app.getConfig()
984 pass
985
986 _handle = None
987 @classmethod
988 def instance(cls):
989 if cls._handle == None:
990 cls._handle = cls()
991 return cls._handle
992
993 def run(self):
994 tce.RpcCommunicator.instance().init( ' messageserver ').initMessageRoute( ' ./services.xml ')
995 server = tce.RpcCommunicator.instance().currentServer().findEndPointByName( ' mq_messageserver ').impl
996 conn = tce.RpcCommunicator.instance().currentServer().findEndPointByName( ' mq_user_event_listener ').impl
997 adapter = tce.RpcAdapterEasyMQ.create( ' server ',server)
998 adapter.addConnection(conn)
999 # 没有主动发送消息的情形
1000 servant = MessagingServiceImpl(self)
1001 adapter.addServant(servant)
1002 tce.RpcCommunicator.instance().waitForShutdown()
1003
1004
1005 if __name__ == ' __main__ ':
1006 ServerApp.instance().run()
1007 # print cm.User.objects.all()
1008 # print cm.User.objects.filter(user='abc')
1009 # print dir(tce) #.mqset_inst
1010 pass # sys.exit( MainApp().run())
1011
2
3
4 import os,os.path,sys,struct,time,traceback,signal,threading,copy
5 import base64
6
7 from datetime import datetime
8 from base import *
9 import tcelib as tce
10 from showbox import *
11 import utils.misc
12 import utils.config
13 # import django.showbox
14
15 # sys.path.insert(0,r'F:\projects\shoebox\database\showbox')
16 os.environ.setdefault( " DJANGO_SETTINGS_MODULE ", " database.showbox.showbox.settings ")
17
18 from django.db import connection
19 from django.db.models import Sum
20 from django.db import transaction
21 # import sns.core.models as cm
22 import database.showbox.core.models as core
23 import database.showbox.nosql.models as nosql
24 import msgentity
25 import utils
26
27
28 # sys.exit()
29
30 # def dumpMsg(m):
31 # '''
32 # from MimeMessage_t to mongo-json object {}
33 # '''
34 # r = {'sender_id':0,
35 # 'target_id':0,
36 # 'team_id':0,
37 # 'issue_time':datetime.now(),
38 # 'ack_time':None,
39 # 'status':SendMsgStatus.UNACKED,
40 # 'level':SendMsgLevel.DURABLE,
41 # 'type':m.type,
42 # 'text':m.text.text,
43 # 'im_type':m.image.type,
44 # 'im_width':m.image.width,
45 # 'im_height':m.image.height,
46 # 'im_data':base64.encodestring(m.image.data),
47 # 'au_type':m.audio.type,
48 # 'au_sample':0,
49 # 'au_channel':0,
50 # 'au_timelen':m.audio.timelen,
51 # 'au_data':base64.encodestring(m.audio.data)
52 # }
53 # return r
54 #
55 # def loadMsg(d):
56 # '''
57 # 从db对象还原为 MimeMessage_t()
58 # '''
59 # m = MimeMessage_t()
60 # m.type = d['type']
61 # m.text.type = 1
62 # m.text.text = d['text']
63 # m.timesec = time.mktime(d['issue_time'].timetuple())
64 # m.sender_id = d['sender_id']
65 #
66 # m.image.type = d['im_type']
67 # m.image.width = d['im_width']
68 # m.image.height = d['im_height']
69 # data = d['im_data']
70 # if data:
71 # m.image.data = base64.decodestring(data)
72 #
73 # m.audio.type = d['au_type']
74 # data = d['au_data']
75 # if data:
76 # m.audio.data = base64.decodestring(data)
77 # return m
78
79
80
81
82
83
84
85
86 # class MessagingServiceImpl(IMessageServer,IUserTeamServer,IUserEventListener):
87 class MessagingServiceImpl(IMessageServer,IUserEventListener):
88 def __init__(self,app):
89 IMessageServer. __init__(self)
90 # IUserTeamServer.__init__(self)
91 IUserEventListener. __init__(self)
92 self.app = app
93 self.serviceprxlist={} # 服务器代理对象缓存
94 self.usergws = {}
95
96
97 def onUserExitTeam(self,userid,teamid,ctx):
98 '''
99 将用户退出群的消息发送给群内其他用户
100 '''
101
102 ents = core.UserTeam.objects.get(id = int(teamid)).teamuser_set.exclude(user__id=int(userid) )
103 for en in ents:
104 nf = nosql.Notification()
105 nf.sid = utils.misc.genUUID()
106 nf.sender_id = userid
107 nf.target_id = str(en.user.id)
108 nf.type =NotifyMsgType.ExitTeam
109 nf.p1 = str(teamid)
110 nf.save()
111 prx = self. __getTerminalProxyByUserId(nf.target_id)
112 if prx:
113 prx.onTeamUserLeave_oneway(userid,teamid)
114
115
116
117 def onUserIntoTeam(self,userid,teamid,ctx):
118 '''
119 用户加入群之后通知群内其他用户
120 '''
121 ents = core.UserTeam.objects.get(id = int(teamid)).teamuser_set.exclude(user__id=int(userid) )
122 for en in ents:
123 nf = nosql.Notification()
124 nf.sid = utils.misc.genUUID()
125 nf.sender_id = userid
126 nf.target_id = str(en.user.id)
127 nf.type =NotifyMsgType.JoinTeam
128 nf.p1 = str(teamid)
129 nf.save()
130 prx = self. __getTerminalProxyByUserId(nf.target_id)
131 if prx:
132 prx.onTeamUserJoinin_oneway(userid,teamid)
133
134 def onUserDismissTeam(self,userid,team_id,ctx):
135 '''
136 用户群集散,通知群内所有用户
137 '''
138 ents = core.UserTeam.objects.get(id = int(team_id)).teamuser_set.exclude(user__id=int(userid) )
139 for en in ents:
140 nf = nosql.Notification()
141 nf.sid = utils.misc.genUUID()
142 nf.sender_id = userid
143 nf.target_id = str(en.user.id)
144 nf.type =NotifyMsgType.DestroyTeam
145 nf.p1 = str(team_id)
146 nf.save()
147 prx = self. __getTerminalProxyByUserId(nf.target_id)
148 if prx:
149 prx.onTeamDismiss_oneway(team_id)
150
151 def onUserOnline(self,userid,gws_id,device,ctx):
152 print ' onUserOnline.. ',userid,gws_id
153 userid = int(userid)
154 self.usergws[userid] = gws_id
155 # 保存用户状态到数据表
156 user = core.User.objects.get(id = int(userid))
157 user.status = UserStatus.Online
158 user.save()
159 # 传递未发送消息到前端用户
160 self._sendPendingMsgToUser(userid)
161 self._sendNotifications(userid)
162
163 self._sendPendingInvitationToInvitee(userid)
164 self._sendPendingInvitationActToInviter(userid)
165 self._notifyUserStatusChanged(userid,UserStatus.Online)
166
167
168 def onUserOffline(self,userid,gws_id,device,ctx):
169 print ' onUserOffline.. '
170 userid = int(userid)
171 gws = self.usergws.get(userid)
172 if gws != None:
173 del self.usergws[userid]
174 user = core.User.objects.get(id = int(userid))
175 user.status = UserStatus.Offline
176 user.save()
177 # 通知所有用户告知本人离线
178 self._notifyUserStatusChanged(userid,UserStatus.Offline)
179
180
181 def inviteUser(self,target_id,whisper,ctx):
182 '''
183 发送加入好友请求
184 '''
185 userid = USER_ID(ctx)
186 target_id = int(target_id)
187 res = CallReturn()
188 try:
189 target_id = int(target_id)
190 user = core.User.objects.get(id=userid)
191 if core.UserRelation.objects.filter(user__id=userid,friend__id=target_id):
192 return CallReturn(ErrorDefs.UserIsFriend)
193 if core.User.objects.filter(id=target_id).count() ==0:
194 return CallReturn(ErrorDefs.UserIdNotExisted)
195
196 # 1.write to invitation
197 inv = nosql.Invitation()
198 # inv.sid = utils.misc.genUUID()
199 inv.sender_id = userid
200 inv.target_id = target_id
201 inv.greeting = whisper
202 inv.sender_name = user.name
203 inv.send_type = InviteSendType.SysInternal
204 inv.confirm_result = InvitationResult.NO_ACK
205
206 if not inv.sender_name:
207 inv.sender_name = user.user # 替换合适的名称
208 inv.save()
209 # 2.send to PeerUser
210 prx = self. __getTerminalProxyByUserId(target_id)
211 if prx:
212 prx.onInviteRequest_oneway( str(inv.id),str(userid),whisper,CALL_USER_ID(target_id))
213 except :
214 print traceback.print_exc()
215 res = CallReturn(ErrorDefs.InternalException)
216 return res
217
218 def inviteReject(self,seq,reason,ctx):
219 try:
220 userid = USER_ID(ctx)
221 seq = int(seq)
222 inv = nosql.Invitation.objects.get(id=seq,target_id=userid)
223 inv.confirm_time = datetime.now()
224 inv.confirm_result = InvitationResult.REJECT
225 inv.save()
226 prx = self. __getTerminalProxyByUserId(inv.sender_id)
227 if prx:
228 prx.onInviteReject_oneway(seq,inv.target_id,CALL_USER_ID(inv.sender_id))
229 except:
230 traceback.print_exc()
231
232 def inviteAccept(self,seq,ctx):
233 '''
234 B 接收到邀请之后 发送接受加为好友的答复到服务器
235 '''
236 try:
237 userid = USER_ID(ctx)
238 inv = nosql.Invitation.objects.get(id=int(seq),target_id=userid)
239 inv.confirm_time = datetime.now()
240 inv.confirm_result = InvitationResult.ACCEPT
241 print inv,inv.id,inv.issue_time
242 inv.save()
243 # 接着记录两者的关系 ,表 UserRelation
244 user1 = core.User.objects.get(id=inv.sender_id)
245 user2 = core.User.objects.get(id=inv.target_id)
246 rel = core.UserRelation()
247 rel.user =user1
248 rel.friend = user2
249 rel.save()
250
251 rel = core.UserRelation()
252 rel.user =user2
253 rel.friend = user1
254 rel.save()
255
256 prx = self. __getTerminalProxyByUserId(inv.sender_id)
257 if prx:
258 prx.onInviteAccept_oneway(seq,inv.target_id,CALL_USER_ID(inv.sender_id))
259 except:
260 traceback.print_exc()
261
262 # def getMessageLogList(self,target_id,type,timerange,ctx):
263 # return QueryMessageLogResult_t()
264
265 def inviteResultConfirm(self,seq,ctx):
266 '''
267 A->S->B
268 B->S->A
269 A->S
270 '''
271 try:
272 userid = USER_ID(ctx)
273 inv = nosql.Invitation.objects.get(id=int(seq))
274 inv.issuer_confirm_time = datetime.now()
275 inv.save()
276 except:
277 traceback.print_exc()
278
279 def nofityConfirm(self,seq_id,ctx):
280 '''
281 除了消息发送、邀请之外的处理类型,需要确认接收到了,必须走此接口
282 '''
283 userid = USER_ID(ctx) # 当前用户编号
284 e = nosql.Notification.objects.get(id=int(seq_id),target_id=int(userid))
285 e.confirm_time = datetime.now()
286 e.save()
287
288 def _sendNotifications(self,userid):
289 userid = int(userid)
290 prx = self. __getTerminalProxyByUserId(userid)
291 # 提取未发送的通知消息
292 ents = nosql.Notification.objects.filter(target_id=int(userid),confirm_time=None).order_by( ' issue_time ')
293
294 for e in ents:
295 nm = NotifyMessage_t()
296 nm.seq = str(e.id)
297 nm.issuer = str(e.sender_id)
298 nm.type = e.type
299 nm.issue_time = utils.misc.maketimestamp(e.issue_time)
300 nm.p1 = e.p1
301 nm.p2 = e.p2
302 prx.onNotifyMessage_oneway( nm.issuer,nm,CALL_USER_ID(userid))
303
304
305 def _sendPendingMsgToUser(self,userid):
306 '''
307 发送未传送的消息到终端用户
308 '''
309 print ' _sendPendingMsgToUser.. ',userid
310 ents = nosql.SendMessage.objects.filter(target_id=userid,confirm_result=SendMsgStatus.UNACKED).order_by( ' issue_time ')
311 prx = self. __getTerminalProxyByUserId(userid)
312 if not prx:
313 return
314
315 for e in ents:
316
317 m = MimeText_t()
318 m.seq = e.id
319 m.text = e.content
320 m.issue_time = utils.misc.maketimestamp(e.issue_time)
321 m.type = e.type
322 m.entities = e.entities
323 if e.team_id ==0:
324 prx.onMessageText_oneway(str(e.sender_id),m,CALL_USER_ID(userid))
325 else: # 传递到用户组
326 prx.onTeamMessageText_oneway(str(e.sender_id),e.team_id,m,CALL_USER_ID(userid))
327
328
329 def _sendPendingInvitationToInvitee(self,invitee_id):
330 '''
331 发送邀请,传送到前端好友
332 '''
333 print ' _sendPendingInvitationToInvitee.. '
334 invitee_id = int(invitee_id)
335 ents = nosql.Invitation.objects.filter(target_id=invitee_id,
336 confirm_result = InvitationResult.NO_ACK,
337 send_type = InviteSendType.SysInternal)
338 prx = self. __getTerminalProxyByUserId(invitee_id)
339 if not prx: return
340 print ents
341 for e in ents:
342 prx.onInviteRequest_oneway( str(e.id),str(e.sender_id),str(e.greeting),CALL_USER_ID(invitee_id))
343
344 def _sendPendingInvitationActToInviter(self,userid):
345 '''
346 被邀请者接收到邀请,并提交到服务器。并将提交结果转发给邀请发送者
347 '''
348 userid = int(userid)
349 ents = nosql.Invitation.objects.filter(sender_id=userid,issuer_confirm_time = None,
350 send_type = InviteSendType.SysInternal).\
351 exclude(confirm_result=InvitationResult.NO_ACK)
352 prx = self. __getTerminalProxyByUserId(userid)
353 if not prx: return
354 for e in ents:
355 if e.confirm_result == InvitationResult.ACCEPT:
356 prx.onInviteAccept_oneway(e.id,e.target_id,CALL_USER_ID(userid))
357 if e.confirm_result == InvitationResult.REJECT:
358 prx.onInviteReject_oneway(e.id,e.target_id,CALL_USER_ID(userid))
359
360
361 def _sendPendingJoinTeamRequestToTeamOwner(self,userid):
362 '''
363 将请求加入隶属B的群的消息,发送给B
364 '''
365 userid = int(userid)
366 rs = nosql.JoinTeam.objects.filter(owner_id = userid,issuer_confirm_time = None,
367 confirm_result=JoinTeamResult.NO_ACK)
368
369
370
371 def _notifyUserStatusChanged(self,userid,status):
372 '''
373 通知user的好友或者加入群内的用户,本人状态改变
374 此消息不用持久化
375 '''
376 user = core.User.objects.get(id = userid)
377 entries = user.userfriend_set.all()
378 for en in entries:
379 target_id = en.friend.id
380 prx = self. __getTerminalProxyByUserId(target_id)
381 if not prx:
382 print ' prx is None ,user_id: %s not online! '%target_id
383 continue
384 nm = NotifyMessage_t()
385 nm.seq = str(0)
386 nm.issuer = str(userid)
387 nm.type_ = NotifyMsgType.UserStatusChanged
388 nm.p1 = status
389 nm.issue_time = int(time.time())
390 prx.onNotifyMessage_oneway(nm.issuer,nm,CALL_USER_ID(target_id))
391
392 # ------------- IUserTeamServer --------------------------------------
393
394 def sendTeamMessageText(self,team_id,text,ctx):
395 print ' sendTeamMessageText.. ',team_id
396
397 userid = USER_ID(ctx)
398 # 群内非本人所有朋友记录, 群主不在 teamrelation表哦,
399 users=[]
400 team_id = team_id
401
402 team = core.UserTeam.objects.get(id=team_id)
403 if team.user.id != userid: # 不是本人的team,把team的owner也加入群发数组
404 users.append(team.user)
405
406 rs = core.TeamRelation.objects.filter(team__id=int(team_id)).exclude(user__id=userid)
407 for r in rs:
408 users.append(r.user)
409
410 for r in users:
411 m = nosql.SendMessage()
412 m.sender_id = userid
413 m.target_id = r.id
414 m.team_id = int(team_id)
415 m.type = text.type_
416 m.level = SendMsgLevel.DURABLE
417 m.content = text.text # to see MineText_t
418 m.entities = text.entities
419 m.save()
420 text.seq = m.id
421 self._ripMessageContent(m,text)
422
423 # 查询目标用户是否接入到某个gws,并将消息传送过去
424 prx = self. __getTerminalProxyByUserId(m.target_id)
425 print ' prx is: ',prx
426 if prx :
427 prx.onTeamMessageText_oneway(str(userid),team_id,text,CALL_USER_ID(m.target_id))
428
429
430
431 # ---------------- IMessageServer -----------------------------------
432 def sendMessageText(self,target_id,text,ctx):
433 print ' sendMessageText: ', target_id,text.text
434 userid = USER_ID(ctx)
435 m = nosql.SendMessage()
436 # m.sid = utils.misc.genUUID()
437 m.sender_id = userid
438 m.target_id = int(target_id)
439 m.team_id = 0
440 m.type = text.type_
441 m.level = SendMsgLevel.DURABLE
442 m.content = text.text # to see MineText_t
443 m.entities = text.entities
444 m.save()
445 self._ripMessageContent(m,text)
446
447 text.seq = m.id
448 # 查询目标用户是否接入到某个gws,并将消息传送过去
449 prx = self. __getTerminalProxyByUserId(target_id)
450 print ' prx is: ',prx
451 if prx :
452 prx.onMessageText_oneway(str(userid),text,CALL_USER_ID(target_id))
453
454
455 def _ripMessageContent(self,dbobj,m):
456 '''
457 抽取消息文本中各个entities,并写入db
458 包括 图像、音频 适当调整和处理
459 图像等新记录会写到 Message的text字段,内包含指向资源编号
460 MimeText内的image和audio数据存放在 MimeText.datas数据内,一次摆放
461 '''
462 enset = msgentity.MessageEntitySet.parse(m.text)
463 if not enset:
464 print ' MessageEntitiySet parse failed. '
465 return
466 idx = 0
467 print repr(m.datas)
468 try:
469 for en in enset.entities:
470 if isinstance(en,msgentity.ImageEntity) or \
471 isinstance(en,msgentity.AudioEntity):
472 en.content = m.datas[idx]
473
474 if isinstance(en,msgentity.ImageEntity):
475 r = nosql.ImageEntity()
476 r.msg_id = dbobj.id
477 r.image_type = 0
478 r.width = en.width
479 r.height = en.height
480 r.content = utils.misc.encodeBase64( m.datas[idx] )
481 print r.content
482 r.save()
483 en.id = r.id # 记录image记录编号
484 en.content= ''
485
486 if isinstance(en,msgentity.AudioEntity):
487 r = nosql.AudioEntity()
488 r.msg_id = dbobj.id
489 r.duration = en.duration
490 r.content = utils.misc.encodeBase64(m.datas[idx])
491 r.save()
492 en.id = r.id
493 en.content = ''
494
495 if isinstance(en,msgentity.ImageEntity) or \
496 isinstance(en,msgentity.AudioEntity):
497 idx+=1
498
499 # 更新消息的文本内容
500 dbobj.content = enset.toJson()
501 dbobj.save()
502 except:
503 traceback.print_exc()
504
505 # def sendMessageImage(self,target_id,image,ctx):
506 # userid = USER_ID(ctx)
507 # m = nosql.SendMessage()
508 # m.sid = utils.misc.genUUID()
509 # m.sender_id = userid
510 # m.target_id = int(target_id)
511 # m.type = MimeMessageType.IMAGE
512 # m.level = SendMsgLevel.DURABLE
513 # m.im_type = image.type
514 # m.im_width = image.width
515 # m.im_height = image.height
516 # m.im_content = base64.encodestring(image.data)
517 # m.save()
518 # #查询目标用户是否接入到某个gws,并将消息传送过去
519 # prx = self.__getTerminalProxyByUserId(userid)
520 # if prx :
521 # prx.onMessageImage_oneway(str(userid),image,m.sid,CALL_USER_ID(target_id))
522 #
523 # def sendMessageAudioClip(self,target_id,clip,ctx):
524 # userid = USER_ID(ctx)
525 # m = nosql.SendMessage()
526 # m.sid = utils.misc.genUUID()
527 # m.sender_id = userid
528 # m.target_id = int(target_id)
529 # m.type = MimeMessageType.AUDIO
530 # m.level = SendMsgLevel.DURABLE
531 # m.au_channel = clip.channel
532 # m.au_duration = clip.timelen
533 # m.au_sample = clip.samples
534 # m.au_type = clip.type
535 # m.au_content = base64.encodestring(clip.data)
536 # m.save()
537 # #查询目标用户是否接入到某个gws,并将消息传送过去
538 # prx = self.__getTerminalProxyByUserId(userid)
539 # if prx :
540 # prx.onMessageAudioclip_oneway(str(userid),clip,m.sid,CALL_USER_ID(target_id))
541
542
543 def sendMessageConfirm(self,seq_id,ctx):
544 '''
545 B 接收到消息之后发送 确认消息,
546 否则系统将定时重发当初的消息或者当B再次在线online时被推送到B
547 '''
548 print ' sendMessageConfirm.. ', ' seq_id: ',seq_id
549 userid = USER_ID(ctx)
550 m = nosql.SendMessage.objects.get(id=int(seq_id),target_id=int(userid))
551 m.confirm_time = datetime.now()
552 m.confirm_result = SendMsgStatus.ACKED
553 m.save()
554
555 # def sendLocation(self,target_id,gps,ctx):
556 # '''
557 # 转发gps坐标到目标用户
558 # '''
559 # userid = USER_ID(ctx)
560 # prx = self.__getTerminalProxyByUserId(target_id)
561 # if prx:
562 # prx.onLocation_oneway(str(userid),gps,CALL_USER_ID(target_id))
563 #
564
565
566 def sendFilePrepare(self,type_,target_id,info,ctx):
567 return CallReturn_t()
568
569 def putFilePrepare(self,info,path,category,ctx):
570 return CallReturn_t()
571
572 def getFilePrepare(self,file_id,ctx):
573 return CallReturn_t()
574
575 def getFileServerUri(self,seq_id,ctx):
576 return ServiceURI_t()
577
578 def retrieveFileFinished(self,seq_id,ctx):
579 pass
580
581 def retrieveFileAccept(self,seq_id,ctx):
582 pass
583
584 def retrieveFileFileReject(self,seq_id,reason,ctx):
585 pass
586
587 def queryUserMessage(self,target_id,type_,timerange,limit,ctx):
588 return UserMessageQueryResult_t()
589
590 # ------------- TEAM operations ------------------
591 def requestJoinTeam(self, team_id, identity, ctx):
592 '''
593 用户请求加入指定的群
594 '''
595 userid = USER_ID(ctx)
596 cr = CallReturn()
597 try:
598 team_id = int(team_id)
599 team = core.UserTeam.objects.get(id = team_id)
600 ownerid = team.user.id
601 if ownerid == userid: # 自己加入自己的群,此操作非法
602 return CallReturn(ErrorDefs.TargetInvalid,msg= ' user_id equals team-owner! ')
603 jt = nosql.JoinTeam()
604 jt.sender_id = userid
605 jt.target_id = team_id
606 jt.owner_id = ownerid
607 jt.greeting = identity
608 jt.sender_name = team.user.name
609 jt.confirm_result = JoinTeamResult.NO_ACK
610 jt.save()
611 # 立马是发送给群拥有者
612 prx = self. __getTerminalProxyByUserId(ownerid)
613 if prx:
614 prx.onJoinTeamRequest_oneway( str(jt.id),team_id,str(userid),identity,CALL_USER_ID(ownerid))
615 except:
616 traceback.print_exc()
617 cr = CallReturn(ErrorDefs.InternalException)
618 return cr
619
620 def joinTeamResultConfirm(self, seq, ctx):
621 '''
622 请求加入群的用户收到 accept,reject之后发送确认信息
623 '''
624 try:
625 userid = USER_ID(ctx)
626 jt = nosql.JoinTeam.objects.get(id = int(seq))
627 jt.issuer_confirm_time = datetime.now()
628 jt.save()
629 except:
630 traceback.print_exc()
631
632
633 def removeTeamUser(self, team_id, friend_id, ctx):
634 '''
635 群创建者直接删除群内用户
636 '''
637 cr = CallReturn()
638 try:
639 userid = USER_ID(ctx)
640 team_id = int(team_id)
641 friend_id = int(friend_id)
642 if core.UserTeam.objects.filter(user__id=userid,id = team_id).count() ==0:
643 return CallReturn_Error(ErrorDefs.TargetObjectNotExisted,msg= ' team id invalid! ')
644 if core.TeamRelation.objects.filter(user__id=friend_id,team__id=team_id).count() == 0:
645 return CallReturn_Error(ErrorDefs.TargetObjectNotExisted,msg= ' friend or team unmatched! ')
646
647 # 通知群内用户 指定用户离开群
648 users = self._getUsersInTeam(team_id)
649 for user in users:
650 # 写入数据库
651 nf = nosql.Notification()
652 nf.sender_id = userid
653 nf.target_id = user.id
654 nf.type = NotifyMsgType.TeamUserLeave # 新成员加入
655 nf.p1 = team_id
656 nf.p2 = friend_id
657 nf.save()
658 # 发送到群用户
659 prx = self. __getTerminalProxyByUserId(user.id)
660 if prx:
661 prx.onNotifyMessage_oneway(userid,nf,CALL_USER_ID(user.id))
662 # 删除数据库记录
663 rs = core.TeamRelation.filter(user__id = friend_id,team__id=team_id)
664 rs.delete()
665 except:
666 traceback.print_exc()
667 cr = CallReturn_Error(ErrorDefs.InternalException)
668 return cr
669
670 def addTeamUser(self, team_id, friend_id, ctx):
671 '''
672 群创建者直接将好友加入指定的群
673
674 '''
675
676 cr = CallReturn()
677 try:
678 userid = USER_ID(ctx)
679 team_id = int(team_id)
680 friend_id = int(friend_id)
681 rs = core.UserTeam.objects.filter(id=team_id)
682 if not rs:
683 return CallReturn_Error(ErrorDefs.TargetInvalid,msg= ' team id do not existed! ')
684 team = rs[0]
685 rs = core.UserRelation.objects.filter(user__id=userid,friend__id=friend_id).count()
686 if not rs:
687 return CallReturn_Error(ErrorDefs.TargetInvalid,msg= ' team id or friend id not matched! ')
688 friend = rs[0].friend
689 rel = core.TeamRelation()
690 rel.user = friend
691 rel.team = team
692 rel.save()
693
694 users = self._getUsersInTeam(team_id)
695 # 发送通知到群成员
696 for user in users:
697 # 写入数据库
698 nf = nosql.Notification()
699 nf.sender_id = userid
700 nf.target_id = user.id
701 nf.type = NotifyMsgType.TeamUserEnter # 新成员加入
702 nf.p1 = team_id
703 nf.p2 = friend_id
704 nf.save()
705 # 发送到群用户
706 prx = self. __getTerminalProxyByUserId(user.id)
707 if prx:
708 prx.onNotifyMessage_oneway(userid,nf,CALL_USER_ID(user.id))
709
710 except:
711 traceback.print_exc()
712 cr = CallReturn_Error(ErrorDefs.InternalException)
713 return cr
714
715 def dismissTeam(self, team_id, ctx):
716 '''
717 群创建者解散群
718 '''
719 cr = CallReturn()
720 userid = USER_ID(ctx)
721 try:
722 team_id = int(team_id)
723 rs = core.UserTeam.objects.filter(id=team_id,user__id=userid)
724 if not rs:
725 return CallReturn_Error(ErrorDefs.TargetInvalid, ' team object not existed! ')
726 team = rs[0]
727 users = self._getUsersInTeam(team_id)
728
729 # 发送通知到群成员
730 for user in users:
731 # 写入数据库
732 nf = nosql.Notification()
733 nf.sender_id = userid
734 nf.target_id = user.id
735 nf.type = NotifyMsgType.DismissTeam
736 nf.p1 = team_id
737 nf.save()
738 # 发送到群用户
739 prx = self. __getTerminalProxyByUserId(user.id)
740 if prx:
741 prx.onNotifyMessage_oneway(userid,nf,CALL_USER_ID(user.id))
742
743 rs.delete() # 删除群内成员
744 team.delete() # 删除群记录
745 except:
746 traceback.print_exc()
747 cr = CallReturn_Error(ErrorDefs.InternalException)
748 return cr
749
750
751
752
753 def _getUsersInTeam(self,team_id,exclusive=0):
754 '''
755 获取群内所有成员用户,包含群主
756 '''
757 users=[]
758 try:
759 team =core.UserTeam.objects.get(id=int(team_id))
760 if exclusive != team.user.id:
761 users.append(team.user)
762 rs = core.TeamRelation.objects.filter(team__id=int(team_id))
763 for r in rs:
764 if exclusive != r.user.id:
765 users.append(r.user)
766 except:
767 traceback.print_exc()
768 return users
769
770 def exitTeam(self, team_id, ctx):
771 '''
772 群用户退出将通知群内其他用户(群创建者不允许)
773 '''
774 cr = CallReturn()
775 try:
776 userid = USER_ID(ctx)
777 team_id = int(team_id)
778 # 群主不能退出自己创建的群
779 if core.UserTeam.objects.filter(user__id= userid,id = team_id).count():
780 return CallReturn_Error(ErrorDefs.IllegalOperation,msg= ' the team belong to curernt user! ')
781 rs = core.TeamRelation.objects.filter(user__id=userid,team__id = team_id)
782 if not rs:
783 return CallReturn_Error(ErrorDefs.IllegalOperation,msg= ' user not in team ! ')
784 rs.delete()
785 # 通知群内其他人
786 users = self._getUsersInTeam(team_id)
787 for user in users:
788 nt = nosql.Notification()
789 nt.sender_id = userid
790 nt.target_id = user.id
791 nt.type = NotifyMsgType.TeamUserLeave
792 nt.p1 = team_id
793 nt.p2 = userid
794 nt.save() # 完成通知存储
795
796 # 发送通知前端客户
797 prx = self. __getTerminalProxyByUserId(user.id)
798 if prx:
799 prx.onNotifyMessage_oneway(userid,nt,CALL_USER_ID(user.id))
800 except:
801 traceback.print_exc()
802 cr = CallReturn_Error(ErrorDefs.InternalException)
803 return cr
804
805
806 def joinTeamAccept(self, seq, ctx):
807 try:
808 userid = USER_ID(ctx)
809 jt = nosql.JoinTeam.objects.get(id = int(seq))
810 jt.confirm_time = datetime.now()
811 jt.confirm_result = JoinTeamResult.ACCEPT
812 jt.save()
813 if core.TeamRelation.objects.filter(team__id=jt.target_id,user__id=jt.sender_id).count() ==0:
814 user = core.User.objects.get(id=jt.sender_id)
815 team = core.UserTeam.objects.get(id=jt.target_id)
816 rel = core.TeamRelation()
817 rel.user = user
818 rel.team = team
819 rel.save()
820 # 通知请求用户,加入群okay
821 prx = self. __getTerminalProxyByUserId(jt.sender_id)
822 if prx:
823 prx.onJoinTeamAccept_oneway(seq,jt.target_id,userid,CALL_USER_ID(jt.sender_id))
824
825 # 通知群内所有其他用户,告知新用户进入
826 users = self._getUsersInTeam(jt.target_id)
827
828 for user in users: # 群内的所有好友
829 # 1.写入通知表
830 nt = nosql.Notification()
831 nt.sender_id = jt.owner_id
832 nt.target_id = user.id
833 nt.type = NotifyMsgType.TeamUserEnter
834 nt.p1 = jt.target_id
835 nt.p2 = jt.sender_id
836 nt.save() # 完成通知存储
837
838 # 发送通知前端客户
839 prx = self. __getTerminalProxyByUserId(user.id)
840 if prx:
841 prx.onJoinTeamAccept_oneway(seq,jt.target_id,jt.owner_id,CALL_USER_ID(user.id))
842 except:
843 traceback.print_exc()
844
845
846 def joinTeamReject(self, seq, reason, ctx):
847 '''
848 用户请求加入群,群主拒绝
849 '''
850 try:
851 userid = USER_ID(ctx)
852 jt = nosql.JoinTeam.objects.get(id = int(seq))
853 jt.confirm_time = datetime.now()
854 jt.confirm_result = JoinTeamResult.REJECT
855 jt.save()
856 # 通知请求用户
857 prx = self. __getTerminalProxyByUserId(jt.sender_id)
858 if prx:
859 prx.onJoinTeamReject_oneway(seq,jt.target_id,userid,CALL_USER_ID(jt.sender_id))
860 except:
861 traceback.print_exc()
862
863
864 # ---------------- Others -----------------------------------
865
866
867 def __getTerminalProxyByUserId(self,user_id):
868 '''
869 server_eps.conf 记录gws对应的接收rpc消息的endpoint名称,
870 获取ep名称,通过RpcCommunicator.findEndpoints()得到ep
871 ep.impl就是对应服务器接收消息的连接
872 '''
873 prx = None
874 try:
875 user_id = int(user_id)
876 if not self.usergws.get(user_id):
877 return None # user没有上线
878 gws = self.usergws.get(user_id)
879 prx = self.serviceprxlist.get(gws)
880 if not prx:
881 cf = utils.config.SimpleConfig()
882 cf.load( ' server_eps.conf ')
883 epname = cf.getValue(gws)
884 ep = tce.RpcCommunicator.instance().currentServer().findEndPointByName(epname)
885 prx = ITerminalPrx(ep.impl)
886 self.serviceprxlist[gws] = prx
887 return prx
888 finally:
889 if not prx:
890 print ' user: %s is not online! '%user_id
891
892
893 # def sendMessage(self,targets,type,msg,ctx):
894 # '''
895 # 消息进入mongodb,待用户发送ack之后才删除,否则等用户再次连接进入时发送给用户
896 # targets - id list
897 # type - MsgTargetType
898 # msg - MimeMessage_t
899 # @deal :
900 # delivery msg to sender
901 # '''
902 # userid = USER_ID(ctx)
903 # # self.app.msgsync.sendMessage(targets,type,msg,userid)
904 # ids = map(int,targets)
905 # for id in ids:
906 # if type == MsgTargetType.USER:
907 # self.app.sendMsgToUser(id,msg,userid)
908 # elif type == MsgTargetType.TEAM:
909 # #发送到群
910 # self.app.sendMsgToTeam(id,msg,userid)
911 #
912 #
913 # def sendLocation(self,targets,type,loc,ctx):
914 # userid = USER_ID(ctx)
915 # ids = map(int,targets)
916 # x,y = geotools.point_g2m(loc.gps.loc.lon,loc.gps.loc.lat)
917 # loc.gps.loc.lon = x
918 # loc.gps.loc.lat = y
919 # for id in ids:
920 # if type == MsgTargetType.USER:
921 # self.app.sendLocationToUser(id,loc,userid)
922 # elif type == MsgTargetType.TEAM:
923 # #发送到群
924 # self.app.sendLocationToTeam(id,loc,userid)
925 # elif type == MsgTargetType.SYSTEM:
926 # pass
927 # self.app.sendLocationToReciever(loc,userid)
928 #
929 # def uploadLocation(self,loc,ctx):
930 # userid = USER_ID(ctx)
931 # pass
932 #
933 # def sendMsgAck(self,seqs,ctx):
934 # #用户发送消息确认消息
935 # db = self.app.getNosqlDb()
936 # for seq in seqs:
937 # try:
938 # #r = db.user_sendmessage.find_one({'_id':seq})
939 # #if r:
940 # db.user_sendmessage.update({'_id':ObjectId(seq)},
941 # {'$set':{'status':1,'ack_time':datetime.now()}},
942 # multi = True
943 # )
944 # # r['status'] = 1
945 # # r['ack_time']= datetime.now()
946 # # r.save()
947 # except:
948 # print traceback.format_exc()
949 #
950 #
951 # def createTalking(self,type,ctx):
952 # '''
953 # talkin建立发送talking创建到talkingserver
954 # 用户根据talkingid链接到talkingserver
955 # '''
956 # return TalkingResource_t()
957 #
958 # def inviteTalking(self,target_id,talking_id,ctx):
959 # pass
960 #
961 # def inviteTalkingAccept(self,talking_id,ctx):
962 # pass
963 #
964 # def inviteTalkingReject(self,talking_id,reason,ctx):
965 # pass
966 #
967 # def initOnlineUserList(self,gwaid,useridlist,ctx):
968 # for uid in useridlist:
969 # self.app.userOnline(uid,gwaid)
970 # #-------- above interface implements ---
971 # #----- local functions ----
972 #
973
974
975
976
977
978 class ServerApp:
979 def __init__(self):
980 pass
981
982 def getConfig(self):
983 # return self.app.getConfig()
984 pass
985
986 _handle = None
987 @classmethod
988 def instance(cls):
989 if cls._handle == None:
990 cls._handle = cls()
991 return cls._handle
992
993 def run(self):
994 tce.RpcCommunicator.instance().init( ' messageserver ').initMessageRoute( ' ./services.xml ')
995 server = tce.RpcCommunicator.instance().currentServer().findEndPointByName( ' mq_messageserver ').impl
996 conn = tce.RpcCommunicator.instance().currentServer().findEndPointByName( ' mq_user_event_listener ').impl
997 adapter = tce.RpcAdapterEasyMQ.create( ' server ',server)
998 adapter.addConnection(conn)
999 # 没有主动发送消息的情形
1000 servant = MessagingServiceImpl(self)
1001 adapter.addServant(servant)
1002 tce.RpcCommunicator.instance().waitForShutdown()
1003
1004
1005 if __name__ == ' __main__ ':
1006 ServerApp.instance().run()
1007 # print cm.User.objects.all()
1008 # print cm.User.objects.filter(user='abc')
1009 # print dir(tce) #.mqset_inst
1010 pass # sys.exit( MainApp().run())
1011