Ejemplo n.º 1
0
    def Plug(self, moduleName):
        self.unplug(moduleName)
        try:
            module = Import(moduleName)
        except Exception as e:
            result = '错误:无法加载插件 %s ,%s: %s' % (moduleName, type(e), e)
            ERROR('', exc_info=True)
            ERROR(result)
            self.unplug(moduleName)
        else:
            self.unplug(moduleName, removeJob=False)

            names = []
            for slotName in self.slotsTable.keys():
                if hasattr(module, slotName):
                    self.slotsTable[slotName].append(getattr(module, slotName))
                    names.append(slotName)

            if (not names) and (moduleName not in self.schedTable):
                result = '警告:插件 %s 中没有定义回调函数或定时任务' % moduleName
                WARN(result)
            else:
                self.plugins[moduleName] = module

                jobs = self.schedTable.get(moduleName, [])
                jobNames = [f.func.__name__ for f in jobs]
                result = '成功:加载插件 %s(回调函数%s、定时任务%s)' % \
                         (moduleName, names, jobNames)
                INFO(result)

                if self.started and hasattr(module, 'onPlug'):
                    _call(module.onPlug, self)

        return result
Ejemplo n.º 2
0
 def get_wds_rank(self, wds, type0=1, page=1, page_size=20):
     """
     获取微打赏聚聚榜
     :param wds:
     :param pro_id:
     :param type0:
     :param page:
     :param page_size:
     :return:
     """
     jizi_url = 'https://wds.modian.com/ajax/backer_ranking_list'
     params = {
         'pro_id': wds.pro_id,
         'type': type0,
         'page': page,
         'page_size': page_size
     }
     try:
         # 注意,这里的param不用转换成json了,因为参数格式为x-www-form-urlencoded
         r = self.session.post(jizi_url, params, headers=self.wds_header())
     except Exception as e:
         ERROR('获取微打赏排名失败')
         ERROR(e)
     r_json = r.json()
     # DEBUG('response: %s', r.text)
     # 微打赏有bug,首页上和排名页上的人数不一致
     if 'data' not in r_json or int(r_json['status']) != 0:
         ERROR('微打赏排名获取失败!')
         return None
     return r_json['data']['html']
Ejemplo n.º 3
0
def getManaulGroupQQDict():

    mgQQDict = collections.defaultdict(list)

    from qqbot import QQBot
    fn = QQBot._bot.conf.absPath('groupqq')

    if not os.path.exists(fn):
        return mgQQDict

    try:
        with open(fn, 'rb') as f:
            s = f.read()
    except Exception as e:
        ERROR('无法读取群 QQ 文件 %s , %s', fn, e)
        return mgQQDict

    try:
        s = BYTES2STR(s)
    except Exception as e:
        ERROR('群 QQ 文件 %s 编码错误, %s', fn, e)
        return mgQQDict

    try:
        for line in s.split('\n'):
            if not line.startswith('#') and (',' in line):
                qq, nick = line.rstrip('\r').split(',', 1)
                mgQQDict[nick].append(qq)
    except Exception as e:
        ERROR('群 QQ 文件 %s 格式错误, %s', fn, e)
        return mgQQDict

    INFO('成功从文件 %s 中读取群的实际 QQ 号码', fn)

    return mgQQDict
Ejemplo n.º 4
0
    def init_comment_queues(self):
        """
        初始化回复队列
        :return:
        """
        try:
            self.comment_id_queues = []
            for i in range(len(self.wds_array)):
                self.comment_id_queues.append([])

            for i in range(len(self.wds_array)):
                queue = self.comment_id_queues[i]
                r = self.monitor_wds_comment(self.wds_array[i])

                soup = BeautifulSoup(r, 'lxml')
                comment_list = soup.findAll(name='li')
                for comment in comment_list:
                    comment_id = comment.find(
                        class_='add-jubao').get('to_comid')
                    queue.append(comment_id)

                self.wds_queue_map[self.wds_array[i]] = queue
        except Exception as e:
            ERROR('初始化微打赏评论队列失败')
            ERROR(e)
    def get_member_room_comment(self, room_id, limit=20):
        """
        获取成员房间的粉丝评论
        :param limit:
        :param room_id: 房间id
        :return:
        """

        if not self.is_login:
            ERROR('尚未登录')
            return False
        # url = 'https://pjuju.48.cn/imsystem/api/im/v1/member/room/message/comment'
        url = 'https://pjuju.48.cn/imsystem/api/im/v1/member/room/message/boardpage'
        params = {
            "roomId": room_id,
            "lastTime": 0,
            "limit": limit,
            "isFirst": "true"
        }
        # 收到响应
        try:
            r = self.session.post(url,
                                  data=json.dumps(params),
                                  headers=self.juju_header_args(),
                                  verify=False)
        except Exception as e:
            ERROR('获取房间评论失败')
            ERROR(e)
        return r.text
Ejemplo n.º 6
0
    def init_msg_queues(self, room_id):
        """
        初始化房间消息队列
        :param room_id:
        :return:
        """
        try:
            self.member_room_msg_ids = []
            self.member_room_comment_ids = []
            self.member_live_ids = []

            self.unread_msg_amount = 0

            r1 = self.get_member_room_msg(room_id)
            r2 = self.get_member_room_comment(room_id)

            r1_json = json.loads(r1)
            r2_json = json.loads(r2)
            for r in r1_json['content']['data']:
                msg_id = r['msgidClient']
                self.member_room_msg_ids.append(msg_id)

            for r in r2_json['content']['data']:
                msg_id = r['msgidClient']
                self.member_room_comment_ids.append(msg_id)

            DEBUG('成员消息队列: %s', len(self.member_room_msg_ids))
            DEBUG('房间评论队列: %s', len(self.member_room_comment_ids))
            DEBUG('房间未读消息数量: %d', self.unread_msg_amount)
        except Exception as e:
            ERROR('初始化消息队列失败')
            ERROR(e)
Ejemplo n.º 7
0
    def login(self, username, password):
        """
        登录
        :param username:
        :param password:
        :return:
        """
        if self.is_login is True:
            ERROR('已经登录!')
            return
        if username is None or password is None:
            ERROR('用户名或密码为空')
            return

        login_url = 'https://puser.48.cn/usersystem/api/user/v1/login/phone'
        params = {
            'latitude': '0',
            'longitude': '0',
            'password': str(password),
            'account': str(username),
        }
        res = self.session.post(login_url,
                                json=params,
                                headers=self.login_header_args()).json()
        # 登录成功
        if res['status'] == 200:
            self.token = res['content']['token']
            self.is_login = True
            INFO('登录成功, 用户名: %s', username)
            INFO('TOKEN: %s', self.token)
            return True
        else:
            ERROR('登录失败')
        return False
 def get_member_live_msg(self, limit=30):
     """
     获取所有直播间信息
     :return:
     """
     # 登录失败 不访问需要鉴权的接口
     if not self.is_login:
         ERROR('尚未登录')
     url = 'https://plive.48.cn/livesystem/api/live/v1/memberLivePage'
     params = {
         "giftUpdTime": 1503766100000,
         "groupId": 0,  # SNH48 Group所有人
         "lastTime": 0,
         "limit": limit,
         "memberId": 0,
         "type": 0
     }
     try:
         r = self.session.post(url,
                               data=json.dumps(params),
                               headers=self.live_header_args(),
                               verify=False)
     except Exception as e:
         ERROR('获取成员直播失败')
         ERROR(e)
     return r.text
Ejemplo n.º 9
0
    def onQQMessage_real(self, dialog, member, content):
        if dialog.qq == '#NULL':
            ERROR("missing dialog.qq for message %s" % content)
            return

        if member is not None:
            if member.qq == '#NULL':
                ERROR("missing member.qq for message %s" % content)
                return
            sender = member
            try:
                target = self.channelNames.toIRC[dialog.qq]
            except KeyError:
                target = '#' + dialog.qq
            isChannel = True
        else:
            sender = dialog
            target = self.me
            isChannel = False
        hostmask = self.server.buildHostmask(self.nickNames.toIRC[sender.qq],
                                             sender.qq)

        for line in self.newLineRegex.split(content):
            if isChannel and target not in self.joinedChannels:
                self.ircmsg(hostmask, 'PRIVMSG', self.rawChannel,
                            '%s: %s' % (target, line))
            else:
                self.ircmsg(hostmask, 'PRIVMSG', target, line)
Ejemplo n.º 10
0
    def Run(self):
        if self.conf.startAfterFetch:
            self.firstFetch()

        self.onPlug()
        self.onStartupComplete()

        # child thread 1~4
        StartDaemonThread(self.pollForever)
        StartDaemonThread(self.intervalForever)
        StartDaemonThread(
            QTermServer(self.conf.termServerPort, self.onTermCommand).Run)
        self.scheduler.start()

        self.started = True

        try:
            MainLoop()
        except SystemExit as e:
            self.onExit(e.code, getReason(e.code), None)
            raise
        except Exception as e:
            ERROR('', exc_info=True)
            ERROR('Mainloop 发生未知错误:%r', e)
            self.onExit(1, 'unknown-error', e)
            raise SystemExit(1)
Ejemplo n.º 11
0
    def FetchTable(self, tinfo):
        ctype, owner = GetCTypeAndOwner(tinfo)
        try:
            if ctype == 'buddy':
                table = self.fetchBuddyTable()
            elif ctype == 'group':
                table = self.fetchGroupTable()
            elif ctype == 'discuss':
                table = self.fetchDiscussTable()
            elif ctype == 'group-member':
                table = self.fetchGroupMemberTable(owner)
            else:
                table = self.fetchDiscussMemberTable(owner)
        except RequestError:
            table = None
        except:
            ERROR('', exc_info=True)
            table = None

        if table is None:
            if ctype in ('buddy', 'group', 'discuss'):
                ERROR('获取 %s 列表失败', CTYPES[ctype])
            else:
                ERROR('获取 %s 的成员列表失败', owner)

        return table
Ejemplo n.º 12
0
 def get_member_room_msg(self, room_id, limit=5):
     """
     获取成员房间消息
     :param limit:
     :param room_id: 房间id
     :return:
     """
     if not self.is_login:
         ERROR('尚未登录')
         return False
     # url = 'https://pjuju.48.cn/imsystem/api/im/v1/member/room/message/chat'
     url = 'https://pjuju.48.cn/imsystem/api/im/v1/member/room/message/mainpage'
     params = {
         "roomId": room_id,
         "lastTime": 0,
         "limit": limit,
         "chatType": 0
     }
     try:
         r = self.session.post(url,
                               data=json.dumps(params),
                               headers=self.juju_header_args(),
                               verify=False)
     except Exception as e:
         ERROR('获取成员消息失败')
         ERROR(e)
     return r.text
Ejemplo n.º 13
0
 def send(self, prefix, command, params, tail):
     words = [':' + prefix, command.upper()] + params + [':' + tail]
     msg = ' '.join(words)
     try:
         self.sock.sendall(STR2BYTES(msg) + b'\r\n')
     except socket.timeout:
         ERROR('在向 %s 发送数据时出现 %s', self.name, 'SOCKET-TIMEOUT')
     except socket.error:
         ERROR('在向 %s 发送数据时出现 %s', self.name, 'SOCKET-ERROR')
         self.close()
     else:
         DEBUG('%s ==> %s: %r', self.servername, self.name, msg)
Ejemplo n.º 14
0
    def onData(self, sock, addr, data):
        try:
            resp = self.response(data)
        except Exception as e:
            resp = '%s 在处理 %s:%s 的请求时发生错误,%s' % (self.name, addr[0], addr[1], e)
            ERROR(resp, exc_info = True)
            resp = STR2BYTES(resp)

        try:
            sock.sendall(resp)
        except socket.error as e:
            ERROR('%s 在向 %s:%s 发送数据时发送错误,%s', self.name, addr[0], addr[1], e)
            self.onSendError(sock, addr, data)
        finally:
            sock.close()
Ejemplo n.º 15
0
    def onTermCommand(bot, command):
        command = BYTES2STR(command)
        if command.startswith('GET /'):
            http = True
            end = command.find('\r\n')
            if end == -1 or not command[:end - 3].endswith(' HTTP/'):
                argv = []
            else:
                url = command[5:end - 9].rstrip('/')
                if url == 'favicon.ico':
                    return b''
                argv = [Unquote(x) for x in url.split('/')]
        else:
            http = False
            argv = command.strip().split(None, 3)

        if argv and argv[0] in cmdFuncs:
            try:
                result, err = cmdFuncs[argv[0]](bot, argv[1:], http)
            except Exception as e:
                result, err = None, '运行命令过程中出错:' + str(type(e)) + str(e)
                ERROR(err, exc_info=True)
        else:
            result, err = None, 'QQBot 命令格式错误'

        if http:
            rep = {'result': result, 'err': err}
            rep = STR2BYTES(JsonDumps(rep, ensure_ascii=False, indent=4))
            rep = (b'HTTP/1.1 200 OK\r\n' + b'Connection: close\r\n' +
                   b'Content-Length: ' + STR2BYTES(str(len(rep))) + b'\r\n' +
                   b'Content-Type: text/plain;charset=utf-8\r\n\r\n' + rep)
        else:
            rep = STR2BYTES(str(err or result)) + b'\r\n'

        return rep
Ejemplo n.º 16
0
    def Plug(cls, moduleName):
        cls.unplug(moduleName)
        try:
            module = Import(moduleName)
        except (Exception, SystemExit) as e:
            result = '错误:无法加载插件 %s ,%s: %s' % (moduleName, type(e), e)
            ERROR(result)
        else:
            cls.unplug(moduleName, removeJob=False)

            names = []
            for slotName in cls.slotsTable.keys():
                if hasattr(module, slotName):
                    cls.slotsTable[slotName].append(getattr(module, slotName))
                    names.append(slotName)

            if (not names) and (moduleName not in cls.schedTable):
                result = '警告:插件 %s 中没有定义回调函数或定时任务' % moduleName
                WARN(result)
            else:
                cls.plugins.add(moduleName)
                jobs = cls.schedTable.get(moduleName, [])
                jobNames = [f.func.__name__ for f in jobs]
                result = '成功:加载插件 %s(回调函数%s、定时任务%s)' % \
                         (moduleName, names, jobNames)
                INFO(result)

        return result
Ejemplo n.º 17
0
def main_loop():
    read = set()
    filters = [
        'edx', 'github', 'noreply', 'docker team', 'intel', 'vuforia',
        'welcome'
    ]
    filters = [a.lower() for a in filters]
    while True:
        try:
            # 遍历未读邮件
            for num in reversed(server.get_unread()):
                if num != '':
                    mail_info = server.get_mail_info(num)
                    mail_id = mail_info['id']
                    if mail_id in read:
                        break
                    content = mail_info['subject'].replace('\n', '')
                    app = "邮箱(" + mail_info['to'][1] + ')'
                    who = mail_info['from'][0]
                    INFO('来自%s%s的邮件:%s' % (app, who, content))
                    for f in filters:
                        if f in who.lower():
                            server.add_flag(num, '\\Deleted')
                            break
                    else:
                        __msg_queue.put((app, who, content))
                    read.add(mail_id)
        except Exception as e:
            ERROR(str(type(e)) + str(e))
        server.expunge()
        time.sleep(3)
Ejemplo n.º 18
0
def main_loop():
    while True:
        try:
            itchat.run()
        except Exception as e:
            ERROR(e)
            time.sleep(3)
Ejemplo n.º 19
0
    def Plug(cls, moduleName):
        try:
            module = Import(moduleName)
        except (Exception, SystemExit) as e:
            cls.unplug(moduleName)
            cls.plugins.discard(moduleName)
            result = '错误:无法加载插件 %s ,%s: %s' % (moduleName, type(e), e)
            ERROR(result)
        else:
            cls.unplug(moduleName)

            names = []
            for slotName in cls.slotsTable.keys():
                if hasattr(module, slotName):
                    cls.slotsTable[slotName].append(getattr(module, slotName))
                    names.append(slotName)

            if not names:
                INFO(module.__dict__.keys())
                result = '警告:插件 %s 中不包含任何可注册的回调函数' % moduleName
                WARN(result)
            else:
                cls.plugins.add(moduleName)
                result = '成功:加载插件 %s%s' % (moduleName, names)
                INFO(result)

        return result
Ejemplo n.º 20
0
def insertChatContent(bot, contact, member, content):
    try:
        # 连接数据库
        connect = pymysql.Connect(host='localhost',
                                  port=3306,
                                  user='******',
                                  passwd='19950105',
                                  db='qq_data',
                                  charset='utf8')

        # 获取游标
        cursor = connect.cursor()
        now = datetime.datetime.now()
        createtime = now.strftime('%Y-%m-%d %H:%M:%S')
        # 插入数据
        sql = "INSERT INTO chat_logs (group_number,group_name,qq,nickname,mark,content,create_time) VALUES ( '%s', '%s', '%s','%s','%s', '%s', '%s')"
        name = pymysql.escape_string(contact.name)
        nickname = pymysql.escape_string(member.name)
        mark = pymysql.escape_string(member.name)
        data = (contact.qq, name, member.qq, nickname, mark, content,
                createtime)
        print('聊天数据 {}'.format(data))
        cursor.execute(sql % data)
        connect.commit()
        connect.close()
        print('insert success', cursor.rowcount, ' record')
    except Exception as e:
        ERROR('存储mysql 失败 原因是: {}'.format(e))
Ejemplo n.º 21
0
 def StoreQQ(self):
     try:
         fn = self.absPath('qq(pid%s)' % os.getpid())
         with open(fn, 'w') as f:
             f.write(getattr(self, 'qq', ''))
     except Exception as e:
         ERROR('无法保存当前 QQ 号码, %s', e)
Ejemplo n.º 22
0
    def membsOperation(self, group, membs, tag, func, exArg):
        if not membs:
            return []

        try:
            ok = func(group.qq, [m.qq for m in membs], exArg)
        except RequestError:
            errInfo = '错误:' + tag + '失败(远程请求被拒绝)'
            result = [errInfo.format(m=str(m)) for m in membs]
        except Exception as e:
            WARN('', exc_info=True)
            errInfo = '错误:' + tag + '失败(' + str(e) + ')'
            result = [errInfo.format(m=str(m)) for m in membs]
        else:
            if ok:
                okInfo = '成功:' + tag
                result = [okInfo.format(m=str(m)) for m in membs]
            else:
                errInfo = '错误:' + tag + '失败(权限不够)'
                result = [errInfo.format(m=str(m)) for m in membs]

        for r in result:
            INFO(r) if r.startswith('成功') else ERROR(r)

        return result
Ejemplo n.º 23
0
def main_loop():
    while True:
        try:
            bot.Run()
        except Exception as e:
            ERROR(e)
            time.sleep(3)
Ejemplo n.º 24
0
 def urlGet(self, url, data=None, Referer=None, Origin=None):
     Referer and self.session.headers.update( {'Referer': Referer} )
     Origin and self.session.headers.update( {'Origin': Origin} )
     timeout = 5 if url != 'https://d1.web2.qq.com/channel/poll2' else 120
         
     try:
         if data is None:
             return self.session.get(url, timeout=timeout)
         else:
             return self.session.post(url, data=data, timeout=timeout)
     except (requests.exceptions.SSLError, AttributeError):
         # by @staugur, @pandolia
         if self.session.verify:
             time.sleep(5)
             ERROR('无法和腾讯服务器建立私密连接,'
                   ' 15 秒后将尝试使用非私密连接和腾讯服务器通讯。'
                   '若您不希望使用非私密连接,请按 Ctrl+C 退出本程序。')
             time.sleep(15)
             WARN('开始尝试使用非私密连接和腾讯服务器通讯。')
             self.session.verify = False
             requests.packages.urllib3.disable_warnings(
                 requests.packages.urllib3.exceptions.
                 InsecureRequestWarning
             )
             return self.urlGet(url, data, Referer, Origin)
         else:
             raise
Ejemplo n.º 25
0
    def SendTo(self, contact, content):        
        if not isinstance(contact, QContact):
            return '错误:消息接受者必须为一个 QContact 对象'
        
        if contact.ctype.endswith('-member'):
            return '错误:不能给群成员或讨论组成员发消息'
        
        if not isinstance(content, str):
            return '错误:只能发送字符串消息'

        if not content:
            return '错误:不允许发送空消息'

        ctype = 'buddy' if contact.ctype.endswith('member') else contact.ctype

        result = '向 %s 发消息成功' % contact
        while content:
            front, content = Partition(content, 600)
            try:
                self.send(ctype, contact.uin, front)
            except Exception as e:
                result = '错误:向 %s 发消息失败 %s' % (str(contact), e)
                ERROR(result, exc_info=(not isinstance(e, RequestError)))
                break
            INFO('%s:%s' % (result, front))

        return result
Ejemplo n.º 26
0
 def Poll(self):
     try:
         result = self.smartRequest(
             url='https://d1.web2.qq.com/channel/poll2',
             data={
                 'r':
                 JsonDumps({
                     'ptwebqq': self.ptwebqq,
                     'clientid': self.clientid,
                     'psessionid': self.psessionid,
                     'key': ''
                 })
             },
             Referer=('https://d1.web2.qq.com/proxy.html?v=20151105001&'
                      'callback=1&id=2'),
             expectedCodes=(0, 100003, 100100, 100012))
         # "{'retcode': 0, 'retmsg': 'ok', 'errmsg': 'error'}"
         if type(result) is dict and \
                 result.get('retcode', 1) == 0 and \
                 result.get('errmsg', '') == 'error':
             DEBUG(result)
             raise RequestError
     except RequestError:
         ERROR('接收消息出错,开始测试登录 cookie 是否过期...')
         try:
             self.TestLogin()
         except RequestError:
             ERROR('登录 cookie 很可能已过期')
             raise
         else:
             INFO('登录 cookie 尚未过期')
             return 'timeout', '', '', ''
     else:
         if (not result) or (not isinstance(result, list)):
             DEBUG(result)
             return 'timeout', '', '', ''
         else:
             result = result[0]
             ctype = {
                 'message': 'buddy',
                 'group_message': 'group',
                 'discu_message': 'discuss'
             }[result['poll_type']]
             fromUin = str(result['value']['from_uin'])
             memberUin = str(result['value'].get('send_uin', ''))
             content = FaceReverseParse(result['value']['content'])
             return ctype, fromUin, memberUin, content
Ejemplo n.º 27
0
 def Login(self, conf):
     try:
         INFO('正在使用“用户名-密码”登录,请耐心等待 1 ~ 3 分钟......')
         self.newLogin(conf)
     except Exception as e:
         ERROR('用户名-密码登录失败,原因:%s', e, exc_info=True)
         INFO('开始使用“手工扫码”登录......')
         BasicQSession.Login(self, conf)
Ejemplo n.º 28
0
    def init_bilibili_video_queues(self, bilibili_video_list):
        """
        初始化b站投稿队列 避免每次一开启 就发送n多消息
        :param room_ids:
        :return:
        """
        try:
            self.bilibili_video_ids = []

            for bilibili_video in bilibili_video_list:
                video_id = bilibili_video['aid']
                self.bilibili_video_ids.append(video_id)

            DEBUG('b站视频消息队列: %s', len(self.bilibili_video_ids))
        except Exception as e:
            ERROR('初始化b站视频消息队列失败')
            ERROR(e)
Ejemplo n.º 29
0
    def SendTo(self, contact, content, resendOn1202=True):
        result = None

        if not hasattr(contact, 'ctype'):
            result = '错误:消息接受者必须为一个 QContact 对象'

        if contact.ctype.endswith('-member'):
            result = '错误:不能给群成员或讨论组成员发消息'

        if PY3:
            if isinstance(content, str):
                content = content
            elif isinstance(content, bytes):
                content = content.decode('utf8')
            else:
                result = '错误:消息内容必须为 str 或 bytes 对象'
        else:
            if isinstance(content, str):
                content = content
            elif isinstance(content, unicode):
                content = content.encode('utf8')
            else:
                result = '错误:消息内容必须为 str 或 unicode 对象'

        if not content:
            result = '错误:不允许发送空消息'

        if result:
            ERROR(result)
            return result

        epCodes = resendOn1202 and [0] or [0, 1202]

        result = '向 %s 发消息成功' % contact
        while content:
            front, content = Partition(content)
            try:
                self.send(contact.ctype, contact.uin, front, epCodes)
            except Exception as e:
                result = '错误:向 %s 发消息失败 %s' % (str(contact), e)
                ERROR(result, exc_info=(not isinstance(e, RequestError)))
                break
            else:
                INFO('%s:%s' % (result, front))
        return result
Ejemplo n.º 30
0
 def onData(self, sock, addr, data):
     resp = self.response(data)
     try:
         sock.sendall(resp)
     except socket.error as e:
         ERROR('%s 在向 %s:%s 发送数据时发送错误 %s', self.name, addr[0], addr[1], e)
         self.onSendError(sock, addr, data)
     finally:
         sock.close()