예제 #1
0
class Configure:
    conf = None
    pixiv = None
    notice = None
    core = None

    def __init__(self, conf):
        self.conf = conf
        if conf is None:
            raise Exception("Conf缺失。")
        if isinstance(conf, str):
            try:
                self.conf = json.loads(conf)
            except Exception:
                raise Exception("Conf不是合法的JSON结构。")
        self.initialize_notice()
        self.initialize_core()
        self.initialize_pixiv()

    def initialize_notice(self):
        log_file = self.conf.get("log", None)
        if log_file is not None:
            log_notice = OutputToFile(log_file)
            self.notice = Notice(log_notice, log_notice)
        else:
            self.notice = Notice()

    def initialize_core(self):
        proxy = self.conf.get("proxy", True) is True
        self.core = Core(use_proxy=proxy)

    def initialize_pixiv(self):
        self.pixiv = Pixiv(core=self.core, notice=self.notice)
        if "account" in self.conf:
            username = self.conf["account"].get("username", None)
            password = self.conf["account"].get("password", None)
            if username is None:
                raise Exception("Conf JSON缺失结构'account.username'。")
            if password is None:
                raise Exception("Conf JSON缺失结构'account.password'。")
            self.pixiv.login(username, password)
        else:
            raise Exception("Conf JSON缺失结构'account'。")

    def run(self):
        content = self.conf.get("content", [])
        for c in content:
            if c.get("enabled", True):
                if "save" not in c:
                    raise Exception("无法找到启动配置的存储路径配置(save)。")
                if "uid" in c:
                    self.run_uid(c)
                elif "pid" in c:
                    self.run_pid(c)
                else:
                    raise Exception("无法找到启动配置的特征码(pid/uid/etc.)。")

    def run_uid(self, content):
        uids = content["uid"]
        replace = content.get("replace", False)
        save = content.get("save")
        multi_save = content.get("multi_save", None)
        if isinstance(uids, str) or isinstance(uids, int):
            uids = [uids]
        elif not isinstance(uids, list):
            raise Exception("启动配置的uid不是合法的User ID或其表达式。")
        for uid in uids:
            if isinstance(uid, str):
                u, begin, end = Configure.get_uid_and_range(uid)
                if u is None:
                    raise Exception("启动配置的uid不是合法的User ID或其表达式。")
                self.run_uid_source(u, begin, end, save, multi_save, replace)
            elif isinstance(uid, int):
                self.run_uid_source(uid, None, None, save, multi_save, replace)
            else:
                raise Exception("启动配置的uid不是合法的User ID或其表达式。")

    def run_pid(self, content):
        pids = content["pid"]
        replace = content.get("replace", False)
        save = content.get("save")
        multi_save = content.get("multi_save", None)
        if isinstance(pids, str) or isinstance(pids, int):
            pids = [pids]
        elif not isinstance(pids, list):
            raise Exception("启动配置的pid不是合法的Pixiv ID或其表达式。")
        for pid in pids:
            if isinstance(pid, str):
                matched = re.match(r'([0-9]*)[-: ]([0-9]*)', pid)
                if matched is not None:
                    min_pid, max_pid = matched.groups()
                    for i in range(int(min_pid), int(max_pid) + 1):
                        self.run_pid_source(i, save, multi_save, replace)
                else:
                    try:
                        p = int(pid)
                    except ValueError:
                        raise Exception("启动配置的pid不是合法的Pixiv ID或其表达式。")
                    self.run_pid_source(p, save, multi_save, replace)
            elif isinstance(pid, int):
                self.run_pid_source(pid, save, multi_save, replace)
            else:
                raise Exception("启动配置的pid不是合法的Pixiv ID或其表达式。")

    def run_uid_source(self, uid, begin, end, save, multi_save, replace=False):
        ret = self.pixiv.get_member_image_list(uid=uid, max_count=end)
        if ret is None:
            return
        self.notice.log("||==处理Member ID %s==||" % (uid,))
        head = begin - 1 if begin is not None else 0
        tail = end if end is not None else len(ret)
        for i in range(head, tail):
            pid, title = ret[i]
            self.run_pid_source(pid, save, multi_save, replace, uid=uid)

    def run_pid_source(self, pid, save, multi_save, replace=False, uid=None):
        ret = self.pixiv.get_image_source(pid)
        if ret is None:
            return
        self.notice.log("|==处理Pixiv ID %s==|" % (pid,))
        if len(ret["content"]) == 1 or (len(ret["content"]) > 1 and multi_save is None):
            content, pg_index, extension = ret["content"][0]
            file_path = save.format(title=ret["title"],
                                    pid=ret["pid"],
                                    user=ret["user"],
                                    uid=uid if uid is not None else ret["user_id"]) + "." + extension
            if not os.path.exists(file_path) or replace:
                Configure.make_dir(file_path)
                with open(file_path, 'wb') as f:
                    f.write(content)
            elif not replace:
                self.notice.log("[%s]已存在,跳过。" % (pid,))
        else:
            for content, pg_index, extension in ret["content"]:
                file_path = multi_save.format(title=ret["title"],
                                              pid=ret["pid"],
                                              user=ret["user"],
                                              uid=uid if uid is not None else ret["user_id"],
                                              index=pg_index) + "." + extension
                if not os.path.exists(file_path) or replace:
                    Configure.make_dir(file_path)
                    with open(file_path, 'wb') as f:
                        f.write(content)
                elif not replace:
                    self.notice.log("[%s]已存在,跳过。" % (pid,))

    @staticmethod
    def get_uid_and_range(uid_str):
        matched = re.match(r'([0-9]*)\[([0-9]*)[-: ]([0-9]*)\]', uid_str)
        if matched is not None:
            u, begin, end = matched.groups()
            return int(u), int(begin), int(end)
        else:
            matched = re.match(r'([0-9]*)\[([0-9]*)\]', uid_str)
            if matched is not None:
                u, num = matched.groups()
                return int(u), 1, int(num)
            else:
                try:
                    u = int(uid_str)
                except ValueError:
                    return None, None, None
                return int(u), None, None

    @staticmethod
    def make_dir(filepath):
        split_index = filepath.rfind('/')
        if split_index >= 0:
            dir_path = filepath[:split_index]
            os.makedirs(dir_path, exist_ok=True)

    @staticmethod
    def help():
        return help_text