def run_parse():
    # extract parameters
    input_file, id_, file_tag = common.extract_parameters()
    repo_name = "events.cbrugger.results"

    # copy previous result files
    common.clone(repo_name)
    result_dir = os.path.join(common.project_path(), repo_name, "inputs")
    for filename in os.listdir(result_dir):
        shutil.copy(os.path.join(result_dir, filename), common.project_path())

    # run script
    returncode = common.run_returncode([
        'python', 'scripts/parse_results.py', '--chunks',
        str(common.N_EVENT_CHUNKS),
        common.to_basename(input_file)
    ])

    # check return code
    if returncode == common.EXIT_FILE_MISSING:
        print("INFO: file missing, exiting gracefully")
        return
    elif returncode != 0:
        raise RuntimeError("Error while calling script")

    # push results to next repository
    filenames = [
        path for path in os.listdir(common.project_path())
        if path.endswith(".html")
    ]

    common.upload_file(filenames, repo_name, id_, file_tag, do_clone=False)

    print("Parse done")
Exemple #2
0
    def __init__(self, parent=None):
        super().__init__(parent)

        self.cf = configparser.RawConfigParser()
        self.mysql_dir_path = abspath(join(common.project_path(), 'mysql'))
        self.ini_path = abspath(join(self.mysql_dir_path, 'my.ini'))
        self.mysql_exist = False
        self.already_load_cf = False
        self.sel_exist_mysql()
Exemple #3
0
    def __init__(self):
        self.cf = configparser.RawConfigParser()
        self.cf.read(abspath(join(common.project_path(), 'base.ini')))
        # 同步锁
        self.mutex = threading.Lock()

        self.access_token = self.cf.get('token', 'access_token')
        self.client_id = self.cf.get('token', 'client_id')
        self.client_secret = self.cf.get('token', 'client_secret')
        self.redirect_uri = self.cf.get('token', 'redirect_uri')
        self.app_url = self.cf.get('token', 'app_url')
        self.refresh_token = self.cf.get('token', 'refresh_token')
        # 实例化时立即尝试获取token,避免多线程并发
        _thread.start_new_thread(self.__get_access_token, ())
Exemple #4
0
class V2ray(QObject):
    """
    V2ray管理
    """

    v2ray_dir_path = abspath(join(common.project_path(), 'v2ray'))
    v2ray_exe_name = 'wv2ray.exe'
    v2ray_conf_name = 'config.json'
    pac_name = join(v2ray_dir_path, 'pac.js')
    proxy_exe_name = 'v2ray_privoxy.exe'
    proxy_conf_name = 'privoxy.conf'
    ndata_path = join(v2ray_dir_path, 'ndata')
    config_path = join(v2ray_dir_path, 'config.json')
    v2rayLogSignal = pyqtSignal(str, arguments=['log'])
    startedSignal = pyqtSignal()
    stopedSignal = pyqtSignal()
    quitedSignal = pyqtSignal()
    updPacStateSignal = pyqtSignal(str, arguments=['state'])

    # processSignal = pyqtSignal(QVariant, arguments=['process'])

    def __init__(self, parent=None):
        super().__init__(parent)
        self.v2ray_popen = None
        self.proxy_popen = None

        # 加载存储的节点
        try:
            with open(self.ndata_path, "rb") as f:
                self.saved_conf = pickle.load(f)
        except:
            self.pac_conf = None
            self.saved_conf = {"local": {}, "subs": {}}
        try:
            # 加载pac
            with open(self.pac_name, "r", encoding="utf-8") as f:
                self.pac_conf = ''.join(f.readlines())
        except:
            self.pac_conf = None
            logging.debug('PAC加载失败')

        self.conf = dict(self.saved_conf['local'], **self.saved_conf['subs'])

        # 开启pac server
        _thread.start_new_thread(self.pac_web_server, ())

    @pyqtSlot(name='sel', result=QVariant)
    def sel(self):
        return self.saved_conf

    @pyqtSlot(name='checkPac', result=str)
    def check_pac(self):
        if self.pac_conf == None:
            return 'error'
        return ''

    @pyqtSlot(name='start')
    def start(self):
        _thread.start_new_thread(self.__start, ())

    def __start(self):
        # 停止v2ray进程
        common.kill_progress(self.v2ray_exe_name)
        # 停止代理进程
        common.kill_progress(self.proxy_exe_name)

        _thread.start_new_thread(self.start_v2ray, ())
        _thread.start_new_thread(self.start_proxy, ())

        mode = setting_instance.settings['proxy_mode']
        if mode == 'Off':
            setting_instance.set_proxy_mode('ProxyOnly')

        self.set_proxy(mode)
        self.startedSignal.emit()

    @pyqtSlot(name='quit')
    def quit(self):
        _thread.start_new_thread(self.__quit, ())

    def __quit(self):
        # 停止v2ray进程
        common.kill_progress(self.v2ray_exe_name)
        # 停止代理进程
        common.kill_progress(self.proxy_exe_name)

        self.set_proxy('Off')
        self.quitedSignal.emit()

    @pyqtSlot(str, name='changeNode', result=str)
    def change_node(self, node):
        try:
            self.setconf(node, '10808')
            self.restart()
            return ''
        except Exception as e:
            return e.args[0]

    @pyqtSlot(str, name='delNode')
    def del_node(self, node):
        self.delconf(node)

    @pyqtSlot(QVariant, name='editNode', result=str)
    def edit_node(self, node):
        # 删除旧的节点配置
        try:
            node = node.toVariant()
            self.delconf(node['oldps'])
            self.add_conf(node['ps'], node)

            if setting_instance.settings['proxy_node'] == node['oldps']:
                setting_instance.set_proxy_node(node['ps'])
                self.setconf(node['ps'], '10808')
                self.restart()
            return ''
        except:
            return 'error'

    def restart(self):
        _thread.start_new_thread(self.__restart, ())

    def __restart(self):
        common.kill_progress(self.v2ray_exe_name)
        common.kill_progress(self.proxy_exe_name)
        self.set_proxy('Off')

        self.__start()

    @pyqtSlot(name='parse', result=str)
    def parse(self):
        try:
            paste_str = pyperclip.paste()
            ret = self.parse_conf_by_uri(paste_str)
            self.add_conf_by_uri(paste_str)
            if setting_instance.settings['proxy_node'] == None:
                setting_instance.set_proxy_node(ret['ps'])
                self.setconf(ret['ps'], '10808')
            return ''
        except Exception as e:
            return e.args[0]

    @pyqtSlot(name='stop')
    def stop(self):
        _thread.start_new_thread(self.__stop, ())

    def __stop(self):
        # 停止v2ray进程
        common.kill_progress(self.v2ray_exe_name)
        # 停止代理进程
        common.kill_progress(self.proxy_exe_name)

        self.set_proxy('Off')
        self.stopedSignal.emit()

    def start_v2ray(self):
        # 窗口信息
        startupinfo = subprocess.STARTUPINFO()
        startupinfo.dwFlags = subprocess.CREATE_NEW_CONSOLE | subprocess.STARTF_USESHOWWINDOW
        startupinfo.wShowWindow = subprocess.SW_HIDE

        # 启动v2ray进程
        cmd = '\"{}\" -config \"{}\"'.format(
            join(self.v2ray_dir_path, self.v2ray_exe_name),
            join(self.v2ray_dir_path, self.v2ray_conf_name))
        popen = subprocess.Popen(cmd,
                                 startupinfo=startupinfo,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 creationflags=subprocess.CREATE_NO_WINDOW)
        self.v2ray_popen = popen
        # 重定向标准输出 None表示正在执行中
        while popen.poll() is None:
            r = popen.stdout.readline().decode('utf8')
            if r.replace('\r', '').replace('\n', '').strip(' ') != '':
                logging.debug(r.replace('\n', ''))
                self.v2rayLogSignal.emit(r.replace('\n', ''))

    def start_proxy(self):
        # 窗口信息
        startupinfo = subprocess.STARTUPINFO()
        startupinfo.dwFlags = subprocess.CREATE_NEW_CONSOLE | subprocess.STARTF_USESHOWWINDOW
        startupinfo.wShowWindow = subprocess.SW_HIDE

        # 启动proxy进程
        cmd = '\"{}\" \"{}\"'.format(
            join(self.v2ray_dir_path, self.proxy_exe_name),
            join(self.v2ray_dir_path, self.proxy_conf_name))
        popen = subprocess.Popen(cmd,
                                 startupinfo=startupinfo,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 creationflags=subprocess.CREATE_NO_WINDOW)
        self.proxy_popen = popen

    def get_uri_type(self, uri):
        try:
            op = uri.split("://")
            if op[0] == "vmess":
                return "vmess"
            elif op[0] == "ss":
                return "shadowsocks"
            else:
                raise MyException("无法解析的链接格式")
        except Exception as e:
            if e.args[0] == "无法解析的链接格式":
                raise MyException("无法解析的链接格式")
            raise MyException("解析失败")

    def b642conf(self, prot, b64str):
        """
        base64转化为dict类型配置
        :param prot:
        :param tp:
        :param b64str:
        :return:
        """
        if prot == "vmess":
            ret = json.loads(
                parse.unquote(base64.b64decode(b64str +
                                               "==").decode()).replace(
                                                   "\'", "\""))
            region = ret['ps']

        elif prot == "shadowsocks":
            string = b64str.split("#")
            cf = string[0].split("@")
            if len(cf) == 1:
                tmp = parse.unquote(base64.b64decode(cf[0] + "==").decode())
            else:
                tmp = parse.unquote(
                    base64.b64decode(cf[0] + "==").decode() + "@" + cf[1])
                print(tmp)
            ret = {
                "method": tmp.split(":")[0],
                "port": tmp.split(":")[2],
                "password": tmp.split(":")[1].split("@")[0],
                "add": tmp.split(":")[1].split("@")[1],
            }
            region = parse.unquote(string[1])

        ret["prot"] = prot
        return ret

    def setconf(self, region, socks, proxy=None):
        """
        生成配置
        :param region: 当前VPN别名
        :param socks: socks端口
        :return:
        """
        use_conf = self.conf[region]
        conf = copy.deepcopy(common.tpl)
        conf["inbounds"][0]["port"] = socks

        #  如果是vmess
        if use_conf['prot'] == "vmess":
            conf['outbounds'][0]["protocol"] = "vmess"
            conf['outbounds'][0]["settings"]["vnext"] = list()
            conf['outbounds'][0]["settings"]["vnext"].append({
                "address":
                use_conf["add"],
                "port":
                int(use_conf["port"]),
                "users": [{
                    "id": use_conf["id"],
                    "alterId": int(use_conf["aid"]),
                    "security": "auto",
                    "level": 8,
                }]
            })
            # webSocket 协议
            if use_conf["net"] == "ws":
                conf['outbounds'][0]["streamSettings"] = {
                    "network": use_conf["net"],
                    "security": "tls" if use_conf["tls"] else "",
                    "tlssettings": {
                        "allowInsecure": True,
                        "serverName":
                        use_conf["host"] if use_conf["tls"] else ""
                    },
                    "wssettings": {
                        "connectionReuse": True,
                        "headers": {
                            "Host": use_conf['host']
                        },
                        "path": use_conf["path"]
                    }
                }
            # mKcp协议
            elif use_conf["net"] == "kcp":
                conf['outbounds'][0]["streamSettings"] = {
                    "network": use_conf["net"],
                    "kcpsettings": {
                        "congestion": False,
                        "downlinkCapacity": 100,
                        "header": {
                            "type":
                            use_conf["type"] if use_conf["type"] else "none"
                        },
                        "mtu": 1350,
                        "readBufferSize": 1,
                        "tti": 50,
                        "uplinkCapacity": 12,
                        "writeBufferSize": 1
                    },
                    "security": "tls" if use_conf["tls"] else "",
                    "tlssettings": {
                        "allowInsecure": True,
                        "serverName":
                        use_conf["host"] if use_conf["tls"] else ""
                    }
                }
            # tcp
            elif use_conf["net"] == "tcp":
                conf['outbounds'][0]["streamSettings"] = {
                    "network": use_conf["net"],
                    "security": "tls" if use_conf["tls"] else "",
                    "tlssettings": {
                        "allowInsecure": True,
                        "serverName":
                        use_conf["host"] if use_conf["tls"] else ""
                    },
                    "tcpsettings": {
                        "connectionReuse": True,
                        "header": {
                            "request": {
                                "version": "1.1",
                                "method": "GET",
                                "path": [use_conf["path"]],
                                "headers": {
                                    "User-Agent": [
                                        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"
                                    ],
                                    "Accept-Encoding": ["gzip, deflate"],
                                    "Connection": ["keep-alive"],
                                    "Pragma":
                                    "no-cache",
                                    "Host": [use_conf["host"]]
                                }
                            },
                            "type": use_conf["type"]
                        }
                    } if use_conf["type"] != "none" else {}
                }
            # QUIC
            # elif use_conf["net"] == "quic":
            #     conf['outbounds'][0]["streamSettings"] = {
            #         "network": use_conf["net"],
            #         "security": "tls" if use_conf["tls"] else "none",
            #         "tlssettings": {
            #             "allowInsecure": True,
            #             "serverName": use_conf["host"]
            #         },
            #         "quicsettings": {
            #             "headers": {
            #                 "type": use_conf['type']
            #             },
            #             "key":
            #         }
            #     }
        # 如果是ss
        elif use_conf['prot'] == "shadowsocks":
            conf['outbounds'][0]["protocol"] = "shadowsocks"
            conf['outbounds'][0]["settings"]["servers"] = list()
            conf['outbounds'][0]["settings"]["servers"].append({
                "address":
                use_conf["add"],
                "port":
                int(use_conf["port"]),
                "password":
                use_conf["password"],
                "ota":
                False,
                "method":
                use_conf["method"]
            })
            conf['outbounds'][0]["streamSettings"] = {"network": "tcp"}
        else:
            raise MyException("不支持的协议类型")

        # 是否进行透明代理
        # if proxy and use_conf['prot'] == "vmess":
        #     # 修改入站协议

        #     conf["inbounds"].append({
        #         "tag": "transparent",
        #         "port": 12345,
        #         "protocol": "dokodemo-door",
        #         "settings": {
        #             "network": "tcp,udp",
        #             "followRedirect": True,
        #             "timeout": 30
        #         },
        #         "sniffing": {
        #             "enabled": True,
        #             "destOverride": [
        #                 "http",
        #                 "tls"
        #             ]
        #         },
        #         "streamSettings": {
        #             "sockopt": {
        #                 "tproxy": "tproxy"  # 透明代理使用 TPROXY 方式
        #             }
        #         }
        #     })

        #     # 配置dns
        #     conf['dns']["servers"] = [
        #         "8.8.8.8",  # 非中国大陆域名使用 Google 的 DNS
        #         "1.1.1.1",
        #         "114.114.114.114",
        #         {
        #             "address": "223.5.5.5",
        #             "port": 53,
        #             "domains": [
        #                 "geosite:cn",
        #                 "ntp.org",
        #                 use_conf['host']
        #             ]
        #         }
        #     ]

        #     # 每一个outbounds添加mark
        #     conf['outbounds'][0]["streamSettings"]["sockopt"] = {"mark": 255}
        #     conf['outbounds'][1]["settings"] = {"domainStrategy": "UseIP"}
        #     conf['outbounds'][1]["streamSettings"] = dict()
        #     conf['outbounds'][1]["streamSettings"]["sockopt"] = {"mark": 255}

        #     conf['outbounds'].append({
        #         "tag": "dns-out",
        #         "protocol": "dns",
        #         "streamSettings": {
        #             "sockopt": {
        #                 "mark": 255
        #             }
        #         }
        #     })
        #     # 配置路由
        #     conf['routing']["rules"].append({
        #         "type": "field",
        #         "inboundTag": [
        #             "transparent"
        #         ],
        #         "port": 53,   # 劫持53端口UDP流量,使用V2Ray的DNS
        #         "network": "udp",
        #         "outboundTag": "dns-out"
        #     })
        #     conf['routing']['rules'].append({
        #         "type": "field",
        #         "inboundTag": [
        #             "transparent"
        #         ],
        #         "port": 123,  # 直连123端口UDP流量(NTP 协议)
        #         "network": "udp",
        #         "outboundTag": "direct"
        #     })
        #     conf["routing"]["rules"].append({
        #         "type": "field",  # 设置DNS配置中的国内DNS服务器地址直连,以达到DNS分流目的
        #         "ip": [
        #             "223.5.5.5",
        #             "114.114.114.114"
        #         ],
        #         "outboundTag": "direct"
        #     })
        #     conf["routing"]["rules"].append({
        #         "type": "field",
        #         "ip": [
        #             "8.8.8.8",  # 设置 DNS 配置中的国内 DNS 服务器地址走代理,以达到DNS分流目的
        #             "1.1.1.1"
        #         ],
        #         "outboundTag": "proxy"
        #     })
        #     conf["routing"]["rules"].append({
        #         "type": "field",
        #         "protocol": ["bittorrent"],  # BT流量直连
        #         "outboundTag": "direct"
        #     })

        #     if proxy == 1:  # 国内网站直连:
        #         conf["routing"]["rules"].append({
        #             "type": "field",
        #             "ip": [
        #                "geoip:private",
        #                "geoip:cn"
        #             ],
        #             "outboundTag": "direct"
        #         })
        #         conf["routing"]["rules"].append({
        #             "type": "field",
        #             "domain": [
        #                 "geosite:cn"
        #             ],
        #             "outboundTag": "direct"
        #         })
        #     else:  # gfw
        #         conf["routing"]["rules"].append({
        #             "type": "field",
        #             "domain": [
        #                 "ext:h2y.dat:gfw"
        #             ],
        #             "outboundTag": "proxy"
        #         })
        #         conf["routing"]["rules"].append({
        #             "type": "field",
        #             "network": "tcp,udp",
        #             "outboundTag": "direct"
        #         })

        with open(self.config_path, "w") as f:
            f.write(json.dumps(conf, indent=4))

    def delconf(self, region):
        """
        删除一个配置
        :param region: 配置名
        :return:
        """
        self.conf.pop(region)
        try:
            self.saved_conf['local'].pop(region)
        except KeyError:
            self.saved_conf['subs'].pop(region)
        except:
            raise MyException("配置删除出错,请稍后再试..")

        with open(self.ndata_path, "wb") as jf:
            pickle.dump(self.saved_conf, jf)

    def parse_conf_by_uri(self, uri):
        uri_type = self.get_uri_type(uri)
        op = uri.split("://")
        ret = self.b642conf(uri_type, op[1])
        return ret

    def add_conf_by_uri(self, uri):
        """
        通过分享的连接添加配置
        """

        ret = self.parse_conf_by_uri(uri)
        op = uri.split("://")
        if op[0] == "vmess":
            region = ret['ps']
        elif op[0] == "ss":
            string = op[1].split("#")
            region = parse.unquote(string[1])
        if region in self.saved_conf["subs"]:
            region = region + "_local"
        self.add_conf(region, ret)

    def add_conf(self, region, node):
        self.saved_conf[["local", "subs"][0]][region] = node
        self.conf = dict(self.saved_conf['local'], **self.saved_conf['subs'])

        with open(self.ndata_path, "wb") as jf:
            pickle.dump(self.saved_conf, jf)

    def conf2b64(self, region):
        tmp = dict()
        prot = self.conf[region]['prot']
        for k, v in self.conf[region].items():
            tmp[k] = v
        tmp.pop("prot")
        if prot == "vmess":
            return prot + "://" + base64.b64encode(str(tmp).encode()).decode()
        else:
            prot = "ss"
            return prot + "://" + base64.b64encode("{}:{}@{}:{}".format(
                tmp["method"], tmp["password"], tmp["add"],
                tmp["port"]).encode()).decode() + "#" + region

    @pyqtSlot(name='updPac')
    def upd_pac(self):
        _thread.start_new_thread(self.__upd_pac, ())

    def __upd_pac(self):
        proxies = {
            "http": "http://127.0.0.1:10809",
            "https": "http://127.0.0.1:10809",
        }

        try:
            r = requests.get(
                "https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt",
                proxies=proxies)
            rt = base64.b64decode(r.content).decode()

            ignoredLineBegins = ['!', '[']
            rt_array = rt.splitlines()

            new_rt_array = []
            for l in rt_array:
                if not (l.startswith(ignoredLineBegins[0])
                        or l.startswith(ignoredLineBegins[1])):
                    if not (l.isspace() or len(l) == 0):
                        new_rt_array.append(l)

            json_str = json.dumps(new_rt_array, indent=2)
            self.pac_conf = v2ray_adpt.adpt.replace('__RULES__', json_str)
            self.pac_conf = self.pac_conf.replace(
                '__PROXY__', 'PROXY {0}:{1};'.format('127.0.0.1', '10809'))
            with open(self.pac_name, 'w') as f:
                f.write(self.pac_conf)
            self.updPacStateSignal.emit('success')
        except:
            self.updPacStateSignal.emit('error')

    def handle_client(self, client_socket):
        """
        处理客户端请求
        """
        # 获取客户端请求数据
        client_socket.recv(1024)
        # 构造响应数据
        response_start_line = "HTTP/1.1 200 OK\r\n"
        # response_body = self.pac_conf.replace('\n','\r\n')
        response_headers = "Server: Microsoft-HTTPAPI/2.0\r\nContent-Type: application/x-ns-proxy-autoconfig\r\nContent-Length: {}\r\n".format(
            len(self.pac_conf.encode('utf-8')))
        response = response_start_line + response_headers + "\r\n" + self.pac_conf

        # 向客户端返回响应数据
        client_socket.send(bytes(response, "utf-8"))

        # 关闭客户端连接
        client_socket.close()

    def pac_web_server(self):
        """
        开启pac web 服务
        """
        server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server_socket.bind(("", 18001))
        server_socket.listen(128)

        print('开始pac运行服务')
        while True:
            client_socket, client_address = server_socket.accept()
            logging.debug("[%s, %s]请求" % client_address)
            _thread.start_new_thread(self.handle_client, (client_socket, ))

    def set_proxy(self, op):
        if op == 'Off':
            disable_proxy()
        else:
            if op == 'ProxyOnly':
                set_proxy_server('127.0.0.1:10809')
            elif op == 'PacOnly':
                set_proxy_auto('http://127.0.0.1:18001/')
Exemple #5
0
 def unzip(self, src_file, out_dir):
     _thread.start_new_thread(self.__unzip, (abspath(join(common.project_path(), src_file))
                                             , abspath(join(common.project_path(), out_dir))))
Exemple #6
0
class Setting(QObject):
    """
    软件设置
    """
    yaml_path = os.path.join(common.project_path(), "setting.yaml")
    program_path = sys.argv[0]
    futility_signal = pyqtSignal()
    settings = {
        'autostarts': 1,
        'lang': 1,
        'opacity': 0.98,
        'service': 'MysqlServer56',
        'top': False,
        'block_size': 2,
        'init': True,
        'log': True,
        'autostart': False,
        'listenurl': False,
        'listenkeyboard': False,
        'window_width': 850,
        'window_height': 600,
    }

    def __init__(self, parent=None):
        super().__init__(parent)
        self.background_run_param = False
        exists = os.path.exists(self.yaml_path)
        if not exists:
            self.save_cfg()

        with open(self.yaml_path, "r", encoding="utf-8") as f:
            self.settings = yaml.load(f)

    def save_cfg(self):
        with open(self.yaml_path, "w", encoding="utf-8") as f:
            yaml.dump(self.settings, f, default_flow_style=False)

    @pyqtProperty(bool, notify=futility_signal)
    def background_run(self):
        return self.background_run_param

    @pyqtProperty(int, notify=futility_signal)
    def lang(self):
        return self.settings['lang']

    @lang.setter
    def lang(self, val):
        self.settings['lang'] = val
        self.save_cfg()

    @pyqtProperty(float, notify=futility_signal)
    def opacity(self):
        return self.settings['opacity']

    @opacity.setter
    def opacity(self, val):
        self.settings['opacity'] = val
        self.save_cfg()

    @pyqtProperty(int, notify=futility_signal)
    def autostarts(self):
        return self.settings['autostarts']

    @autostarts.setter
    def autostarts(self, val):
        self.settings['autostarts'] = val
        self.save_cfg()

    @pyqtProperty(str, notify=futility_signal)
    def service(self):
        return self.settings['service']

    @service.setter
    def service(self, val):
        self.settings['service'] = val
        self.save_cfg()

    @pyqtProperty(bool, notify=futility_signal)
    def top(self):
        return self.settings['top']

    @top.setter
    def top(self, val):
        self.settings['top'] = val
        self.save_cfg()
    
    @pyqtProperty(bool, notify=futility_signal)
    def listenurl(self):
        return self.settings['listenurl']

    @listenurl.setter
    def listenurl(self, val):
        self.settings['listenurl'] = val
        self.save_cfg()
    
    @pyqtProperty(bool, notify=futility_signal)
    def listenkeyboard(self):
        return self.settings['listenkeyboard']

    @listenkeyboard.setter
    def listenkeyboard(self, val):
        self.settings['listenkeyboard'] = val
        self.save_cfg()

    @pyqtProperty(bool, notify=futility_signal)
    def init(self):
        return self.settings['init']

    @init.setter
    def init(self, val):
        self.settings['init'] = val
        self.save_cfg()

    @pyqtProperty(bool, notify=futility_signal)
    def autostart(self):
        return self.settings['autostart']

    @autostart.setter
    def autostart(self, val):
        self.settings['autostart'] = val
        self.save_cfg()
        # 设置开机自启动
        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Run",
                             access=winreg.KEY_WRITE)
        if val:
            winreg.SetValueEx(key, "ZTool", 0, winreg.REG_SZ, '"{0}" background'.format(self.program_path))
        else:
            try:
                winreg.DeleteValue(key, "ZTool")
            except:
                pass

    @pyqtProperty(int, notify=futility_signal)
    def window_width(self):
        return self.settings['window_width']

    @window_width.setter
    def window_width(self, val):
        self.settings['window_width'] = val
        self.save_cfg()

    @pyqtProperty(int, notify=futility_signal)
    def window_height(self):
        return self.settings['window_height']

    @window_height.setter
    def window_height(self, val):
        self.settings['window_height'] = val
        self.save_cfg()
class MysqlServiceManager(QObject):
    """
    Mysql服务管理
    """
    statusSignal = pyqtSignal(str, arguments=['status'])
    pwdSignal = pyqtSignal(str, arguments=['status'])
    mysql_dir_path = abspath(join(common.project_path(), 'mysql'))
    mysqld_name = 'mysqlddkw.exe'

    def __init__(self, parent=None):
        super().__init__(parent)
        self.cf = mysql_configuration_instance.cf
        self.setting = setting_instance
        self.new_pwd = None
        self.rboot = None
        _thread.start_new_thread(self.status_update_thread, ())

    @pyqtSlot(result=str, name='installService')
    def install_service(self):
        """
        安装mysql服务
        """
        cmd = '\"{0}\" --install{1} {2} --defaults-file=\"{3}\"'.format(
            join(self.mysql_dir_path, 'bin', self.mysqld_name),
            ('' if self.setting.settings['autostarts'] == 1 else '-manual'),
            self.setting.settings['service'],
            join(self.mysql_dir_path, 'my.ini'))
        logging.debug('install mysql cmd:{}'.format(cmd))
        tmp = os.popen(cmd).readlines()
        tmp = "".join(tmp).lower()
        if tmp.find('successfully') != -1:
            return 'ok'
        elif tmp.find('already exists') != -1:
            return 'exists'
        else:
            return 'error'

    @pyqtSlot(result=str, name='uninstallService')
    def uninstall_service(self):
        """
        卸载mysql服务
        """
        cmd = '\"{0}\" --remove {1}'.format(
            join(self.mysql_dir_path, 'bin', self.mysqld_name),
            self.setting.settings['service'])
        logging.debug('uninstall mysql cmd:{}'.format(cmd))
        tmp = os.popen(cmd).readlines()
        tmp = "".join(tmp).lower()
        if tmp.find('success') != -1:
            return 'ok'
        else:
            return 'error'

    @pyqtSlot(str, str, result=str, name='modifiedPassword')
    def modified_password(self, newp, rboot):
        """
        强制修改mysql密码
        """
        self.new_pwd = newp
        self.rboot = rboot
        _thread.start_new_thread(self.skip_pwd_start_service, ())

        return 'ok'

    @pyqtSlot(result=str, name='startService')
    def start_service(self):
        """
        启动mysql服务
        """
        cmd = 'sc start ' + self.setting.settings['service']
        logging.debug('start mysql cmd:{}'.format(cmd))
        tmp = os.popen(cmd).readlines()
        tmp = "".join(tmp).lower()
        if tmp.find('start_pending') != -1:
            return 'ok'
        else:
            return 'error'

    def skip_pwd_start_service(self):
        """
        跳过密码启动mysql服务
        """
        self.kill_progress()

        cmd = '\"{0}\" --defaults-file=\"{1}\" --skip-grant-tables'.format(
            join(self.mysql_dir_path, 'bin', self.mysqld_name),
            join(self.mysql_dir_path, 'my.ini'))
        os.popen(cmd)
        logging.debug('modified mysql password cmd:{}'.format(cmd))
        try_count = 0
        successed = False
        while True:
            try:
                try_count += 1
                connect = pymysql.connect(host='127.0.0.1',
                                          port=3309,
                                          user='******',
                                          passwd='123',
                                          db='mysql',
                                          charset='utf8')
                cursor = connect.cursor()
                sql = 'update mysql.user set Password=password(\'{0}\') where User=\'root\';'.format(
                    self.new_pwd)
                # 执行SQL语句
                cursor.execute(sql)
                connect.commit()
                successed = True
                self.kill_progress()
                if self.rboot == '1':
                    self.start_service()
                break
            except:
                logging.debug("try connect mysql fail")
            if try_count == 3:
                break
        self.pwdSignal.emit('ok' if successed else 'false')

    @pyqtSlot(result=str, name='stopService')
    def stop_service(self):
        """
        停止mysql服务
        """
        cmd = 'sc stop ' + self.setting.settings['service']
        logging.debug('stop mysql cmd:{}'.format(cmd))
        tmp = os.popen(cmd).readlines()
        tmp = "".join(tmp).lower()
        if tmp.find('stop_pending') != -1:
            return 'ok'
        else:
            return 'error'

    @pyqtSlot(result=str, name='killProgress')
    def kill_progress(self):
        """
        强制停止进程
        """
        status = common.kill_progress(self.mysqld_name)
        if status:
            return 'ok'
        else:
            return 'error'

    @pyqtSlot(result=str, name='statusService')
    def status_service(self):
        """
        获取mysql服务状态
        """
        cmd = 'sc query ' + self.setting.settings['service']
        tmp = os.popen(cmd).readlines()
        tmp = "".join(tmp).lower()
        if tmp.find('stopped') != -1:
            return 'stopped'
        elif tmp.find('1060') != -1:
            return 'notfound'
        elif tmp.find('running') != -1:
            return 'running'
        elif tmp.find('stop_pending') != -1:
            return 'stopPending'
        elif tmp.find('start_pending') != -1:
            return 'startPending'
        else:
            return 'error'

    def status_update_thread(self):
        """
        会阻塞线程,开启新线程启动
        """
        while True:
            mysql_configuration_instance.sel_exist_mysql()
            if mysql_configuration_instance.mysql_exist:
                status = self.status_service()
            else:
                status = 'notExist'
            self.statusSignal.emit(status)
            time.sleep(0.5)
Exemple #8
0
class Wechat(QObject):
    """
    微信机器人控制器
    """
    futility_signal = pyqtSignal()
    websocket_client = None

    jobs_path = abspath(join(common.project_path(), 'jobs'))
    userListSignal = pyqtSignal(QVariant, arguments=['userList'])
    wechatLogSignal = pyqtSignal(str, arguments=['log'])
    websocketStateSignal = pyqtSignal(bool, arguments=['state'])
    websocketOnline = False
    jobs_conf = None
    jobExedSignal = pyqtSignal(str, arguments=['job_id'])
    hookStateSignal = pyqtSignal(str, arguments=['state'])
    weather_template = '晚上好呀!下面是明天的天气情况[吃瓜]\n\n你的城市:{city_name}\n天气:{tomorrow_text}\n温度:{tomorrow_temp}\n风向:{tomorrow_wind}\n贴心提示:{tomorrow_dress_tips}\n运动:{tomorrow_sport_tips}\n紫外线:{tomorrow_ua_tips}\n预测时间:{update_time}\n\nONE.一个:{one}'

    def __init__(self, parent=None):
        super().__init__(parent)
        
    
    @pyqtSlot(name='initScheduler')
    def init_scheduler(self):
        self.scheduler = BackgroundScheduler()
        self.scheduler.start()

        # 加载存储的节点
        try:
            with open(self.jobs_path, "rb") as f:
                self.jobs_conf = pickle.load(f)
        except:
            self.jobs_conf = []
        # 初始化执行定时器
        self.__reset_scheduler()

    def sync_request(self,url):
        req_count = 0
        while req_count < 10:
            try:
                return requests.get(url, timeout=10, headers={"content-type": "application/json"})
            except:
                req_count += 1
        
        return None
    
    @pyqtSlot(name='hook')
    def hook(self):
        _thread.start_new_thread(self.__hook, ())

    def __hook(self):
        PAGE_READWRITE = 0x00000040
        PROCESS_ALL_ACCESS =  (0x000F0000|0x00100000|0xFFF)
        VIRTUAL_MEM = (0x00001000 | 0x00002000)
        dll_path = bytes((os.path.abspath('.')+"\\version2.9.0.123-4.5.7.71.dll").encode('utf-8'))
        print(dll_path)
        dll_len = len(dll_path)
        kernel32 = ctypes.windll.kernel32
        wechat_path = ''
        #第一步获取整个系统的进程快照
        pids = psutil.pids()
        #第二步在快照中去比对进程名
        for pid in pids:
            p= psutil.Process(pid)
            try:
                if p.name()=='WeChat.exe':
                    wechat_path = p.cwd()
                    break
                else:
                    pid = 0
            except:
                pass
        #第三步用找到的pid去打开进程获取到句柄
        if pid == 0:
            self.hookStateSignal.emit('NOT_FOUND_WECHAT')
        else:
            h_process=kernel32.OpenProcess(PROCESS_ALL_ACCESS,False,(pid))
            if not h_process:
                self.hookStateSignal.emit('ERROR')
                return
            else:
                arg_adress=kernel32.VirtualAllocEx(h_process,None,dll_len*10,VIRTUAL_MEM,PAGE_READWRITE)
                NULL = c_int(0)
                kernel32.WriteProcessMemory(h_process,arg_adress,dll_path,dll_len*10,NULL)
                h_kernel32 = win32api.GetModuleHandle("kernel32.dll")
                h_loadlib = win32api.GetProcAddress(h_kernel32, 'LoadLibraryA')
                thread_id = c_ulong(0)
                c_remt = kernel32.CreateRemoteThread(h_process,None,0,c_long(h_loadlib),arg_adress,0,byref(thread_id))
                self.hookStateSignal.emit('SUCCESS')

    def get_weather(self, job):
        req_count = 0
        res = self.sync_request('https://geoapi.qweather.net/v2/city/lookup?location={}&key={}'.format(
                    job['location'],setting_instance.settings['qweather_key']))

        city_name = None
        if res is not None:
            res_content = res.content.decode()
            print(res_content)
            json_res = json.loads(res_content)
            city_name = json_res['location'][0]['name']

        req_count = 0
        res = self.sync_request('https://api.qweather.net/v7/weather/3d?location={}&key={}'.format(
                    job['location'],setting_instance.settings['qweather_key']))

        tomorrow_text = None
        tomorrow_temp = None
        tomorrow_wind = None
        update_time = None
        if res is not None:
            res_content = res.content.decode()
            print(res_content)
            json_res = json.loads(res_content)
            update_time = json_res['updateTime']
            tomorrow_text = json_res['daily'][1]['textDay']
            tomorrow_temp = json_res['daily'][1]['tempMin'] + \
                '~' + json_res['daily'][1]['tempMax']
            tomorrow_wind = json_res['daily'][1]['windDirDay'] + \
                json_res['daily'][1]['windScaleDay'] + '级'

        print('update_time:{},tomorrow_text:{},tomorrow_temp:{},tomorrow_wind:{}'.format(
            update_time, tomorrow_text, tomorrow_temp, tomorrow_wind))

        req_count = 0
        res = self.sync_request('https://api.qweather.net/v7/indices/3d?location={}&type=1,3,5&key={}'.format(
                    job['location'],setting_instance.settings['qweather_key']))

        tomorrow_dress_tips = None
        tomorrow_sport_tips = None
        tomorrow_ua_tips = None
        if res is not None:
            res_content = res.content.decode()
            print(res_content)
            json_res = json.loads(res_content)
            tomorrow_sport_tips = json_res['daily'][3]['text']
            tomorrow_dress_tips = json_res['daily'][4]['text']
            tomorrow_ua_tips = json_res['daily'][5]['text']

        print('tomorrow_dress_tips:{},tomorrow_sport_tips:{},tomorrow_ua_tips:{}'.format(
            tomorrow_dress_tips, tomorrow_sport_tips, tomorrow_ua_tips))

        # 获取ONE
        one = common.get_wufazhuce_info()
        result = self.weather_template.format(tomorrow_text=tomorrow_text, tomorrow_temp=tomorrow_temp, tomorrow_wind=tomorrow_wind, tomorrow_dress_tips=tomorrow_dress_tips,
                                              tomorrow_sport_tips=tomorrow_sport_tips, tomorrow_ua_tips=tomorrow_ua_tips, update_time=update_time, city_name=city_name, one=one)
        return result

    def __job_task(self, job):
        self.jobExedSignal.emit(job['job_id'])
        msg = None
        if job['msg_type'] == 'weather':
            msg = self.get_weather(job)
        elif job['msg_type'] == 'text':
            msg = job['msg']
        json_msg = {
            'id': self._getid(),
            'type': 555,
            'content': msg,
            'wxid': job['wxid']
        }
        if self.websocketOnline:
            self.ws.send(json.dumps(json_msg))

    def __reset_scheduler(self):
        self.scheduler.remove_all_jobs()
        for index, item in enumerate(self.jobs_conf):
            if item['job_enable']:
                if item['trigger'] == 'interval':
                    self.scheduler.add_job(self.__job_task, 'interval', coalesce=True, misfire_grace_time=3600, weeks=int(item['weeks']), days=int(item['days']), hours=int(
                        item['hours']), minutes=int(item['minutes']), seconds=int(item['seconds']), jitter=int(item['jitter']), id=item['job_id'], args=[item])
                elif item['trigger'] == 'cron':
                    self.scheduler.add_job(self.__job_task, 'cron', coalesce=True, misfire_grace_time=3600, second=item['second'], minute=item[
                                           'minute'], hour=item['hour'], day_of_week=item['day_of_week'], jitter=int(item['jitter']), id=item['job_id'], args=[item])

    @pyqtSlot(QVariant, name='addJob')
    def add_job(self, job):
        job = job.toVariant()
        job['job_id'] = self._getid()
        self.jobs_conf.append(job)
        self._save_conf()
        self.__reset_scheduler()

    @pyqtSlot(QVariant, name='editJob')
    def edit_job(self, job):
        job = job.toVariant()
        for index, item in enumerate(self.jobs_conf):
            if item['job_id'] == job['job_id']:
                self.jobs_conf[index] = job
        self._save_conf()
        self.__reset_scheduler()

    @pyqtSlot(str, name='delJob')
    def del_job(self, job_id):
        job_index = 0
        for index, item in enumerate(self.jobs_conf):
            if item['job_id'] == job_id:
                job_index = index
        self.jobs_conf.pop(job_index)
        self._save_conf()
        self.__reset_scheduler()

    @pyqtSlot(name='getJobsConf', result=QVariant)
    def get_jobs_conf(self):
        return self.jobs_conf

    @pyqtSlot(name='getJobsState', result=QVariant)
    def get_jobs_state(self):
        jobs = self.scheduler.get_jobs()
        jobs_state = {}
        for job in jobs:
            jobs_state[job.id] = datetime_repr(job.next_run_time)
        return jobs_state

    def _save_conf(self):
        with open(self.jobs_path, "wb") as jf:
            pickle.dump(self.jobs_conf, jf)

    def _getid(self):
        id = str(int(time.time() * 1000))
        return id

    @pyqtSlot(name='getUserList')
    def get_user_list(self):
        if self.websocketOnline:
            self.ws.send(
                '{"id":"1231231236","type":5000,"content":"user list","wxid":"null"}')

    @pyqtSlot(str, str, name='sendMessage')
    def send_message(self, wxid, msg):
        logging.debug("发送消息,wxid:{0},msg:{1}".format(wxid, msg))
        json_msg = {
            'id': self._getid(),
            'type': 555,
            'content': msg,
            'wxid': wxid
        }
        if self.websocketOnline:
            self.ws.send(json.dumps(json_msg))

    @pyqtSlot(name='websocketInit')
    def websocket_init(self):
        if self.websocketOnline:
            self.ws.close()
        _thread.start_new_thread(self._websocket_init, ())

    def _websocket_init(self):
        self.ws = websocket.WebSocketApp('ws://127.0.0.1:5555',
                                         on_open=self.on_open,
                                         on_message=self.on_message,
                                         on_error=self.on_error,
                                         on_close=self.on_close)
        self.ws.run_forever()

    def on_message(self, message):
        logging.debug('wechat msg:{0}'.format(message))
        json_message = json.loads(message)
        self.wechatLogSignal.emit(message)

        if json_message['type'] == 5000:
            self.userListSignal.emit(json_message)

    def on_error(self, error):
        print("on_error")

    def on_open(self):
        print("on_open")
        self.websocketOnline = True
        self.websocketStateSignal.emit(True)

    def on_close(self):
        print("on_close")
        self.websocketOnline = False
        self.websocketStateSignal.emit(False)
Exemple #9
0
 def open_dir(self, file_path):
     if file_path.find(':') != -1:
         common.open_dir(abspath(file_path))
     else:
         common.open_dir(abspath(join(common.project_path(), file_path)))
Exemple #10
0
class Aria2(QObject):
    """
    下载控制器
    """
    processSignal = pyqtSignal(QVariant, arguments=['process'])
    taskStateSignal = pyqtSignal(str, QVariant, arguments=['gid', 'process'])
    msgSignal = pyqtSignal(str, arguments=['msg'])
    flagMsgSignal = pyqtSignal(str,
                               str,
                               str,
                               arguments=['msg', 'flag', 'taskId'])
    aria2StopedSignal = pyqtSignal()
    listenerUrl = pyqtSignal(str, arguments=['url'])
    aria2_path = abspath(join(common.project_path(), 'aria2', 'aria2c.exe'))
    default_config = {
        # 文件的保存路径(可使用绝对路径或相对路径), 默认: 当前启动位置
        'dir': 'aria2/Download',
        # 启用磁盘缓存, 0为禁用缓存, 需1.16以上版本, 默认:16M
        'disk-cache': '32M',
        # 文件预分配方式, 能有效降低磁盘碎片, 默认:prealloc
        # 预分配所需时间: none < falloc < trunc < prealloc
        # NTFS建议使用falloc
        'file-allocation': 'none',
        # 断点续传
        'continue': 'true',
        # 最大同时下载任务数, 运行时可修改, 默认:5
        'max-concurrent-downloads': '5',
        # 同一服务器连接数, 添加时可指定, 默认:1
        'max-connection-per-server': '16',
        # 最小文件分片大小, 添加时可指定, 取值范围1M -1024M, 默认:20M
        # 假定size=10M, 文件为20MiB 则使用两个来源下载; 文件为15MiB 则使用一个来源下载
        'min-split-size': '1M',
        # 单个任务最大线程数, 添加时可指定, 默认:5
        'split': '100',
        # 整体上传速度限制, 运行时可修改, 默认:0
        'max-overall-upload-limit': '1M',
        # 禁用IPv6, 默认:false
        'disable-ipv6': 'true',
        # 从会话文件中读取下载任务
        'input-file': 'aria2/aria2.session',
        # 在Aria2退出时保存`错误/未完成`的下载任务到会话文件
        'save-session': 'aria2/aria2.session',
        # 定时保存会话, 0为退出时才保存, 需1.16.1以上版本, 默认:0
        'save-session-interval': '60',
        # 启用RPC, 默认:false
        'enable-rpc': 'true',
        # rpc端口
        'rpc-listen-port': '6800',
        # 允许所有来源, 默认:false
        'rpc-allow-origin-all': 'true',
        # 允许非外部访问, 默认:false
        'rpc-listen-all': 'true',
    }

    def __init__(self, parent=None):
        super().__init__(parent)
        self.popen = None
        # 启动aria2
        _thread.start_new_thread(self.start_aria2, ())

        # 启动监听剪贴板
        _thread.start_new_thread(self.listener_paste, ())

    @pyqtSlot(str, name='openDir')
    def open_dir(self, file_path):
        if file_path.find(':') != -1:
            common.open_dir(abspath(file_path))
        else:
            common.open_dir(abspath(join(common.project_path(), file_path)))

    def start_aria2(self):
        """
        启动aria2 需要开启新线程启动,会阻塞
        """
        # 干掉上次的aria2进程
        common.kill_progress('aria2c.exe')

        args = []
        for item in self.default_config.items():
            args.append('--' + item[0] + '=' + item[1])

        args.insert(0, self.aria2_path)
        popen = subprocess.Popen(
            args,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            # bufsize=1,
            creationflags=subprocess.CREATE_NO_WINDOW)
        self.popen = popen
        # 重定向标准输出 None表示正在执行中
        while popen.poll() is None:
            r = popen.stdout.readline().decode('utf8')
            if r.replace('\r', '').replace('\n', '').strip(' ') != '':
                logging.debug(r.replace('\n', ''))

    @pyqtSlot(name='stopAria2')
    def stop_aria2(self):
        """
        停止aria2 子进程
        """
        _thread.start_new_thread(self.__stop_aria2, ())

    def __stop_aria2(self):
        aria2 = Aria2RPC()
        aria2.saveSession()
        if self.popen is not None:
            self.popen.kill()
        self.aria2StopedSignal.emit()

    @pyqtSlot(str, QVariant, name='addTask')
    def add_task(self, url, options=None):
        """
        添加任务
        :param url: 文件地址
        :param options: 可选项
        """
        _thread.start_new_thread(self.__add_task, (url, options, None))

    @pyqtSlot(str, str, name='addFlagTask')
    def add_flag_task(self, url, flag, options=None):
        """
        添加任务
        :param flag: 标志
        :param url: 文件地址
        :param options: 可选项
        """
        _thread.start_new_thread(self.__add_task, (url, options, flag))

    def __add_task(self, url, options, flag):
        aria2 = Aria2RPC()
        if options is None:
            options = {}
        else:
            options = options.toVariant()

        try:
            id = aria2.addUri([url], options=options)
            if flag is None:
                self.msgSignal.emit("addSuccess")
            else:
                self.flagMsgSignal.emit("addSuccess", flag, id)

        except:
            if flag is None:
                self.msgSignal.emit("addFail")
            else:
                self.flagMsgSignal.emit("addFail", flag, None)

    @pyqtSlot(str, name='pauseTask')
    def pause_task(self, gid):
        """
        暂停任务
        :param gid: 主键
        """
        _thread.start_new_thread(self.__pause_task, (gid, ))

    def __pause_task(self, gid):
        aria2 = Aria2RPC()
        try:
            aria2.pause(gid)
            self.msgSignal.emit("pauseSuccess")
        except:
            self.msgSignal.emit("pauseFail")

    @pyqtSlot(str, name='unpauseTask')
    def start_task(self, gid):
        """
        开始任务
        :param gid: 主键
        """
        _thread.start_new_thread(self.__start_task, (gid, ))

    def __start_task(self, gid):
        aria2 = Aria2RPC()
        try:
            aria2.unpause(gid)
            self.msgSignal.emit("startSuccess")
        except:
            self.msgSignal.emit("startFail")

    @pyqtSlot(str, name='removeTask')
    def remove_task(self, gid):
        """
        删除任务
        :param gid: 主键
        """
        _thread.start_new_thread(self.__remove_task, (gid, ))

    def __remove_task(self, gid):
        aria2 = Aria2RPC()
        try:
            aria2.remove(gid)
            self.msgSignal.emit("removeSuccess")
        except:
            self.msgSignal.emit("removeFail")

    @pyqtSlot(name='selTask')
    def sel_task(self):
        """
        查询当前任务的状态
        """
        _thread.start_new_thread(self.__sel_task, ())

    @pyqtSlot(str, name='selTaskById')
    def sel_task_id(self, gid):
        """
        查询任务的状态
        """
        _thread.start_new_thread(self.__sel_task_id, (gid, ))

    def __sel_task_id(self, gid):
        aria2 = Aria2RPC()
        file_state = aria2.getFiles(gid)
        self.taskStateSignal.emit(gid, QVariant(file_state))

    def __sel_task(self):
        aria2 = Aria2RPC()
        res = aria2.multicall([{
            'methodName': 'aria2.getGlobalStat'
        }, {
            'methodName': 'aria2.tellActive'
        }, {
            'methodName': 'aria2.tellWaiting',
            'params': [0, 1000]
        }, {
            'methodName': 'aria2.tellStopped',
            'params': [0, 1000]
        }])
        self.processSignal.emit(QVariant(res))

    def listener_paste(self):
        """
        监听剪贴板
        """
        recent_value = ''
        while True:
            try:
                tmp_value = pyperclip.paste()  # 读取剪切板复制的内容
                if tmp_value != recent_value:  # 如果检测到剪切板内容有改动,那么就进入文本的修改
                    recent_value = tmp_value
                    if recent_value.startswith(
                            'http://') or recent_value.startswith('https://'):
                        logging.debug("发现链接:" + recent_value)
                        self.listenerUrl.emit(recent_value)
            except:
                pass
            time.sleep(0.1)