def updateTable(self, tinfo, table, bot): oldTable = self.getTable(tinfo) if oldTable.IsNull(): self.setTable(tinfo, table) return if oldTable.lastUpdateTime > table.lastUpdateTime: return ctype, owner = GetCTypeAndOwner(tinfo) for c in table: if c not in oldTable: INFO('新增联系人: %s(owner=%s)', c, owner) Put(bot.onNewContact, c, owner) if c.ctype in ('group', 'discuss'): self.ctables[c.ctype + '-member'][c.uin] = NullTable for c in oldTable: if c not in table: INFO('丢失联系人: %s(owner=%s)', c, owner) Put(bot.onLostContact, c, owner) if ctype in ('group', 'discuss'): self.ctables[ctype + '-member'].pop(c.uin) if ctype in ('buddy', 'group', 'discuss'): self.ctables[ctype] = table INFO('已更新 %s 列表', CTYPES[ctype]) else: self.ctables[ctype][owner.uin] = table INFO('已更新 %s 的成员列表', owner)
def updateTable(self, tinfo, table, bot): oldTable = self._table(tinfo) if oldTable.lastUpdateTime >= table.lastUpdateTime: return if table.lastUpdateTime - oldTable.lastUpdateTime > 3600: self.setTable(tinfo, table) return ctype, owner = GetCTypeAndOwner(tinfo) for c in table: if c not in oldTable: INFO('新增联系人: %s(owner=%s)', c, owner) Put(bot.onNewContact, c, owner) # if c.ctype in ('group', 'discuss'): # self.ctables[c.ctype+'-member'][c.uin] = NullTable for c in oldTable: if c not in table: INFO('丢失联系人: %s(owner=%s)', c, owner) Put(bot.onLostContact, c, owner) if ctype in ('group', 'discuss'): self.ctables[ctype + '-member'].pop(c.uin, None) self.setTable(tinfo, table)
def Run(self): import qqbot.qslots as _x _x StartDaemonThread(self.pollForever) StartDaemonThread(self.termForver, self.onTermCommand) StartDaemonThread(self.intervalForever) Put(self.updateForever, bot=self) Put(self.onStartupComplete) MainLoop()
def pollForever(self): while True: try: result = self.poll() except RequestError: Put(sys.exit, LOGIN_EXPIRE) break except: ERROR('qsession.Poll 方法出错', exc_info=True) else: Put(self.onPollComplete, *result)
def pollForever(self): while True: try: result = self.poll() except RequestError: self.conf.StoreQQ() Put(sys.exit, POLL_ERROR) break except: ERROR('qsession.Poll 方法出错', exc_info=True) else: Put(self.onPollComplete, *result)
def pollForever(self): while True: try: # time.sleep(5) # raise RequestError result = self.poll() except RequestError: Put(sys.exit, POLL_ERROR) break except: ERROR('qsession.Poll 方法出错', exc_info=True) else: Put(self.onPollComplete, *result)
def fetchUpdate(self, tinfo, needFetch, tinfoQueue, bot): if needFetch: table = self.autoSession.FetchTable(tinfo) table and Put(self.updateTable, tinfo, table, bot) if tinfo == 'end': if bot.conf.fetchInterval < 0: INFO('已完成所有联系人资料和资料,不再对联系人列表和资料进行刷新') sys.exit(0) else: time.sleep(bot.conf.fetchInterval) else: time.sleep(3) Put(self.autoUpdate, tinfoQueue, bot)
def cmd_fresh_restart(bot, args, http=False): '''1 fresh-restart''' if len(args) == 0: Put(bot.FreshRestart) return 'QQBot已重启(手工登录)', None else: return None, 'QQBot 命令格式错误'
def cmd_restart(bot, args, http=False): '''1 restart''' if len(args) == 0: Put(bot.Restart) return 'QQBot已重启(自动登录)', None else: return None, 'QQBot 命令格式错误'
def cmd_stop(bot, args, http=False): '''1 stop''' if len(args) == 0: Put(bot.Stop) return 'QQBot已停止', None else: return None, 'QQBot 命令格式错误'
def onPollComplete(self, ctype, fromUin, memberUin, content): if ctype == 'timeout': return contact = self.find(ctype, fromUin) member = None nameInGroup = None if contact is None: contact = QContact(ctype=ctype, uin=fromUin, name='uin'+fromUin) if ctype in ('group', 'discuss'): member = QContact(ctype=ctype+'-member', uin=memberUin, name='uin'+memberUin) elif ctype in ('group', 'discuss'): member = self.find(contact, memberUin) if member is None: member = QContact(ctype=ctype+'-member', uin=memberUin, name='uin'+memberUin) if ctype == 'group': cl = self.List(contact, self.conf.qq) if cl: nameInGroup = cl[0].name if nameInGroup and ('@'+nameInGroup) in content: INFO('有人 @ 我:%s[%s]' % (contact, member)) content = '[@ME] ' + content.replace('@'+nameInGroup, '') else: content = content.replace('@ME', '@Me') if ctype == 'buddy': INFO('来自 %s 的消息: "%s"' % (contact, content)) else: INFO('来自 %s[%s] 的消息: "%s"' % (contact, member, content)) Put(self.onQQMessage, contact, member, content)
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 = 30 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 退出本程序。') try: time.sleep(15) except KeyboardInterrupt: Put(sys.exit, 0) sys.exit(0) WARN('开始尝试使用非私密连接和腾讯服务器通讯。') self.session.verify = False requests.packages.urllib3.disable_warnings( requests.packages.urllib3.exceptions.InsecureRequestWarning ) return self.urlGet(url, data, Referer, Origin) else: raise
def autoUpdate(self, tinfoQueue, bot): tinfo = tinfoQueue.popleft() if tinfo == 'buddy': tinfoQueue.append('group') elif tinfo == 'group': tinfoQueue.append('discuss') elif tinfo == 'discuss': tinfoQueue.append('member') elif tinfo == 'member': tinfoQueue.extend(self.ctables['group'].clist) tinfoQueue.extend(self.ctables['discuss'].clist) tinfoQueue.append('end') elif tinfo == 'end': self.Dump() Put(bot.onFetchComplete) tinfoQueue.append('buddy') else: pass needFetch = (tinfo not in ('end', 'member')) and \ (not self.getTable(tinfo).IsFresh()) PutTo('auto-fetch', self.fetchUpdate, tinfo, needFetch, tinfoQueue, bot)
def wrapper(func): job = lambda: Put(_call, func, self) job.__name__ = func.__name__ trigger = CronTrigger(**triggerArgs) j = self.scheduler.add_job(job, trigger) self.schedTable[func.__module__].append(j) return func
def Run(self, onCommand=None): try: self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.bind((HOST, self.port)) self.sock.listen(5) except socket.error as e: WARN('无法开启 QQBot term 服务器。%s', e) WARN(' qq 命令无法使用') else: time.sleep(0.1) INFO('已在 %s 端口开启 QQBot-Term 服务器,', self.port) INFO('QQBot 已启动,请在其他控制台窗口使用 qq 命令来控制 QQBot ,' '示例: qq send buddy jack hello') while True: try: sock, addr = self.sock.accept() except socket.error: WARN('QQBot-Term 服务器出现 accept 错误') else: name = 'QTerm客户端"%s:%s"' % addr sock.settimeout(5.0) try: data = sock.recv(8192) except socket.error: sock.close() else: command = BYTES2STR(data) # INFO('QTerm 命令:%s', repr(command)) Put(onCommand, Client(name, sock), command)
def send(self,group_name, member_name, message,html=None): if html is not None: html = html.get_content(self.type) message += "\n" + html logger.info("qq消息发送:[%s][%s][%s]"%(group_name,member_name,message)) Put(self._send, group_name, member_name, message)
def Run(self): import qqbot.qslots as _x; _x if self.conf.fetchInterval < 0: self.firstFetch() self.onFetchComplete() self.onStartupComplete() else: Put(self.updateForever, bot=self) Put(self.onStartupComplete) StartDaemonThread(self.pollForever) StartDaemonThread(self.termForver, self.onTermCommand) StartDaemonThread(self.intervalForever) MainLoop()
def Find(self, tinfo, uin, bot=None): cl = self.List(tinfo, 'uin=' + uin) if cl is None: return None elif not cl: if tinfo == 'buddy': binfo = self.session.FetchNewBuddyInfo(uin) if binfo: buddy = self.ctables['buddy'].Add(**binfo) Put(bot.onNewContact, buddy, None) return buddy else: return None else: table = self.session.FetchTable(tinfo) if table: self.updateTable(tinfo, table, bot) cl = table.List('uin=' + uin) if cl: return cl[0] else: return None else: return None else: return cl[0]
def Run(self): import qqbot.qslots as _x _x if self.conf.startAfterFetch: self.firstFetch() self.onFetchComplete() self.onStartupComplete() StartDaemonThread(self.pollForever) StartDaemonThread(self.termForver, self.onTermCommand) Put(self.updateForever, bot=self) Put(self.monitorForever, bot=self) StartDaemonThread(self.intervalForever) MainLoop()
def MonitorForever(self, bot): if bot.conf.monitorTables: session = self.session.Copy() monitorTables = bot.conf.monitorTables[:] PutTo( 'monitor-fetch', lambda: (INFO('特别监视将在 30 秒后启动'), time.sleep(30), INFO('特别监视已启动'), Put(self.monitor, monitorTables, session, bot)))
def Run(self): import qqbot.qslots as _x _x StartDaemonThread(self.pollForever) StartDaemonThread(self.termForver, self.onTermCommand) StartDaemonThread(self.intervalForever) Put(self.updateForever, self.onNewContact, self.onLostContact) MainLoop()
def Test(self): def onTermCommand(client, command): if command == 'stop': client.Reply('QQBot已停止') sys.exit(0) else: client.Reply('Hello, ' + command) Put(StartDaemonThread, self.Run, onTermCommand) MainLoop()
def fetch(self, fetcher, *args, **kwargs): Put(self.fetcher_, fetcher, *args, **kwargs) self.fetch_cv.acquire() self.fetch_cv.wait() (result, exception) = self.fetch_result self.fetch_result = None self.fetch_cv.release() if exception: raise exception return result
def Run(self): QQBot.initScheduler(self) import qqbot.qslots as _x _x for plugin in self.conf.plugins: self.Plug(plugin) if self.conf.startAfterFetch: self.firstFetch() self.onFetchComplete() self.onStartupComplete() StartDaemonThread(self.pollForever) StartDaemonThread(self.termForver, self.onTermCommand) Put(self.updateForever, bot=self) Put(self.monitorForever, bot=self) StartDaemonThread(self.intervalForever) MainLoop()
def recvLoop(self): buf = b'' while True: try: data = self.sock.recv(8192) except socket.timeout: if self.handler is None: DEBUG('END IRC-CLIENT\'S RECV LOOP') break except Exception as e: ERROR('在接收来自 %s 的数据时发送错误,%s', self.name, e) if self.handler: Put(self.close) break else: if data: lines = (buf + data).split(b'\n') buf = lines.pop() if lines: Put(self.parseLines, lines) else: Put(self.close) break
def DeleteMember(self, group, memb, bot): if self.getTable(group).Remove(memb): Put(bot.onLostContact, memb, group)
def cmd_restart(bot, args): '''1 restart''' if len(args) == 0: Put(bot.Restart) return 'QQBot已重启'
def cmd_stop(bot, args): '''1 stop''' if len(args) == 0: Put(bot.Stop) return 'QQBot已停止'
def intervalForever(self): while True: time.sleep(300) Put(self.onInterval)
def fetchUpdate(self, tinfo, needFetch, args): if needFetch: table = self.autoSession.FetchTable(tinfo) table and Put(self.updateTable, tinfo, table, *args[1:]) time.sleep(120 if tinfo == 'end' else 5) Put(self.autoUpdate, args)