def QLogin(qq=None, user=None): conf = QConf(qq, user) conf.Display() if conf.qq: INFO('开始自动登录...') picklePath = conf.PicklePath() session = QSession() contactdb = QContactDB(session) try: contactdb.Restore(picklePath) except Exception as e: WARN('自动登录失败,原因:%s', e) else: INFO('成功从文件 "%s" 中恢复登录信息' % picklePath) try: contactdb.session.TestLogin() except RequestError: WARN('自动登录失败,原因:上次保存的登录信息已过期') except Exception as e: WARN('自动登录失败,原因:%s', e) DEBUG('', exc_info=True) else: return contactdb.session.Copy(), contactdb, conf INFO('开始手动登录...') session = QSession() session.Login(conf) contactdb = QContactDB(session, conf.PicklePath()) contactdb.Dump() return session.Copy(), contactdb, conf
def runBot(argv): # argv -1, sub program call if sys.argv[-1] == '--subprocessCall': # Remove the last item sys.argv.pop() try: # Bot login, run # QQBot is defined below. bot = QQBot._bot bot.Login(argv) bot.Run() finally: # Finally, always run, no matter what # If bot has conf, bot conf storeQQ if hasattr(bot, 'conf'): bot.conf.StoreQQ() else: # Not sub program called conf = QConf() # QQ run in background if conf.daemon: conf.Daemonize() if sys.argv[0].endswith('py') or sys.argv[0].endswith('pyc'): args = [sys.executable] + sys.argv else: args = sys.argv args = args + ['--mailAuthCode', conf.mailAuthCode] args = args + ['--qq', conf.qq] args = args + ['--subprocessCall'] while True: p = subprocess.Popen(args) code = p.wait() if code == 0: INFO('QQBot 正常停止') sys.exit(code) elif code == RESTART: args[-2] = conf.LoadQQ() INFO('5 秒后重新启动 QQBot (自动登陆,qq=%s)', args[-2]) time.sleep(5) elif code == FRESH_RESTART: args[-2] = '' INFO('5 秒后重新启动 QQBot (手工登陆)') time.sleep(5) else: CRITICAL('QQBOT 异常停止(code=%s)', code) if conf.restartOnOffline: args[-2] = conf.LoadQQ() INFO('15秒后重新启动 QQBot (自动登陆,qq=%s)', args[-2]) time.sleep(15) else: sys.exit(code)
def init(self, argv): for name, slots in self.slotsTable.items(): setattr(self, name, self.wrap(slots)) self.conf = QConf(argv) self.conf.Display() for pluginName in self.conf.plugins: self.Plug(pluginName) self.onInit()
def runBot(botCls, qq, user): if sys.argv[-1] == '--subprocessCall': isSubprocessCall = True sys.argv.pop() else: isSubprocessCall = False if isSubprocessCall: bot = botCls() try: bot.Login(qq, user) bot.Run() finally: if hasattr(bot, 'conf'): bot.conf.StoreQQ() else: conf = QConf(qq, user) if sys.argv[0].endswith('py') or sys.argv[0].endswith('pyc'): args = [sys.executable] + sys.argv else: args = sys.argv args = args + ['--mailAuthCode', conf.mailAuthCode] args = args + ['--qq', conf.qq] args = args + ['--subprocessCall'] while True: p = subprocess.Popen(args) pid = p.pid code = p.wait() qq = conf.LoadQQ(pid) if code == 0: INFO('QQBot 正常停止') sys.exit(code) elif code == RESTART: args[-2] = qq INFO('5 秒后重新启动 QQBot (自动登陆,qq=%s)', args[-2]) time.sleep(5) elif code == FRESH_RESTART: args[-2] = '' INFO('5 秒后重新启动 QQBot (手工登陆)') time.sleep(5) else: CRITICAL('QQBOT 异常停止(code=%s)', code) if conf.restartOnOffline: args[-2] = qq INFO('15秒后重新启动 QQBot (自动登陆,qq=%s)', args[-2]) time.sleep(15) else: sys.exit(code)
def Login(self, qq=None, user=None): self.conf = QConf(qq, user) session, contactdb, self.conf = QLogin(conf=self.conf) # main thread self.SendTo = session.SendTo self.groupKick = session.GroupKick self.groupSetAdmin = session.GroupSetAdmin self.groupShut = session.GroupShut self.groupSetCard = session.GroupSetCard # main thread self.List = contactdb.List self.Update = contactdb.Update self.StrOfList = contactdb.StrOfList self.ObjOfList = contactdb.ObjOfList self.findSender = contactdb.FindSender self.firstFetch = contactdb.FirstFetch self.Delete = contactdb.db.Delete self.Modify = contactdb.db.Modify # child thread 1 self.poll = session.Copy().Poll # child thread 2 self.termForver = QTermServer(self.conf.termServerPort).Run
def QLogin(qq=None, user=None): conf = QConf(qq, user) conf.Display() if conf.qq: INFO('开始自动登录...') picklePath = conf.PicklePath() session = QSession() try: with open(picklePath, 'rb') as f: session.__dict__ = pickle.load(f) except Exception as e: WARN('自动登录失败,原因:%s', e) else: INFO('成功从文件 "%s" 中恢复登录信息' % SYSTEMSTR2STR(picklePath)) try: session.TestLogin() except RequestError: WARN('自动登录失败,原因:上次保存的登录信息已过期') except Exception as e: WARN('自动登录失败,原因:%s', e) DEBUG('', exc_info=True) else: return session, QContactDB(session), conf if os.path.exists(session.dbname): try: os.remove(session.dbname) except OSError: pass except: WARN('', exc_info=True) INFO('开始手动登录...') session = QSession() session.Login(conf) picklePath = conf.PicklePath() try: with open(picklePath, 'wb') as f: pickle.dump((session.__dict__), f) except Exception as e: WARN('保存登录信息及联系人失败:%s %s', (e, SYSTEMSTR2STR(picklePath))) else: INFO('登录信息已保存至文件:file://%s' % SYSTEMSTR2STR(picklePath)) return session, QContactDB(session), conf
def runBot(botCls, qq, user): if sys.argv[-1] == '--subprocessCall': isSubprocessCall = True sys.argv.pop() else: isSubprocessCall = False if isSubprocessCall: bot = botCls() bot.Login(qq, user) bot.Run() else: conf = QConf(qq, user) if sys.argv[0].endswith('py') or sys.argv[0].endswith('pyc'): args = [sys.executable] + sys.argv else: args = sys.argv args = args + ['--mailAuthCode', conf.mailAuthCode] args = args + ['--qq', conf.qq] args = args + ['--subprocessCall'] while True: code = subprocess.call(args) if code == 0: INFO('QQBot 正常停止') sys.exit(code) elif code == RESTART: args[-2] = conf.LoadQQ() INFO('5 秒后重新启动 QQBot (自动登陆)') time.sleep(5) elif code == FRESH_RESTART: args[-2] = '' INFO('5 秒后重新启动 QQBot (手工登陆)') time.sleep(5) else: CRITICAL('QQBOT 异常停止(code=%s)', code) if conf.restartOnOffline: args[-2] = conf.LoadQQ() INFO('30秒后重新启动 QQBot (自动登陆)') time.sleep(30) else: sys.exit(code)
def __init__(self, qq=None, user=None, conf=None, ai=None): MessageFactory.__init__(self) self.conf = conf if conf else QConf(qq, user) ai = ai if ai else BasicAI() termServer = QTermServer(self.conf.termServerPort) self.On('qqmessage', ai.OnQQMessage) # main thread self.On('polltimeout', ai.OnPollTimeout) # main thread self.On('termmessage', ai.OnTermMessage) # main thread self.On('pollcomplete', QQBot.onPollComplete) # main thread self.AddGenerator(self.pollForever) # child thread 1 self.AddGenerator(termServer.Run) # child thread 2
class QQBot(GroupManager, TermBot): # this class, arg def Login(self, argv=None): # init bot self.init(argv) session, contactdb = QLogin(self.conf) self.session, self.contactdb = session, contactdb # main thread self.SendTo = session.Copy().SendTo self.groupKick = session.GroupKick self.groupSetAdmin = session.GroupSetAdmin self.groupShut = session.GroupShut self.groupSetCard = session.GroupSetCard # main thread self.List = contactdb.List self.Update = contactdb.Update self.StrOfList = contactdb.StrOfList self.ObjOfList = contactdb.ObjOfList self.findSender = contactdb.FindSender self.firstFetch = contactdb.FirstFetch self.Delete = contactdb.db.Delete self.Modify = contactdb.db.Modify # child thread 1 self.poll = session.Copy().Poll 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) def Stop(self): sys.exit(0) def Restart(self): sys.exit(RESTART) def FreshRestart(self): sys.exit(FRESH_RESTART) # child thread 1 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 onPollComplete(self, ctype, fromUin, membUin, content): if ctype == 'timeout': return contact, member, nameInGroup = \ self.findSender(ctype, fromUin, membUin, self.conf.qq, content) if contact.ctype == 'group' and member == 'SYSTEM-MESSAGE': INFO('来自 %s 的系统消息: "%s"', contact, content) return if self.detectAtMe(nameInGroup, 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)) self.onQQMessage(contact, member, content) def detectAtMe(self, nameInGroup, content): return nameInGroup and ('@' + nameInGroup) in content # child thread 2 def intervalForever(self): while True: time.sleep(300) Put(self.onInterval) def __init__(self): self.scheduler = BackgroundScheduler(daemon=True) self.schedTable = defaultdict(list) self.slotsTable = { 'onInit': [], 'onQrcode': [], 'onStartupComplete': [], 'onQQMessage': [], 'onInterval': [], 'onUpdate': [], 'onPlug': [], 'onUnplug': [], 'onExit': [], } self.started = False self.plugins = {} def init(self, argv): for name, slots in self.slotsTable.items(): setattr(self, name, self.wrap(slots)) self.conf = QConf(argv) self.conf.Display() for pluginName in self.conf.plugins: self.Plug(pluginName) self.onInit() def wrap(self, slots): def func(*args, **kwargs): for f in slots: _call(f, self, *args, **kwargs) return func def AddSlot(self, func): self.slotsTable[func.__name__].append(func) return func def AddSched(self, **triggerArgs): def wrapper(func): job = lambda: Put(_call, func, self) job.__name__ = func.__name__ j = self.scheduler.add_job(job, CronTrigger(**triggerArgs)) self.schedTable[func.__module__].append(j) return func return wrapper def unplug(self, moduleName, removeJob=True): for slots in self.slotsTable.values(): i = 0 while i < len(slots): if slots[i].__module__ == moduleName: slots[i] = slots[-1] slots.pop() else: i += 1 if removeJob: for job in self.schedTable.pop(moduleName, []): job.remove() self.plugins.pop(moduleName, None) 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 def Unplug(self, moduleName): if moduleName not in self.plugins: result = '警告:试图卸载未安装的插件 %s' % moduleName WARN(result) return result else: module = self.plugins[moduleName] self.unplug(moduleName) if hasattr(module, 'onUnplug'): _call(module.onUnplug, self) result = '成功:卸载插件 %s' % moduleName INFO(result) return result def Plugins(self): return list(self.plugins.keys())
INFO('正在获取 %s ...', rname) try: if ttype == 'buddy': table = fetchBuddyTable(self) elif ttype == 'group': table = fetchGroupTable(self) elif ttype == 'discuss': table = fetchDiscussTable(self) elif ttype == 'group-member': table = fetchGroupMemberTable(self, tinfo) else: table = fetchDiscussMemberTable(self, tinfo) except RequestError: table = None except: ERROR('', exc_info=True) table = None if table is None: ERROR('获取 %s 失败', rname) return table if __name__ == '__main__': from qqbot.qconf import QConf from qqbot.basicqsession import BasicQSession self = BasicQSession() self.Login(QConf())
pass except: WARN('', exc_info=True) INFO('开始手动登录...') session = QSession() session.Login(conf) picklePath = conf.PicklePath() try: with open(picklePath, 'wb') as f: pickle.dump((session.__dict__), f) except Exception as e: WARN('保存登录信息及联系人失败:%s %s', (e, SYSTEMSTR2STR(picklePath))) else: INFO('登录信息已保存至:%s' % SYSTEMSTR2STR(picklePath)) return session, QContactDB(session) class QSession(BasicQSession, GroupManagerSession): pass if __name__ == '__main__': from qqbot.qconf import QConf conf = QConf(['-q', '1261422618']) conf.Display() session, contactdb = QLogin(conf) self = session c = contactdb.List('buddy', 'Eva')[0]
email_id = id_list[i] except IndexError: return None data = conn.fetch(email_id, '(BODY.PEEK[HEADER.FIELDS (SUBJECT)])')[1] if not PY3: msg = message_from_string(data[0][1]) s, encoding = decode_header(msg['Subject'])[0] subject = s.decode(encoding or 'utf-8').encode('utf-8') else: msg = message_from_bytes(data[0][1]) s, encoding = decode_header(msg['Subject'])[0] subject = s if type(s) is str else s.decode(encoding or 'utf-8') return subject if __name__ == '__main__': from qqbot.qconf import QConf conf = QConf(['-u', 'xxx']) conf.Display() ma = MailAgent(conf.mailAccount, conf.mailAuthCode) with ma.SMTP() as s: s.send(conf.mailAccount, 'hello', 'faf房间多啦') print('send ok') with ma.IMAP() as i: subject = i.getSubject(-1) print('latest email: ' + str(subject)) print('recv ok')
if ttype == 'buddy': table = fetchBuddyTable(self) elif ttype == 'group': table = fetchGroupTable(self) elif ttype == 'discuss': table = fetchDiscussTable(self) elif ttype == 'group-member': table = fetchGroupMemberTable(self, tinfo) else: table = fetchDiscussMemberTable(self, tinfo) except RequestError: table = None except: ERROR('', exc_info=True) table = None if table is None: ERROR('获取 %s 失败', rname) return table if __name__ == '__main__': from qqbot.qconf import QConf from qqbot.basicqsession import BasicQSession self = BasicQSession() conf = QConf(['-q', '158297369']) conf.Display() self.Login(conf)