madwind / flexget_qbittorrent_mod

flexget qbittorrent删种、辅种 自动签到 插件
MIT License
552 stars 117 forks source link

修复了一些遇到的 bug #16

Closed luyiming closed 3 years ago

luyiming commented 3 years ago
  1. 北邮人前两天重新开站,url 改为 https://byr.pt/
  2. hdtime 有签到功能,改为继承自 Attendance
  3. 在 auto_sign_in sites yml 结构下,添加了 proxy 和 no_proxy 的选项,no_proxy 主要用于像 GGn 这类不允许代理访问的站点,proxy 可用于 u2, filelist 这类需要代理访问的站点
  4. 给 auto_sign_in 插件新增了 details_report_path 的属性,默认是 details_report.png,不影响原有的 yml 配置文件
  5. 给 telegram_mod 插件的 image 属性加了一个 warning:如果使用的图片是相对路径,在 daemon 模式下会报错,因为 daemon 模式下 flexget 会把当前目录改为根目录,如果是相对路径的话,图片路径就变成了 /details_report.png;目前没找到比较好的办法来解决这个问题,只能建议 image 属性用绝对路径。
madwind commented 3 years ago

有2个问题

  1. 关于代理这个问题,我不是很清楚python的机制怎么样的,如果设置了全局代理,我觉得用户应该为自己的行为负责,自行调整黑白名单。否者会不会影响其它任务?所以要配置代理的话,应该只需要一个proxy配置就好。 2.相对路径的问题 我也不是很理解,当前配置 details_report.png 也算是个相对路径,那是不是也会收到warning? docker中运行的一直都是daemon模式,不知道你说的报错是哪里产生的,以及修改 details_report_path 的原因
luyiming commented 3 years ago

抱歉前几天太忙了没回复。 一般来说,命令行程序走不走代理是通过 HTTP_PROXY, HTTPS_PROXY, NO_PROXY 这类环境变量来控制的,也就是如果不设置环境变量的话,命令行程序一般是不走代理的,但是我发现 requests 库好像不仅仅这样,我稍微研究了下。

requests 走代理的判断逻辑主要在 requests/session.py::701

def merge_environment_settings(self, url, proxies, stream, verify, cert):
    """
    Check the environment and merge it with some settings.

    :rtype: dict
    """
    # Gather clues from the surrounding environment.
    if self.trust_env:
        # Set environment's proxies.
        no_proxy = proxies.get('no_proxy') if proxies is not None else None
        env_proxies = get_environ_proxies(url, no_proxy=no_proxy)
        for (k, v) in env_proxies.items():
            proxies.setdefault(k, v)

        # Look for requests environment configuration and be compatible
        # with cURL.
        if verify is True or verify is None:
            verify = (os.environ.get('REQUESTS_CA_BUNDLE') or
                        os.environ.get('CURL_CA_BUNDLE'))

    # Merge all the kwargs.
    proxies = merge_setting(proxies, self.proxies)
    stream = merge_setting(stream, self.stream)
    verify = merge_setting(verify, self.verify)
    cert = merge_setting(cert, self.cert)

    return {'verify': verify, 'proxies': proxies, 'stream': stream,
            'cert': cert}

其中 get_environ_proxies(url, no_proxy=no_proxy) 函数最终会调用 getproxies() 来获取代理配置,在 macOS 上它是:

def getproxies():
    return getproxies_environment() or getproxies_macosx_sysconf()

在 windows 上它是:

def getproxies():
    """Return a dictionary of scheme -> proxy server URL mappings.

    Returns settings gathered from the environment, if specified,
    or the registry.

    """
    return getproxies_environment() or getproxies_registry()

所以 requests 不仅会受 *_PROXY 这类环境变量控制,还会读取代理软件设置的系统代理配置。所以要不走代理,看起来设置 trust_env=False 是最直接的。这样子也不会对别的程序造成影响。说起来感觉 no_proxy 确实不太必要,我就是担心自己犯蠢一不小心走了代理啥的 233

luyiming commented 3 years ago

关于第二个问题,当前配置 details_report.png 确实是相对路径,但是我代码里是有处理的, details_report.py::227

            if not os.path.isabs(details_report_path):
                details_report_path = os.path.join(task.manager.config_base, details_report_path)
            img.save(details_report_path)

这也是参考了 flexget 一些内置插件的做法,在创建 report 的时候,我是可以获取到代码运行目录的,所以相对路径我可以手动给它拼接起来,但是在 telegram mod 里面,我没有办法获取到代码运行目录,所以就没办法处理相对路径问题。 至于 docker 运行没出问题,我猜是因为你的 docker 默认 CWD 路径就是根目录?

luyiming commented 3 years ago

flexget 处理 daemon 的代码在 flexget/manager.py

def daemonize(self) -> None:
    """Daemonizes the current process. Returns the new pid"""
    if sys.platform.startswith('win'):
        logger.error('Cannot daemonize on windows')
        return
    if threading.active_count() != 1:
        logger.critical(
            'There are {!r} active threads. Daemonizing now may cause strange failures.',
            threading.enumerate(),
        )

    logger.info('Daemonizing...')

    try:
        pid = os.fork()
        if pid > 0:
            # Don't run the exit handlers on the parent
            atexit._exithandlers = []
            # exit first parent
            sys.exit(0)
    except OSError as e:
        sys.stderr.write(f'fork #1 failed: {e.errno} ({e.strerror})\n')
        sys.exit(1)

    # decouple from parent environment
    os.chdir('/')
    os.setsid()
    os.umask(0)
...

可以看到它在 daemon 模式会设置当前路径为根目录 /

madwind commented 3 years ago

那其实这个行为就是使用系统代理,很多软件都有类似的行为。总的来说,还是用户的代理设置问题,而且我觉得大多数还是路由级别的代理,这个设置,只能说防止本机的代理软件吧。所以docker化可以避免很多不必要的麻烦。 不过既然有这样的需求,那改一下代码 if 'no_proxy' in entry['site_config']: 最好改成 entry['site_config'].get('no_proxy') 不然 yes 和 no 就没什么意义,临时变量的还原放在finally 至于details_report.png,docker启动是没有加 -d 参数的 也没有必要,所以它不会执行 daemonize 。按我的理解,既然cwd被改成 / 那telegram_mod也应该是去 / 找文件。为什么会出现找不到的情况? 针对这样的情况的话,我认为有2种方式处理

  1. 检测是否为 -d (daemonize) 启动 才发出警告,不过不知道有没有办法检测
  2. 生成 details_report.png 的时候,保存路径到系统环境变量

我比较倾向第二种,details_report.png 只相当于一个临时文件,除非发送失败,不然保存的意义不大,用作配置感觉有些多余