├── .gitignore ├── Desensitization.py ├── LICENSE ├── MyRules ├── AI.yaml ├── CustomRulesDirect.yaml ├── CustomRulesProxy.yaml ├── Download.yaml ├── EpicGames.yaml ├── GOG.yaml ├── GeforceExperience.yaml ├── Git.yaml ├── GoogleSearch.yaml ├── UNMProxy.yaml ├── UPlay.yaml └── Video.yaml ├── README.md ├── auto-check-in.js ├── bak ├── genpac.ini ├── genpac_script.bat ├── gfwlist-local ├── parser_v1.0.js ├── parser_v2.0.js └── userrules.txt ├── broprint ├── code │ ├── EncryptDecrypt.js │ ├── GenerateCanvasFingerprint.js │ └── generateTheAudioPrints.js └── index.js ├── glados-checkin.js ├── subconverter ├── base │ └── all_base.tpl ├── pref.yml └── snippets │ ├── emoji.txt │ └── groups_clash.txt └── variables.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | *.bat -------------------------------------------------------------------------------- /Desensitization.py: -------------------------------------------------------------------------------- 1 | import re 2 | import os 3 | import shutil 4 | """ 5 | 数据脱敏 6 | """ 7 | 8 | # HOME Directory path 9 | path = "../" 10 | # files name 11 | yaml = "parser.yaml" 12 | setting = "cfw-settings.yaml" 13 | 14 | # patterns 15 | user = (r"(C:(\\\\|\\|/)Users(\\\\|\\|/))[^\\/]*(?=(\\\\|\\|/)\.config)",r"\1YOURNAME") 16 | # 删除被'##delete start'和'##end'包围的内容 17 | delete = (r"\s*##\s?delete\s?start((?!##\s?(delete\s?)?end)[\s\S])*?##\s?(delete\s?)?end","") 18 | 19 | # parser.yaml 20 | with open(os.path.join(path, yaml), "r", encoding="utf-8") as f: 21 | result = re.sub(delete[0], delete[1], f.read(), count=0, flags=0) 22 | with open(yaml, "w", encoding="utf-8") as f: 23 | f.write(result) 24 | 25 | # cfw-settings.yaml 26 | with open(os.path.join(path, setting), "r", encoding="utf-8") as f: 27 | result = re.sub(user[0], user[1], f.read(), count=0, flags=0) 28 | result = re.sub(delete[0], delete[1], result, count=0, flags=0) 29 | with open(setting, "w", encoding="utf-8") as f: 30 | f.write(result) 31 | 32 | # for copy 33 | copy = ["subconverter/pref.yml", "subconverter/snippets/emoji.txt", 34 | "subconverter/snippets/groups_clash.txt", "subconverter/base/all_base.tpl", 35 | "parser.js", "auto-check-in.js", "trayscript.js", "glados-checkin.js"] 36 | try: 37 | for file in copy: 38 | filepath = os.path.join(os.getcwd(), file) 39 | filedir = os.path.dirname(filepath) 40 | if not os.path.exists(filepath) and os.path.normcase(filedir) != os.path.normcase(os.getcwd()): 41 | os.mkdir(filedir) 42 | shutil.copyfile(os.path.join(path, file), filepath) 43 | except IOError as e: 44 | print("copy failed: ", file, " ", e) 45 | 46 | print("Desensitization finished...") -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MyRules/AI.yaml: -------------------------------------------------------------------------------- 1 | payload: 2 | - DOMAIN-SUFFIX,oaiusercontent.com 3 | - DOMAIN-SUFFIX,oaistatic.com 4 | - DOMAIN-SUFFIX,openai.com 5 | - DOMAIN-SUFFIX,ai.com 6 | - DOMAIN-SUFFIX,openaiapi-site.azureedge.net 7 | - DOMAIN-SUFFIX,bingapis.com 8 | - DOMAIN-SUFFIX,edgeservices.bing.com 9 | - DOMAIN-SUFFIX,business.bing.com 10 | - DOMAIN-SUFFIX,copilot.microsoft.com 11 | - DOMAIN-SUFFIX,edge.microsoft.com 12 | - DOMAIN-SUFFIX,applicationinsights.azure.com 13 | - DOMAIN-SUFFIX,edge-consumer-static.azureedge.net 14 | - DOMAIN-KEYWORD,chatgpt 15 | - DOMAIN-SUFFIX,files.oaiusercontent.com 16 | - DOMAIN-SUFFIX,prodregistryv2.org -------------------------------------------------------------------------------- /MyRules/CustomRulesDirect.yaml: -------------------------------------------------------------------------------- 1 | payload: 2 | - DOMAIN-SUFFIX,supanx.com 3 | - DOMAIN-SUFFIX,lauchdarkly.com 4 | - DOMAIN-SUFFIX,publicsuffix.org 5 | - DOMAIN-SUFFIX,freedownloadmanager.org 6 | - DOMAIN-SUFFIX,xboxlive.com 7 | - DOMAIN-SUFFIX,ibit6.com 8 | - DOMAIN,api.nuget.org 9 | - DOMAIN-SUFFIX,123345.xyz 10 | - DOMAIN-SUFFIX,bejingyongjiu.com 11 | - DOMAIN,office365-test.herokuapp.com 12 | - DOMAIN,linuxlink.timesys.com 13 | # 机场、订阅 14 | - DOMAIN-SUFFIX,sy168.site 15 | - DOMAIN,api.ikuuu.science 16 | - DOMAIN,api.wcc.best 17 | - DOMAIN,rss.cnrss.xyz 18 | - DOMAIN,subcon.dlj.tf 19 | - DOMAIN,subconverter-web.now.sh 20 | - DOMAIN,subconverter.herokuapp.com 21 | - DOMAIN,api.dler.io 22 | - DOMAIN-SUFFIX,glados-config.net 23 | - DOMAIN-SUFFIX,glados-config.com 24 | - IP-CIDR6,2606:4700::0/32 25 | # epic cdn 26 | - DOMAIN-SUFFIX,fastly-edge.com 27 | # steam download 28 | - DOMAIN-SUFFIX,steamcontent.com 29 | - DOMAIN-SUFFIX,steamchina.com 30 | - DOMAIN,csgo.wmsj.cn 31 | - DOMAIN,dota2.wmsj.cn 32 | - DOMAIN,wmsjsteam.com 33 | - DOMAIN,dl.steam.clngaa.com 34 | - DOMAIN,dl.steam.ksyna.com 35 | - DOMAIN,st.dl.bscstorage.net 36 | - DOMAIN,st.dl.eccdnx.com 37 | - DOMAIN,st.dl.pinyuncloud.com 38 | - DOMAIN,steampipe.steamcontent.tnkjmec.com 39 | - DOMAIN,steampowered.com.8686c.com 40 | - DOMAIN,steamstatic.com.8686c.com 41 | - DOMAIN,steambroadcast.akamaized.net 42 | - DOMAIN,steamcdn-a.akamaihd.net 43 | - DOMAIN,steamcommunity-a.akamaihd.net 44 | - DOMAIN,steamstore-a.akamaihd.net 45 | - DOMAIN,steamusercontent-a.akamaihd.net 46 | - DOMAIN,steamuserimages-a.akamaihd.net 47 | - DOMAIN-SUFFIX,steamserver.net 48 | - DOMAIN,steampipe-kr.akamaized.net 49 | - DOMAIN,steampipe-partner.akamaized.net 50 | - DOMAIN,steampipe.akamaized.net 51 | - DOMAIN-SUFFIX,steam.eca.qtlglb.com 52 | - DOMAIN,steam.cdn.on.net 53 | - DOMAIN,cdn.steamstatic.com:443 54 | # debian mirror 55 | - DOMAIN,ftp.cn.debian.org 56 | # company 57 | - DOMAIN-SUFFIX,advantech.com 58 | - DOMAIN-SUFFIX,advantech.com.tw 59 | - DOMAIN-SUFFIX,advantech.com.cn 60 | - DOMAIN-SUFFIX,advantech.corp 61 | - DOMAIN-SUFFIX,wise-iot-cloud.com 62 | # DNS 63 | - IP-CIDR,8.8.8.8/32 #谷歌 64 | - IP-CIDR,8.8.4.4/32 65 | - IP-CIDR,1.1.1.1/32 #cloudflare 66 | - IP-CIDR,1.0.0.1/32 67 | - IP-CIDR,80.80.80.80/32 #freenomm 68 | - IP-CIDR,80.80.81.81/32 69 | - IP-CIDR,4.2.2.2/32 #微软 70 | - IP-CIDR,4.2.2.1/32 71 | - IP-CIDR,1.2.4.8/32 #中科大 72 | - IP-CIDR,223.5.5.5/32 #阿里 73 | - IP-CIDR,223.6.6.6/32 74 | - IP-CIDR,202.96.128.86/32 #电信dns 75 | - IP-CIDR,202.96.134.33/32 76 | - IP-CIDR,208.67.222.222/32 #opendns 77 | - IP-CIDR,208.67.220.220/32 78 | - IP-CIDR,9.9.9.9/32 #qurd9 79 | - PROCESS-NAME,SearchApp.exe 80 | # 手机连接 81 | - PROCESS-NAME,PhoneExperienceHost.exe 82 | - DOMAIN-SUFFIX,dcg.microsoft.com 83 | - DOMAIN-SUFFIX,mp.microsoft.com 84 | -------------------------------------------------------------------------------- /MyRules/CustomRulesProxy.yaml: -------------------------------------------------------------------------------- 1 | payload: 2 | - DOMAIN-KEYWORD,v2ray 3 | - DOMAIN-KEYWORD,ssr 4 | - DOMAIN-KEYWORD,dlsite 5 | - DOMAIN-SUFFIX,appveyor.com 6 | - DOMAIN-SUFFIX,500px.com 7 | #- DOMAIN-SUFFIX,amazonaws.com 8 | - DOMAIN-SUFFIX,den4b.com 9 | - DOMAIN-SUFFIX,duckduckgo.com 10 | - DOMAIN-SUFFIX,filecrypt.cc 11 | - DOMAIN-SUFFIX,filezilla-project.org 12 | - DOMAIN-SUFFIX,giphy.com 13 | - DOMAIN-SUFFIX,gravatar.com 14 | - DOMAIN-SUFFIX,henry-hu.com 15 | - DOMAIN-SUFFIX,imgur.com 16 | - DOMAIN-SUFFIX,itorrents.org 17 | - DOMAIN-SUFFIX,last.fm 18 | - DOMAIN-SUFFIX,mathjax.org 19 | - DOMAIN-SUFFIX,megaup.net 20 | - DOMAIN-SUFFIX,moddb.com 21 | - DOMAIN-SUFFIX,mxmcdn.net 22 | - DOMAIN-SUFFIX,nexusmods.com 23 | - DOMAIN-SUFFIX,parastorage.com 24 | - DOMAIN-SUFFIX,patreon.com 25 | - DOMAIN-SUFFIX,pixfs.net 26 | - DOMAIN-SUFFIX,recaptcha.net 27 | - DOMAIN-SUFFIX,riffsy.com 28 | - DOMAIN-SUFFIX,s-msft.com 29 | - DOMAIN-SUFFIX,shadowsocks.com 30 | - DOMAIN-SUFFIX,softwareupdate.vmware.com 31 | - DOMAIN-SUFFIX,storetorrents.xyz 32 | - DOMAIN-KEYWORD,torrentkitty 33 | - DOMAIN-SUFFIX,wemod.com 34 | - DOMAIN-SUFFIX,wixmp.com 35 | - DOMAIN-SUFFIX,zhainanzhongzi.me 36 | - DOMAIN-SUFFIX,fanbox.cc 37 | - DOMAIN-SUFFIX,netify.ai 38 | - DOMAIN,s.youtube.com 39 | - DOMAIN,default.exp-tas.com 40 | - DOMAIN-SUFFIX,lbyczf.com 41 | - DOMAIN-SUFFIX,mumuceo.com 42 | - DOMAIN-SUFFIX,regex101.com 43 | - DOMAIN-SUFFIX,userstyles.org 44 | - DOMAIN-SUFFIX,appcenter.ms 45 | - DOMAIN-SUFFIX,vancedapp.com 46 | - DOMAIN,dingyue.suying666.info 47 | - DOMAIN-SUFFIX,gstatic.cn 48 | - DOMAIN-SUFFIX,bandi.so 49 | - DOMAIN-SUFFIX,balena.io 50 | - DOMAIN-SUFFIX,balena-cloud.com 51 | - DOMAIN-SUFFIX,googleapis.cn 52 | - DOMAIN-SUFFIX,gstatic.com 53 | - DOMAIN,clash.razord.top 54 | - DOMAIN,yacd.haishan.me 55 | - DOMAIN,gist.github.com 56 | - DOMAIN,fonts.gstatic.com 57 | - DOMAIN-SUFFIX,t.co 58 | - DOMAIN-SUFFIX,googleapis.com -------------------------------------------------------------------------------- /MyRules/Download.yaml: -------------------------------------------------------------------------------- 1 | payload: 2 | # 迅雷 3 | - PROCESS-NAME,DownloadSDKServer.exe 4 | - PROCESS-NAME,Thunder.exe 5 | # 下载 6 | - PROCESS-NAME,Ibit6.exe 7 | #- PROCESS-NAME,aria2c.exe 8 | - PROCESS-NAME,SpeedPanX.exe 9 | - PROCESS-NAME,KinhDown.exe 10 | - PROCESS-NAME,FlashDownloadDesktop.exe 11 | - PROCESS-NAME,XDown.exe 12 | - PROCESS-NAME,MiniThunderPlatform.exe -------------------------------------------------------------------------------- /MyRules/EpicGames.yaml: -------------------------------------------------------------------------------- 1 | payload: 2 | - PROCESS-NAME,EpicGamesLauncher.exe 3 | - PROCESS-NAME,EOSOverlayRenderer-Win64-Shipping.exe 4 | - PROCESS-NAME,EOSOverlayRenderer-Win32-Shipping.exe 5 | - PROCESS-NAME,UnrealEngineLauncher.exe 6 | - PROCESS-NAME,CrashReportClient.exe 7 | - PROCESS-NAME,UnrealCEFSubProcess.exe 8 | - PROCESS-NAME,EpicWebHelper.exe 9 | - PROCESS-NAME,UnrealVersionSelector.exe -------------------------------------------------------------------------------- /MyRules/GOG.yaml: -------------------------------------------------------------------------------- 1 | payload: 2 | - PROCESS-NAME,GalaxyClient Helper.exe 3 | - PROCESS-NAME,GalaxyClient.exe 4 | - PROCESS-NAME,GalaxyClientService.exe 5 | - PROCESS-NAME,GOG Galaxy Notifications Renderer.exe -------------------------------------------------------------------------------- /MyRules/GeforceExperience.yaml: -------------------------------------------------------------------------------- 1 | payload: 2 | - PROCESS-NAME,courgette.exe 3 | - PROCESS-NAME,NVIDIA GeForce Experience.exe 4 | - PROCESS-NAME,NVIDIA Notification.exe 5 | - PROCESS-NAME,NVIDIA Share.exe -------------------------------------------------------------------------------- /MyRules/Git.yaml: -------------------------------------------------------------------------------- 1 | # Git 2 | payload: 3 | - PROCESS-NAME,git-add.exe 4 | - PROCESS-NAME,git-am.exe 5 | - PROCESS-NAME,git-annotate.exe 6 | - PROCESS-NAME,git-apply.exe 7 | - PROCESS-NAME,git-archive.exe 8 | - PROCESS-NAME,git-askpass.exe 9 | - PROCESS-NAME,git-bisect--helper.exe 10 | - PROCESS-NAME,git-blame.exe 11 | - PROCESS-NAME,git-branch.exe 12 | - PROCESS-NAME,git-bundle.exe 13 | - PROCESS-NAME,git-cat-file.exe 14 | - PROCESS-NAME,git-check-attr.exe 15 | - PROCESS-NAME,git-check-ignore.exe 16 | - PROCESS-NAME,git-check-mailmap.exe 17 | - PROCESS-NAME,git-check-ref-format.exe 18 | - PROCESS-NAME,git-checkout-index.exe 19 | - PROCESS-NAME,git-checkout.exe 20 | - PROCESS-NAME,git-cherry-pick.exe 21 | - PROCESS-NAME,git-cherry.exe 22 | - PROCESS-NAME,git-clean.exe 23 | - PROCESS-NAME,git-clone.exe 24 | - PROCESS-NAME,git-column.exe 25 | - PROCESS-NAME,git-commit-graph.exe 26 | - PROCESS-NAME,git-commit-tree.exe 27 | - PROCESS-NAME,git-commit.exe 28 | - PROCESS-NAME,git-config.exe 29 | - PROCESS-NAME,git-count-objects.exe 30 | - PROCESS-NAME,git-credential-manager.exe 31 | - PROCESS-NAME,git-credential-store.exe 32 | - PROCESS-NAME,git-credential-wincred.exe 33 | - PROCESS-NAME,git-credential.exe 34 | - PROCESS-NAME,git-daemon.exe 35 | - PROCESS-NAME,git-describe.exe 36 | - PROCESS-NAME,git-diff-files.exe 37 | - PROCESS-NAME,git-diff-index.exe 38 | - PROCESS-NAME,git-diff-tree.exe 39 | - PROCESS-NAME,git-diff.exe 40 | - PROCESS-NAME,git-difftool.exe 41 | - PROCESS-NAME,git-fast-export.exe 42 | - PROCESS-NAME,git-fast-import.exe 43 | - PROCESS-NAME,git-fetch-pack.exe 44 | - PROCESS-NAME,git-fetch.exe 45 | - PROCESS-NAME,git-fmt-merge-msg.exe 46 | - PROCESS-NAME,git-for-each-ref.exe 47 | - PROCESS-NAME,git-format-patch.exe 48 | - PROCESS-NAME,git-fsck-objects.exe 49 | - PROCESS-NAME,git-fsck.exe 50 | - PROCESS-NAME,git-gc.exe 51 | - PROCESS-NAME,git-get-tar-commit-id.exe 52 | - PROCESS-NAME,git-grep.exe 53 | - PROCESS-NAME,git-hash-object.exe 54 | - PROCESS-NAME,git-help.exe 55 | - PROCESS-NAME,git-http-backend.exe 56 | - PROCESS-NAME,git-http-fetch.exe 57 | - PROCESS-NAME,git-http-push.exe 58 | - PROCESS-NAME,git-imap-send.exe 59 | - PROCESS-NAME,git-index-pack.exe 60 | - PROCESS-NAME,git-init-db.exe 61 | - PROCESS-NAME,git-init.exe 62 | - PROCESS-NAME,git-interpret-trailers.exe 63 | - PROCESS-NAME,git-log.exe 64 | - PROCESS-NAME,git-ls-files.exe 65 | - PROCESS-NAME,git-ls-remote.exe 66 | - PROCESS-NAME,git-ls-tree.exe 67 | - PROCESS-NAME,git-mailinfo.exe 68 | - PROCESS-NAME,git-mailsplit.exe 69 | - PROCESS-NAME,git-merge-base.exe 70 | - PROCESS-NAME,git-merge-file.exe 71 | - PROCESS-NAME,git-merge-index.exe 72 | - PROCESS-NAME,git-merge-ours.exe 73 | - PROCESS-NAME,git-merge-recursive.exe 74 | - PROCESS-NAME,git-merge-subtree.exe 75 | - PROCESS-NAME,git-merge-tree.exe 76 | - PROCESS-NAME,git-merge.exe 77 | - PROCESS-NAME,git-mktag.exe 78 | - PROCESS-NAME,git-mktree.exe 79 | - PROCESS-NAME,git-multi-pack-index.exe 80 | - PROCESS-NAME,git-mv.exe 81 | - PROCESS-NAME,git-name-rev.exe 82 | - PROCESS-NAME,git-notes.exe 83 | - PROCESS-NAME,git-pack-objects.exe 84 | - PROCESS-NAME,git-pack-redundant.exe 85 | - PROCESS-NAME,git-pack-refs.exe 86 | - PROCESS-NAME,git-patch-id.exe 87 | - PROCESS-NAME,git-prune-packed.exe 88 | - PROCESS-NAME,git-prune.exe 89 | - PROCESS-NAME,git-pull.exe 90 | - PROCESS-NAME,git-push.exe 91 | - PROCESS-NAME,git-range-diff.exe 92 | - PROCESS-NAME,git-read-tree.exe 93 | - PROCESS-NAME,git-rebase.exe 94 | - PROCESS-NAME,git-receive-pack.exe 95 | - PROCESS-NAME,git-reflog.exe 96 | - PROCESS-NAME,git-remote-ext.exe 97 | - PROCESS-NAME,git-remote-fd.exe 98 | - PROCESS-NAME,git-remote-ftp.exe 99 | - PROCESS-NAME,git-remote-ftps.exe 100 | - PROCESS-NAME,git-remote-http.exe 101 | - PROCESS-NAME,git-remote-https.exe 102 | - PROCESS-NAME,git-remote.exe 103 | - PROCESS-NAME,git-repack.exe 104 | - PROCESS-NAME,git-replace.exe 105 | - PROCESS-NAME,git-rerere.exe 106 | - PROCESS-NAME,git-reset.exe 107 | - PROCESS-NAME,git-rev-list.exe 108 | - PROCESS-NAME,git-rev-parse.exe 109 | - PROCESS-NAME,git-revert.exe 110 | - PROCESS-NAME,git-rm.exe 111 | - PROCESS-NAME,git-send-pack.exe 112 | - PROCESS-NAME,git-sh-i18n--envsubst.exe 113 | - PROCESS-NAME,git-shortlog.exe 114 | - PROCESS-NAME,git-show-branch.exe 115 | - PROCESS-NAME,git-show-index.exe 116 | - PROCESS-NAME,git-show-ref.exe 117 | - PROCESS-NAME,git-show.exe 118 | - PROCESS-NAME,git-stage.exe 119 | - PROCESS-NAME,git-stash.exe 120 | - PROCESS-NAME,git-status.exe 121 | - PROCESS-NAME,git-stripspace.exe 122 | - PROCESS-NAME,git-submodule--helper.exe 123 | - PROCESS-NAME,git-symbolic-ref.exe 124 | - PROCESS-NAME,git-tag.exe 125 | - PROCESS-NAME,git-unpack-file.exe 126 | - PROCESS-NAME,git-unpack-objects.exe 127 | - PROCESS-NAME,git-update-index.exe 128 | - PROCESS-NAME,git-update-ref.exe 129 | - PROCESS-NAME,git-update-server-info.exe 130 | - PROCESS-NAME,git-upload-archive.exe 131 | - PROCESS-NAME,git-upload-pack.exe 132 | - PROCESS-NAME,git-var.exe 133 | - PROCESS-NAME,git-verify-commit.exe 134 | - PROCESS-NAME,git-verify-pack.exe 135 | - PROCESS-NAME,git-verify-tag.exe 136 | - PROCESS-NAME,git-whatchanged.exe 137 | - PROCESS-NAME,git-worktree.exe 138 | - PROCESS-NAME,git-write-tree.exe 139 | - PROCESS-NAME,git.exe 140 | - PROCESS-NAME,GitHub.Authentication.exe 141 | - PROCESS-NAME,GitHubDesktop.exe -------------------------------------------------------------------------------- /MyRules/GoogleSearch.yaml: -------------------------------------------------------------------------------- 1 | payload: 2 | - DOMAIN-SUFFIX,google.com 3 | - DOMAIN-SUFFIX,google.jp 4 | - DOMAIN-SUFFIX,google.com 5 | - DOMAIN-SUFFIX,google.ad 6 | - DOMAIN-SUFFIX,google.ae 7 | - DOMAIN-SUFFIX,google.com.af 8 | - DOMAIN-SUFFIX,google.com.ag 9 | - DOMAIN-SUFFIX,google.al 10 | - DOMAIN-SUFFIX,google.am 11 | - DOMAIN-SUFFIX,google.co.ao 12 | - DOMAIN-SUFFIX,google.com.ar 13 | - DOMAIN-SUFFIX,google.as 14 | - DOMAIN-SUFFIX,google.at 15 | - DOMAIN-SUFFIX,google.com.au 16 | - DOMAIN-SUFFIX,google.az 17 | - DOMAIN-SUFFIX,google.ba 18 | - DOMAIN-SUFFIX,google.com.bd 19 | - DOMAIN-SUFFIX,google.be 20 | - DOMAIN-SUFFIX,google.bf 21 | - DOMAIN-SUFFIX,google.bg 22 | - DOMAIN-SUFFIX,google.com.bh 23 | - DOMAIN-SUFFIX,google.bi 24 | - DOMAIN-SUFFIX,google.bj 25 | - DOMAIN-SUFFIX,google.com.bn 26 | - DOMAIN-SUFFIX,google.com.bo 27 | - DOMAIN-SUFFIX,google.com.br 28 | - DOMAIN-SUFFIX,google.bs 29 | - DOMAIN-SUFFIX,google.bt 30 | - DOMAIN-SUFFIX,google.co.bw 31 | - DOMAIN-SUFFIX,google.by 32 | - DOMAIN-SUFFIX,google.com.bz 33 | - DOMAIN-SUFFIX,google.ca 34 | - DOMAIN-SUFFIX,google.cd 35 | - DOMAIN-SUFFIX,google.cf 36 | - DOMAIN-SUFFIX,google.cg 37 | - DOMAIN-SUFFIX,google.ch 38 | - DOMAIN-SUFFIX,google.ci 39 | - DOMAIN-SUFFIX,google.co.ck 40 | - DOMAIN-SUFFIX,google.cl 41 | - DOMAIN-SUFFIX,google.cm 42 | - DOMAIN-SUFFIX,google.cn 43 | - DOMAIN-SUFFIX,google.com.co 44 | - DOMAIN-SUFFIX,google.co.cr 45 | - DOMAIN-SUFFIX,google.com.cu 46 | - DOMAIN-SUFFIX,google.cv 47 | - DOMAIN-SUFFIX,google.com.cy 48 | - DOMAIN-SUFFIX,google.cz 49 | - DOMAIN-SUFFIX,google.de 50 | - DOMAIN-SUFFIX,google.dj 51 | - DOMAIN-SUFFIX,google.dk 52 | - DOMAIN-SUFFIX,google.dm 53 | - DOMAIN-SUFFIX,google.com.do 54 | - DOMAIN-SUFFIX,google.dz 55 | - DOMAIN-SUFFIX,google.com.ec 56 | - DOMAIN-SUFFIX,google.ee 57 | - DOMAIN-SUFFIX,google.com.eg 58 | - DOMAIN-SUFFIX,google.es 59 | - DOMAIN-SUFFIX,google.com.et 60 | - DOMAIN-SUFFIX,google.fi 61 | - DOMAIN-SUFFIX,google.com.fj 62 | - DOMAIN-SUFFIX,google.fm 63 | - DOMAIN-SUFFIX,google.fr 64 | - DOMAIN-SUFFIX,google.ga 65 | - DOMAIN-SUFFIX,google.ge 66 | - DOMAIN-SUFFIX,google.gg 67 | - DOMAIN-SUFFIX,google.com.gh 68 | - DOMAIN-SUFFIX,google.com.gi 69 | - DOMAIN-SUFFIX,google.gl 70 | - DOMAIN-SUFFIX,google.gm 71 | - DOMAIN-SUFFIX,google.gr 72 | - DOMAIN-SUFFIX,google.com.gt 73 | - DOMAIN-SUFFIX,google.gy 74 | - DOMAIN-SUFFIX,google.com.hk 75 | - DOMAIN-SUFFIX,google.hn 76 | - DOMAIN-SUFFIX,google.hr 77 | - DOMAIN-SUFFIX,google.ht 78 | - DOMAIN-SUFFIX,google.hu 79 | - DOMAIN-SUFFIX,google.co.id 80 | - DOMAIN-SUFFIX,google.ie 81 | - DOMAIN-SUFFIX,google.co.il 82 | - DOMAIN-SUFFIX,google.im 83 | - DOMAIN-SUFFIX,google.co.in 84 | - DOMAIN-SUFFIX,google.iq 85 | - DOMAIN-SUFFIX,google.is 86 | - DOMAIN-SUFFIX,google.it 87 | - DOMAIN-SUFFIX,google.je 88 | - DOMAIN-SUFFIX,google.com.jm 89 | - DOMAIN-SUFFIX,google.jo 90 | - DOMAIN-SUFFIX,google.co.jp 91 | - DOMAIN-SUFFIX,google.co.ke 92 | - DOMAIN-SUFFIX,google.com.kh 93 | - DOMAIN-SUFFIX,google.ki 94 | - DOMAIN-SUFFIX,google.kg 95 | - DOMAIN-SUFFIX,google.co.kr 96 | - DOMAIN-SUFFIX,google.com.kw 97 | - DOMAIN-SUFFIX,google.kz 98 | - DOMAIN-SUFFIX,google.la 99 | - DOMAIN-SUFFIX,google.com.lb 100 | - DOMAIN-SUFFIX,google.li 101 | - DOMAIN-SUFFIX,google.lk 102 | - DOMAIN-SUFFIX,google.co.ls 103 | - DOMAIN-SUFFIX,google.lt 104 | - DOMAIN-SUFFIX,google.lu 105 | - DOMAIN-SUFFIX,google.lv 106 | - DOMAIN-SUFFIX,google.com.ly 107 | - DOMAIN-SUFFIX,google.co.ma 108 | - DOMAIN-SUFFIX,google.md 109 | - DOMAIN-SUFFIX,google.me 110 | - DOMAIN-SUFFIX,google.mg 111 | - DOMAIN-SUFFIX,google.mk 112 | - DOMAIN-SUFFIX,google.ml 113 | - DOMAIN-SUFFIX,google.com.mm 114 | - DOMAIN-SUFFIX,google.mn 115 | - DOMAIN-SUFFIX,google.com.mt 116 | - DOMAIN-SUFFIX,google.mu 117 | - DOMAIN-SUFFIX,google.mv 118 | - DOMAIN-SUFFIX,google.mw 119 | - DOMAIN-SUFFIX,google.com.mx 120 | - DOMAIN-SUFFIX,google.com.my 121 | - DOMAIN-SUFFIX,google.co.mz 122 | - DOMAIN-SUFFIX,google.com.na 123 | - DOMAIN-SUFFIX,google.com.ng 124 | - DOMAIN-SUFFIX,google.com.ni 125 | - DOMAIN-SUFFIX,google.ne 126 | - DOMAIN-SUFFIX,google.nl 127 | - DOMAIN-SUFFIX,google.no 128 | - DOMAIN-SUFFIX,google.com.np 129 | - DOMAIN-SUFFIX,google.nr 130 | - DOMAIN-SUFFIX,google.nu 131 | - DOMAIN-SUFFIX,google.co.nz 132 | - DOMAIN-SUFFIX,google.com.om 133 | - DOMAIN-SUFFIX,google.com.pa 134 | - DOMAIN-SUFFIX,google.com.pe 135 | - DOMAIN-SUFFIX,google.com.pg 136 | - DOMAIN-SUFFIX,google.com.ph 137 | - DOMAIN-SUFFIX,google.com.pk 138 | - DOMAIN-SUFFIX,google.pl 139 | - DOMAIN-SUFFIX,google.pn 140 | - DOMAIN-SUFFIX,google.com.pr 141 | - DOMAIN-SUFFIX,google.ps 142 | - DOMAIN-SUFFIX,google.pt 143 | - DOMAIN-SUFFIX,google.com.py 144 | - DOMAIN-SUFFIX,google.com.qa 145 | - DOMAIN-SUFFIX,google.ro 146 | - DOMAIN-SUFFIX,google.ru 147 | - DOMAIN-SUFFIX,google.rw 148 | - DOMAIN-SUFFIX,google.com.sa 149 | - DOMAIN-SUFFIX,google.com.sb 150 | - DOMAIN-SUFFIX,google.sc 151 | - DOMAIN-SUFFIX,google.se 152 | - DOMAIN-SUFFIX,google.com.sg 153 | - DOMAIN-SUFFIX,google.sh 154 | - DOMAIN-SUFFIX,google.si 155 | - DOMAIN-SUFFIX,google.sk 156 | - DOMAIN-SUFFIX,google.com.sl 157 | - DOMAIN-SUFFIX,google.sn 158 | - DOMAIN-SUFFIX,google.so 159 | - DOMAIN-SUFFIX,google.sm 160 | - DOMAIN-SUFFIX,google.sr 161 | - DOMAIN-SUFFIX,google.st 162 | - DOMAIN-SUFFIX,google.com.sv 163 | - DOMAIN-SUFFIX,google.td 164 | - DOMAIN-SUFFIX,google.tg 165 | - DOMAIN-SUFFIX,google.co.th 166 | - DOMAIN-SUFFIX,google.com.tj 167 | - DOMAIN-SUFFIX,google.tl 168 | - DOMAIN-SUFFIX,google.tm 169 | - DOMAIN-SUFFIX,google.tn 170 | - DOMAIN-SUFFIX,google.to 171 | - DOMAIN-SUFFIX,google.com.tr 172 | - DOMAIN-SUFFIX,google.tt 173 | - DOMAIN-SUFFIX,google.com.tw 174 | - DOMAIN-SUFFIX,google.co.tz 175 | - DOMAIN-SUFFIX,google.com.ua 176 | - DOMAIN-SUFFIX,google.co.ug 177 | - DOMAIN-SUFFIX,google.co.uk 178 | - DOMAIN-SUFFIX,google.com.uy 179 | - DOMAIN-SUFFIX,google.co.uz 180 | - DOMAIN-SUFFIX,google.com.vc 181 | - DOMAIN-SUFFIX,google.co.ve 182 | - DOMAIN-SUFFIX,google.co.vi 183 | - DOMAIN-SUFFIX,google.com.vn 184 | - DOMAIN-SUFFIX,google.vu 185 | - DOMAIN-SUFFIX,google.ws 186 | - DOMAIN-SUFFIX,google.rs 187 | - DOMAIN-SUFFIX,google.co.za 188 | - DOMAIN-SUFFIX,google.co.zm 189 | - DOMAIN-SUFFIX,google.co.zw 190 | - DOMAIN-SUFFIX,google.cat 191 | - DOMAIN-SUFFIX,goo.gl -------------------------------------------------------------------------------- /MyRules/UNMProxy.yaml: -------------------------------------------------------------------------------- 1 | payload: 2 | - DOMAIN-SUFFIX,music.163.com 3 | - DOMAIN-SUFFIX,music.126.net 4 | - DOMAIN-SUFFIX,interface.music.163.com 5 | - DOMAIN-SUFFIX,interface3.music.163.com 6 | - DOMAIN-SUFFIX,apm.music.163.com 7 | - DOMAIN-SUFFIX,apm3.music.163.com 8 | - DOMAIN-SUFFIX,man.netease.com 9 | - DOMAIN-SUFFIX,api.iplay.163.com 10 | - IP-CIDR,39.105.63.80/32 11 | - IP-CIDR,45.254.48.1/32 12 | - IP-CIDR,47.100.127.239/32 13 | - IP-CIDR,59.111.160.195/32 14 | - IP-CIDR,59.111.160.197/32 15 | - IP-CIDR,59.111.181.35/32 16 | - IP-CIDR,59.111.181.38/32 17 | - IP-CIDR,59.111.181.60/32 18 | - IP-CIDR,101.71.154.241/32 19 | - IP-CIDR,103.126.92.132/32 20 | - IP-CIDR,103.126.92.133/32 21 | - IP-CIDR,112.13.119.17/32 22 | - IP-CIDR,112.13.122.1/32 23 | - IP-CIDR,115.236.118.33/32 24 | - IP-CIDR,115.236.121.1/32 25 | - IP-CIDR,118.24.63.156/32 26 | - IP-CIDR,193.112.159.225/32 27 | - IP-CIDR,223.252.199.66/32 28 | - IP-CIDR,223.252.199.67/32 -------------------------------------------------------------------------------- /MyRules/UPlay.yaml: -------------------------------------------------------------------------------- 1 | payload: 2 | - PROCESS-NAME,UbisoftGameLauncher.exe 3 | - PROCESS-NAME,UbisoftGameLauncher64.exe 4 | - PROCESS-NAME,upc.exe 5 | - PROCESS-NAME,Uplay.exe 6 | - PROCESS-NAME,UbisoftConnect.exe 7 | - PROCESS-NAME,UplayCrashReporter.exe 8 | - PROCESS-NAME,UplayCrashHelper.exe 9 | - PROCESS-NAME,UplayCrashHelper64.exe 10 | - PROCESS-NAME,UplayService.exe 11 | - PROCESS-NAME,UplayWebCore.exe -------------------------------------------------------------------------------- /MyRules/Video.yaml: -------------------------------------------------------------------------------- 1 | payload: 2 | #NETFLIX 3 | - DOMAIN-KEYWORD,netflix 4 | - DOMAIN-SUFFIX,netflix.com 5 | - DOMAIN-SUFFIX,netflix.net 6 | - DOMAIN-SUFFIX,nflxext.com 7 | - DOMAIN-SUFFIX,nflximg.com 8 | - DOMAIN-SUFFIX,nflximg.net 9 | - DOMAIN-SUFFIX,nflxso.net 10 | - DOMAIN-KEYWORD,dualstack.apiproxy- 11 | - DOMAIN-KEYWORD,dualstack.ichnaea-web- 12 | - DOMAIN-SUFFIX,netflix.com.edgesuite.net 13 | - DOMAIN-SUFFIX,us-west-2.amazonaws.com 14 | - DOMAIN-KEYWORD,apiproxy-device-prod-nlb- 15 | - DOMAIN-KEYWORD,ichnaea-web- 16 | - DOMAIN,netflix.com.edgesuite.net 17 | - DOMAIN-SUFFIX,netflix.com 18 | - DOMAIN-SUFFIX,netflix.net 19 | - DOMAIN-SUFFIX,nflxext.com 20 | - DOMAIN-SUFFIX,nflximg.com 21 | - DOMAIN-SUFFIX,nflximg.net 22 | - DOMAIN-SUFFIX,nflxso.net 23 | - DOMAIN-SUFFIX,nflxvideo.net 24 | 25 | # > Fox+ 26 | - DOMAIN-KEYWORD,foxplus 27 | - DOMAIN-SUFFIX,config.fox.com 28 | - DOMAIN-SUFFIX,emome.net 29 | - DOMAIN-SUFFIX,fox.com 30 | - DOMAIN-SUFFIX,foxdcg.com 31 | - DOMAIN-SUFFIX,foxnow.com 32 | - DOMAIN-SUFFIX,foxplus.com 33 | - DOMAIN-SUFFIX,foxplay.com 34 | - DOMAIN-SUFFIX,ipinfo.io 35 | - DOMAIN-SUFFIX,mstage.io 36 | - DOMAIN-SUFFIX,now.com 37 | - DOMAIN-SUFFIX,theplatform.com 38 | - DOMAIN-SUFFIX,urlload.net 39 | 40 | # > HBO && HBO Go 41 | - DOMAIN-SUFFIX,hbo.com 42 | - DOMAIN-SUFFIX,hboasia.com 43 | - DOMAIN-SUFFIX,hbogo.com 44 | - DOMAIN-SUFFIX,hbogoasia.hk 45 | 46 | # > Hulu 47 | - DOMAIN-SUFFIX,hulu.com 48 | - DOMAIN-SUFFIX,huluim.com 49 | - DOMAIN-SUFFIX,hulustream.com 50 | 51 | #Fast.com 52 | - DOMAIN-SUFFIX,fast.com 53 | - DOMAIN-SUFFIX,oca.nflxvideo.net 54 | - DOMAIN-SUFFIX,nflxvideo.net 55 | 56 | - DOMAIN,cdn.registerdisney.go.com 57 | - DOMAIN-SUFFIX,adobedtm.com 58 | - DOMAIN-SUFFIX,bam.nr-data.net 59 | - DOMAIN-SUFFIX,bamgrid.com 60 | - DOMAIN-SUFFIX,braze.com 61 | - DOMAIN-SUFFIX,cdn.optimizely.com 62 | - DOMAIN-SUFFIX,cdn.registerdisney.go.com 63 | - DOMAIN-SUFFIX,cws.conviva.com 64 | - DOMAIN-SUFFIX,d9.flashtalking.com 65 | - DOMAIN-SUFFIX,disney-plus.net 66 | - DOMAIN-SUFFIX,disney-portal.my.onetrust.com 67 | - DOMAIN-SUFFIX,disney.demdex.net 68 | - DOMAIN-SUFFIX,disney.my.sentry.io 69 | - DOMAIN-SUFFIX,disneyplus.bn5x.net 70 | - DOMAIN-SUFFIX,disneyplus.com 71 | - DOMAIN-SUFFIX,disneyplus.com.ssl.sc.omtrdc.net 72 | - DOMAIN-SUFFIX,disneystreaming.com 73 | - DOMAIN-SUFFIX,dssott.com 74 | - DOMAIN-SUFFIX,execute-api.us-east-1.amazonaws.com 75 | - DOMAIN-SUFFIX,js-agent.newrelic.com 76 | 77 | # > Bahamut 78 | - DOMAIN-SUFFIX,bahamut.com.tw 79 | - DOMAIN-SUFFIX,gamer.com.tw 80 | - DOMAIN-SUFFIX,hinet.net 81 | 82 | # youtube 83 | - DOMAIN-KEYWORD,youtube 84 | - DOMAIN-SUFFIX,youtu.be 85 | - DOMAIN-SUFFIX,youtube.com 86 | - DOMAIN-SUFFIX,yt.be 87 | - DOMAIN-SUFFIX,ytimg.com 88 | - DOMAIN-SUFFIX,googlevideo.com 89 | - DOMAIN-SUFFIX,googleusercontent.com 90 | - DOMAIN-SUFFIX,gvt2.com,Video 91 | 92 | # tiktok 93 | - DOMAIN-SUFFIX,byteoversea.com 94 | - DOMAIN-SUFFIX,muscdn.com 95 | - DOMAIN-SUFFIX,musical.ly 96 | - DOMAIN-SUFFIX,tik-tokapi.com 97 | - DOMAIN-SUFFIX,tiktokcdn.com 98 | - DOMAIN-SUFFIX,tiktok.com 99 | - DOMAIN-SUFFIX,tiktokv.com 100 | - DOMAIN-SUFFIX,full:p16-tiktokcdn-com.akamaized.net 101 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Clash_configuration 2 | 3 | 一些自用脚本 4 | -------------------------------------------------------------------------------- /auto-check-in.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @module auto_check_in 3 | * @description The script was used to automatic check in. 4 | * @param {string[]} [domains = []] - The site of domain will be check in. 5 | * @param {string[]} [keep = []] - Value of keep. 6 | * @param {string[]} [email = []] - Value of email. 7 | * @param {string[]} [pwd = []] - Value of pwd. 8 | */ 9 | 10 | const { 11 | readFileSync, 12 | writeFileSync, 13 | existsSync, 14 | appendFileSync, 15 | } = require("fs"); 16 | const { resolve, join } = require("path"); 17 | const { homedir } = require("os"); 18 | const variable_path = resolve(__dirname, "./variables.yaml"); 19 | const myDate = new Date(); 20 | const debug = false; 21 | const homeDirectory = join(homedir(), ".config/clash"); 22 | // log file路径 23 | const logFile = join(homeDirectory, "logs/cfw-autocheckin.log"); 24 | let newParse = true; 25 | const maxLogLine = 20000; 26 | 27 | // 检查日志行数,超过maxLogLine切半 28 | const checkLog = function () { 29 | if (!existsSync(logFile)) { 30 | log( 31 | "[warn]: doesn't find log file: cfw-autocheckin.log, Automatically create it." 32 | ); 33 | } 34 | const lines = readFileSync(logFile, "utf-8").toString().split("\n"); 35 | if (lines.length > maxLogLine) { 36 | let start = Math.round(lines.length / 2); 37 | //从有意义的日期开始切 38 | while (!/-{2,}.*-{2,}/.test(lines[start]) && start < lines.length) { 39 | start++; 40 | } 41 | //backup old file 42 | writeFileSync(logFile + ".bak", lines.join("\n"), "utf-8"); 43 | //write new log 44 | writeFileSync(logFile, lines.slice(start).join("\n"), "utf-8"); 45 | log( 46 | `[info]: log line count is: ${lines.length} larger than ${maxLogLine}, cut it by half.` 47 | ); 48 | } else if (debug) { 49 | log(`[debug]: log line count is: ${lines.length}`); 50 | } 51 | }; 52 | 53 | const log = function (text) { 54 | if (newParse) { 55 | appendFileSync( 56 | logFile, 57 | `\n --------------${myDate.toLocaleString()}--------------\n`, 58 | "utf-8" 59 | ); 60 | newParse = false; 61 | } 62 | appendFileSync(logFile, text + "\n", "utf-8"); 63 | }; 64 | 65 | // 从日志获取历史流量,仅统计通过自动签到获取的流量 66 | // 同时因为会有日志大小监控,日志过长会被切断,因此数据可能不准确,日志限制数在上面 67 | const cal_data_used_fromlog = function (name) { 68 | if (!existsSync(logFile)) { 69 | log( 70 | "[warn]: doesn't find log file: cfw-autocheckin.log, Automatically create it." 71 | ); 72 | return 0; 73 | } 74 | let reg = new RegExp( 75 | '"' + name + '".*?[你您]获得了\\s*(\\d+)\\s*MB流量', 76 | "gi" 77 | ); 78 | let matches = readFileSync(logFile, "utf-8").matchAll(reg); 79 | let total = 0; 80 | let count = 0; 81 | for (const match of matches) { 82 | total += parseInt(match[1]); 83 | count++; 84 | if (debug) { 85 | log( 86 | `[debug]: 迁移:match:${match[0]} num:${match[1]} start=${ 87 | match.index 88 | } end=${match.index + match[0].length}.` 89 | ); 90 | } 91 | } 92 | log(`[info]: calculate total data used from log: ${total}M`); 93 | return [total, count]; 94 | }; 95 | 96 | let check_in = async (raw, { yaml, axios, notify }, variable) => { 97 | try { 98 | // iso 时区+8 99 | var _time = new Date(+myDate + 8 * 3600 * 1000) 100 | .toISOString() 101 | .replace(/Z$/, "+08:00"); 102 | var today = _time.slice(0, 10); 103 | var rawObj = yaml.parse(raw); 104 | var check = false; 105 | var sign = false; 106 | var should_modify = false; 107 | log(`[info]: start check in "${variable["name"]}".`); 108 | //检查历史,是否有今天签到记录 109 | if (variable["history"] && variable["history"].length > 0) { 110 | if (variable["history"][0]["checkinDate"].slice(0, 10) === today) { 111 | log(`[info]: "${variable["name"]}" has been already check in.`); 112 | notify( 113 | "Already check in", 114 | `You has been already check in in "${variable["name"]}"`, 115 | true 116 | ); 117 | //跳过登陆和签到 118 | check = true; 119 | sign = true; 120 | } 121 | } else variable["history"] = []; 122 | 123 | var domain = variable["domain"] 124 | .replace(/^https?:\/\//, "") 125 | .replace(/\/$/, ""); 126 | // check sign 127 | if (!check && !sign) { 128 | try { 129 | log(`[info]: try check sign with "${variable["name"]}".`); 130 | let resp = await axios.get(`https://${domain}/user`); 131 | //数据量很大 132 | if (debug) { 133 | log(`[debug]: response of https://${domain}/user:`); 134 | log(`${JSON.stringify(resp.data, null, 2)}`); 135 | } 136 | sign = 137 | /(? 1024 * 1024) { 206 | total_text += 207 | ", i.e., " + (total / (1024 * 1024)).toFixed(4) + "TB"; 208 | } else if (total > 1024) { 209 | total_text += ", i.e., " + (total / 1024).toFixed(2) + "GB"; 210 | } 211 | variable["total"] = total_text; 212 | variable["days"] = days; 213 | 214 | // history 215 | let nowData = {}; 216 | nowData["checkinDate"] = _time; 217 | nowData["checkinMessage"] = resp.data.msg; 218 | variable["history"].unshift(nowData); 219 | should_modify = true; 220 | 221 | log(`[info]: "${variable["name"]}" checkinDate: ${_time}.`); 222 | log( 223 | `[info]: "${variable["name"]}" checkinMessage: ${resp.data.msg}.` 224 | ); 225 | notify( 226 | `check in "${variable["name"]}" successful`, 227 | resp.data.msg, 228 | true 229 | ); 230 | log(`[info]: "${variable["name"]}" check in completely.`); 231 | } else { 232 | log(`[info]: "${variable["name"]}" has been already check in.`); 233 | notify( 234 | `You have checked in "${variable["name"]}" today.`, 235 | resp.data.msg, 236 | true 237 | ); 238 | // 前面检查过签到记录,说明没有今天的记录,说明漏记录一次签到,可能是手动签到的,数据补不回来了 239 | } 240 | } catch (e) { 241 | log(`[error]: check in "${variable["name"]}" failed: ${e}.`); 242 | notify(`check in "${variable["name"]}" failed`, e.message, true); 243 | } 244 | } else if (!sign) log(`[warning]: "${variable["name"]}" need to sign in`); 245 | 246 | // 保留5天记录 247 | while (variable["history"].length > 5) { 248 | variable["history"].pop(); 249 | } 250 | 251 | //不管成没成功,添加信息到配置 252 | if (variable["history"].length > 0) { 253 | if (!rawObj["proxies"]) rawObj["proxies"] = []; 254 | rawObj["proxies"].push( 255 | { 256 | name: `⏰ [${variable["name"]}]签到时间:${variable["history"][0]["checkinDate"]}`, 257 | server: "server", 258 | type: "http", 259 | port: 443, 260 | }, 261 | { 262 | name: `🎁 [${variable["name"]}]签到消息:${variable["history"][0]["checkinMessage"]}`, 263 | server: "server", 264 | type: "http", 265 | port: 443, 266 | } 267 | ); 268 | if (!rawObj["proxy-groups"]) rawObj["proxy-groups"] = []; 269 | if ( 270 | rawObj["proxy-groups"].length === 0 || 271 | rawObj["proxy-groups"][rawObj["proxy-groups"].length - 1]["name"] != 272 | "🤚 CHECK-INFO" 273 | ) { 274 | rawObj["proxy-groups"].push({ 275 | name: "🤚 CHECK-INFO", 276 | type: "select", 277 | proxies: [], 278 | }); 279 | } 280 | rawObj["proxy-groups"][rawObj["proxy-groups"].length - 1]["proxies"].push( 281 | rawObj["proxies"][rawObj["proxies"].length - 2]["name"], 282 | rawObj["proxies"][rawObj["proxies"].length - 1]["name"] 283 | ); 284 | if (debug) { 285 | log(`[debug]: rawObj['proxies']:`); 286 | log(`${JSON.stringify(rawObj["proxies"], null, 2)}`); 287 | log(`[debug]: rawObj['proxy-groups']:`); 288 | log(`${JSON.stringify(rawObj["proxy-groups"], null, 2)}`); 289 | } 290 | } 291 | 292 | return [yaml.stringify(rawObj), variable, should_modify]; 293 | } catch (e) { 294 | log(`[error]: "${variable["name"]}" something happened: ${e}.`); 295 | notify(`"${variable["name"]}" something happened`, e.message, true); 296 | throw e; 297 | } 298 | }; 299 | 300 | let auto_check_in = async (raw, { yaml, axios, console, notify }, { url }) => { 301 | // check yaml 302 | try { 303 | console.log(`see log in ${logFile}.`); 304 | var rawObj = yaml.parse(raw); 305 | } catch (e) { 306 | if ( 307 | e.message === "Implicit map keys need to be on a single line" && 308 | !new RegExp("^((?!www.example.com).)*$").test(url) 309 | ) { 310 | log("[warning]: raw is not yaml."); 311 | rawObj = { proxies: [], "proxy-groups": [], rules: [] }; 312 | } else { 313 | log(`[error]: check yaml fail: ${e}.`); 314 | throw e; 315 | } 316 | } 317 | 318 | // check log length 319 | checkLog(); 320 | 321 | //check variables.yml 322 | if (!existsSync(variable_path)) { 323 | log('[warning]: no found "./variables.yaml".'); 324 | throw 'no found "./variables.yaml"'; 325 | } 326 | var _variables = yaml.parse(readFileSync(variable_path, "utf-8")); 327 | if (!_variables["auto_check_in"]) { 328 | log("[warning]: no found auto_check_in variables."); 329 | notify(`auto-check-in failed`, "no found auto_check_in variables", true); 330 | return yaml.stringify(rawObj); 331 | } else var auto_check_in = _variables["auto_check_in"]; 332 | // skip reserve auto check in 333 | let reserve = auto_check_in.filter((item) => item["reserve"]); 334 | auto_check_in = auto_check_in.filter((item) => !item["reserve"]); 335 | // try check in 336 | try { 337 | if (debug) { 338 | log("[debug]: auto_check_in variables:"); 339 | log(`${JSON.stringify(auto_check_in, null, 2)}`); 340 | } 341 | raw = yaml.stringify(rawObj); 342 | let check_list = [...Array(auto_check_in.length)].map((_) => false); 343 | for (let i = 0; i < auto_check_in.length; i++) { 344 | [raw, auto_check_in[i], check_list[i]] = await check_in( 345 | raw, 346 | { yaml, axios, notify }, 347 | auto_check_in[i] 348 | ); 349 | } 350 | if (check_list.some((v) => v)) { 351 | if (debug) log("[debug]: have modified variables."); 352 | delete _variables["auto_check_in"]; 353 | writeFileSync( 354 | variable_path, 355 | yaml.stringify( 356 | { ..._variables, auto_check_in: auto_check_in.concat(reserve) }, 357 | null, 358 | 2 359 | ), 360 | "utf-8" 361 | ); 362 | } 363 | return raw; 364 | } catch (e) { 365 | log(`[error]: ${e}.`); 366 | throw e; 367 | } 368 | }; 369 | 370 | module.exports.parse = auto_check_in; 371 | -------------------------------------------------------------------------------- /bak/genpac.ini: -------------------------------------------------------------------------------- 1 | ; 配置示例 2 | ; 注: 命令中直接输入的选项优先级高于配置文件 3 | ; 布尔型的设置仅当为true时才为真 4 | 5 | ; 通用配置节点 6 | ; [job]节点使用其值作为默认值 7 | [config] 8 | ; gfwlist获取相关设置 9 | 10 | ; 完全禁止使用gfwlist 默认 false 11 | ; gfwlist-disabled = false 12 | 13 | ; gfwlist文件网址,留空使用默认,值为`-`则表示不在线获取 14 | ; gfwlist-url = https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt 15 | gfwlist-url = https://raw.githubusercontent.com/v2fly/domain-list-community/release/gfwlist.txt 16 | ; 获取gfwlist时的代理 17 | gfwlist-proxy = SOCKS5 localhost:2222 18 | 19 | ; gfwlist本地文件,在线地址获取失败时读取本地 20 | gfwlist-local = gfwlist-local 21 | 22 | ; 更新本地gfwlist文件 默认 false 23 | ; 当成功获取在线的gfwlist文件并且gfwlist-local存在,是否更新gfwlist-local 24 | gfwlist-update-local = true 25 | 26 | ; 保存解码后的gfwlist文件 用于开发测试 27 | ; gfwlist-decoded-save = gfwlist_.txt 28 | 29 | ; 用户自定义规则相关 30 | 31 | ; 规则,支持使用`,`或换行分割多个规则 32 | ; urer-rule = RULE1,RULE2,RULE3 33 | ; RULE4 34 | ; RULE5 35 | ; RULE6 36 | 37 | ; 规则文件,可使用`,`或换行分割多个文件 38 | user-rule-from = userrules.txt 39 | ; /PATH/TO/USER/RULE/FILE_3 40 | ; /PATH/TO/USER/RULE/FILE_4 41 | 42 | ; 默认输出格式,当下面的format节点没有指定格式时使用该值,最好不要在[config]中设置 43 | format = pac 44 | 45 | ; 输出文件 该值为空或`-`则输出到stdout 46 | output = pac 47 | 48 | 49 | ; 格式定义, 可重复, 所有选项可使用, 优先级高于[config]节点 50 | ; 支持[job]及[job:FORMAT]形式 51 | ; 每个节点表示一个任务, 因而多次使用可生成多个文件 52 | ; 注意节点中的FORMAT优先级高于config节点的format值但低于本节点的format值,如: 53 | ; 54 | ; [config] 55 | ; format = fmt1 56 | ; [job:fmt2] 57 | ; format = fmt3 58 | ; 59 | ; job:fmt2节点中选项format的值为 fmt3 60 | ; !建议不要在节点名和选项中重复指定FMT 61 | ;[job] 62 | ; format = pac 63 | ; 输出文件,将覆盖[config]中的同名选项 64 | ; output = /PATH/OUTPUT 65 | 66 | ; 可重复 67 | ;[job] 68 | ;[job:pac] 69 | ;[job:pac] 70 | 71 | ; 目前支持格式的具体配置 72 | ; PAC格式 73 | [job:pac] 74 | ; PAC文件中的代理 默认为空 75 | ; 注: 如果配置的是多条可选项,最好使用引号包围,如下面的例子 76 | pac-proxy = "SOCKS5 127.0.0.1:2222; PROXY 127.0.0.1:2222; DIRECT" 77 | ; 压缩,默认 false 78 | ; pac-compress = true 79 | ; 精确匹配 默认 false 80 | pac-precise = true 81 | 82 | ; DNSMASQ格式 83 | ;[job:dnsmasq] 84 | ; 解析符合规则的域名使用的dns服务器,形式:HOST#PORT 85 | ; dnsmasq-dns = 127.0.0.1#53 86 | ; ipset名 87 | ; dnsmasq-ipset = GFWLIST 88 | 89 | ; WINGY格式 90 | ;[job:wingy] 91 | ; adapter选项 92 | ; wingy-adapter-opts = 93 | ; 匹配规则使用的adapter ID 94 | ; wingy-rule-adapter-id = 95 | ; 自定义模板文件 96 | ; template = /PATH/TO/WINGY/TEMPLATE/FILE -------------------------------------------------------------------------------- /bak/genpac_script.bat: -------------------------------------------------------------------------------- 1 | genpac --config-from="genpac.ini" 2 | ::copy /y pac.txt userrules.txt .\Clash_configuration 3 | ::cd Clash_configuration 4 | ::git add . 5 | ::git commit -m "update pac" 6 | ::git push 7 | ::pause -------------------------------------------------------------------------------- /bak/parser_v1.0.js: -------------------------------------------------------------------------------- 1 | module.exports.parse = (raw, { yaml, notify }) => { 2 | const doc = yaml.parse(raw) 3 | //兼容性 4 | if (doc['proxies'] === undefined) { 5 | doc['proxies'] = doc['Proxy'] 6 | delete doc['Proxy'] 7 | doc['proxy-groups'] = doc['Proxy Group'] 8 | delete doc['Proxy Group'] 9 | doc['rules'] = doc['Rule'] 10 | delete doc['Rule'] 11 | } 12 | /* 使用subconvertor转换 13 | // 删除订阅本身包含的解锁节点 14 | var i = doc['proxies'].length 15 | while (i--) { 16 | if(doc['proxies'][i]['name'].indexOf("NeteaseUnblock") != -1){ 17 | doc['proxies'].splice(i,1) 18 | } 19 | } 20 | // 添加常用前缀 21 | var prefix = {'🇭🇰':'香港', '🇨🇳':'大陆','🇸🇬':'新加坡', '🇯🇵':'日本', 22 | '🇺🇸':'美国', '🇷🇺':'俄罗斯', '🇰🇷':'韩国', '🇦🇺':'澳大利亚', 23 | '🇩🇪':'德国', '🇬🇧':'英国', '🇻🇳':'越南', '🇹🇼':'台湾', 24 | '🇹🇭':'泰国', '🇮🇹':'意大利', '🇮🇳':'印度', '🇫🇷':'法国'} 25 | for(i = 0;i < doc['proxies'].length;i ++) { 26 | var shouldAdd = false 27 | var key_str = '' 28 | for(var key in prefix){ 29 | if(doc['proxies'][i]['name'].indexOf(key) != -1){ 30 | shouldAdd = false 31 | break 32 | } 33 | else if(doc['proxies'][i]['name'].indexOf(prefix[key]) != -1) { 34 | shouldAdd = true 35 | key_str = key 36 | } 37 | } 38 | if(shouldAdd){ 39 | doc['proxies'][i]['name'] = key_str + ' ' + doc['proxies'][i]['name'] 40 | } 41 | } 42 | */ 43 | //自动节点组,不包含解锁网易云音乐节点和自定义节点 44 | var proxies = [] 45 | doc['proxies'].forEach((v, i) => { 46 | proxies.push(v['name']) 47 | }) 48 | // 手动节点组,深拷贝 49 | var proxies_munual = JSON.parse(JSON.stringify(proxies)) 50 | //添加自定义节点名 51 | proxies_munual = proxies_munual.concat(['🇭🇰 Azure 亚洲','🇺🇸 IBM 达拉斯']) 52 | //规则组🚀⚙️🔓👋 53 | doc['proxy-groups'] = [ 54 | {'name':'👋Manual', 'type':'select', 'proxies':proxies_munual}, 55 | {'name':'⚙️Auto', 'type':'url-test', 'url':'http://www.gstatic.com/generate_204', 'interval':600, 'proxies':proxies}, 56 | {'name':'⛔️屏蔽广告', 'type':'select', 'proxies':['REJECT', '🐟漏网之鱼']}, 57 | {'name':'🐟漏网之鱼', 'type':'select', 'proxies':['🚀Proxy', 'DIRECT']}, 58 | {'name':'🚀Proxy', 'type':'select', 'proxies':['⚙️Auto', '👋Manual']}, 59 | {'name':'🔓解锁网易云灰色歌曲', 'type':'select', 'proxies':['DIRECT','🇨🇳 UNM_Network','🇯🇵 UNM-JP-PC','🇯🇵 UNM-CN-HHHT-PC']} 60 | ] 61 | //清理无用字典 62 | delete doc['rules'] 63 | delete doc['port'] 64 | delete doc['socks-port'] 65 | delete doc['mixed-port'] 66 | delete doc['redir-port'] 67 | delete doc['allow-lan'] 68 | delete doc['mode'] 69 | delete doc['log-level'] 70 | delete doc['external-controller'] 71 | delete doc['secret'] 72 | delete doc['cfw-bypass'] 73 | delete doc['cfw-latency-url'] 74 | delete doc['cfw-conn-break-strategy'] 75 | delete doc['cfw-child-process'] 76 | delete doc['cfw-latency-timeout'] 77 | delete doc['Rule'] 78 | delete doc['Proxy Group'] 79 | delete doc['Proxy'] 80 | notify("profile has been updated", "Personal rules has been updated.", true) 81 | return yaml.stringify(doc) 82 | } -------------------------------------------------------------------------------- /bak/parser_v2.0.js: -------------------------------------------------------------------------------- 1 | module.exports.parse = async (raw, { axios, yaml, notify, console }, { name, url, interval, selected, mode }) => { 2 | // 写log 3 | const fs = require('fs') 4 | const myDate = new Date() 5 | const log = function (text){ 6 | // log file路径 7 | let logFile = "C:\\Users\\YOURNAME\\.config\\clash\\logs\\cfw-parser.log" 8 | fs.appendFile(logFile, myDate.toLocaleString()+": "+text+"\n", function (err) { 9 | if (err) { 10 | console.log("error: ",err," ",myDate.toLocaleString(),",",text) 11 | throw err 12 | } 13 | }) 14 | } 15 | 16 | const rawObj = yaml.parse(raw) 17 | //规则组,往Manual里添加新增的非UNM节点,UNM添加到解锁组 18 | rawObj['proxies'].forEach((v, i) => { 19 | if(rawObj['proxy-groups'][0]['proxies'].findIndex(x => x === v['name']) === -1){ 20 | if(v['name'].indexOf('UNM') === -1){ 21 | rawObj['proxy-groups'][0]['proxies'].push(v['name']) 22 | } 23 | else{ 24 | rawObj['proxy-groups'][6]['proxies'].push(v['name']) 25 | } 26 | } 27 | }) 28 | /* //不支持proxy-providers ,subconverter会给删掉 29 | // 如果有proxy-providers则添加所含节点,否则删除 30 | if (rawObj['proxy-providers'] == undefined || JSON.stringify(rawObj['proxy-providers']) === "{}") { 31 | delete rawObj['proxy-providers'] 32 | } 33 | else { 34 | log("Found proxy-providers") 35 | rawObj['proxy-providers'].forEach((v, i) => { 36 | rawObj['proxy-groups'][0]['use'].push(v['name']) 37 | rawObj['proxy-groups'][1]['use'].push(v['name']) 38 | rawObj['proxy-groups'][2]['use'].push(v['name']) 39 | }) 40 | } 41 | */ 42 | delete rawObj['proxy-providers'] 43 | //清理无用字典 44 | delete rawObj['port'] 45 | delete rawObj['socks-port'] 46 | delete rawObj['mixed-port'] 47 | delete rawObj['redir-port'] 48 | delete rawObj['allow-lan'] 49 | delete rawObj['mode'] 50 | delete rawObj['log-level'] 51 | delete rawObj['external-controller'] 52 | delete rawObj['secret'] 53 | delete rawObj['cfw-bypass'] 54 | delete rawObj['cfw-latency-url'] 55 | delete rawObj['cfw-conn-break-strategy'] 56 | delete rawObj['cfw-child-process'] 57 | delete rawObj['cfw-latency-timeout'] 58 | delete rawObj['Rule'] 59 | delete rawObj['Proxy Group'] 60 | delete rawObj['Proxy'] 61 | 62 | const ret = yaml.stringify(rawObj) 63 | var message = "" 64 | // 不是新建配置,而是在更新订阅 65 | if(name){ 66 | // {关键词:文件名,关键词:文件名} 67 | const fileNames = {"v2ray":"clash"} 68 | let fileName = "" 69 | for(let key in fileNames){ 70 | if(name.indexOf(key) !== -1){ 71 | fileName = fileNames[key] 72 | break 73 | } 74 | } 75 | // 上传gist 76 | if(fileName){ 77 | // 添加dns,配合安卓Adgurd 78 | rawObj['dns'] = {'enable':true,'ipv6':true,'enhanced-mode':'redir-host', 79 | 'listen':'0.0.0.0:5450','nameserver':['8.8.8.8','223.5.5.5'], 80 | 'fallback':['https://dns.google/dns-query','https://1.1.1.1/dns-query', 81 | 'https://223.5.5.5/dns-query','https://9.9.9.9/dns-query'], 82 | 'fallback-filter':{'geoip':true,'ipcidr':['240.0.0.0/4']}} 83 | const upload = yaml.stringify(rawObj) 84 | let files = {} 85 | files[fileName] = {"content":upload} 86 | // gist id 87 | const gistId = "" 88 | // gitub api 获取的token, 需要勾选gist权限 89 | const token = "" 90 | axios.patch( 91 | 'https://api.github.com/gists/' + gistId, 92 | {"public":false,"files":files}, 93 | {headers:{"Content-Type":"application/json;charset='utf-8'","Authorization": "token "+token}}) 94 | .then((res) => { 95 | // 正则删除链接中的文件commit码 96 | var link = res["data"]["files"][fileName]["raw_url"].replace(/[a-z0-9]{40}\//i,"") 97 | message = "Profile \""+name+"\" has been updated. And successfully uploaded to gist:\"" 98 | +fileName+"\", file links is:"+link 99 | log(message) 100 | notify("Profile has been updated", message, true) 101 | }) 102 | .catch(err => { 103 | if (err.response) { 104 | // The request was made and the server responded with a status code 105 | // that falls out of the range of 2xx 106 | message = "Profile \""+name+"\" has been updated. But fail to upload to gist:\"" 107 | +fileName+"\", the request was made and the server responded with a fail status code," 108 | +" because "+JSON.stringify(err) 109 | notify("Profile has been updated", 110 | "profile \""+name+"\" has been updated. But fail to upload to gist:\"" 111 | +fileName+"\", see log for more details", true) 112 | } 113 | else if (err.request) { 114 | // The request was made but no response was received 115 | message = "Profile \""+name+"\" has been updated. And maybe successfully uploaded to gist:\"" 116 | +fileName+"\", the request was made but no response was received, because " 117 | +JSON.stringify(err.request) 118 | notify("Profile has been updated", 119 | "profile \""+name+"\" has been updated. And maybe successfully uploaded to gist:\"" 120 | +fileName+"\", see log for more details", true) 121 | } 122 | else { 123 | // Something happened in setting up the request that triggered an Error 124 | message = "Something happened: "+err.message+", see log for more details" 125 | notify("Profile updated fail", message, true) 126 | throw err 127 | } 128 | log(message) 129 | }) 130 | } 131 | // 不上传gist 132 | else { 133 | message = "Profile \""+name+"\" has been updated." 134 | log(message) 135 | notify("Profile has been updated", message, true) 136 | } 137 | } 138 | // 配置是新建的 139 | else { 140 | message = "A new profile has been added." 141 | log(message) 142 | notify("A new profile has been added", message, true) 143 | } 144 | return ret 145 | } -------------------------------------------------------------------------------- /bak/userrules.txt: -------------------------------------------------------------------------------- 1 | ! 用户自定义的代理规则 2 | ! 3 | ! 语法与gfwlist相同,即AdBlock Plus过滤规则 4 | ! 5 | ! 简单说明如下: 6 | ! 通配符支持,如 *.example.com/* 实际书写时可省略* 如.example.com/ 意即*.example.com/* 7 | ! 正则表达式支持,以\开始和结束, 如 \[\w]+:\/\/example.com\ 8 | ! 例外规则 @@,如 @@*.example.com/* 满足@@后规则的地址不使用代理 9 | ! 匹配地址开始和结尾 |,如 |http://example.com、example.com|分别表示以http://example.com开始和以example.com结束的地址 10 | ! || 标记,如 ||example.com 则http://example.com、https://example.com、ftp://example.com等地址均满足条件 11 | ! 注释 ! 如 ! Comment 12 | ! 13 | ! 更详细说明 请访问 http://adblockplus.org/en/filters 14 | ! 15 | ! 配置该文件时需谨慎,尽量避免与gfwlist产生冲突, 16 | ! 或将一些本不需要代理的网址添加到代理列表 17 | ! 可用test目录工具进行网址测试 18 | ! 19 | 20 | ! Tip: 在最终生成的PAC文件中,用户定义规则先于gfwlist规则被处理 21 | ! 因此可以在这里添加一些常用网址规则,或能减少在访问这些网址进行查询的时间 22 | ! 代理:域名DOMAIN:||,后缀DOMAIN-SUFFIX: . 23 | ! 直连:域名:@@||,后缀@@ 24 | 25 | ! 下面的直连 26 | @@geforce.com 27 | @@epicgames.com 28 | @@xboxlive.com 29 | @@s-microsoft.com 30 | @@office.com 31 | @@live.com 32 | @@microsoft.net 33 | @@microsoft.com 34 | @@||aka.ms 35 | @@msftauth.net 36 | @@msft*.com 37 | @@msauth.net 38 | @@xbox.com 39 | @@onestore.ms 40 | @@azureedge.* 41 | @@office365.com 42 | ! @@akamized.com 43 | @@windows.net 44 | @@windows.com 45 | @@windowsupdate.com 46 | @@msedge.net 47 | @@bing.com 48 | @@msecnd.com 49 | @@msecnd.net 50 | @@visualstudio.com 51 | @@microsoftonline.com 52 | @@pinyuncloud.com 53 | @@||cdn.jsdelivr.net 54 | @@||edge.activity.windows.com 55 | @@||edge.microsoft.com 56 | @@||client.wns.windows.com 57 | @@||config.edge.skype.com 58 | @@unpkg.com 59 | @@steampowered.com 60 | 61 | ! 下面的走代理 62 | .github*.com 63 | .ubi.com 64 | .ubisoft.com 65 | ||update.googleapis.com 66 | .uplay.com 67 | .usertrust.com 68 | .wemod.com 69 | .wikimedia.org 70 | .wixmp.com 71 | .steam-chat.com 72 | .steamcommunity.com 73 | .steamcontent.com 74 | ||steamcommunity-a.akamaihd.net 75 | ||steamuserimages-a.akamaihd.net 76 | .daumcdn.net 77 | .dropbox.com 78 | ||filezilla-project.org 79 | .github.io 80 | ||dl.google.com 81 | ||translate.googleapis.com 82 | .yandex* 83 | .beijingyongjiu.com -------------------------------------------------------------------------------- /broprint/code/EncryptDecrypt.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.cyrb53 = exports.javaHashCode = exports.murmurhash3_32_gc = void 0; 4 | // @ts-nocheck 5 | // https://github.com/artem0/canvas-fingerprinting/blob/master/hash/murmurhash3.js 6 | // output - 3705295134 a hashed number of the string. 7 | // https://en.wikipedia.org/wiki/MurmurHash 8 | function murmurhash3_32_gc(key, seed) { 9 | var remainder, bytes, h1, h1b, c1, c2, k1, i; 10 | remainder = key.length & 3; // key.length % 4 11 | bytes = key.length - remainder; 12 | h1 = seed; 13 | c1 = 0xcc9e2d51; 14 | c2 = 0x1b873593; 15 | i = 0; 16 | while (i < bytes) { 17 | k1 = 18 | ((key.charCodeAt(i) & 0xff)) | 19 | ((key.charCodeAt(++i) & 0xff) << 8) | 20 | ((key.charCodeAt(++i) & 0xff) << 16) | 21 | ((key.charCodeAt(++i) & 0xff) << 24); 22 | ++i; 23 | k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff; 24 | k1 = (k1 << 15) | (k1 >>> 17); 25 | k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff; 26 | h1 ^= k1; 27 | h1 = (h1 << 13) | (h1 >>> 19); 28 | h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff; 29 | h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16)); 30 | } 31 | k1 = 0; 32 | switch (remainder) { 33 | case 3: 34 | k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16; 35 | break; 36 | case 2: 37 | k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8; 38 | break; 39 | case 1: 40 | k1 ^= (key.charCodeAt(i) & 0xff); 41 | k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff; 42 | k1 = (k1 << 15) | (k1 >>> 17); 43 | k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff; 44 | h1 ^= k1; 45 | break; 46 | default: 47 | return 0; 48 | } 49 | h1 ^= key.length; 50 | h1 ^= h1 >>> 16; 51 | h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff; 52 | h1 ^= h1 >>> 13; 53 | h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff; 54 | h1 ^= h1 >>> 16; 55 | return h1 >>> 0; 56 | } 57 | exports.murmurhash3_32_gc = murmurhash3_32_gc; 58 | // taken from same above repo 59 | const javaHashCode = (string, K) => { 60 | var hash = 0; 61 | if (string.length === 0) { 62 | return hash; 63 | } 64 | let char; 65 | for (var i = 0; i < string.length; i++) { 66 | char = string.charCodeAt(i); 67 | hash = K * ((hash << 5) - hash) + char; 68 | hash = hash & hash; 69 | } 70 | return hash; 71 | }; 72 | exports.javaHashCode = javaHashCode; 73 | // reference - https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript#answer-52171480 74 | // output - 6533356943844037 75 | const cyrb52 = function (str, seed = 0) { 76 | let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed; 77 | for (let i = 0, ch; i < str.length; i++) { 78 | ch = str.charCodeAt(i); 79 | h1 = Math.imul(h1 ^ ch, 2654435761); 80 | h2 = Math.imul(h2 ^ ch, 1597334677); 81 | } 82 | h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909); 83 | h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909); 84 | return 4294967296 * (2097151 & h2) + (h1 >>> 0); 85 | }; 86 | 87 | 88 | const cyrb53 = function (str, seed = 0) { 89 | return cyrb52(str.slice(0,str.length/2 >> 0),seed) + "" + cyrb52(str.slice(str.length/2 >> 0),seed); 90 | }; 91 | 92 | 93 | exports.cyrb53 = cyrb53; 94 | -------------------------------------------------------------------------------- /broprint/code/GenerateCanvasFingerprint.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.getCanvasFingerprint = exports.isCanvasSupported = void 0; 4 | const isCanvasSupported = () => { 5 | var elem = document.createElement('canvas'); 6 | return !!(elem.getContext && elem.getContext('2d')); 7 | }; 8 | exports.isCanvasSupported = isCanvasSupported; 9 | // this working code snippet is taken from - https://github.com/artem0/canvas-fingerprinting/blob/master/fingerprinting/fingerprint.js 10 | const getCanvasFingerprint = () => { 11 | // If canvas is not supported simply return a static string 12 | if (!(0, exports.isCanvasSupported)()) 13 | return window.screen.height + "x" + window.screen.width; 14 | // draw a canvas of given text and return its data uri 15 | // different browser generates different dataUri based on their hardware configs 16 | var canvas = document.createElement('canvas'); 17 | var ctx = canvas.getContext('2d'); 18 | // https://www.browserleaks.com/canvas#how-does-it-work 19 | var txt = 'abz190#$%^@£éúGLaDOS!6.5[-%-&*]@345876 '; 20 | ctx.textBaseline = "top"; 21 | ctx.font = "32px 'Arial'"; 22 | ctx.textBaseline = "alphabetic"; 23 | ctx.fillStyle = "#f1680e"; 24 | ctx.fillRect(125, 1, 62, 20); 25 | ctx.fillStyle = "#0c6d9e"; 26 | ctx.fillText(txt, 2, 15); 27 | ctx.fillStyle = "rgba(102, 204, 0, 0.7)"; 28 | ctx.fillText(txt, 4, 17); 29 | ctx.fillStyle = "rgba(12, 24, 10, 0.2)"; 30 | ctx.fillText(txt, 10, 107); 31 | ctx.rotate(.03); 32 | ctx.fillText(txt, 4, 17); 33 | ctx.fillStyle = "rgb(155,255,5)"; 34 | ctx.shadowBlur=8; 35 | ctx.shadowColor="red"; 36 | ctx.fillRect(20,12,100,5); 37 | return canvas.toDataURL(); 38 | }; 39 | exports.getCanvasFingerprint = getCanvasFingerprint; 40 | -------------------------------------------------------------------------------- /broprint/code/generateTheAudioPrints.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.generateTheAudioFingerPrint = void 0; 4 | // ref = https://github.com/rickmacgillis/audio-fingerprint/blob/master/audio-fingerprinting.js 5 | // @ts-nocheck 6 | exports.generateTheAudioFingerPrint = (function () { 7 | var context = null; 8 | var currentTime = null; 9 | var oscillator = null; 10 | var compressor = null; 11 | var fingerprint = null; 12 | var callback = null; 13 | function run(cb, debug = false) { 14 | callback = cb; 15 | try { 16 | setup(); 17 | oscillator.connect(compressor); 18 | compressor.connect(context.destination); 19 | oscillator.start(0); 20 | context.startRendering(); 21 | context.oncomplete = onComplete; 22 | } 23 | catch (e) { 24 | if (debug) { 25 | throw e; 26 | } 27 | } 28 | } 29 | function setup() { 30 | setContext(); 31 | currentTime = context.currentTime; 32 | setOscillator(); 33 | setCompressor(); 34 | } 35 | function setContext() { 36 | var audioContext = window.OfflineAudioContext || window.webkitOfflineAudioContext; 37 | context = new audioContext(1, 44100, 44100); 38 | } 39 | function setOscillator() { 40 | oscillator = context.createOscillator(); 41 | oscillator.type = "triangle"; 42 | oscillator.frequency.setValueAtTime(10000, currentTime); 43 | } 44 | function setCompressor() { 45 | compressor = context.createDynamicsCompressor(); 46 | setCompressorValueIfDefined('threshold', -50); 47 | setCompressorValueIfDefined('knee', 40); 48 | setCompressorValueIfDefined('ratio', 12); 49 | setCompressorValueIfDefined('reduction', -20); 50 | setCompressorValueIfDefined('attack', 0); 51 | setCompressorValueIfDefined('release', .25); 52 | } 53 | function setCompressorValueIfDefined(item, value) { 54 | if (compressor[item] !== undefined && typeof compressor[item].setValueAtTime === 'function') { 55 | compressor[item].setValueAtTime(value, context.currentTime); 56 | } 57 | } 58 | function onComplete(event) { 59 | generateFingerprints(event); 60 | compressor.disconnect(); 61 | } 62 | function generateFingerprints(event) { 63 | var output = null; 64 | for (var i = 4500; 5e3 > i; i++) { 65 | var channelData = event.renderedBuffer.getChannelData(0)[i]; 66 | output += Math.abs(channelData); 67 | } 68 | fingerprint = output.toString(); 69 | if (typeof callback === 'function') { 70 | return callback(fingerprint); 71 | } 72 | } 73 | return { 74 | run: run 75 | }; 76 | })(); 77 | -------------------------------------------------------------------------------- /broprint/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.getCurrentBrowserFingerPrint = void 0; 4 | const EncryptDecrypt_1 = require("./code/EncryptDecrypt"); 5 | const GenerateCanvasFingerprint_1 = require("./code/GenerateCanvasFingerprint"); 6 | const generateTheAudioPrints_1 = require("./code/generateTheAudioPrints"); 7 | /** 8 | * This functions working 9 | * @Param {null} 10 | * @return {Promise} - resolve(string) 11 | */ 12 | const getCurrentBrowserFingerPrint = () => { 13 | /** 14 | * @return {Promise} - a frequency number 120.256896523 15 | * @reference - https://fingerprintjs.com/blog/audio-fingerprinting/ 16 | */ 17 | const getTheAudioPrints = new Promise((resolve, reject) => { 18 | generateTheAudioPrints_1.generateTheAudioFingerPrint.run(function (fingerprint) { 19 | resolve(fingerprint); 20 | }); 21 | }); 22 | /** 23 | * 24 | * @param {null} 25 | * @return {Promise} - and sha512 hashed string 26 | */ 27 | const DevicePrints = new Promise((resolve, reject) => { 28 | getTheAudioPrints.then((audioChannelResult) => { 29 | let fingerprint = window.btoa(audioChannelResult) + (0, GenerateCanvasFingerprint_1.getCanvasFingerprint)(); 30 | // using btoa to hash the values to looks better readable 31 | resolve((0, EncryptDecrypt_1.cyrb53)(fingerprint, 0)); 32 | }).catch(() => { 33 | try { 34 | // if failed with audio fingerprint then resolve only with canvas fingerprint 35 | resolve((0, EncryptDecrypt_1.cyrb53)((0, GenerateCanvasFingerprint_1.getCanvasFingerprint)()).toString()); 36 | } 37 | catch (error) { 38 | reject("Failed to generate the finger print of this browser"); 39 | } 40 | }); 41 | }); 42 | return DevicePrints; 43 | }; 44 | exports.getCurrentBrowserFingerPrint = getCurrentBrowserFingerPrint; 45 | -------------------------------------------------------------------------------- /glados-checkin.js: -------------------------------------------------------------------------------- 1 | const { 2 | readFileSync, 3 | writeFileSync, 4 | existsSync, 5 | appendFileSync, 6 | } = require("fs"); 7 | const { resolve, join } = require("path"); 8 | const { homedir } = require("os"); 9 | const variable_path = resolve(__dirname, "./variables.yaml"); 10 | const { getCurrentBrowserFingerPrint } = require("./broprint"); 11 | const myDate = new Date(); 12 | const debug = false; 13 | const homeDirectory = join(homedir(), ".config/clash"); 14 | // log file路径 15 | const logFile = join(homeDirectory, "logs/cfw-autocheckin.log"); 16 | let newParse = true; 17 | const maxLogLine = 20000; 18 | 19 | // 检查日志行数,超过maxLogLine切半 20 | const checkLog = function () { 21 | if (!existsSync(logFile)) { 22 | log( 23 | "[warn]: doesn't find log file: cfw-autocheckin.log, Automatically create it." 24 | ); 25 | } 26 | const lines = readFileSync(logFile, "utf-8").toString().split("\n"); 27 | if (lines.length > maxLogLine) { 28 | let start = Math.round(lines.length / 2); 29 | //从有意义的日期开始切 30 | while (!/-{2,}.*-{2,}/.test(lines[start]) && start < lines.length) { 31 | start++; 32 | } 33 | //backup old file 34 | writeFileSync(logFile + ".bak", lines.join("\n"), "utf-8"); 35 | //write new log 36 | writeFileSync(logFile, lines.slice(start).join("\n"), "utf-8"); 37 | log( 38 | `[info]: log line count is: ${lines.length} larger than ${maxLogLine}, cut it by half.` 39 | ); 40 | } else if (debug) { 41 | log(`[debug]: log line count is: ${lines.length}`); 42 | } 43 | }; 44 | 45 | const log = function (text) { 46 | if (newParse) { 47 | appendFileSync( 48 | logFile, 49 | `\n --------------${myDate.toLocaleString()}--------------\n`, 50 | "utf-8" 51 | ); 52 | newParse = false; 53 | } 54 | appendFileSync(logFile, text + "\n", "utf-8"); 55 | }; 56 | 57 | let axios; 58 | let yaml; 59 | const puppeteer = require('puppeteer-extra'); 60 | const StealthPlugin = require('puppeteer-extra-plugin-stealth'); 61 | const { Agent } = require("http"); 62 | 63 | puppeteer.use(StealthPlugin()); 64 | 65 | const INFO = { 66 | account: '账号', 67 | leftDays: '天数', 68 | checkInMessage: '签到情况', 69 | checkInFailed: '签到失败', 70 | getStatusFailed: '获取信息失败', 71 | authorization: '', 72 | 'koa:sess.sig': "", 73 | "koa:sess": "", 74 | "mailcode": "" 75 | }; 76 | 77 | const rawCookie2JSON = (cookie) => { 78 | return cookie.split(/\s*;\s*/).reduce((pre, current) => { 79 | const pair = current.split(/\s*=\s*/); 80 | const name = pair[0]; 81 | const value = pair.splice(1).join('='); 82 | return [ 83 | ...pre, 84 | { 85 | name, 86 | value, 87 | 'domain': 'glados.rocks' 88 | } 89 | ]; 90 | }, []); 91 | }; 92 | 93 | function waitForOneMinute() { 94 | return new Promise(resolve => { 95 | setTimeout(() => { 96 | resolve(); 97 | }, 60000); 98 | }); 99 | } 100 | 101 | const getAuthorization = async () => { 102 | const fingerPrint = await getCurrentBrowserFingerPrint(); 103 | return fingerPrint + "-" + window.screen.height + "-" + window.screen.width; 104 | } 105 | 106 | const login = async () => { 107 | const browser = await puppeteer.launch({ 108 | headless: true, 109 | executablePath: 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 110 | args: ['--proxy-server=socks5://127.0.0.1:2222'] 111 | }); 112 | 113 | const page = await browser.newPage(); 114 | 115 | await page.goto('https://glados.rocks/login', { 116 | timeout: 0, 117 | waitUntil: 'load' 118 | }); 119 | 120 | page.on('console', msg => { 121 | log(msg.text()); 122 | }); 123 | 124 | var _variables = yaml.parse(readFileSync(variable_path, "utf-8")); 125 | INFO.mail = _variables['GlaDOSAutoCheckin']["mail"] 126 | 127 | await page.evaluate(async (INFO) => { 128 | const auth = () => 129 | fetch('https://glados.rocks/api/authorization', { 130 | method: 'POST', 131 | headers: { 132 | 'Content-Type': 'application/json;charset=UTF-8', 133 | // hack broprint 134 | Authorization: INFO.authorization, 135 | }, 136 | body: JSON.stringify({ 137 | "address": INFO.mail, 138 | "site": "glados.network" 139 | }), 140 | }).catch(error => { 141 | return { reason: '网络错误' + error.message } 142 | }); 143 | 144 | const authRes = await auth(); 145 | if (!authRes.ok) { 146 | const reason = authRes.reason || `状态码:${authRes.status}`; 147 | console.log(reason); 148 | } else { 149 | const { message } = await authRes.json(); 150 | console.log(message); 151 | } 152 | }, INFO); 153 | 154 | log(`fill 'GlaDOSAutoCheckin: mailcode' with your login code sent to your email: ${INFO.email} in 1 minute`); 155 | await waitForOneMinute(); 156 | 157 | _variables = yaml.parse(readFileSync(variable_path, "utf-8")); 158 | INFO.mailcode = _variables['GlaDOSAutoCheckin']["mailcode"].toString(); 159 | if (!INFO.mailcode) { 160 | log("login code empty"); 161 | await browser.close(); 162 | return _variables; 163 | } 164 | 165 | await page.evaluate(async (INFO) => { 166 | const login = () => fetch('https://glados.rocks/api/login', { 167 | method: "POST", 168 | headers: { 169 | 'Content-Type': 'application/json;charset=UTF-8', 170 | // hack broprint 171 | Authorization: INFO.authorization, 172 | }, 173 | body: JSON.stringify({ 174 | "method": "email", 175 | "site": "glados.network", 176 | "email": INFO.mail, 177 | "mailcode": INFO.mailcode 178 | }) 179 | }).catch(error => { 180 | console.log('网络错误: ' + error.message) 181 | return { reason: '网络错误: ' + error.message } 182 | }); 183 | 184 | const loginRes = await login(); 185 | if (!loginRes.ok) { 186 | const reason = loginRes.reason || `状态码:${loginRes.status}`; 187 | console.log(reason); 188 | } else { 189 | const message = await loginRes.json(); 190 | console.log(JSON.stringify(message)); 191 | } 192 | }, INFO); 193 | 194 | const cookies = await page.cookies(); 195 | 196 | const koaSessCookie = cookies.find(cookie => cookie.name === 'koa:sess'); 197 | if (koaSessCookie) { 198 | log(`koaSessCookie: ${koaSessCookie.value}`); // 输出 Cookie 的值 199 | INFO['koa:sess'] = koaSessCookie.value 200 | } else { 201 | log('Cookie "koa:sess" not found'); 202 | } 203 | 204 | const koaSessSigCookie = cookies.find(cookie => cookie.name === 'koa:sess.sig'); 205 | if (koaSessSigCookie) { 206 | log(`koaSessSigCookie ${koaSessSigCookie.value}`); // 输出 Cookie 的值 207 | INFO['koa:sess.sig'] = koaSessSigCookie.value 208 | } else { 209 | log('Cookie "koa:sess" not found'); 210 | } 211 | await browser.close(); 212 | 213 | if (!INFO['koa:sess.sig'] || !INFO['koa:sess']) { 214 | log("get cookie failed") 215 | return _variables; 216 | } 217 | 218 | _variables['GlaDOSAutoCheckin']['cookie'] = `koa:sess=${INFO["koa:sess"]}; koa:sess.sig=${INFO["koa:sess.sig"]}`; 219 | writeFileSync(variable_path, yaml.stringify(_variables), "utf-8"); 220 | return _variables; 221 | } 222 | 223 | const checkInAndGetStatus = async (cookie) => { 224 | const browser = await puppeteer.launch({ 225 | headless: true, 226 | executablePath: 'C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe', 227 | args: ['--proxy-server=socks5://127.0.0.1:2222'] 228 | }); 229 | 230 | const page = await browser.newPage(); 231 | 232 | const cookieJSON = rawCookie2JSON(cookie); 233 | await page.setCookie(...cookieJSON); 234 | 235 | await page.goto('https://glados.rocks/console/checkin', { 236 | timeout: 0, 237 | waitUntil: 'load' 238 | }); 239 | 240 | page.on('console', msg => { 241 | log(msg.text()); 242 | }); 243 | 244 | const info = await page.evaluate(async (INFO) => { 245 | const checkIn = () => 246 | fetch('https://glados.rocks/api/user/checkin', { 247 | method: 'POST', 248 | headers: { 249 | 'Content-Type': 'application/json;charset=UTF-8', 250 | // hack broprint 251 | Authorization: INFO.authorization, 252 | }, 253 | body: JSON.stringify({ 254 | token: "glados.one" 255 | }), 256 | }).catch(error => { 257 | return { reason: '网络错误' + error.message } 258 | }); 259 | 260 | const getStatus = () => fetch('https://glados.rocks/api/user/status', { 261 | headers: { 262 | 'Content-Type': 'application/json;charset=UTF-8', 263 | // hack broprint 264 | Authorization: INFO.authorization, 265 | }, 266 | }).catch(error => { 267 | console.log('网络错误: ' + error.message) 268 | return { reason: '网络错误: ' + error.message } 269 | }); 270 | 271 | let ret = {}; 272 | 273 | const checkInRes = await checkIn(); 274 | if (!checkInRes.ok) { 275 | const reason = checkInRes.reason || `状态码:${checkInRes.status}`; 276 | ret[INFO.checkInFailed] = reason; 277 | console.log(reason); 278 | } else { 279 | const { message } = await checkInRes.json(); 280 | ret[INFO.checkInMessage] = message; 281 | console.log(message); 282 | } 283 | 284 | const statusRes = await getStatus(); 285 | if (!statusRes.ok) { 286 | const reason = statusRes.reason || `状态码:${statusRes.status}`; 287 | console.log(reason) 288 | ret[INFO.getStatusFailed] = reason; 289 | } else { 290 | const stateJson = await statusRes.json(); 291 | const { data: { email, phone, leftDays } = {} } = stateJson; 292 | console.log(JSON.stringify(stateJson)) 293 | let account = '未知账号'; 294 | if (email) { 295 | account = email.replace(/^(.)(.*)(.@.*)$/, 296 | (_, a, b, c) => a + b.replace(/./g, '*') + c 297 | ); 298 | } else if (phone) { 299 | account = phone.replace(/^(.)(.*)(.)$/, 300 | (_, a, b, c) => a + b.replace(/./g, '*') + c 301 | ); 302 | } 303 | ret[INFO.account] = account; 304 | ret[INFO.leftDays] = parseInt(leftDays); 305 | } 306 | 307 | return ret; 308 | }, INFO); 309 | 310 | await browser.close(); 311 | 312 | return info; 313 | }; 314 | 315 | const pushplus = (token, info) => { 316 | const data = { 317 | token, 318 | title: 'GLaDOS签到', 319 | content: JSON.stringify(info), 320 | template: 'json' 321 | }; 322 | log('pushData', { 323 | ...data, 324 | token: data.token.replace(/^(.{1,4})(.*)(.{4,})$/, (_, a, b, c) => a + b.replace(/./g, '*') + c) 325 | }); 326 | 327 | return axios({ 328 | method: 'post', 329 | url: `http://www.pushplus.plus/send`, 330 | data 331 | }).catch((error) => { 332 | if (error.response) { 333 | // 请求成功发出且服务器也响应了状态码,但状态代码超出了 2xx 的范围 334 | log(`PUSHPLUS推送 请求失败,状态码:${error.response.status}`); 335 | } else if (error.request) { 336 | // 请求已经成功发起,但没有收到响应 337 | log('PUSHPLUS推送 网络错误'); 338 | } else { 339 | // 发送请求时出了点问题 340 | log('Axios Error', error.message); 341 | } 342 | }); 343 | }; 344 | 345 | let auto_check_in = async (raw, { yaml: _yaml, axios: _axios, console, notify }, { url }) => { 346 | axios = _axios; 347 | yaml = _yaml; 348 | // check log length 349 | checkLog(); 350 | 351 | //check variables.yml 352 | if (!existsSync(variable_path)) { 353 | log('[warning]: no found "./variables.yaml".'); 354 | throw 'no found "./variables.yaml"'; 355 | } 356 | var _variables = yaml.parse(readFileSync(variable_path, "utf-8")); 357 | 358 | if (!_variables["GlaDOSAutoCheckin"]) { 359 | log("[warning]: no found GlaDOSAutoCheckin variables."); 360 | notify(`auto-check-in failed`, "no found GlaDOSAutoCheckin variables", true); 361 | return raw; 362 | } 363 | 364 | INFO.authorization = await getAuthorization(); 365 | 366 | // try check in 367 | try { 368 | if (!_variables["GlaDOSAutoCheckin"]["cookie"]) { 369 | _variables = await login() 370 | } 371 | if (!_variables["GlaDOSAutoCheckin"]["cookie"]) { 372 | log("login failed"); 373 | return raw; 374 | } 375 | const info = await checkInAndGetStatus(_variables["GlaDOSAutoCheckin"]["cookie"]); 376 | log(JSON.stringify(info)) 377 | notify(`GlaDOS 签到`, `剩余天数: ${info[INFO.leftDays]}`, true); 378 | const pushResult = (await pushplus(_variables["GlaDOSAutoCheckin"]["plusplusToken"], info))?.data?.msg; 379 | log(pushResult); 380 | } catch (e) { 381 | log(`[error]: ${e}.`); 382 | return raw; 383 | } 384 | return raw; 385 | }; 386 | 387 | module.exports.parse = auto_check_in; -------------------------------------------------------------------------------- /subconverter/base/all_base.tpl: -------------------------------------------------------------------------------- 1 | {% if request.target == "clash" or request.target == "clashr" %} 2 | 3 | port: {{ default(global.clash.http_port, "7890") }} 4 | socks-port: {{ default(global.clash.socks_port, "7891") }} 5 | allow-lan: {{ default(global.clash.allow_lan, "true") }} 6 | mixed-port: {{ default(global.clash.mixed_port, "7890") }} 7 | mode: {{ default(global.clash.mode, "Rule") }} 8 | log-level: {{ default(global.clash.log_level, "info") }} 9 | external-controller: {{ default(global.clash.external_controller, ":9090") }} 10 | {% if default(request.clash.dns, "") == "1" %} 11 | dns: 12 | enabled: true 13 | listen: 1053 14 | {% endif %} 15 | {% if local.clash.new_field_name == "true" %} 16 | proxies: ~ 17 | proxy-groups: ~ 18 | rules: ~ 19 | {% else %} 20 | Proxy: ~ 21 | Proxy Group: ~ 22 | Rule: ~ 23 | {% endif %} 24 | 25 | {% endif %} 26 | {% if request.target == "surge" %} 27 | 28 | [General] 29 | loglevel = notify 30 | bypass-system = true 31 | skip-proxy = 127.0.0.1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,100.64.0.0/10,localhost,*.local,e.crashlytics.com,captive.apple.com,::ffff:0:0:0:0/1,::ffff:128:0:0:0/1 32 | #DNS设置或根据自己网络情况进行相应设置 33 | bypass-tun = 192.168.0.0/16,10.0.0.0/8,172.16.0.0/12 34 | dns-server = 119.29.29.29,223.5.5.5 35 | 36 | [Script] 37 | http-request https?:\/\/.*\.iqiyi\.com\/.*authcookie= script-path=https://raw.githubusercontent.com/NobyDa/Script/master/iQIYI-DailyBonus/iQIYI.js 38 | 39 | {% endif %} 40 | {% if request.target == "loon" %} 41 | 42 | [General] 43 | skip-proxy = 192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,localhost,*.local,e.crashlynatics.com 44 | bypass-tun = 10.0.0.0/8,100.64.0.0/10,127.0.0.0/8,169.254.0.0/16,172.16.0.0/12,192.0.0.0/24,192.0.2.0/24,192.88.99.0/24,192.168.0.0/16,198.18.0.0/15,198.51.100.0/24,203.0.113.0/24,224.0.0.0/4,255.255.255.255/32 45 | dns-server = system,119.29.29.29,223.5.5.5 46 | allow-udp-proxy = false 47 | host = 127.0.0.1 48 | 49 | [Proxy] 50 | 51 | [Remote Proxy] 52 | 53 | [Proxy Group] 54 | 55 | [Rule] 56 | 57 | [Remote Rule] 58 | 59 | [URL Rewrite] 60 | enable = true 61 | ^https?:\/\/(www.)?(g|google)\.cn https://www.google.com 302 62 | 63 | [Remote Rewrite] 64 | https://raw.githubusercontent.com/Loon0x00/LoonExampleConfig/master/Rewrite/AutoRewrite_Example.list,auto 65 | 66 | [MITM] 67 | hostname = *.example.com,*.sample.com 68 | enable = true 69 | skip-server-cert-verify = true 70 | #ca-p12 = 71 | #ca-passphrase = 72 | 73 | {% endif %} 74 | {% if request.target == "quan" %} 75 | 76 | [SERVER] 77 | 78 | [SOURCE] 79 | 80 | [BACKUP-SERVER] 81 | 82 | [SUSPEND-SSID] 83 | 84 | [POLICY] 85 | 86 | [DNS] 87 | 1.1.1.1 88 | 89 | [REWRITE] 90 | 91 | [URL-REJECTION] 92 | 93 | [TCP] 94 | 95 | [GLOBAL] 96 | 97 | [HOST] 98 | 99 | [STATE] 100 | STATE,AUTO 101 | 102 | [MITM] 103 | 104 | {% endif %} 105 | {% if request.target == "quanx" %} 106 | 107 | [general] 108 | excluded_routes=192.168.0.0/16, 172.16.0.0/12, 100.64.0.0/10, 10.0.0.0/8 109 | geo_location_checker=http://ip-api.com/json/?lang=zh-CN, https://github.com/KOP-XIAO/QuantumultX/raw/master/Scripts/IP_API.js 110 | network_check_url=http://www.baidu.com/ 111 | server_check_url=http://www.gstatic.com/generate_204 112 | 113 | [dns] 114 | server=119.29.29.29 115 | server=223.5.5.5 116 | server=1.0.0.1 117 | server=8.8.8.8 118 | 119 | [policy] 120 | static=♻️ 自动选择, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Auto.png 121 | static=🔰 节点选择, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Proxy.png 122 | static=🌍 国外媒体, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/GlobalMedia.png 123 | static=🌏 国内媒体, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/DomesticMedia.png 124 | static=Ⓜ️ 微软服务, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Microsoft.png 125 | static=📲 电报信息, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Telegram.png 126 | static=🍎 苹果服务, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Apple.png 127 | static=🎯 全球直连, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Direct.png 128 | static=🛑 全球拦截, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Advertising.png 129 | static=🐟 漏网之鱼, direct, img-url=https://raw.githubusercontent.com/Koolson/Qure/master/IconSet/Final.png 130 | 131 | [server_remote] 132 | 133 | [filter_remote] 134 | 135 | [rewrite_remote] 136 | 137 | [server_local] 138 | 139 | [filter_local] 140 | 141 | [rewrite_local] 142 | 143 | [mitm] 144 | 145 | {% endif %} 146 | {% if request.target == "mellow" %} 147 | 148 | [Endpoint] 149 | DIRECT, builtin, freedom, domainStrategy=UseIP 150 | REJECT, builtin, blackhole 151 | Dns-Out, builtin, dns 152 | 153 | [Routing] 154 | domainStrategy = IPIfNonMatch 155 | 156 | [Dns] 157 | hijack = Dns-Out 158 | clientIp = 114.114.114.114 159 | 160 | [DnsServer] 161 | localhost 162 | 223.5.5.5 163 | 8.8.8.8, 53, Remote 164 | 8.8.4.4 165 | 166 | [DnsRule] 167 | DOMAIN-KEYWORD, geosite:geolocation-!cn, Remote 168 | DOMAIN-SUFFIX, google.com, Remote 169 | 170 | [DnsHost] 171 | doubleclick.net = 127.0.0.1 172 | 173 | [Log] 174 | loglevel = warning 175 | 176 | {% endif %} 177 | {% if request.target == "surfboard" %} 178 | 179 | [General] 180 | loglevel = notify 181 | interface = 127.0.0.1 182 | skip-proxy = 127.0.0.1, 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12, 100.64.0.0/10, localhost, *.local 183 | ipv6 = false 184 | dns-server = system, 223.5.5.5 185 | exclude-simple-hostnames = true 186 | enhanced-mode-by-rule = true 187 | {% endif %} 188 | {% if request.target == "sssub" %} 189 | { 190 | "route": "bypass-lan-china", 191 | "remote_dns": "dns.google", 192 | "ipv6": false, 193 | "metered": false, 194 | "proxy_apps": { 195 | "enabled": false, 196 | "bypass": true, 197 | "android_list": [ 198 | "com.eg.android.AlipayGphone", 199 | "com.wudaokou.hippo", 200 | "com.zhihu.android" 201 | ] 202 | }, 203 | "udpdns": false 204 | } 205 | 206 | {% endif %} 207 | -------------------------------------------------------------------------------- /subconverter/pref.yml: -------------------------------------------------------------------------------- 1 | common: 2 | api_mode: false 3 | api_access_token: password 4 | default_url: [] 5 | enable_insert: true 6 | insert_url: [] 7 | prepend_insert_url: true 8 | exclude_remarks: ["(到期|剩余流量|时间|官网|产品)"] 9 | include_remarks: [] 10 | enable_filter: false 11 | filter_script: "" 12 | default_external_config: "" # config/example_external_config.yml 13 | base_path: base 14 | clash_rule_base: base/all_base.tpl 15 | surge_rule_base: base/all_base.tpl 16 | surfboard_rule_base: base/all_base.tpl 17 | mellow_rule_base: base/all_base.tpl 18 | quan_rule_base: base/all_base.tpl 19 | quanx_rule_base: base/all_base.tpl 20 | loon_rule_base: base/all_base.tpl 21 | sssub_rule_base: base/all_base.tpl 22 | # http://127.0.0.1:2222 23 | proxy_config: http://127.0.0.1:2222 24 | proxy_ruleset: http://127.0.0.1:2222 25 | proxy_subscription: http://127.0.0.1:2222 26 | append_proxy_type: false 27 | 28 | userinfo: 29 | stream_rule: 30 | - {match: "^剩余流量:(.*?)\\|总流量:(.*)$", replace: "total=$2&left=$1"} 31 | - {match: "^剩余流量:(.*?) (.*)$", replace: "total=$1&left=$2"} 32 | - {match: "^Bandwidth: (.*?)/(.*)$", replace: "used=$1&total=$2"} 33 | - {match: "^.*剩余(.*?)(?:\\s*?)@(?:.*)$", replace: "total=$1"} 34 | - {match: "^.*?流量:(.*?) 剩:(?:.*)$", replace: "total=$1"} 35 | time_rule: 36 | - {match: "^过期时间:(\\d+)-(\\d+)-(\\d+) (\\d+):(\\d+):(\\d+)$", replace: "$1:$2:$3:$4:$5:$6"} 37 | - {match: "^到期时间(:|:)(\\d+)-(\\d+)-(\\d+)$", replace: "$1:$2:$3:0:0:0"} 38 | - {match: "^Smart Access expire: (\\d+)/(\\d+)/(\\d+)$", replace: "$1:$2:$3:0:0:0"} 39 | - {match: "^.*?流量:(?:.*?) 剩:(.*?)天$", replace: "left=$1d"} 40 | 41 | node_pref: 42 | # udp_flag: false 43 | # tcp_fast_open_flag: false 44 | # skip_cert_verify_flag: false 45 | # tls13_flag: true 46 | sort_flag: false 47 | sort_script: "" 48 | filter_deprecated_nodes: false 49 | append_sub_userinfo: true 50 | clash_use_new_field_name: true 51 | clash_proxies_style: block 52 | rename_node: 53 | # - {match: "\\(?((x|X)?(\\d+)(\\.?\\d+)?)((\\s?倍率?)|(x|X))\\)?", replace: "$1x"} 54 | # - {script: "function rename(node){}"} 55 | # - {script: "path:/path/to/script.js"} 56 | #- {import: snippets/rename_node.txt} 57 | 58 | managed_config: 59 | write_managed_config: true 60 | managed_config_prefix: "http://127.0.0.1:25500" 61 | config_update_interval: 86400 62 | config_update_strict: false 63 | quanx_device_id: "" 64 | 65 | surge_external_proxy: 66 | surge_ssr_path: "" # /usr/bin/ssr-local 67 | resolve_hostname: true 68 | 69 | emojis: 70 | add_emoji: true 71 | remove_old_emoji: true 72 | rules: 73 | # - {match: "(流量|时间|应急)", emoji: "🏳️‍🌈"} 74 | # - {script: "function getEmoji(node){}"} 75 | # - {script: "path:/path/to/script.js"} 76 | - {import: snippets/emoji.txt} 77 | 78 | rulesets: 79 | enabled: false 80 | overwrite_original_rules: true 81 | update_ruleset_on_request: false 82 | rulesets: 83 | # - {rule: "GEOIP,CN", group: "DIRECT"} 84 | # - {ruleset: "rules/LocalAreaNetwork.list", group: "DIRECT"} 85 | # - {ruleset: "surge:rules/LocalAreaNetwork.list", group: "DIRECT"} 86 | # - {ruleset: "quanx:https://raw.githubusercontent.com/ConnersHua/Profiles/master/Quantumult/X/Filter/Advertising.list", group: "Advertising", interval: 86400} 87 | # - {ruleset: "clash-domain:https://ruleset.dev/clash_domestic_services_domains", group: "Domestic Services", interval: 86400} 88 | # - {ruleset: "clash-ipcidr:https://ruleset.dev/clash_domestic_services_ips", group: "Domestic Services", interval: 86400} 89 | # - {ruleset: "clash-classic:https://raw.githubusercontent.com/DivineEngine/Profiles/master/Clash/RuleSet/China.yaml", group: "DIRECT", interval: 86400} 90 | # - {import: snippets/rulesets.txt} 91 | 92 | proxy_groups: 93 | custom_proxy_group: 94 | # - {name: UrlTest, type: url-test, rule: [".*"], url: http://www.gstatic.com/generate_204, interval: 300, tolerance: 100, timeout: 5} 95 | # - {name: Proxy, type: select, rule: [".*"]} 96 | # - {name: group1, type: select, rule: ["!!GROUPID=0"]} 97 | # - {name: v2ray, type: select, rule: ["!!GROUP=V2RayProvider"]} 98 | # - {import: snippets/groups_forcerule.txt} 99 | # - {name: ssid group, type: ssid, rule: ["default_group", "celluar=group0,ssid1=group1,ssid2=group2"]} 100 | - {import: snippets/groups_clash.txt} 101 | 102 | template: 103 | template_path: templates 104 | globals: 105 | #- {key: clash.http_port, value: 7890} 106 | #- {key: clash.socks_port, value: 7891} 107 | #- {key: clash.allow_lan, value: true} 108 | - {key: clash.log_level, value: info} 109 | - {key: clash.mixed_port, value: 6666} 110 | - {key: clash.external_controller, value: ':19090'} 111 | - {key: clash.allow_lan, value: true} 112 | - {key: clash.mode, value: Rule} 113 | 114 | aliases: 115 | - {uri: /v, target: /version} 116 | - {uri: /clash, target: "/sub?target=clash"} 117 | - {uri: /clashr, target: "/sub?target=clashr"} 118 | - {uri: /surge, target: "/sub?target=surge"} 119 | - {uri: /quan, target: "/sub?target=quan"} 120 | - {uri: /quanx, target: "/sub?target=quanx"} 121 | - {uri: /mellow, target: "/sub?target=mellow"} 122 | - {uri: /surfboard, target: "/sub?target=surfboard"} 123 | - {uri: /loon, target: "/sub?target=loon"} 124 | - {uri: /ss, target: "/sub?target=ss"} 125 | - {uri: /ssd, target: "/sub?target=ssd"} 126 | - {uri: /sssub, target: "/sub?target=sssub"} 127 | - {uri: /ssr, target: "/sub?target=ssr"} 128 | - {uri: /v2ray, target: "/sub?target=v2ray"} 129 | - {uri: /trojan, target: "/sub?target=trojan"} 130 | 131 | server: 132 | listen: 0.0.0.0 133 | port: 25500 134 | serve_file_root: "" 135 | 136 | advanced: 137 | log_level: info 138 | print_debug_info: false 139 | max_pending_connections: 10240 140 | max_concurrent_threads: 2 141 | max_allowed_rulesets: 0 142 | max_allowed_rules: 0 143 | max_allowed_download_size: 0 144 | enable_cache: true 145 | cache_subscription: 60 146 | cache_config: 300 147 | cache_ruleset: 21600 148 | async_fetch_ruleset: false 149 | skip_failed_links: false 150 | -------------------------------------------------------------------------------- /subconverter/snippets/emoji.txt: -------------------------------------------------------------------------------- 1 | ((?