diff options
author | felinae98 | 2020-04-12 00:04:52 +0800 |
---|---|---|
committer | felinae98 | 2020-04-12 00:04:52 +0800 |
commit | 07997a3643a0d85c2b7a3e584be9b5fe5f4cba21 (patch) | |
tree | 3c6f22187feea2e85499192872e3b9ab39eced6a | |
download | aur-07997a3643a0d85c2b7a3e584be9b5fe5f4cba21.tar.gz |
init
-rw-r--r-- | .SRCINFO | 16 | ||||
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | PKGBUILD | 17 | ||||
-rw-r--r-- | README.md | 37 | ||||
-rwxr-xr-x | clashup | 133 | ||||
-rw-r--r-- | clashup.conf | 3 |
6 files changed, 209 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO new file mode 100644 index 000000000000..f1ea909a83d7 --- /dev/null +++ b/.SRCINFO @@ -0,0 +1,16 @@ +pkgbase = clashup + pkgdesc = auto update clash's config file + pkgver = 0.1 + pkgrel = 3 + arch = any + license = GPL + depends = python + depends = clash + depends = python-requests + source = clashup + source = clashup.conf + md5sums = baaa9b4feb4f5500bad97feb4cc259c7 + md5sums = 177338346005e11d33e27edc1f8ab780 + +pkgname = clashup + diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000000..6e5ec0890804 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +pkg/* +src/* +*.tar.xz
\ No newline at end of file diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 000000000000..832198c1e414 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,17 @@ +# Maintainer: Tang Yuming <felinae225@qq.com> +pkgname=clashup +pkgver=0.1 +pkgrel=3 +pkgdesc="auto update clash's config file" +license=('GPL') +arch=('any') +depends=(python + clash + python-requests) +source=(clashup clashup.conf) +package() { + install -Dm755 clashup ${pkgdir}/usr/bin/clashup + install -Dm644 clashup.conf ${pkgdir}/etc/systemd/user/clash.service.d/clashup.conf +} +md5sums=('baaa9b4feb4f5500bad97feb4cc259c7' + '177338346005e11d33e27edc1f8ab780') diff --git a/README.md b/README.md new file mode 100644 index 000000000000..9957b8a37b77 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# clashup + +An updator for clash on Archlinux + +## Install +`$ git clone https://github.com/felinae98/clashup.git && cd clashup && makepkg -si` + +or use aur + +`tbd` + +and just + +`$ systemctl --user start clash` + +## Config +The config file is `~/.config/clash/clashup.json` +```json +{ + "http_port": 7890, + "socks5_port": 7891, + "redir_port": 7892, + "allow_lan": true, + "external_controller": "127.0.0.1:9090", + "subscribe_url": "", + "is_subscribe_banned": false, + "custom_rules": [] +} +``` +* Set `is_subscribe_banned` true if your subscribe address was banned. +* `http_port` is required if `is_subscribe_banned` is true +## How it works +It just simply download the subscribe config file and override `http-port`, `socks-port`, `redir-port`, `allow-lan`, `external-controller` in the config file, and append `custom_rules` to `Rules`. + +If your can access your subscribe url directly, it just download and update config file before clash start. + +Otherwise your subscribe url is banned, it download and update the config file after clash start and then restart clash.
\ No newline at end of file diff --git a/clashup b/clashup new file mode 100755 index 000000000000..b7010f2a6094 --- /dev/null +++ b/clashup @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 + +import requests +import yaml +import json +import os +import shutil +import logging +import time +import argparse +import subprocess +import hashlib + +logging.basicConfig(format='%(asctime)s %(levelname)s: %(message)s', level=logging.INFO) + +class ClashUp: + + EXAMPLE_CONF = '''{ + "http_port": 7890, + "socks5_port": 7891, + "redir_port": 7892, + "allow_lan": true, + "external_controller": "127.0.0.1:9090", + "subscribe_url": "", + "is_subscribe_banned": false, + "custom_rules": [] +} +''' + def __init__(self): + self.conf_file_path = os.path.expanduser('~/.config/clash/clashup.json') + self.clash_conf_path = os.path.expanduser('~/.config/clash/config.yaml') + self.clash_conf_path_old = os.path.expanduser('~/.config/clash/config.yaml.old') + self.cache_file_path = os.path.expanduser('~/.cache/clashup') + + def load_conf(self): + if not os.path.isfile(self.conf_file_path): + with open(self.conf_file_path, 'w') as f: + f.write(self.EXAMPLE_CONF) + raise OSError('plz edit ~/.config/clash/clashup.json') + with open(self.conf_file_path) as f: + raw_config_text = f.read() + raw_config = json.loads(raw_config_text) + if not raw_config.get('subscribe_url'): + raise ValueError('subscribe_url can not be empty') + self.config = raw_config + hash_item = hashlib.sha256(raw_config_text.encode()) + self.config_hash = hash_item.hexdigest() + + def download(self, use_proxy=False): + if use_proxy: + proxy = { + 'http': 'http://127.0.0.1:{}'.format(self.config['http_port']), + 'https': 'http://127.0.0.1:{}'.format(self.config['http_port']) + } + res = requests.get(self.config['subscribe_url'], timeout=5, proxies=proxy) + else: + res = requests.get(self.config['subscribe_url'], timeout=5) + res.raise_for_status() + raw_clash_conf = yaml.safe_load(res.text) + return raw_clash_conf + + def _load_conf(self, config, local_config_key, config_key): + if local_config_key in self.config: + config[config_key] = self.config[local_config_key] + + def parse_config(self, config): + self._load_conf(config, 'http_port', 'port') + self._load_conf(config, 'socks5_port', 'socks-port') + self._load_conf(config, 'redir_port', 'redir-port') + self._load_conf(config, 'allow_lan', 'allow-lan') + self._load_conf(config, 'external_controller', 'external-controller') + for rule in self.config.get('custom_rules', []): + config['Rule'].append(rule) + return config + + def save(self, config): + if os.path.isfile(self.clash_conf_path): + shutil.move(self.clash_conf_path, self.clash_conf_path_old) + with open(self.clash_conf_path, 'w') as f: + f.write(yaml.safe_dump(config)) + + def update(self, use_proxy): + logging.info('Update Start') + try: + raw_clash_conf = self.download(use_proxy) + parsed_clash_conf = self.parse_config(raw_clash_conf) + self.save(parsed_clash_conf) + logging.info('Update Finish') + except requests.exceptions.RequestException: + logging.warning('Update Fail') + + def update_time_cache(self): + if not os.path.isfile(self.cache_file_path): + self._write_cache() + return True + else: + with open(self.cache_file_path, 'r') as f: + cache_text = f.read().split('-') + last_time = float(cache_text[1]) + if cache_text[0] != self.config_hash or time.time() - last_time > 86400: + self._write_cache() + return True + else: + return False + + def _write_cache(self): + with open(self.cache_file_path, 'w') as f: + f.write('{}-{}'.format(self.config_hash, time.time())) + + def run(self): + parser = argparse.ArgumentParser() + parser.add_argument('--pre', action='store_true') + parser.add_argument('--post', action='store_true') + args = parser.parse_args() + self.load_conf() + if args.pre: + if self.config['is_subscribe_banned']: + logging.info('Subscribe is banned, pass this run') + else: + self.update(False) + elif args.post: + if self.config['is_subscribe_banned']: + if self.update_time_cache(): + self.update(True) + subprocess.run(['systemctl', '--user', 'restart', 'clash']) + else: + logging.info('config file updated in 24h, pass this run') + else: + logging.info('pass this run') + + +if __name__ == '__main__': + ClashUp().run() diff --git a/clashup.conf b/clashup.conf new file mode 100644 index 000000000000..02ef3296594c --- /dev/null +++ b/clashup.conf @@ -0,0 +1,3 @@ +[Service] +ExecStartPre=/usr/bin/clashup --pre +ExecStartPost=/usr/bin/clashup --post
\ No newline at end of file |