Ejemplo n.º 1
0
 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)
Ejemplo n.º 2
0
def QTerm():
    try:
        # python qterm.py -s
        # python qterm.py [PORT] [COMMAND]
        if len(sys.argv) == 2 and sys.argv[1] == '-s':
            QTermServer(DEFPORT).Test()
        else:
            if len(sys.argv) >= 2 and sys.argv[1].isdigit():
                port = int(sys.argv[1])
                command = ' '.join(sys.argv[2:]).strip()
            else:
                port = DEFPORT
                command = ' '.join(sys.argv[1:]).strip()
    
            if command:
                if not PY3:
                    command = command.decode(sys.getfilesystemencoding())
                command = command.encode('utf8')
                resp = BYTES2STR(query(port, command))
                if not resp:
                    PRINT('无法连接 QQBot-term 服务器')
                elif not resp.strip():
                    PRINT('QQBot 命令格式错误')
                else:
                    PRINT(resp.strip())

    except KeyboardInterrupt:
        pass
Ejemplo n.º 3
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.º 4
0
 def Run(self):
     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('请在其他控制台窗口使用 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(1024)
                 except socket.error:
                     sock.close()
                 else:
                     content = BYTES2STR(data)
                     INFO('QTerm 命令:%s', content)
                     yield TermMessage(name, sock, content)
Ejemplo n.º 5
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.º 6
0
    def readConfFile(self):
        conf = ast.literal_eval(sampleConfStr)['默认配置']

        confPath = self.ConfPath()

        if os.path.exists(confPath):
            try:
                with open(confPath, 'rb') as f:
                    cusConf = ast.literal_eval(BYTES2STR(f.read()))

                if type(cusConf) is not dict:
                    raise ConfError('文件内容必须是一个dict')

                elif self.user is None:
                    pass

                elif self.user not in cusConf:
                    raise ConfError('用户 %s 不存在' % self.user)

                elif type(cusConf[self.user]) is not dict:
                    raise ConfError('用户 %s 的配置必须是一个 dict' % self.user)

                else:
                    for k, v in list(cusConf[self.user].items()):
                        if k not in conf:
                            raise ConfError('不存在的配置选项 %s.%s ' % (self.user, k))

                        elif type(v) is not type(conf[k]):
                            raise ConfError(
                                '%s.%s 必须是一个 %s' %
                                (self.user, k, type(conf[k]).__name__))

                        else:
                            conf[k] = v

            except (IOError, SyntaxError, ValueError, ConfError) as e:
                PRINT('配置文件 %s 错误: %s\n' % (confPath, e), end='')
                sys.exit(1)

        else:
            try:
                with open(confPath, 'wb') as f:
                    f.write(STR2BYTES(sampleConfStr))
            except IOError:
                pass

            if self.user is not None:
                PRINT('用户 %s 不存在\n' % self.user, end='')
                sys.exit(1)

        for k, v in list(conf.items()):
            if getattr(self, k, None) is None:
                setattr(self, k, v)

        if self.mailAccount and not self.mailAuthCode:
            msg = '请输入 %s 的 IMAP/SMTP 服务授权码: ' % self.mailAccount
            self.mailAuthCode = RAWINPUT(msg)
Ejemplo n.º 7
0
def QTerm():
    # python qterm.py [PORT] [COMMAND]
    if len(sys.argv) >= 2 and sys.argv[1].isdigit():
        port = sys.argv[1]
        command = ' '.join(sys.argv[2:]).strip()
    else:
        port = DEFPORT
        command = ' '.join(sys.argv[1:]).strip()

    if command:
        resp = BYTES2STR(Query(HOST, port, SYSTEMSTR2BYTES(command)))
        if not resp:
            PRINT('无法连接 QQBot-Term 服务器')
        elif not resp.strip():
            PRINT('QQBot 命令格式错误')
        else:
            PRINT(resp.strip())
Ejemplo n.º 8
0
    def response(self, request):
        request = BYTES2STR(request)
        url = None
        if request.startswith('GET /'):
            end = request.find('\r\n')
            if end != -1 and request[:end - 3].endswith(' HTTP/'):
                url = request[5:end - 9].rstrip('/')

        resp = b''
        if (url is not None) and (url != 'favicon.ico'):
            try:
                with open(self.qrcodePath, 'rb') as f:
                    png = f.read()
            except Exception as e:
                ERROR('读取二维码文件 %s 出错:%s', SYSTEMSTR2STR(self.qrcodePath), e)
            else:
                resp = (b'HTTP/1.1 200 OK\r\n' + b'Connection: close\r\n' +
                        b'Content-Length: ' + STR2BYTES(str(len(png))) +
                        b'\r\n' + b'Content-Type: image/png\r\n\r\n' + png)

        return resp
Ejemplo n.º 9
0
    def parseLines(self, lines):
        if self.handler is None:
            return

        for line in lines:
            line = line.rstrip(b'\r').lstrip()

            if not line:
                continue

            try:
                line = BYTES2STR(line)
            except Exception as e:
                DEBUG('%r\n%r', e, line)
                continue

            head, sep, tail = line.partition(' :')
            params = head.rstrip().split()
            command, params = params[0].upper(), params[1:]
            DEBUG('%s <== %s: %r', self.servername, self.name, line)
            DEBUG('%r, %r, %r', command, params, tail)
            self.handler(command, params, tail)
Ejemplo n.º 10
0
    def readConfFile(self):
        confPath = self.ConfPath()
        strConfPath = SYSTEMSTR2STR(confPath)
        conf = rootConf.copy()

        if os.path.exists(confPath):
            try:
                with open(confPath, 'rb') as f:
                    cusConf = ast.literal_eval(BYTES2STR(f.read()))

                if type(cusConf) is not dict:
                    raise ConfError('文件内容必须是一个 dict')

                if type(cusConf.get('默认配置', {})) is not dict:
                    raise ConfError('默认配置必须是一个 dict')

                if self.user is not None:
                    if self.user not in cusConf:
                        raise ConfError('用户 %s 不存在' % self.user)
                    elif type(cusConf[self.user]) is not dict:
                        raise ConfError('用户 %s 的配置必须是一个 dict' % self.user)
                    else:
                        names = ['默认配置', self.user]
                else:
                    names = ['默认配置']

                for name in names:
                    for k, v in list(cusConf.get(name, {}).items()):
                        if k in deprecatedConfKeys:
                            PRINT('被废弃的配置选项 %s ,将忽略此选项' % k)
                        elif k not in conf:
                            raise ConfError('不存在的配置选项 %s.%s ' % (name, k))
                        elif type(v) is not type(conf[k]):
                            t = type(conf[k]).__name__
                            raise ConfError('%s.%s 必须是一个 %s' % (name, k, t))
                        else:
                            conf[k] = v

            except (IOError, SyntaxError, ValueError, ConfError) as e:
                PRINT('配置文件 %s 错误: %s\n' % (strConfPath, e), end='')
                sys.exit(1)

        else:
            PRINT('未找到配置文件“%s”,将使用默认配置' % strConfPath)
            try:
                with open(confPath, 'wb') as f:
                    f.write(STR2BYTES(sampleConfStr))
            except IOError:
                pass
            else:
                PRINT('已创建一个默认配置文件“%s”' % strConfPath)

            if self.user is not None:
                PRINT('用户 %s 不存在\n' % self.user, end='')
                sys.exit(1)

        for k, v in list(conf.items()):
            if getattr(self, k, None) is None:
                setattr(self, k, v)

        if self.pluginPath and not os.path.isdir(STR2SYSTEMSTR(
                self.pluginPath)):
            PRINT('配置文件 %s 错误: 插件目录 “%s” 不存在\n' % \
                  (strConfPath, self.pluginPath), end='')
            sys.exit(1)

        if self.mailAccount and not self.mailAuthCode:
            msg = '请输入 %s 的 IMAP/SMTP 服务授权码: ' % self.mailAccount
            self.mailAuthCode = RAWINPUT(msg)

        if self.cmdQrcode:
            try:
                import PIL
                import wcwidth
            except ImportError:
                PRINT('您已选择以文本模式显示二维码,请先安装 pillow, wcwidth 库')
                sys.exit(1)