def handle_cmd(self, frame):
        """
        Method:    handle_cmd
        Description: 处理文本消息主动发送给订阅者命令 
        Parameter: 
            frame: AppFrame
        Return: 
        Others: 
        """
        tracelog.info(self)
        
        buf = frame.get_data()
        push_msg = msg_params_def.CloudPortalTextPushMessage.deserialize(buf)
        
        for open_id in push_msg.subscriber_open_ids:
            processor = self.get_worker().get_state_manager().get_processor(open_id)
            if processor is None:
                tracelog.warning('portal text msg reply push to the unknown subscriber(openid %s)' % open_id)
            else:
                fakeid = processor.get_target().get_spec().fake_id

                tracelog.info('send text msg to fake_id %s' % fakeid)
                self.get_worker().get_app().get_task_worker().push_text(fakeid, push_msg.text_msg)
    def handle_cmd(self, frame):
        """
        Method:    handle_cmd
        Description: 处理主题内容上传到微信后台命令
        Parameter: 
            frame: AppFrame
        Return: 
        Others: 
        """
        tracelog.info(self)
        
        op = frame.get_data()
        article_id = int(frame.get_data(1))
        
        if op == msg_params_def.PORTAL_CLOUD_IMAGE_UPLOAD_DEL:
            wx_news_id = frame.get_data(2)
            tracelog.info('del article on WX portal(id %d)' % article_id)
            if len(wx_news_id) == 0:
                tracelog.warning('the deleted article(id %d) has not created the news!' % article_id)
                return

            self.get_worker().get_app().get_task_worker().del_article(wx_news_id)
            return
        
        arts = self.get_worker().get_app().get_mit_manager().rdm_find('Article', article_id = article_id)
        if len(arts) == 0:
            tracelog.warning('portal want to %s the unknown article (id %d) on wx portal' % (op, article_id))
            self.get_worker().get_app().send_ack_dispatch(frame, ('', ))
            return
        
        if op == msg_params_def.PORTAL_CLOUD_IMAGE_UPLOAD_NEW:
            tracelog.info('create new article on WX portal(id %d)' % article_id)
            pic_url = arts[0].pic_url.strip('http://')
            pic_path = msg_params_def.PORTAL_IMG_FILE_LOCAL_PATH_PREFIX + pic_url[pic_url.find('/'):].lstrip('/')
            self.get_worker().get_app().get_task_worker().upload_article(article_id, pic_path, arts[0].title, arts[0].description, arts[0].content, 0)
                           
        elif op == msg_params_def.PORTAL_CLOUD_IMAGE_UPLOAD_MOD:
            tracelog.info('mod article on WX portal(id %d)' % article_id)
            if len(arts[0].wx_news_id) > 0:
                self.get_worker().get_app().get_task_worker().del_article(arts[0].wx_news_id)               

            pic_url = arts[0].pic_url.strip('http://')
            pic_path = msg_params_def.PORTAL_IMG_FILE_LOCAL_PATH_PREFIX + pic_url[pic_url.find('/'):].lstrip('/')
            self.get_worker().get_app().get_task_worker().upload_article(article_id, pic_path, arts[0].title, arts[0].description, arts[0].content, 0)               
        else:
            tracelog.warning('article upload msg has the unknown operation code %s' % op)               
    def handle_cmd(self, frame):
        """
        Method:    handle_cmd
        Description: 处理微信订阅者事件消息
        Parameter: 
            frame: AppFrame
        Return: 
        Others: 
        """
        tracelog.info(self)        
        buf = frame.get_data()
        tracelog.info('receive WX event msg :%s' % buf)
        
        event_msg = msg_params_def.WXPushEventMessage.deserialize(buf)
     
        processor = self.get_worker().get_state_manager().get_processor(event_msg.subscriber_open_id)
        if processor is None:
            if event_msg.event == msg_params_def.WX_EVENT_TYPE_SUBSCRIBE:
                sub_moc = self.get_worker().get_app().get_mit_manager().gen_rdm("Subscriber")
                sub_moc.subscribe_seq_no = self.get_worker().get_app().get_sub_no_creator().get_new_no()
                sub_moc.subscriber_open_id = event_msg.subscriber_open_id
                sub_moc.sub_time = time.strftime('%Y-%m-%d %H:%M:%S')
                sub_moc.admin_flag = 'False'
                gids = msg_params_def.GroupList()
                gids.group_ids = [msg_params_def.GROUP_SYS_DEFAULT] # 初次订阅默认为未分组

                tracelog.info('new subscriber: openid %s, seqno %d' % (sub_moc.subscriber_open_id, sub_moc.subscribe_seq_no))

                sub = subscriber_def.Subscriber(sub_moc, gids, fsm_def.SUBSCRIBER_INIT_STATE)
                sub.save_frame(frame.clone())
                processor = fsm_def.StateProcessor(sub, self.get_worker())
                processor.register_state_handler(fsm_def.SUBSCRIBER_INIT_STATE, subscriber_state_man.SubInitStateHandler(processor))
                processor.register_state_handler(fsm_def.SUBSCRIBER_SESSION_STATE, subscriber_state_man.SubSessionStateHandler(processor))
                
                self.get_worker().get_state_manager().add_processor(processor)

                ret = self.get_worker().get_app().get_mit_manager().rdm_add(sub_moc)
                if ret.get_err_code() == err_code_mgr.ER_OBJECT_ADD_CONFLICT:
                    tracelog.warning('receive duplicate WX subscribe event from subscriber(sub id %d)' % event_msg.subscriber_open_id)

                moid = self.get_worker().get_app().get_mit_manager().gen_moid('Subscriber', subscriber_open_id = sub_moc.subscriber_open_id)
                self.get_worker().get_app().get_mit_manager().mod_complex_attr('Subscriber', moid = moid, group_ids = gids)
            else:
                tracelog.error('receive WX event(%s) msg from unknown subscriber(open_id %s)' % (event_msg.event, event_msg.subscriber_open_id))
            return
        else:
            if event_msg.event == msg_params_def.WX_EVENT_TYPE_UNSUBSCRIBE:
                tracelog.info('subscriber unsub openid %s' % event_msg.subscriber_open_id)
                
                subs = self.get_worker().get_app().get_mit_manager().rdm_find("Subscriber", subscriber_open_id = event_msg.subscriber_open_id)
                if len(subs) == 0:
                    tracelog.warning('receive unsubscribe event from open id %s, but the subscriber info does not exist in DB' % event_msg.subscriber_open_id)
                else:
                    self.get_worker().get_app().get_mit_manager().rdm_remove(subs[0])
                
                # 订阅事件上报
                event_report = msg_params_def.PortalEventEventReportReq()
                event_report.init_all_attr()
                event_report.user_session = '0'
                event_report.event_type = msg_params_def.EVENT_TYPE_SUBSCRIBE
                event = msg_params_def.SubscribeEvent()
                event.init_all_attr()
                event.subscriber_open_id = event_msg.subscriber_open_id
                event.weixin_id = processor.get_target().get_spec().weixin_id
                event.nickname = processor.get_target().get_spec().nickname
                event.action = '取消订阅'.decode('gbk').encode('utf-8')
                event.time = time.strftime('%Y-%m-%d %H:%M:%S')
    
                event_report.content = event.serialize()
                
                evt_frame = bf.AppFrame()
                evt_frame.set_cmd_code(cmd_code_def.PORTAL_EVENT_EVENT_REPORT)
                evt_frame.add_data(event_report.serialize())
                self.get_worker().dispatch_frame_to_process_by_pid(self.get_worker().get_pid('EventCenterApp'), evt_frame)

                self.get_worker().get_state_manager().remove_processor(processor)
                del processor

                return
        
        tracelog.warning('receive WX unsupported event(%s) notification msg' % event_msg.event)