aboutsummarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorfelinae982020-04-12 00:04:52 +0800
committerfelinae982020-04-12 00:04:52 +0800
commit07997a3643a0d85c2b7a3e584be9b5fe5f4cba21 (patch)
tree3c6f22187feea2e85499192872e3b9ab39eced6a
downloadaur-07997a3643a0d85c2b7a3e584be9b5fe5f4cba21.tar.gz
init
-rw-r--r--.SRCINFO16
-rw-r--r--.gitignore3
-rw-r--r--PKGBUILD17
-rw-r--r--README.md37
-rwxr-xr-xclashup133
-rw-r--r--clashup.conf3
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