├── FILES ├── etc │ ├── rc.local │ ├── config │ │ ├── clash │ │ │ ├── clash-dashboard │ │ │ │ ├── yacd.ico │ │ │ │ ├── registerSW.js │ │ │ │ ├── manifest.webmanifest │ │ │ │ ├── assets │ │ │ │ │ ├── TwemojiCountryFlags-9f04f144.woff2 │ │ │ │ │ ├── Rec.module-c7e11c0c.js │ │ │ │ │ ├── Modal-86bce5c3.css │ │ │ │ │ ├── useRemainingViewPortHeight-3d85719a.js │ │ │ │ │ ├── postcss.config.js │ │ │ │ │ ├── Rec-312c2e4e.css │ │ │ │ │ ├── TextFilter-ced87fc6.css │ │ │ │ │ ├── Select-dedf689a.js │ │ │ │ │ ├── Refresh-9ad264f8.js │ │ │ │ │ ├── Config-cf41b8ef.css │ │ │ │ │ ├── Select-3de40504.css │ │ │ │ │ ├── Modal.module-ed8aaa1f.js │ │ │ │ │ ├── Rules-e11cb70e.css │ │ │ │ │ ├── index.modern-c58ff412.js │ │ │ │ │ ├── Rec-a6497d9f.js │ │ │ │ │ ├── logs-e2001386.js │ │ │ │ │ ├── zh-8b65fcca.js │ │ │ │ │ ├── Logs-5e5ee0ad.css │ │ │ │ │ ├── Fab-e423cc40.js │ │ │ │ │ ├── TextFilter-78284216.js │ │ │ │ │ ├── play-d4b35340.js │ │ │ │ │ ├── debounce-c1ba2006.js │ │ │ │ │ ├── en-eb14609d.js │ │ │ │ │ ├── Connections-ddae4f70.css │ │ │ │ │ ├── Logs-d0203c28.js │ │ │ │ │ ├── Proxies-40f80166.css │ │ │ │ │ ├── Fab-a434d836.css │ │ │ │ │ ├── Config-68e91a0b.js │ │ │ │ │ ├── sha.js │ │ │ │ │ ├── index.esm-af95069f.js │ │ │ │ │ ├── Proxies-92327b11.js │ │ │ │ │ ├── Rules-77f1d37d.js │ │ │ │ │ └── index-454097a7.css │ │ │ │ ├── index_base.html │ │ │ │ └── net_rec_show.html │ │ │ ├── socks5.yaml │ │ │ └── base.yaml │ │ ├── network │ │ └── system │ ├── banner │ └── profile └── usr │ └── bin │ ├── reload │ ├── watch.sh │ ├── nft_tcp.sh │ └── nft.sh ├── .gitignore ├── Dockerfile ├── custom.config.sh ├── patch.sh ├── .github └── workflows │ ├── release.yml │ ├── docker-latest-schedule.yml │ └── docker-latest-schedule -with-fullmod.yml ├── makeiso.sh ├── pkg.conf ├── remakeiso.sh ├── ReadMe.md └── ppgw.go /FILES/etc/rc.local: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | /usr/bin/ppg.sh & 3 | exit 0 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | iso/ 2 | ppgw/ 3 | FILES/usr/bin/ppgw 4 | renote.txt 5 | go.mod 6 | go.sum 7 | ppgw.exe -------------------------------------------------------------------------------- /FILES/usr/bin/reload: -------------------------------------------------------------------------------- 1 | if [ -f /tmp/ppgw.ini ]; then 2 | . /tmp/ppgw.ini 3 | fi 4 | /usr/bin/ppg.sh reload -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/yacd.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkkgo/PaoPaoGateWay/HEAD/FILES/etc/config/clash/clash-dashboard/yacd.ico -------------------------------------------------------------------------------- /FILES/etc/config/clash/socks5.yaml: -------------------------------------------------------------------------------- 1 | proxies: 2 | - name: "ppgwsocks" 3 | type: socks5 4 | server: "{socks5_ip}" 5 | port: {socks5_port} 6 | udp: true -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/registerSW.js: -------------------------------------------------------------------------------- 1 | if('serviceWorker' in navigator) {window.addEventListener('load', () => {navigator.serviceWorker.register('./sw.js', { scope: './' })})} -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/manifest.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"yacd","short_name":"yacd","start_url":"./","display":"standalone","background_color":"#ffffff","lang":"en","scope":"./"} 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/TwemojiCountryFlags-9f04f144.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkkgo/PaoPaoGateWay/HEAD/FILES/etc/config/clash/clash-dashboard/assets/TwemojiCountryFlags-9f04f144.woff2 -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Rec.module-c7e11c0c.js: -------------------------------------------------------------------------------- 1 | const _="_body_1e6s5_3",s="_h1_1e6s5_7",o="_oh1_1e6s5_13",h="_h3_1e6s5_19",n="_h4_1e6s5_23",t="_link_1e6s5_28",e={body:_,h1:s,oh1:o,h3:h,h4:n,link:t};export{e as s}; 2 | -------------------------------------------------------------------------------- /FILES/etc/config/network: -------------------------------------------------------------------------------- 1 | config interface 'loopback' 2 | option device 'lo' 3 | option proto 'static' 4 | option ipaddr '127.0.0.1' 5 | option netmask '255.0.0.0' 6 | config interface 'eth0' 7 | option device 'eth0' 8 | option proto 'dhcp' 9 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Modal-86bce5c3.css: -------------------------------------------------------------------------------- 1 | ._overlay_1i06e_1{position:fixed;top:0;right:0;left:0;bottom:0;background:#444}._content_1i06e_10{outline:none;position:relative;color:var(--color-text);background:#444;top:50%;left:50%;transform:translate(-50%,-50%);padding:20px;border-radius:10px} 2 | -------------------------------------------------------------------------------- /FILES/etc/config/system: -------------------------------------------------------------------------------- 1 | config system 2 | option hostname 'PaoPaoGW' 3 | option ttylogin '0' 4 | option log_size '64' 5 | option urandom_seed '0' 6 | option zonename 'Asia/Shanghai' 7 | option timezone 'CST-8' 8 | config timeserver 'ntp' 9 | option enabled '0' 10 | option enable_server '0' -------------------------------------------------------------------------------- /FILES/etc/banner: -------------------------------------------------------------------------------- 1 | _____ _____ 2 | | __ \ | __ \ 3 | | |__) |_ _ ___ | |__) |_ _ ___ 4 | | ___/ _` |/ _ \| ___/ _` |/ _ \ 5 | | | | (_| | (_) | | | (_| | (_) | 6 | |_| \__,_|\___/|_| \__,_|\___/ 7 | 8 | == Welcome to PaoPao Gateway == 9 | == Reload Config : reload == 10 | 11 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/useRemainingViewPortHeight-3d85719a.js: -------------------------------------------------------------------------------- 1 | import{e as r}from"./index-969cf72a.js";const{useState:s,useRef:u,useCallback:a,useLayoutEffect:c}=r;function d(){const t=u(null),[n,i]=s(200),e=a(()=>{const{top:o}=t.current.getBoundingClientRect();i(window.innerHeight-o)},[]);return c(()=>(e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}),[e]),[t,n]}export{d as u}; 2 | -------------------------------------------------------------------------------- /FILES/etc/profile: -------------------------------------------------------------------------------- 1 | [ -f /etc/banner ] && cat /etc/banner 2 | 3 | export PATH="/usr/sbin:/usr/bin:/sbin:/bin" 4 | export HOME=$(grep -e "^${USER:-root}:" /etc/passwd | cut -d ":" -f 6) 5 | export HOME=${HOME:-/root} 6 | export PS1='\u@\h:\w\$ ' 7 | export ENV=/etc/shinit 8 | ulimit -SHn 1048576 9 | case "$TERM" in 10 | xterm*|rxvt*) 11 | export PS1='\[\e]0;\u@\h: \w\a\]'$PS1 12 | ;; 13 | esac 14 | 15 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/postcss.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // '--breakpoint-not-small': 'screen and (min-width: 30em)', 4 | // '--breakpoint-medium': 'screen and (min-width: 30em) and (max-width: 60em)', 5 | // '--breakpoint-large': 'screen and (min-width: 60em)', 6 | 7 | module.exports = { 8 | plugins: [ 9 | require('postcss-import')(), 10 | require('postcss-simple-vars')(), 11 | require('autoprefixer')(), 12 | ], 13 | }; 14 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Rec-312c2e4e.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";._body_1e6s5_3{font-family:Arial,sans-serif}._h1_1e6s5_7{font-size:36px;color:#9c27b0;margin:20px 0}._oh1_1e6s5_13{font-size:36px;color:#ff6f00;margin:20px 0}._h3_1e6s5_19{font-size:24px}._h4_1e6s5_23{font-size:12px;color:#666}._link_1e6s5_28{display:inline-block;padding:10px 20px;background-color:#007bff;color:#fff;text-decoration:none;border:2px solid #007bff;border-radius:5px;transition:background-color .3s,color .3s;margin-right:20px}._link_1e6s5_28:hover{background-color:#0056b3;border-color:#0056b3}._link_1e6s5_28:active{background-color:#003d71;border-color:#003d71} 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:edge AS singbuilder 2 | RUN apk add go git && apk upgrade 3 | WORKDIR /data 4 | RUN git clone https://github.com/kkkgo/box.git box 5 | WORKDIR /data/box 6 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags "-s -w -extldflags -static" -trimpath -tags "" -o /data/sing-box ./cmd/sing-box 7 | FROM alpine:edge 8 | WORKDIR /data 9 | COPY ./remakeiso.sh / 10 | COPY ./root.7z / 11 | COPY --from=singbuilder /data/sing-box /sing-box 12 | COPY --from=sliamb/opbuilder /src/isolinux /isolinux 13 | RUN apk add --no-cache xorriso 7zip && chmod +x /sing-box && chmod +x /remakeiso.sh 14 | ENV sha="rootsha" 15 | ENV SNIFF=no 16 | ENTRYPOINT ["/remakeiso.sh"] -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/TextFilter-ced87fc6.css: -------------------------------------------------------------------------------- 1 | ._rotate_1dspl_1{display:inline-flex}._isRotating_1dspl_5{animation:_rotating_1dspl_1 3s infinite linear;animation-fill-mode:forwards}@keyframes _rotating_1dspl_1{0%{transform:rotate(0)}to{transform:rotate(360deg)}}._input_16a1f_1{-webkit-appearance:none;background-color:var(--color-input-bg);background-image:none;border-radius:20px;border:1px solid var(--color-input-border);box-sizing:border-box;color:#c1c1c1;display:inline-block;font-size:inherit;outline:none;padding:8px 15px;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}._input_16a1f_1:focus{border:1px solid var(--color-focus-blue)} 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Select-dedf689a.js: -------------------------------------------------------------------------------- 1 | import{r as a,j as t,a9 as r}from"./index-969cf72a.js";function g({id:o,checked:s,disabled:c,onChange:e}){const[l,u]=a.useState(!!s),p=a.useRef(!!s);a.useEffect(()=>{p.current!==s&&u(!!s),p.current=!!s},[s]);const f=a.useCallback(n=>{c||(u(n),e&&e(n))},[c,e]);return t.jsxs("label",{className:r.toggle,children:[t.jsx("input",{className:r.input,id:o,type:"checkbox",onChange:n=>f(n.target.checked),checked:l,disabled:c}),t.jsx("span",{className:r.track})]})}const x="_select_13zm8_1",m={select:x};function i({options:o,selected:s,onChange:c}){return t.jsx("select",{className:m.select,value:s,onChange:c,children:o.map(([e,l])=>t.jsx("option",{value:e,children:l},e))})}export{i as S,g as T}; 2 | -------------------------------------------------------------------------------- /FILES/usr/bin/watch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | getsha256() { 4 | echo -n "$1" | sha256sum | cut -d" " -f1 5 | } 6 | 7 | home="/etc/config/clash/clash-dashboard/" 8 | 9 | if [ -f /tmp/ppgw.ini ]; then 10 | echo 1 >/etc/watch 11 | . /tmp/ppgw.ini 2>/dev/tty0 12 | secret="$(getsha256 "$clash_web_password")" 13 | stamp=$(date +%s)$(cat /dev/urandom | tr -cd 'a-zA-Z0-9' | head -c 64) 14 | echo "{\"stamp\": \"$stamp\"}" >"$home/stamp.json" 15 | stamp_key=$(getsha256 "$stamp""$secret") 16 | reload_touch="$home/${stamp_key}reload.json" 17 | cp "$home/stamp.json" "$reload_touch" 18 | inotifywait -e access -e close_nowrite "$reload_touch" 19 | rm "$home/stamp.json" 20 | rm "$reload_touch" 21 | rm /etc/watch 22 | /usr/bin/ppg.sh reload 23 | fi 24 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/base.yaml: -------------------------------------------------------------------------------- 1 | port: 0 2 | socks-port: 0 3 | redir-port: 0 4 | tproxy-port: 1082 5 | mixed-port: 1080 6 | allow-lan: {openport} 7 | bind-address: '127.0.0.1' 8 | mode: {clashmode} 9 | external-controller: 0.0.0.0:{clash_web_port} 10 | #interface-name: tun114 11 | external-ui: /etc/config/clash/clash-dashboard 12 | secret: {clash_web_password} 13 | log-level: info 14 | ipv6: false 15 | profile: 16 | store-fake-ip: true 17 | store-selected: true 18 | hosts: 19 | paopaogateway.dns: 127.0.0.1 20 | dns: 21 | enable: true 22 | use-hosts: false 23 | use-system-hosts: false 24 | listen: 0.0.0.0:53 25 | ipv6: false 26 | enhanced-mode: fake-ip 27 | fake-ip-range: {fake_cidr} 28 | nameserver: 29 | - {dns_ip}:{dns_port}#eth0 30 | 31 | #mihomo exclude 32 | tls: 33 | external-controller-tls: 34 | external-ui-name: 35 | external-ui-url: 36 | tun: 37 | enable: false 38 | ebpf: 39 | sniffer: 40 | enable: false 41 | listeners: 42 | find-process-mode: -------------------------------------------------------------------------------- /FILES/usr/bin/nft_tcp.sh: -------------------------------------------------------------------------------- 1 | #!/usr/sbin/nft -f 2 | 3 | flush ruleset 4 | 5 | table ip ppgw { 6 | set localnetwork { 7 | typeof ip daddr 8 | flags interval 9 | elements = { 10 | 0.0.0.0/8, 11 | 127.0.0.0/8, 12 | 10.0.0.0/8, 13 | 169.254.0.0/16, 14 | 172.16.0.0/12, 15 | 192.168.0.0/16, 16 | 224.0.0.0/4, 17 | 240.0.0.0-255.255.255.255 18 | } 19 | } 20 | 21 | chain clashtcp { 22 | type filter hook prerouting priority mangle; policy accept; 23 | ip daddr @localnetwork return 24 | ip protocol tcp tproxy to 127.0.0.1:1082 meta mark set 1 25 | } 26 | 27 | chain fakeping { 28 | type nat hook prerouting priority 0; policy accept; 29 | ip protocol icmp dnat to 127.0.0.1 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /custom.config.sh: -------------------------------------------------------------------------------- 1 | CONFIG_TARGET_ROOTFS_TARGZ=n 2 | CONFIG_TARGET_ROOTFS_EXT4FS=n 3 | CONFIG_GRUB_EFI_IMAGES=n 4 | CONFIG_GRUB_TIMEOUT="0" 5 | CONFIG_GRUB_CONSOLE=n 6 | CONFIG_TARGET_ROOTFS_CPIOGZ=n 7 | CONFIG_GRUB_TITLE="PaoPao Gateway" 8 | CONFIG_VERSION_DIST="PaoPao Gateway" 9 | CONFIG_VERSION_NUMBER="PPGW_version" 10 | CONFIG_ISO_IMAGES=y 11 | CONFIG_TARGET_IMAGES_GZIP=n 12 | CONFIG_SIGNED_PACKAGES=n 13 | CONFIG_SIGNATURE_CHECK=n 14 | 15 | CONFIG_IPV6=n 16 | BUSYBOX_DEFAULT_FEATURE_IPV6=n 17 | IPV6=n 18 | KERNEL_IPV6=n 19 | KERNEL_IPV6_MROUTE=n 20 | KERNEL_IPV6_MROUTE_MULTIPLE_TABLES=n 21 | KERNEL_IPV6_MULTIPLE_TABLES=n 22 | KERNEL_IPV6_PIMSM_V2=n 23 | KERNEL_IPV6_SEG6_LWTUNNEL=n 24 | KERNEL_IPV6_SUBTREES=n 25 | CONFIG_JSON_OVERVIEW_IMAGE_INFO=n 26 | CONFIG_SIGNED_PACKAGES=n 27 | CONFIG_SIGNATURE_CHECK=n 28 | CONFIG_CLEAN_IPKG=y 29 | CONFIG_KERNEL_IPV6_PIMSM_V2=n 30 | CONFIG_STRIP_KERNEL_EXPORTS=n 31 | CONFIG_PACKAGE_openwrt-keyring=n 32 | 33 | CONFIG_BUSYBOX_DEFAULT_CRONTAB=n 34 | BUSYBOX_CONFIG_CROND=n 35 | BUSYBOX_DEFAULT_CROND=n -------------------------------------------------------------------------------- /FILES/usr/bin/nft.sh: -------------------------------------------------------------------------------- 1 | #!/usr/sbin/nft -f 2 | 3 | flush ruleset 4 | 5 | table ip ppgw { 6 | set localnetwork { 7 | typeof ip daddr 8 | flags interval 9 | elements = { 10 | 0.0.0.0/8, 11 | 127.0.0.0/8, 12 | 10.0.0.0/8, 13 | 169.254.0.0/16, 14 | 172.16.0.0/12, 15 | 192.168.0.0/16, 16 | 224.0.0.0/4, 17 | 240.0.0.0-255.255.255.255 18 | } 19 | } 20 | 21 | chain clashboth { 22 | type filter hook prerouting priority mangle; policy accept; 23 | ip daddr @localnetwork return 24 | ip protocol tcp tproxy to 127.0.0.1:1082 meta mark set 1 25 | ip protocol udp tproxy to 127.0.0.1:1082 meta mark set 1 26 | } 27 | 28 | chain fakeping { 29 | type nat hook prerouting priority 0; policy accept; 30 | ip protocol icmp dnat to 127.0.0.1 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Refresh-9ad264f8.js: -------------------------------------------------------------------------------- 1 | import{r as p,u,j as r}from"./index-969cf72a.js";import{s as o}from"./Rec.module-c7e11c0c.js";function x(){const[a,t]=p.useState(!1),{t:e}=u();async function l(){t(!0);try{if(!window.confirm(e("confirm_refresh"))){t(!1);return}const c=Math.floor(Date.now()/1e3),i=await fetch(`./stamp.json?=${c}`);if(!i.ok)throw new Error("Failed to fetch stamp");const{stamp:f}=await i.json(),h="PaoPaoGateWay",s=JSON.parse(localStorage.getItem(h));if(!s||!s.clashAPIConfigs||!s.clashAPIConfigs[0].secret)throw new Error("Secret not found");const d=s.clashAPIConfigs[0].secret,m=sha256(f+d);if(!(await fetch(`./${m}reload.json?=${c}`)).ok)throw new Error("Reload failed");alert(e("refresh_success"))}catch(n){console.error(n),alert(e("refresh_fail"))}finally{t(!1)}}return r.jsxs("div",{className:o.body,children:[" ",r.jsx("h1",{className:o.oh1,children:e("refresh_title")}),r.jsx("h3",{className:o.h3,children:e("refresh_tips")}),r.jsx("button",{onClick:l,disabled:a,className:o.link,children:e(a?"loading":"Refresh")})]})}export{x as default}; 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Config-cf41b8ef.css: -------------------------------------------------------------------------------- 1 | ._root_1s1gc_1,._section_1s1gc_2{display:grid;grid-template-columns:repeat(auto-fill,minmax(345px,1fr));max-width:900px;gap:5px}@media screen and (min-width: 30em){._root_1s1gc_1,._section_1s1gc_2{gap:15px}}._root_1s1gc_1 ._item_1s1gc_14,._section_1s1gc_2 ._item_1s1gc_14{margin-top:11px}._root_1s1gc_1 ._item_1s1gc_14 label,._section_1s1gc_2 ._item_1s1gc_14 label{padding-left:12px}._root_1s1gc_1,._section_1s1gc_2{padding:6px 15px 10px}@media screen and (min-width: 30em){._root_1s1gc_1,._section_1s1gc_2{padding:10px 40px 15px}}._sep_1s1gc_34{max-width:900px;padding:0 15px}@media screen and (min-width: 30em){._sep_1s1gc_34{padding:0 40px}}._sep_1s1gc_34>div{border-top:1px dashed #373737}._label_1s1gc_47{padding:11px 0}._fieldset_1ghjp_1{margin:0;padding:0;border:0;display:flex;flex-wrap:wrap}._input_1ghjp_9+._cnt_1ghjp_9{border:1px solid transparent;border-radius:8px;cursor:pointer;margin-right:5px;margin-bottom:5px}._input_1ghjp_9:focus+._cnt_1ghjp_9{border-color:#387cec}._input_1ghjp_9:checked+._cnt_1ghjp_9{border-color:#387cec} 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Select-3de40504.css: -------------------------------------------------------------------------------- 1 | ._select_13zm8_1{height:40px;line-height:1.5;width:100%;padding-left:8px;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:var(--color-input-bg);color:var(--color-text);padding-right:20px;border-radius:4px;border:1px solid var(--color-input-border);background-image:url(data:image/svg+xml,%0A%20%20%20%20%3Csvg%20width%3D%228%22%20height%3D%2224%22%20viewBox%3D%220%200%208%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%207L7%2011H1L4%207Z%22%20fill%3D%22%23999999%22%20%2F%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%2017L1%2013L7%2013L4%2017Z%22%20fill%3D%22%23999999%22%20%2F%3E%0A%20%20%20%20%3C%2Fsvg%3E%0A%20%20);background-position:right 8px center;background-repeat:no-repeat}._select_13zm8_1:hover,._select_13zm8_1:focus{border-color:#343434;outline:none!important;color:var(--color-text-highlight);background-image:var(--select-bg-hover)}._select_13zm8_1:focus{box-shadow:#4299e199 0 0 0 3px}._select_13zm8_1 option{background-color:var(--color-background)} 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Modal.module-ed8aaa1f.js: -------------------------------------------------------------------------------- 1 | import{r as f,R as c,P as a}from"./index-969cf72a.js";function s(){return s=Object.assign||function(e){for(var o=1;o=0)&&Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}function u(e,o){if(e==null)return{};var r={},t=Object.keys(e),n,i;for(i=0;i=0)&&(r[n]=e[n]);return r}var l=f.forwardRef(function(e,o){var r=e.color,t=r===void 0?"currentColor":r,n=e.size,i=n===void 0?24:n,p=v(e,["color","size"]);return c.createElement("svg",s({ref:o,xmlns:"http://www.w3.org/2000/svg",width:i,height:i,viewBox:"0 0 24 24",fill:"none",stroke:t,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},p),c.createElement("polyline",{points:"6 9 12 15 18 9"}))});l.propTypes={color:a.string,size:a.oneOfType([a.string,a.number])};l.displayName="ChevronDown";const m=l,y="_overlay_1i06e_1",g="_content_1i06e_10",w={overlay:y,content:g};export{m as C,w as m}; 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Rules-e11cb70e.css: -------------------------------------------------------------------------------- 1 | ._RuleProviderItem_12aid_1{display:grid;grid-template-columns:40px 1fr 46px;height:100%}._left_12aid_7{display:inline-flex;align-items:center;color:var(--color-text-secondary);opacity:.4}._middle_12aid_14{display:grid;gap:6px;grid-template-rows:1fr auto auto;align-items:center}._gray_12aid_21{color:#777}._action_12aid_25{display:grid;gap:4px;grid-template-columns:auto 1fr;align-items:center}._refreshBtn_12aid_32{padding:5px}._rule_1kxgd_1{display:flex;align-items:center;padding:6px 15px}@media screen and (min-width: 30em){._rule_1kxgd_1{padding:10px 40px}}._left_1kxgd_12{width:40px;padding-right:15px;color:var(--color-text-secondary);opacity:.4}._a_1kxgd_19{display:flex;align-items:center;font-size:12px;opacity:.8}._b_1kxgd_26{padding:10px 0;font-family:Roboto Mono,Menlo,monospace;font-size:16px}@media screen and (min-width: 30em){._b_1kxgd_26{font-size:19px}}._type_1kxgd_37{width:110px}._header_n1m95_1{display:grid;grid-template-columns:1fr minmax(auto,330px);align-items:center;padding-right:15px}@media screen and (min-width: 30em){._header_n1m95_1{padding-right:40px}}._RuleProviderItemWrapper_n1m95_17{padding:6px 15px}@media screen and (min-width: 30em){._RuleProviderItemWrapper_n1m95_17{padding:10px 40px}} 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/index.modern-c58ff412.js: -------------------------------------------------------------------------------- 1 | var f=new Map;function s(t){if(f.has(t))return f.get(t);var a=v(t);return f.set(t,a),a}var v=function(){var t=null;try{t=document.createElement("canvas").getContext("2d")}catch{}if(!t)return function(){return!1};var a=25,e=20,u=Math.floor(a/2);return t.font=u+"px Arial, Sans-Serif",t.textBaseline="top",t.canvas.width=e*2,t.canvas.height=a,function(n){t.clearRect(0,0,e*2,a),t.fillStyle="#FF0000",t.fillText(n,0,22),t.fillStyle="#0000FF",t.fillText(n,e,22);for(var l=t.getImageData(0,0,e,a).data,o=l.length,r=0;r=o)return!1;var c=e+r/4%e,p=Math.floor(r/4/e),i=t.getImageData(c,p,1,1).data;return!(l[r]!==i[0]||l[r+2]!==i[2]||t.measureText(n).width>=e)}}();function E(t="Twemoji Country Flags",a="https://cdn.jsdelivr.net/npm/country-flag-emoji-polyfill@0.1/dist/TwemojiCountryFlags.woff2"){if(s("😊")&&!s("🇨🇭")){const e=document.createElement("style");return e.textContent=`@font-face { 2 | font-family: "${t}"; 3 | unicode-range: U+1F1E6-1F1FF, U+1F3F4, U+E0062-E0063, U+E0065, U+E0067, 4 | U+E006C, U+E006E, U+E0073-E0074, U+E0077, U+E007F; 5 | src: url('${a}') format('woff2'); 6 | font-display: swap; 7 | }`,document.head.appendChild(e),!0}return!1}export{E as polyfillCountryFlagEmojis}; 8 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Rec-a6497d9f.js: -------------------------------------------------------------------------------- 1 | import{u as p,r as c,j as e}from"./index-969cf72a.js";import{s}from"./Rec.module-c7e11c0c.js";function k(){const{t}=p(),[l,i]=c.useState("./data.csv");c.useEffect(()=>{const n=Math.floor(Date.now()/1e3);fetch(`./reckey.json?=${n}`).then(a=>a.json()).then(a=>{const r=a.reckey;if(r){const d="PaoPaoGateWay",o=JSON.parse(localStorage.getItem(d));if(o&&o.clashAPIConfigs&&o.clashAPIConfigs[0].secret){const f=o.clashAPIConfigs[0].secret,m=sha256(r+f);i(`./rec_data/${m}/data.csv`)}}else throw new Error("Invalid reckey")}).catch(a=>{console.error("Error:",a),alert(`尚未生成数据或者监控程序未启动,请确保ppgw.ini的net_rec=yes 2 | The data has not been generated, or the monitoring program has not started. Please ensure that net_rec=yes in ppgw.ini.`),window.location.href="/ui"})},[]);function h(n){n.button===0&&(alert(`请右键点击链接并选择 '另存为' 来下载表格文件,并修改后缀为CSV。 3 | Please right-click on the link and select 'Save As' to download the CSV.`),n.preventDefault())}return e.jsxs("div",{className:s.body,children:[" ",e.jsx("h1",{className:s.h1,children:t("netrec")}),e.jsx("h3",{className:s.h4,children:t("netrec_data_no")}),e.jsx("h3",{className:s.h3,children:t("netrec_data")}),e.jsxs("p",{children:[e.jsx("a",{href:l,id:"downloadLink",onMouseDown:h,className:s.link,children:t("downcsv")})," "]}),e.jsxs("p",{children:[e.jsx("a",{href:"./net_rec_show.html",target:"_blank",className:s.link,children:t("loadonline")})," "]})]})}export{k as default}; 4 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/logs-e2001386.js: -------------------------------------------------------------------------------- 1 | import{H as w,I as D,J as u}from"./index-969cf72a.js";const v="/logs",L=new TextDecoder("utf-8"),M=()=>Math.floor((1+Math.random())*65536).toString(16);let h=!1,i=!1,f="",s,g;function m(e,n){let t;try{t=JSON.parse(e)}catch{console.log("JSON.parse error",JSON.parse(e))}const r=new Date,l=$(r);t.time=l,t.id=+r-0+M(),t.even=h=!h,n(t)}function $(e){const n=e.getFullYear()%100,t=u(e.getMonth()+1,2),r=u(e.getDate(),2),l=u(e.getHours(),2),o=u(e.getMinutes(),2),c=u(e.getSeconds(),2);return`${n}-${t}-${r} ${l}:${o}:${c}`}function p(e,n){return e.read().then(({done:t,value:r})=>{const l=L.decode(r,{stream:!t});f+=l;const o=f.split(` 2 | `),c=o[o.length-1];for(let d=0;de[t]).join("|")}let b,a;function k(e,n){if(e.logLevel==="uninit"||i||s&&s.readyState===1)return;g=n;const t=w(e,v);s=new WebSocket(t),s.addEventListener("error",()=>{y(e,n)}),s.addEventListener("message",function(r){m(r.data,n)})}function H(){s.close(),a&&a.abort()}function J(e){!g||!s||(s.close(),i=!1,k(e,g))}function y(e,n){if(a&&S(e)!==b)a.abort();else if(i)return;i=!0,b=S(e),a=new AbortController;const t=a.signal,{url:r,init:l}=D(e);fetch(r+v+"?level="+e.logLevel,{...l,signal:t}).then(o=>{const c=o.body.getReader();p(c,n)},o=>{i=!1,!t.aborted&&console.log("GET /logs error:",o.message)})}export{k as f,J as r,H as s}; 3 | -------------------------------------------------------------------------------- /patch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo $1 3 | cd "$1" 4 | 5 | rm etc/banner.failsafe 6 | rm etc/board.d/01_leds 7 | rm -rf etc/capabilities 8 | rm etc/init.d/gpio_switch 9 | rm etc/init.d/led 10 | rm etc/openwrt_release 11 | rm etc/openwrt_version 12 | rm etc/os-release 13 | rm etc/rc.d/K10gpio_switch 14 | rm etc/rc.d/S94gpio_switch 15 | rm etc/rc.d/S96led 16 | rm etc/sysupgrade.conf 17 | rm -rf etc/rc.button 18 | rm -rf etc/opkg 19 | rm -rf lib/upgrade 20 | rm -rf usr/lib/opkg 21 | rm -rf usr/lib/os-release 22 | rm sbin/firstboot 23 | rm sbin/sysupgrade 24 | rm sbin/wifi 25 | rm -rf usr/lib/share/acl.d 26 | rm -rf usr/lib/share/libubox 27 | cd lib/preinit 28 | rm 10_indicate_failsafe 29 | rm 30_failsafe_wait 30 | rm 40_run_failsafe_hook 31 | rm 99_10_failsafe_dropbear 32 | rm 99_10_failsafe_login 33 | if [ -f /src/iso/root.7z ]; then 34 | rm /src/iso/root.7z 35 | fi 36 | rootfs="$(dirname "$1""/*")" 37 | bootdir="$(dirname "$2""/*")" 38 | echo "exec /sbin/init" > "$rootfs"/init 39 | echo "echo" > "$rootfs"/sbin/wifi 40 | chmod +x "$rootfs"/init 41 | chmod +x "$rootfs"/sbin/wifi 42 | cd $rootfs || exit 43 | mkdir -p /tmp/cdrom 44 | find . | cpio -H newc -o | gzip -9 >/tmp/cdrom/initrd.gz 45 | cp "$bootdir"/boot/vmlinuz /tmp/cdrom/ 46 | 47 | packroot="/tmp/ppgwroot.tar" 48 | tar -cf "$packroot" -C "/tmp/cdrom/" ./ 49 | rootsha=$(sha256sum $packroot | cut -d ' ' -f 1) 50 | echo "$rootsha" >/src/iso/rootsha.txt 51 | 7z a -t7z -m0=lzma2 -mx=9 -mfb=64 -md=32m -ms=on -mhe=on -bsp1 -bso1 -bse1 -y -p"$rootsha" "/src/iso/root.7z" "$packroot" 52 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/zh-8b65fcca.js: -------------------------------------------------------------------------------- 1 | const e={Overview:"概览",Proxies:"代理",Rules:"规则",Rec:"记录",netrec:"网络流量记录",netrec_data:"请选择数据查阅方式:",netrec_data_no:"[提示] 该功能需要ppgw.ini的net_rec=yes",Refresh:"重载",refresh_title:"重新加载配置",refresh_tips:"手动重载刷新ppgw.ini、订阅等所有配置文件",confirm_refresh:"重载刷新所有配置可能引起网络中断,确认要马上重载吗?",refresh_success:"重载刷新任务已成功部署!",refresh_fail:"请求重载刷新失败,可能已有其他任务正在进行中",downcsv:"下载表格",loadonline:"在线网页加载",Conns:"连接",Config:"配置",Logs:"日志",Upload:"上传",DL:"下载量",UL:"上传量",DLSpeed:"下载速度",ULSpeed:"上传速度",Chains:"链路",Rule:"规则",Time:"时刻",Source:"源",DestinationIP:"目标",Type:"入站",Host:"请求头",Download:"下载",Remaining:"剩余",Expires:"过期",Updated:"更新于",Update:"更新",justNow:"刚刚",minutesAgo:"分钟前",hoursAgo:"小时前",daysAgo:"天前",monthsAgo:"月前",yearsAgo:"年前",secondsAgo:"秒前","Upload Total":"上传总量","Download Total":"下载总量","Active Connections":"活动连接","Pause Refresh":"暂停刷新","Resume Refresh":"继续刷新",Up:"上传",Down:"下载","Test Latency":"延迟测速",settings:"设置",sort_in_grp:"代理组条目排序",hide_unavail_proxies:"隐藏不可用代理",auto_close_conns:"切换代理时自动断开旧连接",order_natural:"原 config 文件中的排序",order_latency_asc:"按延迟从小到大",order_latency_desc:"按延迟从大到小",order_name_asc:"按名称字母排序 (A-Z)",order_name_desc:"按名称字母排序 (Z-A)",Connections:"连接",current_backend:"当前后端",Active:"活动",switch_backend:"切换后端",Closed:"已断开",switch_theme:"切换主题",theme:"主题",about:"PaoPao GateWay",no_logs:"暂无日志...",chart_style:"流量图样式",latency_test_url:"延迟测速 URL",allow_lan_mixed:"允许局域网访问1080端口代理[http+socks5]",Mode:"模式(不明白请保持Global)",LogLevel:"日志等级",lang:"语言",update_all_rule_provider:"更新所有 rule provider",update_all_proxy_provider:"更新所有 proxy providers",dark_mode_pure_black_toggle_label:"在黑色主题下使用纯黑背景"};export{e as data}; 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Logs-5e5ee0ad.css: -------------------------------------------------------------------------------- 1 | ._RuleSearch_bd30s_1{padding:0 40px 5px}._RuleSearchContainer_bd30s_5{position:relative;height:40px}._inputWrapper_bd30s_10{position:absolute;top:50%;transform:translateY(-50%);left:0;width:100%}._input_bd30s_10{-moz-appearance:none;appearance:none;-webkit-appearance:none;background-color:var(--color-input-bg);background-image:none;border-radius:20px;border:1px solid var(--color-input-border);box-sizing:border-box;color:#c1c1c1;display:inline-block;font-size:inherit;height:40px;outline:none;padding:0 15px 0 35px;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}._iconWrapper_bd30s_36{position:absolute;top:50%;transform:translateY(-50%);left:10px;display:flex;justify-content:center;align-items:center}._logMeta_7a1x3_1{display:flex;align-items:center;flex-wrap:wrap;font-size:.9em}._logType_7a1x3_8{color:#eee;flex-shrink:0;text-align:center;width:66px;border-radius:100px;padding:3px 5px;margin:0 8px}._logTime_7a1x3_18{flex-shrink:0;color:#999;font-size:14px}._logText_7a1x3_24{flex-shrink:0;display:flex;font-family:Roboto Mono,Menlo,monospace;align-items:center;padding:8px 0;width:100%;white-space:pre;overflow:auto}._logsWrapper_7a1x3_37{margin:0;padding:0;color:var(--color-text)}._logsWrapper_7a1x3_37 .log{padding:10px 40px;background:var(--color-background)}._logsWrapper_7a1x3_37 .log.even{background:var(--color-background)}._logPlaceholder_7a1x3_51{display:flex;flex-direction:column;align-items:center;justify-content:center;color:#2d2d30}._logPlaceholder_7a1x3_51 div:nth-child(2){color:var(--color-text-secondary);font-size:1.4em;opacity:.6}._logPlaceholderIcon_7a1x3_64{opacity:.3}._search_7a1x3_68{max-width:1000px} 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Fab-e423cc40.js: -------------------------------------------------------------------------------- 1 | import{j as t,e as C,r as l}from"./index-969cf72a.js";const E="_spining_4i8sg_1",I="_spining_keyframes_4i8sg_1",y={spining:E,spining_keyframes:I},{useState:F}=C;function A({children:n}){return t.jsx("span",{className:y.spining,children:n})}const B={right:10,bottom:10},R=({children:n,...e})=>t.jsx("button",{type:"button",...e,className:"rtf--ab",children:n}),M=({children:n,...e})=>t.jsx("button",{type:"button",className:"rtf--mb",...e,children:n}),v={bottom:24,right:24},H=({event:n="hover",style:e=v,alwaysShowTitle:o=!1,children:b,icon:f,mainButtonStyles:g,onClick:p,text:u,...x})=>{const[a,r]=F(!1),c=o||!a,d=()=>r(!0),m=()=>r(!1),h=()=>n==="hover"&&d(),_=()=>n==="hover"&&m(),j=s=>p?p(s):(s.persist(),n==="click"?a?m():d():null),k=(s,i)=>{s.persist(),r(!1),setTimeout(()=>{i(s)},1)},N=()=>l.Children.map(b,(s,i)=>l.isValidElement(s)?t.jsxs("li",{className:`rtf--ab__c ${"top"in e?"top":""}`,children:[l.cloneElement(s,{"data-testid":`action-button-${i}`,"aria-label":s.props.text||`Menu button ${i+1}`,"aria-hidden":c,tabIndex:a?0:-1,...s.props,onClick:$=>{s.props.onClick&&k($,s.props.onClick)}}),s.props.text&&t.jsx("span",{className:`${"right"in e?"right":""} ${o?"always-show":""}`,"aria-hidden":c,children:s.props.text})]}):null);return t.jsx("ul",{onMouseEnter:h,onMouseLeave:_,className:`rtf ${a?"open":"closed"}`,"data-testid":"fab",style:e,...x,children:t.jsxs("li",{className:"rtf--mb__c",children:[t.jsx(M,{onClick:j,style:g,"data-testid":"main-button",role:"button","aria-label":"Floating menu",tabIndex:0,children:f}),u&&t.jsx("span",{className:`${"right"in e?"right":""} ${o?"always-show":""}`,"aria-hidden":c,children:u}),t.jsx("ul",{children:N()})]})})};export{R as A,H as F,A as I,B as p}; 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/TextFilter-78284216.js: -------------------------------------------------------------------------------- 1 | import{r as g,R as c,P as i,c as m,j as l,v as x,e as v}from"./index-969cf72a.js";import{d}from"./debounce-c1ba2006.js";function u(){return u=Object.assign||function(t){for(var n=1;n=0)&&Object.prototype.propertyIsEnumerable.call(t,o)&&(e[o]=t[o])}return e}function b(t,n){if(t==null)return{};var e={},o=Object.keys(t),r,s;for(s=0;s=0)&&(e[r]=t[r]);return e}var p=g.forwardRef(function(t,n){var e=t.color,o=e===void 0?"currentColor":e,r=t.size,s=r===void 0?24:r,a=h(t,["color","size"]);return c.createElement("svg",u({ref:n,xmlns:"http://www.w3.org/2000/svg",width:s,height:s,viewBox:"0 0 24 24",fill:"none",stroke:o,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},a),c.createElement("polyline",{points:"23 4 23 10 17 10"}),c.createElement("path",{d:"M20.49 15a9 9 0 1 1-2.12-9.36L23 10"}))});p.propTypes={color:i.string,size:i.oneOfType([i.string,i.number])};p.displayName="RotateCw";const y=p,R="_rotate_1dspl_1",_="_isRotating_1dspl_5",j="_rotating_1dspl_1",f={rotate:R,isRotating:_,rotating:j};function $(t){const n=t.size||16,e=m(f.rotate,{[f.isRotating]:t.isRotating});return l.jsx("span",{className:e,children:l.jsx(y,{size:n})})}const{useCallback:w,useState:O,useMemo:T}=v;function C(t){const[,n]=x(t),[e,o]=O(""),r=T(()=>d(n,300),[n]);return[w(a=>{o(a.target.value),r(a.target.value)},[r]),e]}const z="_input_16a1f_1",P={input:z};function L(t){const[n,e]=C(t.textAtom);return l.jsx("input",{className:P.input,type:"text",value:e,onChange:n,placeholder:t.placeholder})}export{$ as R,L as T,y as a}; 2 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Build and Release ISO and docker 2 | 3 | on: 4 | workflow_dispatch: 5 | permissions: 6 | contents: write 7 | 8 | jobs: 9 | build_release: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout code 13 | uses: actions/checkout@v4 14 | - name: remove full mod flag 15 | run: sed -i '/usefullmod/d' makeiso.sh 16 | - name: Set SHSHA 17 | run: echo "SHSHA="$(echo "${{ github.sha }}"|grep -Eo "^[0-9a-z]{7}"|head -1) >> $GITHUB_ENV 18 | - name: Gen sha.txt 19 | run: echo "${{ env.SHSHA }}" >sha.txt 20 | - name: Set TAG_NAME 21 | run: echo "TAG_NAME=""$(date +%Y%m%d)"""-"${{ env.SHSHA }}" >> $GITHUB_ENV 22 | - name: build iso 23 | run: sh makeiso.sh 24 | - name: Set variables 25 | run: echo "RE_NOTE=$(cat ./iso/renote.txt | tr -d '[:space:]')" >> $GITHUB_ENV 26 | - name: show iso sha256sum 27 | run: cat ./iso/renote.txt 28 | - name: Set up QEMU 29 | uses: docker/setup-qemu-action@v3 30 | - name: Set up Docker Buildx 31 | uses: docker/setup-buildx-action@v3 32 | - name: Login to Docker Hub 33 | uses: docker/login-action@v3 34 | with: 35 | username: ${{ secrets.DOCKERHUB_USERNAME }} 36 | password: ${{ secrets.DOCKERHUB_TOKEN }} 37 | - name: Build and push 38 | uses: docker/build-push-action@v5 39 | with: 40 | context: "./iso" 41 | push: true 42 | platforms: linux/amd64 43 | tags: sliamb/ppgwiso 44 | - name: Upload files to GitHub release 45 | uses: svenstaro/upload-release-action@v2 46 | with: 47 | repo_token: ${{ secrets.GITHUB_TOKEN }} 48 | file_glob: true 49 | file: ./iso/paopao-gateway*.7z 50 | tag: ${{ env.TAG_NAME }} 51 | body: ${{ env.RE_NOTE }} 52 | - name: Remove old release 53 | uses: dev-drprasad/delete-older-releases@v0.3.2 54 | with: 55 | keep_latest: 30 56 | env: 57 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/play-d4b35340.js: -------------------------------------------------------------------------------- 1 | import{r as g,R as s,P as a}from"./index-969cf72a.js";function f(){return f=Object.assign||function(t){for(var o=1;o=0)&&Object.prototype.propertyIsEnumerable.call(t,e)&&(r[e]=t[e])}return r}function y(t,o){if(t==null)return{};var r={},e=Object.keys(t),n,i;for(i=0;i=0)&&(r[n]=t[n]);return r}var c=g.forwardRef(function(t,o){var r=t.color,e=r===void 0?"currentColor":r,n=t.size,i=n===void 0?24:n,l=v(t,["color","size"]);return s.createElement("svg",f({ref:o,xmlns:"http://www.w3.org/2000/svg",width:i,height:i,viewBox:"0 0 24 24",fill:"none",stroke:e,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},l),s.createElement("rect",{x:"6",y:"4",width:"4",height:"16"}),s.createElement("rect",{x:"14",y:"4",width:"4",height:"16"}))});c.propTypes={color:a.string,size:a.oneOfType([a.string,a.number])};c.displayName="Pause";const b=c;function p(){return p=Object.assign||function(t){for(var o=1;o=0)&&Object.prototype.propertyIsEnumerable.call(t,e)&&(r[e]=t[e])}return r}function O(t,o){if(t==null)return{};var r={},e=Object.keys(t),n,i;for(i=0;i=0)&&(r[n]=t[n]);return r}var u=g.forwardRef(function(t,o){var r=t.color,e=r===void 0?"currentColor":r,n=t.size,i=n===void 0?24:n,l=h(t,["color","size"]);return s.createElement("svg",p({ref:o,xmlns:"http://www.w3.org/2000/svg",width:i,height:i,viewBox:"0 0 24 24",fill:"none",stroke:e,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},l),s.createElement("polygon",{points:"5 3 19 12 5 21 5 3"}))});u.propTypes={color:a.string,size:a.oneOfType([a.string,a.number])};u.displayName="Play";const w=u;export{w as P,b as a}; 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/debounce-c1ba2006.js: -------------------------------------------------------------------------------- 1 | function O(e){var n=typeof e;return e!=null&&(n=="object"||n=="function")}var M=typeof global=="object"&&global&&global.Object===Object&&global;const R=M;var w=typeof self=="object"&&self&&self.Object===Object&&self,B=R||w||Function("return this")();const W=B;var F=function(){return W.Date.now()};const S=F;var G=/\s/;function U(e){for(var n=e.length;n--&&G.test(e.charAt(n)););return n}var _=/^\s+/;function D(e){return e&&e.slice(0,U(e)+1).replace(_,"")}var H=W.Symbol;const y=H;var L=Object.prototype,X=L.hasOwnProperty,q=L.toString,g=y?y.toStringTag:void 0;function z(e){var n=X.call(e,g),i=e[g];try{e[g]=void 0;var o=!0}catch{}var f=q.call(e);return o&&(n?e[g]=i:delete e[g]),f}var J=Object.prototype,K=J.toString;function Q(e){return K.call(e)}var V="[object Null]",Y="[object Undefined]",$=y?y.toStringTag:void 0;function Z(e){return e==null?e===void 0?Y:V:$&&$ in Object(e)?z(e):Q(e)}function ee(e){return e!=null&&typeof e=="object"}var ne="[object Symbol]";function te(e){return typeof e=="symbol"||ee(e)&&Z(e)==ne}var E=0/0,re=/^[-+]0x[0-9a-f]+$/i,ie=/^0b[01]+$/i,oe=/^0o[0-7]+$/i,ae=parseInt;function k(e){if(typeof e=="number")return e;if(te(e))return E;if(O(e)){var n=typeof e.valueOf=="function"?e.valueOf():e;e=O(n)?n+"":n}if(typeof e!="string")return e===0?e:+e;e=D(e);var i=ie.test(e);return i||oe.test(e)?ae(e.slice(2),i?2:8):re.test(e)?E:+e}var fe="Expected a function",ce=Math.max,ue=Math.min;function se(e,n,i){var o,f,s,u,r,c,d=0,v=!1,l=!1,T=!0;if(typeof e!="function")throw new TypeError(fe);n=k(n)||0,O(i)&&(v=!!i.leading,l="maxWait"in i,s=l?ce(k(i.maxWait)||0,n):s,T="trailing"in i?!!i.trailing:T);function j(t){var a=o,b=f;return o=f=void 0,d=t,u=e.apply(b,a),u}function N(t){return d=t,r=setTimeout(m,n),v?j(t):u}function P(t){var a=t-c,b=t-d,I=n-a;return l?ue(I,s-b):I}function h(t){var a=t-c,b=t-d;return c===void 0||a>=n||a<0||l&&b>=s}function m(){var t=S();if(h(t))return x(t);r=setTimeout(m,P(t))}function x(t){return r=void 0,T&&o?j(t):(o=f=void 0,u)}function A(){r!==void 0&&clearTimeout(r),d=0,o=c=f=r=void 0}function C(){return r===void 0?u:x(S())}function p(){var t=S(),a=h(t);if(o=arguments,f=this,c=t,a){if(r===void 0)return N(c);if(l)return clearTimeout(r),r=setTimeout(m,n),j(c)}return r===void 0&&(r=setTimeout(m,n)),u}return p.cancel=A,p.flush=C,p}export{se as d}; 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/en-eb14609d.js: -------------------------------------------------------------------------------- 1 | const e={Overview:"Overview",Proxies:"Proxies",Rules:"Rules",Rec:"Record",netrec:"Network traffic records",netrec_data:"Select Data Access Method:",netrec_data_no:"[Tips] Need net_rec=yes in ppgw.ini",Refresh:"Reload",refresh_title:"Reload Configuration",refresh_tips:"Manually reload to refresh all configuration files such as ppgw.ini, subscriptions, etc.",confirm_refresh:"Reloading and refreshing all configurations may cause network interruptions. Are you sure you want to reload immediately?",refresh_success:"The reload refresh task has been successfully deployed!",refresh_fail:"Request to reload refresh failed, there may be other tasks in progress",downcsv:"Download CSV",loadonline:"Load Online",Conns:"Conns",Config:"Config",Logs:"Logs",Upload:"Upload",DL:"DL",UL:"UL",DLSpeed:"DL Speed",ULSpeed:"UL Speed",Chains:"Chains",Rule:"Rule",Time:"Time",Source:"Source",DestinationIP:"Destination IP",Type:"Type",Host:"Host",Download:"Download",Remaining:"Remaining",Expires:"Expires",Updated:"Updated",justNow:"just now",minutesAgo:"minutes ago",hoursAgo:"hours ago",daysAgo:"days ago",monthsAgo:"months ago",yearsAgo:"years ago",secondsAgo:"seconds Ago","Upload Total":"Upload Total","Download Total":"Download Total","Active Connections":"Active Connections","Pause Refresh":"Pause Refresh","Resume Refresh":"Resume Refresh",Up:"Up",Down:"Down","Test Latency":"Test Latency",settings:"settings",sort_in_grp:"Sorting in group",hide_unavail_proxies:"Hide unavailable proxies",auto_close_conns:"Automatically close old connections",order_natural:"Original order in config file",order_latency_asc:"By latency from small to big",order_latency_desc:"By latency from big to small",order_name_asc:"By name alphabetically (A-Z)",order_name_desc:"By name alphabetically (Z-A)",Connections:"Connections",current_backend:"Current Backend",Active:"Active",switch_backend:"Switch backend",Closed:"Closed",switch_theme:"Switch theme",theme:"theme",about:"PaoPao GateWay",no_logs:"No logs yet, hang tight...",chart_style:"Chart Style",latency_test_url:"Latency Test URL",allow_lan_mixed:"Allow LAN :1080 proxy [http+socks5]",lang:"Language",LogLevel:"Log Level",update_all_rule_provider:"Update all rule providers",update_all_proxy_provider:"Update all proxy providers",dark_mode_pure_black_toggle_label:"Use pure black in dark mode"};export{e as data}; 2 | -------------------------------------------------------------------------------- /.github/workflows/docker-latest-schedule.yml: -------------------------------------------------------------------------------- 1 | name: Schedule Latest Build Docker 2 | 3 | on: 4 | # schedule: 5 | # - cron: '05 23 * * *' 6 | push: 7 | paths-ignore: 8 | - '*.md' 9 | - '.github/**' 10 | - 'LICENSE' 11 | workflow_dispatch: 12 | permissions: 13 | contents: write 14 | 15 | jobs: 16 | build_release: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout code 20 | uses: actions/checkout@v4 21 | - name: remove full mod flag 22 | run: sed -i '/usefullmod/d' makeiso.sh 23 | - name: Set SHSHA 24 | run: echo "SHSHA="$(echo "${{ github.sha }}"|grep -Eo "^[0-9a-z]{7}"|head -1) >> $GITHUB_ENV 25 | - name: Gen sha.txt 26 | run: echo "${{ env.SHSHA }}" >sha.txt 27 | - name: Set TAG_NAME 28 | run: echo "TAG_NAME=""$(date +%Y%m%d)"""-"${{ env.SHSHA }}" >> $GITHUB_ENV 29 | - name: build iso 30 | run: sh makeiso.sh 31 | - name: Set variables 32 | run: echo "RE_NOTE=$(cat ./iso/renote.txt | tr -d '[:space:]')" >> $GITHUB_ENV 33 | - name: show iso sha256sum 34 | run: cat ./iso/renote.txt 35 | - name: Set up QEMU 36 | uses: docker/setup-qemu-action@v3 37 | - name: Set up Docker Buildx 38 | uses: docker/setup-buildx-action@v3 39 | - name: Login to Docker Hub 40 | uses: docker/login-action@v3 41 | with: 42 | username: ${{ secrets.DOCKERHUB_USERNAME }} 43 | password: ${{ secrets.DOCKERHUB_TOKEN }} 44 | - name: Build and push 45 | uses: docker/build-push-action@v5 46 | with: 47 | context: "./iso" 48 | push: true 49 | platforms: linux/amd64 50 | tags: sliamb/ppgwiso 51 | push-ecr: 52 | needs: build_release 53 | runs-on: ubuntu-latest 54 | container: alpine:edge 55 | steps: 56 | - name: "Configure AWS Credentials" 57 | uses: aws-actions/configure-aws-credentials@v4.0.2 58 | with: 59 | aws-region: us-east-1 60 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 61 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 62 | - name: install skopeo and aws-cli 63 | run: apk update && apk upgrade && apk add skopeo aws-cli 64 | - name: login ecr 65 | run: aws ecr-public get-login-password --region us-east-1 | skopeo login --username AWS --password-stdin public.ecr.aws 66 | - name: push ecr 67 | run: skopeo copy --all docker://sliamb/ppgwiso:latest docker://public.ecr.aws/sliamb/ppgwiso:latest -------------------------------------------------------------------------------- /.github/workflows/docker-latest-schedule -with-fullmod.yml: -------------------------------------------------------------------------------- 1 | name: Schedule Latest Build Docker -with-full-mod 2 | 3 | on: 4 | # schedule: 5 | # - cron: '25 23 * * *' 6 | push: 7 | paths-ignore: 8 | - '*.md' 9 | - '.github/**' 10 | - 'LICENSE' 11 | workflow_dispatch: 12 | permissions: 13 | contents: write 14 | 15 | jobs: 16 | build_release: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout code 20 | uses: actions/checkout@v4 21 | - name: set full mod flag 22 | run: sed -i "s/#usefullmod//g" makeiso.sh 23 | - name: Set SHSHA 24 | run: echo "SHSHA="$(echo "${{ github.sha }}"|grep -Eo "^[0-9a-z]{7}"|head -1) >> $GITHUB_ENV 25 | - name: Gen sha.txt 26 | run: echo "${{ env.SHSHA }}" >sha.txt 27 | - name: Set TAG_NAME 28 | run: echo "TAG_NAME=""$(date +%Y%m%d)"""-"${{ env.SHSHA }}" >> $GITHUB_ENV 29 | - name: build iso 30 | run: sh makeiso.sh 31 | - name: Set variables 32 | run: echo "RE_NOTE=$(cat ./iso/renote.txt | tr -d '[:space:]')" >> $GITHUB_ENV 33 | - name: show iso sha256sum 34 | run: cat ./iso/renote.txt 35 | - name: Set up QEMU 36 | uses: docker/setup-qemu-action@v3 37 | - name: Set up Docker Buildx 38 | uses: docker/setup-buildx-action@v3 39 | - name: Login to Docker Hub 40 | uses: docker/login-action@v3 41 | with: 42 | username: ${{ secrets.DOCKERHUB_USERNAME }} 43 | password: ${{ secrets.DOCKERHUB_TOKEN }} 44 | - name: Build and push -with-full-mod 45 | uses: docker/build-push-action@v5 46 | with: 47 | context: "./iso" 48 | push: true 49 | platforms: linux/amd64 50 | tags: sliamb/ppgwiso:fullmod 51 | 52 | push-ecr: 53 | needs: build_release 54 | runs-on: ubuntu-latest 55 | container: alpine:edge 56 | steps: 57 | - name: "Configure AWS Credentials" 58 | uses: aws-actions/configure-aws-credentials@v4.0.2 59 | with: 60 | aws-region: us-east-1 61 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 62 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 63 | - name: install skopeo and aws-cli 64 | run: apk update && apk upgrade && apk add skopeo aws-cli 65 | - name: login ecr 66 | run: aws ecr-public get-login-password --region us-east-1 | skopeo login --username AWS --password-stdin public.ecr.aws 67 | - name: push ecr 68 | run: skopeo copy --all docker://sliamb/ppgwiso:fullmod docker://public.ecr.aws/sliamb/ppgwiso:fullmod -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Connections-ddae4f70.css: -------------------------------------------------------------------------------- 1 | .react-tabs{-webkit-tap-highlight-color:transparent}.react-tabs__tab-list{margin:0 0 10px;padding:0 30px}.react-tabs__tab{display:inline-flex;align-items:center;border:1px solid transparent;border-radius:5px;bottom:-1px;position:relative;list-style:none;padding:6px 10px;cursor:pointer;font-size:1.2em;opacity:.5}.react-tabs__tab--selected{opacity:1}.react-tabs__tab--disabled{color:GrayText;cursor:default}.react-tabs__tab:focus{border-color:#0188fe;outline:none}.react-tabs__tab:focus:after{content:"";position:absolute}.react-tabs__tab-panel{display:none}.react-tabs__tab-panel--selected{display:block}._placeHolder_1mf9d_1{height:100%;display:flex;align-items:center;justify-content:center;color:var(--color-background);opacity:.1}._connQty_1mf9d_10{font-family:var(--font-normal);font-size:.75em;margin-left:3px;padding:2px 7px;display:inline-flex;justify-content:center;align-items:center;background-color:var(--bg-near-transparent);border-radius:30px}._inputWrapper_1mf9d_22{margin:0 30px;width:100%;max-width:350px;justify-self:flex-end}._input_1mf9d_22{-moz-appearance:none;appearance:none;-webkit-appearance:none;background-color:var(--color-input-bg);background-image:none;border-radius:18px;border:1px solid var(--color-input-border);box-sizing:border-box;color:#c1c1c1;display:inline-block;font-size:inherit;height:36px;outline:none;padding:0 15px;transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}._tr_ludqf_1{display:grid;grid-template-columns:repeat(var(--col-count, 11),minmax(-webkit-max-content,auto));grid-template-columns:repeat(var(--col-count, 11),minmax(max-content,auto))}._pointer_ludqf_6{cursor:pointer}._table_ludqf_10{border:none;border-collapse:collapse}._table_ludqf_10 thead tr{position:-webkit-sticky;position:sticky;top:0;background:var(--color-background)}._table_ludqf_10 th{padding:8px 13px;height:50px;font-weight:initial;font-size:.8em;text-align:left;white-space:nowrap}._table_ludqf_10 td{border:none;white-space:nowrap;padding:8px 13px;font-size:.9em;font-family:var(--font-normal)}._table_ludqf_10>tbody>tr:nth-of-type(odd)>*{background:var(--color-row-odd)}._thWrap_ludqf_38{-webkit-user-select:none;user-select:none;display:inline-flex;align-items:center;justify-content:space-between}._thWrap_ludqf_38:hover{color:var(--color-text-highlight)}._sortIconContainer_ludqf_48{display:inline-flex;margin-left:10px;width:16px;height:16px}._rotate180_ludqf_55{transform:rotate(180deg)}._overlay_148w6_1{background-color:#0009}._cnt_148w6_5{background-color:var(--bg-modal);color:var(--color-text);max-width:300px;line-height:1.4;transform:translate(-50%,-50%) scale(1.2);opacity:.6;transition:all .3s ease}._afterOpen_148w6_15{opacity:1;transform:translate(-50%,-50%) scale(1)}._btngrp_148w6_20{display:flex;align-items:center;justify-content:center;margin-top:30px} 2 | -------------------------------------------------------------------------------- /makeiso.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ppgwver=$(date +%Y%m%d) 3 | builddir=$(pwd) 4 | if [ -f "$builddir""/sha.txt" ]; then 5 | sha="-"$(cat ./sha.txt) 6 | ppgwver="$ppgwver""$sha" 7 | sed -i "s/PPGW_version/$ppgwver/g" "$builddir"/custom.config.sh 8 | sed -i '/.*dropbear.*/s/.*/-dropbear/' "$builddir"/pkg.conf 9 | fi 10 | 11 | # build ppgw 12 | if [ -f "$builddir"/FILES/usr/bin/ppgw ]; then 13 | rm "$builddir"/FILES/usr/bin/ppgw 14 | fi 15 | docker pull golang:alpine 16 | docker run --rm --name gobuilder \ 17 | -v "$builddir"/ppgw.go:/go/main.go \ 18 | -v "$builddir"/FILES/usr/bin/:/go/ppgw/ \ 19 | -v "$builddir"/buildppgw.sh:/go/build/buildppgw.sh \ 20 | golang:alpine sh /go/build/buildppgw.sh 21 | 22 | if [ -f "$builddir""/FILES/usr/bin/ppgw" ]; then 23 | echo "ppgw compilation OK." 24 | else 25 | echo "ppgw compilation failed." 26 | exit 27 | fi 28 | 29 | echo "make iso files..." 30 | docker pull sliamb/opbuilder 31 | mkdir -p "$builddir"/iso 32 | mkdir -p "$builddir"/FILES/ 33 | rm -rf "$builddir"/iso/* 34 | ls -lah "$builddir"/iso/ 35 | export FULLMOD="no" 36 | #usefullmod export FULLMOD="yes" 37 | docker run --rm --name opbuilder \ 38 | -e ppgwver="$ppgwver" \ 39 | -e FULLMOD="$FULLMOD" \ 40 | -v "$builddir"/custom.config.sh:/src/custom.config.sh \ 41 | -v "$builddir"/iso/:/src/iso/ \ 42 | -v "$builddir"/FILES:/src/cpfiles/ \ 43 | -v "$builddir"/pkg.conf:/src/pkg.conf \ 44 | -v "$builddir"/patch.sh:/src/patch.sh \ 45 | sliamb/opbuilder 46 | 47 | echo "make docker files..." 48 | rootsha=$(head -1 "$builddir""/iso/rootsha.txt") 49 | echo "docker rootsha: ""$rootsha" 50 | sed "s/rootsha/$rootsha/g" "$builddir"/Dockerfile >"$builddir"/iso/Dockerfile 51 | cp "$builddir"/remakeiso.sh "$builddir"/iso/ 52 | sed -i "s/PPGW_version/$ppgwver/g" "$builddir"/iso/remakeiso.sh 53 | if [ -f "$builddir""/sha.txt" ]; then 54 | ls -lah "$builddir"/iso/ 55 | else 56 | cd "$builddir"/iso || exit 57 | docker build -t ppgwiso . 58 | fi 59 | 60 | echo "make sha256hashsum.txt ..." 61 | isofilename=paopao-gateway-x86-64"$sha".iso 62 | mv "$builddir"/iso/*.iso "$builddir"/iso/"$isofilename" 63 | beijing_time=$(TZ='Asia/Shanghai' date +'%Y-%m-%d %H:%M:%S') 64 | sha256hashsumfile="$builddir"/iso/sha256hashsum.txt 65 | echo "$beijing_time" >"$sha256hashsumfile" 66 | ls -lah "$builddir"/iso/paopao-gateway*.iso | grep iso >>"$sha256hashsumfile" 67 | echo " " >>"$sha256hashsumfile" 68 | echo "Linux shell:" >>"$sha256hashsumfile" 69 | echo " sha256sum ""$isofilename" >>"$sha256hashsumfile" 70 | echo "Windows Powershell: " >>"$sha256hashsumfile" 71 | echo " Get-FileHash ""$isofilename" >>"$sha256hashsumfile" 72 | echo "SHA256SUM: " >>"$sha256hashsumfile" 73 | cd "$builddir"/iso || exit 74 | sha256sum paopao-gateway*.iso >>"$sha256hashsumfile" 75 | ls -lah "$sha256hashsumfile" 76 | 77 | if [ -f "$builddir""/sha.txt" ]; then 78 | echo "make 7z files..." 79 | tail -1 "$builddir"/iso/sha256hashsum.txt | cut -d" " -f1 >"$builddir"/iso/renote.txt 80 | mkdir -p "$builddir"/iso/pack 81 | mv "$builddir"/iso/"$isofilename" "$builddir"/iso/pack/ 82 | mv "$sha256hashsumfile" "$builddir"/iso/pack/ 83 | ls -lah "$builddir"/iso/pack 84 | docker run --rm --name opbuilder \ 85 | -v "$builddir"/iso/pack:/src/iso/ \ 86 | -e sha="$sha" \ 87 | sliamb/opbuilder bash 7z.sh 88 | mv "$builddir"/iso/pack/*.7z "$builddir"/iso/ 89 | fi 90 | ls -lah "$builddir"/iso 91 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Logs-d0203c28.js: -------------------------------------------------------------------------------- 1 | import{r as u,R as x,P as h,j as t,b as y,z as R,A as T,t as P,D as w,u as L,C as N,S as C,E as W,F as O,g as z,G as k,e as I,c as E}from"./index-969cf72a.js";import{a as F,F as M}from"./index.esm-af95069f.js";import{r as $,s as A,f as D}from"./logs-e2001386.js";import{d as B}from"./debounce-c1ba2006.js";import{u as H}from"./useRemainingViewPortHeight-3d85719a.js";import{F as q,p as G}from"./Fab-e423cc40.js";import{P as K,a as V}from"./play-d4b35340.js";function f(){return f=Object.assign||function(e){for(var r=1;r=0)&&Object.prototype.propertyIsEnumerable.call(e,o)&&(s[o]=e[o])}return s}function J(e,r){if(e==null)return{};var s={},o=Object.keys(e),a,n;for(n=0;n=0)&&(s[a]=e[a]);return s}var _=u.forwardRef(function(e,r){var s=e.color,o=s===void 0?"currentColor":s,a=e.size,n=a===void 0?24:a,l=Y(e,["color","size"]);return x.createElement("svg",f({ref:r,xmlns:"http://www.w3.org/2000/svg",width:n,height:n,viewBox:"0 0 24 24",fill:"none",stroke:o,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},l),x.createElement("circle",{cx:"11",cy:"11",r:"8"}),x.createElement("line",{x1:"21",y1:"21",x2:"16.65",y2:"16.65"}))});_.propTypes={color:h.string,size:h.oneOfType([h.string,h.number])};_.displayName="Search";const Q=_,U="_RuleSearch_bd30s_1",X="_RuleSearchContainer_bd30s_5",Z="_inputWrapper_bd30s_10",ee="_input_bd30s_10",te="_iconWrapper_bd30s_36",p={RuleSearch:U,RuleSearchContainer:X,inputWrapper:Z,input:ee,iconWrapper:te};function se({dispatch:e,searchText:r,updateSearchText:s}){const[o,a]=u.useState(r),n=u.useCallback(i=>{e(s(i))},[e,s]),l=u.useMemo(()=>B(n,300),[n]),g=i=>{a(i.target.value),l(i.target.value)};return t.jsx("div",{className:p.RuleSearch,children:t.jsxs("div",{className:p.RuleSearchContainer,children:[t.jsx("div",{className:p.inputWrapper,children:t.jsx("input",{type:"text",value:o,onChange:g,className:p.input})}),t.jsx("div",{className:p.iconWrapper,children:t.jsx(Q,{size:20})})]})})}const oe=e=>({searchText:R(e),updateSearchText:T}),re=y(oe)(se),ae="_logMeta_7a1x3_1",ne="_logType_7a1x3_8",ce="_logTime_7a1x3_18",ie="_logText_7a1x3_24",le="_logsWrapper_7a1x3_37",pe="_logPlaceholder_7a1x3_51",ge="_logPlaceholderIcon_7a1x3_64",de="_search_7a1x3_68",c={logMeta:ae,logType:ne,logTime:ce,logText:ie,logsWrapper:le,logPlaceholder:pe,logPlaceholderIcon:ge,search:de},{useCallback:v,memo:he,useEffect:ue}=I,m=30,xe={debug:"#28792c",info:"var(--bg-log-info-tag)",warning:"#b99105",error:"#c11c1c"};function me({time:e,even:r,payload:s,type:o}){const a=E({even:r},"log");return t.jsx("div",{className:a,children:t.jsxs("div",{className:c.logMeta,children:[t.jsx("div",{className:c.logTime,children:e}),t.jsx("div",{className:c.logType,style:{backgroundColor:xe[o]},children:o}),t.jsx("div",{className:c.logText,children:s})]})})}function fe(e,r){return r[e].id}const b=he(({index:e,style:r,data:s})=>{const o=s[e];return t.jsx("div",{style:r,children:t.jsx(me,{...o})})},F);b.displayName="MemoRow";function _e({dispatch:e,logLevel:r,apiConfig:s,logs:o,logStreamingPaused:a}){const n=P(),l=v(()=>{a?$({...s,logLevel:r}):A(),n.app.updateAppConfig("logStreamingPaused",!a)},[s,r,a,n.app]),g=v(S=>e(w(S)),[e]);ue(()=>{D({...s,logLevel:r},g)},[s,r,g]);const[i,j]=H(),{t:d}=L();return t.jsxs("div",{children:[t.jsx(N,{title:d("Logs")}),t.jsx("div",{className:c.search,children:t.jsx(re,{})}),t.jsx("div",{ref:i,style:{paddingBottom:m},children:o.length===0?t.jsxs("div",{className:c.logPlaceholder,style:{height:j-m},children:[t.jsx("div",{className:c.logPlaceholderIcon,children:t.jsx(C,{width:200,height:200})}),t.jsx("div",{children:d("no_logs")})]}):t.jsxs("div",{className:c.logsWrapper,children:[t.jsx(M,{height:j-m,width:"100%",itemCount:o.length,itemSize:80,itemData:o,itemKey:fe,children:b}),t.jsx(q,{icon:a?t.jsx(K,{size:16}):t.jsx(V,{size:16}),mainButtonStyles:a?{background:"#e74c3c"}:{},style:G,text:d(a?"Resume Refresh":"Pause Refresh"),onClick:l})]})})]})}const je=e=>({logs:W(e),logLevel:O(e),apiConfig:z(e),logStreamingPaused:k(e)}),we=y(je)(_e);export{we as default}; 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Proxies-40f80166.css: -------------------------------------------------------------------------------- 1 | ._FlexCenter_1380a_1{display:flex;justify-content:center;align-items:center}._header_1y9js_1{display:flex;align-items:center}._header_1y9js_1:focus{outline:none}._header_1y9js_1 ._arrow_1y9js_8{display:inline-flex;transform:rotate(0);transition:transform .3s}._header_1y9js_1 ._arrow_1y9js_8._isOpen_1y9js_13{transform:rotate(180deg)}._header_1y9js_1 ._arrow_1y9js_8:focus{outline:var(--color-focus-blue) solid 1px}._btn_1y9js_20{margin-left:5px}._qty_1y9js_25{font-family:var(--font-normal);font-size:.75em;margin-left:3px;padding:2px 7px;display:inline-flex;justify-content:center;align-items:center;background-color:var(--bg-near-transparent);border-radius:30px}._header_5pmv2_1{margin-bottom:12px}._groupHead_5pmv2_5{display:flex;flex-wrap:wrap;align-items:center}._action_5pmv2_11{margin:0 5px}._proxy_5mgcm_1{margin:3px;padding:5px;position:relative;border-radius:8px;overflow:hidden;display:flex;flex-direction:column;justify-content:space-between;outline:none;border:1px solid transparent;max-width:200px;background-color:var(--color-bg-proxy)}._proxy_5mgcm_1:focus{border:1px solid var(--color-focus-blue)}@media screen and (min-width: 30em){._proxy_5mgcm_1{min-width:200px;border-radius:10px;padding:10px}}._proxy_5mgcm_1._now_5mgcm_25{background-color:var(--color-focus-blue);color:#ddd}._proxy_5mgcm_1._error_5mgcm_29{opacity:.5}._proxy_5mgcm_1._selectable_5mgcm_32{transition:transform .2s ease-in-out;cursor:pointer}._proxy_5mgcm_1._selectable_5mgcm_32:hover{border-color:hsl(0deg,0%,var(--card-hover-border-lightness))}._proxyType_5mgcm_40{font-family:var(--font-mono);font-size:.6em;margin-right:3px}@media screen and (min-width: 30em){._proxyType_5mgcm_40{font-size:.85em}}._row_5mgcm_51{display:flex;align-items:center;justify-content:space-between}._proxyName_5mgcm_57{width:100%;margin-bottom:5px;font-size:.8em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}._proxySmall_5mgcm_66{--size: 13px;width:var(--size);height:var(--size);border-radius:50%;position:relative}._proxySmall_5mgcm_66._now_5mgcm_25{--size: 15px}._proxySmall_5mgcm_66._now_5mgcm_25:before{--size-dot: 7px;content:"";position:absolute;width:var(--size-dot);height:var(--size-dot);background-color:#fff;border:1px solid var(--color-proxy-dot-selected-ind-bo);border-radius:4px;top:50%;left:50%;transform:translate(-50%,-50%)}._proxySmall_5mgcm_66._selectable_5mgcm_32{transition:transform .1s ease-in-out;cursor:pointer}._proxySmall_5mgcm_66._selectable_5mgcm_32:hover{transform:scale(1.2)}._proxyLatency_pw0sa_1{border-radius:20px;color:#eee;font-size:.6em}@media screen and (min-width: 30em){._proxyLatency_pw0sa_1{font-size:.85em}}._list_1oy7w_1{display:flex;flex-wrap:wrap;margin:8px 0 8px -3px}._listSummaryView_1oy7w_8{margin:14px 0;display:grid;grid-template-columns:repeat(auto-fill,13px);grid-gap:10px;place-items:center;max-width:900px}._updatedAt_919yi_1{margin-bottom:12px}._updatedAt_919yi_1 small{color:#777}._main_919yi_8{padding:10px 15px}@media screen and (min-width: 30em){._main_919yi_8{padding:10px 40px}}._head_919yi_17{display:flex;align-items:center;flex-wrap:wrap}._action_919yi_23{margin:0 5px;display:grid;grid-template-columns:auto auto;gap:10px;place-items:center}._refresh_919yi_31{display:flex;justify-content:center;align-items:center;cursor:pointer}._labeledInput_cmki0_1{max-width:85vw;width:400px;display:flex;justify-content:space-between;align-items:center;font-size:13px;padding:13px 0}hr{height:1px;background-color:var(--color-separator);border:none;outline:none;margin:1rem 0px}._overlay_uuk3b_1{background-color:#0009}._cnt_uuk3b_5{position:absolute;background-color:var(--bg-modal);color:var(--color-text);line-height:1.4;opacity:.6;transition:all .3s ease;transform:translate(-50%,-50%) scale(1.2);box-shadow:#0000001f 0 4px 4px,#0000003d 0 16px 32px}._afterOpen_uuk3b_16{opacity:1;transform:translate(-50%,-50%) scale(1)}._topBar_16fpp_1{position:-webkit-sticky;position:sticky;top:0;display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;z-index:1;background-color:var(--color-background2);-webkit-backdrop-filter:blur(36px);backdrop-filter:blur(36px)}._topBarRight_16fpp_13{display:flex;align-items:center;flex-wrap:wrap;flex:1;justify-content:flex-end;margin-right:20px}._textFilterContainer_16fpp_22{max-width:350px;min-width:150px;flex:1;margin-right:8px}._group_16fpp_29{padding:10px 15px}@media screen and (min-width: 30em){._group_16fpp_29{padding:10px 40px}} 2 | -------------------------------------------------------------------------------- /pkg.conf: -------------------------------------------------------------------------------- 1 | 2 | -amd64-microcode 3 | acpid 4 | base-files 5 | -bnx2-firmware 6 | -bnx2x-firmware 7 | busybox 8 | ca-bundle 9 | -coreutils-nohup 10 | -dnsmasq 11 | dropbear 12 | e100-firmware 13 | -e2fsprogs 14 | -firewall4 15 | -fstools 16 | -fwtool 17 | getrandom 18 | -grub2 19 | -grub2-bios-setup 20 | -intel-microcode 21 | -ip-full 22 | -ipset 23 | -iptables 24 | -iptables-mod-conntrack-extra 25 | -iptables-mod-extra 26 | -iptables-mod-iprange 27 | -iptables-mod-socket 28 | -iptables-mod-tproxy 29 | inotifywait 30 | -jansson4 31 | kernel 32 | -kmod-3c59x 33 | kmod-8139cp 34 | kmod-8139too 35 | -kmod-alx 36 | -kmod-amazon-ena 37 | -kmod-amd-xgbe 38 | -kmod-atl1 39 | -kmod-atl1c 40 | -kmod-atl1e 41 | -kmod-atl2 42 | -kmod-atlantic 43 | -kmod-atm 44 | -kmod-b44 45 | -kmod-be2net 46 | -kmod-bnx2 47 | -kmod-bnx2x 48 | -kmod-button-hotplug 49 | kmod-crypto-acompress 50 | kmod-crypto-aead 51 | kmod-crypto-crc32c 52 | kmod-crypto-ctr 53 | kmod-crypto-gcm 54 | kmod-crypto-gf128 55 | kmod-crypto-ghash 56 | kmod-crypto-hash 57 | kmod-crypto-hmac 58 | kmod-crypto-manager 59 | kmod-crypto-null 60 | kmod-crypto-rng 61 | kmod-crypto-seqiv 62 | kmod-crypto-sha512 63 | -kmod-dm9000 64 | kmod-e100 65 | kmod-e1000 66 | kmod-e1000e 67 | -kmod-et131x 68 | -kmod-ethoc 69 | -kmod-fixed-phy 70 | -kmod-forcedeth 71 | -kmod-fs-vfat 72 | -kmod-hfcmulti 73 | -kmod-hfcpci 74 | -kmod-hwmon-core 75 | -kmod-i2c-algo-bit 76 | -kmod-i2c-core 77 | -kmod-i40e 78 | -kmod-iavf 79 | -kmod-ifb 80 | kmod-igb 81 | -kmod-igbvf 82 | kmod-igc 83 | kmod-input-core 84 | -kmod-ipt-conntrack 85 | -kmod-ipt-conntrack-extra 86 | -kmod-ipt-core 87 | -kmod-ipt-extra 88 | -kmod-ipt-filter 89 | -kmod-ipt-iprange 90 | -kmod-ipt-ipset 91 | -kmod-ipt-nat 92 | -kmod-ipt-offload 93 | -kmod-ipt-raw 94 | -kmod-ipt-socket 95 | -kmod-ipt-tproxy 96 | -kmod-ipvlan 97 | -kmod-ixgbe 98 | -kmod-ixgbevf 99 | -kmod-lan743x 100 | kmod-lib-crc32c 101 | kmod-lib-crc-ccitt 102 | kmod-lib-lzo 103 | -kmod-libphy 104 | kmod-lib-zlib-inflate 105 | -kmod-macsec 106 | -kmod-macvlan 107 | -kmod-mdio 108 | -kmod-mdio-devres 109 | -kmod-mdio-gpio 110 | -kmod-mhi-bus 111 | -kmod-mhi-net 112 | -kmod-mhi-wwan-ctrl 113 | -kmod-mhi-wwan-mbim 114 | -kmod-mii 115 | -kmod-misdn 116 | -kmod-mlx4-core 117 | -kmod-mlx5-core 118 | -kmod-natsemi 119 | -kmod-ne2k-pci 120 | -kmod-net-selftests 121 | -kmod-nf-conntrack6 122 | -kmod-nf-conntrack-netlink 123 | -kmod-nf-flow 124 | -kmod-nf-ipt 125 | -kmod-nf-log6 126 | -kmod-nfnetlink 127 | -kmod-nf-reject6 128 | -kmod-nf-socket 129 | kmod-nft-core 130 | kmod-nft-fib 131 | kmod-nft-nat 132 | -kmod-nft-offload 133 | kmod-nft-tproxy 134 | -kmod-niu 135 | kmod-nls-base 136 | kmod-nls-cp437 137 | kmod-nls-iso8859-1 138 | kmod-nls-utf8 139 | kmod-pcnet32 140 | -kmod-phy-aquantia 141 | -kmod-phy-ax88796b 142 | -kmod-phy-bcm84881 143 | -kmod-phylink 144 | -kmod-phy-marvell 145 | -kmod-phy-microchip 146 | -kmod-phy-realtek 147 | -kmod-phy-smsc 148 | -kmod-ppp 149 | -kmod-pppoe 150 | -kmod-pppox 151 | -kmod-pps 152 | -kmod-ptp 153 | -kmod-qlcnic 154 | -kmod-r6040 155 | -kmod-r8169 156 | -kmod-sfc 157 | -kmod-sfc-falcon 158 | -kmod-sfp 159 | -kmod-sis190 160 | -kmod-sis900 161 | -kmod-skge 162 | -kmod-sky2 163 | -kmod-slhc 164 | -kmod-solos-pci 165 | -kmod-spi-ks8995 166 | -kmod-ssb 167 | -kmod-swconfig 168 | -kmod-switch-ar8xxx 169 | -kmod-switch-bcm53xx 170 | -kmod-switch-bcm53xx-mdio 171 | -kmod-switch-ip17xx 172 | -kmod-switch-rtl8306 173 | -kmod-switch-rtl8366rb 174 | -kmod-switch-rtl8366s 175 | -kmod-switch-rtl8366-smi 176 | -kmod-switch-rtl8367 177 | -kmod-switch-rtl8367b 178 | -kmod-tg3 179 | -kmod-tulip 180 | -kmod-via-rhine 181 | -kmod-via-velocity 182 | kmod-vmxnet3 183 | -kmod-wwan 184 | libblkid1 185 | libc 186 | libcomerr0 187 | -libext2fs2 188 | -libf2fs6 189 | libgcc 190 | libgcc1 191 | -libjson-c5 192 | libmbedtls12 193 | libmnl0 194 | libnftnl11 195 | libpthread 196 | librt 197 | -libsmartcols1 198 | libss2 199 | libustream-mbedtls 200 | libuuid1 201 | -logd 202 | -mkf2fs 203 | -mtd 204 | netifd 205 | nftables 206 | -odhcp6c 207 | -odhcpd-ipv6only 208 | -opkg 209 | -partx-utils 210 | -ppp 211 | -ppp-mod-pppoe 212 | procd 213 | procd-seccomp 214 | procd-ujail 215 | -r8169-firmware 216 | ubox 217 | ubus 218 | ubusd 219 | uci 220 | -uclient-fetch 221 | ucode 222 | ucode-mod-fs 223 | ucode-mod-ubus 224 | ucode-mod-uci 225 | urandom-seed 226 | urngd 227 | -usign 228 | -wget-ssl 229 | -wget 230 | -pciutils 231 | openvpn 232 | 233 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Fab-a434d836.css: -------------------------------------------------------------------------------- 1 | .rtf{box-sizing:border-box;margin:25px;position:fixed;white-space:nowrap;z-index:9998;padding-left:0;list-style:none}.rtf.open .rtf--mb{box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.rtf.open .rtf--mb>ul{list-style:none;margin:0;padding:0}.rtf.open .rtf--ab__c:hover>span{transition:ease-in-out opacity .2s;opacity:.9}.rtf.open .rtf--ab__c>span.always-show{transition:ease-in-out opacity .2s;opacity:.9}.rtf.open .rtf--ab__c:nth-child(1){transform:translateY(-60px) scale(1);transition-delay:.03s}.rtf.open .rtf--ab__c:nth-child(1).top{transform:translateY(60px) scale(1)}.rtf.open .rtf--ab__c:nth-child(2){transform:translateY(-120px) scale(1);transition-delay:.09s}.rtf.open .rtf--ab__c:nth-child(2).top{transform:translateY(120px) scale(1)}.rtf.open .rtf--ab__c:nth-child(3){transform:translateY(-180px) scale(1);transition-delay:.12s}.rtf.open .rtf--ab__c:nth-child(3).top{transform:translateY(180px) scale(1)}.rtf.open .rtf--ab__c:nth-child(4){transform:translateY(-240px) scale(1);transition-delay:.15s}.rtf.open .rtf--ab__c:nth-child(4).top{transform:translateY(240px) scale(1)}.rtf.open .rtf--ab__c:nth-child(5){transform:translateY(-300px) scale(1);transition-delay:.18s}.rtf.open .rtf--ab__c:nth-child(5).top{transform:translateY(300px) scale(1)}.rtf.open .rtf--ab__c:nth-child(6){transform:translateY(-360px) scale(1);transition-delay:.21s}.rtf.open .rtf--ab__c:nth-child(6).top{transform:translateY(360px) scale(1)}.rtf--mb__c{padding:25px;margin:-25px}.rtf--mb__c *:last-child{margin-bottom:0}.rtf--mb__c:hover>span{transition:ease-in-out opacity .2s;opacity:.9}.rtf--mb__c>span.always-show{transition:ease-in-out opacity .2s;opacity:.9}.rtf--mb__c>span{opacity:0;transition:ease-in-out opacity .2s;position:absolute;top:50%;transform:translateY(-50%);margin-right:6px;margin-left:4px;background:rgba(0,0,0,.75);padding:2px 4px;border-radius:2px;color:#fff;font-size:13px;box-shadow:0 0 4px #00000024,0 4px 8px #00000047}.rtf--mb__c>span.right{right:100%}.rtf--mb{width:48px;height:48px;background:var(--btn-bg);z-index:9999;display:inline-flex;justify-content:center;align-items:center;position:relative;border:none;border-radius:50%;box-shadow:0 0 4px #00000024,0 4px 8px #00000047;cursor:pointer;outline:none;padding:0;-webkit-user-drag:none;font-weight:700;color:#f1f1f1;font-size:18px}.rtf--mb>*{transition:ease-in-out transform .2s}.rtf--ab__c{display:block;position:absolute;top:0;right:1px;padding:10px 0;margin:-10px 0;transition:ease-in-out transform .2s}.rtf--ab__c>span{opacity:0;transition:ease-in-out opacity .2s;position:absolute;top:50%;transform:translateY(-50%);margin-right:6px;background:rgba(0,0,0,.75);padding:2px 4px;border-radius:2px;color:#fff;font-size:13px;box-shadow:0 0 4px #00000024,0 4px 8px #00000047}.rtf--ab__c>span.right{right:100%}.rtf--ab__c:nth-child(1){transform:translateY(-60px) scale(0);transition-delay:.21s}.rtf--ab__c:nth-child(1).top{transform:translateY(60px) scale(0)}.rtf--ab__c:nth-child(2){transform:translateY(-120px) scale(0);transition-delay:.18s}.rtf--ab__c:nth-child(2).top{transform:translateY(120px) scale(0)}.rtf--ab__c:nth-child(3){transform:translateY(-180px) scale(0);transition-delay:.15s}.rtf--ab__c:nth-child(3).top{transform:translateY(180px) scale(0)}.rtf--ab__c:nth-child(4){transform:translateY(-240px) scale(0);transition-delay:.12s}.rtf--ab__c:nth-child(4).top{transform:translateY(240px) scale(0)}.rtf--ab__c:nth-child(5){transform:translateY(-300px) scale(0);transition-delay:.09s}.rtf--ab__c:nth-child(5).top{transform:translateY(300px) scale(0)}.rtf--ab__c:nth-child(6){transform:translateY(-360px) scale(0);transition-delay:.03s}.rtf--ab__c:nth-child(6).top{transform:translateY(360px) scale(0)}.rtf--ab{height:40px;width:40px;margin-right:4px;background-color:#aaa;display:inline-flex;justify-content:center;align-items:center;position:relative;border:none;border-radius:50%;box-shadow:0 0 4px #00000024,0 4px 8px #00000047;cursor:pointer;outline:none;padding:0;-webkit-user-drag:none;font-weight:700;color:#f1f1f1;font-size:16px;z-index:10000}.rtf--ab:hover{background:#387cec;border:1px solid #387cec;color:#fff}.rtf--ab:focus{border-color:var(--color-focus-blue)}._spining_4i8sg_1{position:relative;border-radius:50%;background:linear-gradient(60deg,#e66465,#9198e5);width:48px;height:48px;display:flex;justify-content:center;align-items:center}._spining_4i8sg_1:before{content:"";position:absolute;top:0;bottom:0;left:0;right:0;border:2px solid transparent;border-top-color:currentColor;border-radius:50%;animation:_spining_keyframes_4i8sg_1 1s linear infinite}@keyframes _spining_keyframes_4i8sg_1{0%{transform:rotate(0)}to{transform:rotate(360deg)}} 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Config-68e91a0b.js: -------------------------------------------------------------------------------- 1 | import{j as e,s as P,e as v,c as U,h as D,i as S,k as w,l as V,b as N,m as F,g as L,n as G,o as q,q as j,t as z,v as H,u as J,C as W,w as K,x as Q,y as X}from"./index-969cf72a.js";import{r as Y}from"./logs-e2001386.js";import{S as C,T as I}from"./Select-dedf689a.js";const{useState:Z,useRef:ee,useEffect:te,useCallback:se}=v;function ne({value:t,...n}){const[o,c]=Z(t),a=ee(t);te(()=>{a.current!==t&&c(t),a.current=t},[t]);const r=se(u=>c(u.target.value),[c]);return e.jsx("input",{className:P.input,value:o,onChange:r,...n})}const ae="_root_1s1gc_1",le="_section_1s1gc_2",oe="_item_1s1gc_14",ce="_sep_1s1gc_34",re="_label_1s1gc_47",d={root:ae,section:le,item:oe,sep:ce,label:re},ie="_fieldset_1ghjp_1",de="_input_1ghjp_9",ue="_cnt_1ghjp_9",_={fieldset:ie,input:de,cnt:ue};function ge({OptionComponent:t,optionPropsList:n,selectedIndex:o,onChange:c}){const a=U("visually-hidden",_.input),r=u=>{c(u.target.value)};return e.jsx("fieldset",{className:_.fieldset,children:n.map((u,p)=>e.jsxs("label",{children:[e.jsx("input",{type:"radio",checked:o===p,name:"selection",value:p,"aria-labelledby":"traffic chart type "+p,onChange:r,className:a}),e.jsx("div",{className:_.cnt,children:e.jsx(t,{...u})})]},p))})}const{useMemo:pe}=v,he={plugins:{legend:{display:!1}},scales:{x:{display:!1,type:"category"},y:{display:!1,type:"linear"}}},T=[23e3,35e3,46e3,33e3,9e4,68e3,23e3,45e3],me=[184e3,183e3,196e3,182e3,19e4,186e3,182e3,189e3],fe=T;function xe({id:t}){const n=D.read(),o=pe(()=>({labels:fe,datasets:[{...S,...w[t].up,data:T},{...S,...w[t].down,data:me}]}),[t]),c="chart-"+t;return V(n.Chart,c,o,null,he),e.jsx("div",{style:{width:100,padding:5},children:e.jsx("canvas",{id:c})})}const{useEffect:R,useState:je,useCallback:h,useRef:Ce,useMemo:_e}=v,ve=[{id:0},{id:1},{id:2},{id:3}],be=[["debug","Debug"],["info","Info"],["warning","Warning"],["error","Error"],["silent","Silent"]],ye=[["zh","中文"],["en","English"]],ke=[["Global","Global"],["Rule","Rule"],["Direct","Direct"]],Se=t=>({configs:F(t),apiConfig:L(t)}),we=t=>({selectedChartStyleIndex:Q(t),latencyTestUrl:X(t),apiConfig:L(t)}),Ie=N(we)(Le),Ee=N(Se)(Ne);function Ne({dispatch:t,configs:n,apiConfig:o}){return R(()=>{t(G(o))},[t,o]),e.jsx(Ie,{configs:n})}function Le({dispatch:t,configs:n,selectedChartStyleIndex:o,latencyTestUrl:c,apiConfig:a}){const[r,u]=je(n),p=Ce(n);R(()=>{p.current!==n&&u(n),p.current=n},[n]),h(()=>{t(q("apiConfig"))},[t]);const m=h((s,l)=>{u({...r,[s]:l})},[r]),$=h(s=>{const l="allow-lan",i=s;m(l,i),t(j(a,{"allow-lan":i}))},[a,t,m]),f=h(({name:s,value:l})=>{switch(s){case"mode":case"log-level":m(s,l),t(j(a,{[s]:l})),s==="log-level"&&Y({...a,logLevel:l});break;case"redir-port":case"socks-port":case"mixed-port":case"port":if(l!==""){const i=parseInt(l,10);if(i<0||i>65535)return}m(s,l);break;default:return}},[a,t,m]);h(s=>f(s.target),[f]);const{selectChartStyleIndex:E,updateAppConfig:b}=z(),M=h(s=>{const l=s.target,{name:i,value:k}=l;switch(i){case"port":case"socks-port":case"mixed-port":case"redir-port":{const x=parseInt(k,10);if(x<0||x>65535)return;t(j(a,{[i]:x}));break}case"latencyTestUrl":{b(i,k);break}default:throw new Error(`unknown input name ${i}`)}},[a,t,b]),O=_e(()=>{const s=r.mode;return typeof s=="string"&&s[0].toUpperCase()+s.slice(1)},[r.mode]),[A,B]=H(K),{t:g,i18n:y}=J();return e.jsxs("div",{children:[e.jsx(W,{title:g("Config")}),e.jsxs("div",{className:d.root,children:[e.jsxs("div",{children:[e.jsx("div",{className:d.label,children:g("Mode")}),e.jsx(C,{options:ke,selected:O,onChange:s=>f({name:"mode",value:s.target.value})})]}),e.jsxs("div",{children:[e.jsx("div",{className:d.label,children:g("LogLevel")}),e.jsx(C,{options:be,selected:r["log-level"],onChange:s=>f({name:"log-level",value:s.target.value})})]}),e.jsxs("div",{className:d.item,children:[e.jsx(I,{id:"config-allow-lan",checked:r["allow-lan"],onChange:$}),e.jsx("label",{htmlFor:"config-allow-lan",children:g("allow_lan_mixed")})]})]}),e.jsx("div",{className:d.sep,children:e.jsx("div",{})}),e.jsxs("div",{className:d.section,children:[e.jsxs("div",{children:[e.jsx("div",{className:d.label,children:g("latency_test_url")}),e.jsx(ne,{name:"latencyTestUrl",type:"text",value:c,onBlur:M})]}),e.jsxs("div",{children:[e.jsx("div",{className:d.label,children:g("lang")}),e.jsx("div",{children:e.jsx(C,{options:ye,selected:y.language,onChange:s=>y.changeLanguage(s.target.value)})})]}),e.jsxs("div",{children:[e.jsx("div",{className:d.label,children:g("chart_style")}),e.jsx(ge,{OptionComponent:xe,optionPropsList:ve,selectedIndex:o,onChange:E})]}),e.jsxs("div",{className:d.item,children:[e.jsx(I,{id:"dark-mode-pure-black-toggle",checked:A,onChange:B}),e.jsx("label",{htmlFor:"dark-mode-pure-black-toggle",children:g("dark_mode_pure_black_toggle_label")})]})]})]})}export{Ee as default}; 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/index_base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | PaoPaoGateWay - PPGW_version 15 | 16 | 151 | 152 | 153 | 154 | 155 | 156 |
157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/net_rec_show.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | PaoPao GateWay - NET REC 15 | 16 | 71 | 72 | 73 | 74 |

PaoPaoGateWay REC

75 | 76 | 77 | 78 | 79 |
80 |
81 | © PaoPaoGateWay | GitHub 82 |
83 | 175 | 176 | 177 | 178 | -------------------------------------------------------------------------------- /remakeiso.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo iso builder version: PPGW_version 4 | echo run docker pull to fetch the latest image. 5 | json='{ 6 | "log": { 7 | "level": "info" 8 | }, 9 | "inbounds": [ 10 | { 11 | "type": "tproxy", 12 | "tag": "tproxy-in", 13 | "listen": "127.0.0.1", 14 | "sniff": true, 15 | "sniff_override_destination": true, 16 | "sniff_timeout": "300ms", 17 | "listen_port": 1081 18 | } 19 | ], 20 | "outbounds": [ 21 | { 22 | "type": "socks", 23 | "tag": "socks-clash", 24 | "server": "127.0.0.1", 25 | "server_port": 1080 26 | }, 27 | { 28 | "type": "direct", 29 | "tag": "free" 30 | }, 31 | { 32 | "type": "block", 33 | "tag": "block-quic" 34 | } 35 | ], 36 | "route": { 37 | "final": "socks-clash", 38 | "rules": [ 39 | { 40 | "protocol": [ 41 | "quic", 42 | "bitTorrent" 43 | ], 44 | "outbound": "block-quic" 45 | } 46 | ] 47 | } 48 | }' 49 | 50 | dnsjson='{ 51 | "log": { 52 | "level": "info" 53 | }, 54 | "dns": { 55 | "servers": [ 56 | { 57 | "tag": "trustdns", 58 | "address": "udp://dns_ip:dns_port", 59 | "strategy": "prefer_ipv4", 60 | "detour": "free" 61 | } 62 | ] 63 | }, 64 | "inbounds": [ 65 | { 66 | "type": "tproxy", 67 | "tag": "tproxy-in", 68 | "listen": "127.0.0.1", 69 | "sniff": true, 70 | "sniff_override_destination": true, 71 | "sniff_timeout": "300ms", 72 | "domain_strategy": "prefer_ipv4", 73 | "listen_port": 1081 74 | } 75 | ], 76 | "outbounds": [ 77 | { 78 | "type": "socks", 79 | "tag": "socks-clash", 80 | "server": "127.0.0.1", 81 | "server_port": 1080 82 | }, 83 | { 84 | "type": "direct", 85 | "tag": "free" 86 | }, 87 | { 88 | "type": "block", 89 | "tag": "block-quic" 90 | } 91 | ], 92 | "route": { 93 | "final": "socks-clash", 94 | "rules": [ 95 | { 96 | "protocol": [ 97 | "quic" 98 | ], 99 | "outbound": "block-quic" 100 | } 101 | ] 102 | } 103 | }' 104 | 105 | echo Patching new iso ... 106 | 7z x -p"$sha" -o"/tmp/" /root.7z >/dev/null 107 | cdroot=/tmp/cdrom 108 | mkdir -p $cdroot 109 | tar -xf /tmp/ppgwroot.tar -C $cdroot >/dev/null 110 | rm /tmp/ppgwroot.tar /root.7z 111 | mkdir $cdroot/rootfs 112 | mv $cdroot/initrd.gz $cdroot/rootfs 113 | cd $cdroot/rootfs || exit 114 | gunzip -c initrd.gz | cpio -idmv >/dev/null 2>&1 115 | rm initrd.gz 116 | root=$cdroot/rootfs 117 | 118 | if [ -f /data/Country.mmdb ]; then 119 | ls -lah /data/Country.mmdb 120 | echo Patching Country.mmdb... 121 | cp /data/Country.mmdb $root"/etc/config/clash/Country.mmdb" 122 | fi 123 | 124 | if [ "$SNIFF" = "yes" ] || [ "$SNIFF" = "dns" ] || [ "$sniff" = "yes" ] || [ "$sniff" = "dns" ]; then 125 | echo Patching sniff... 126 | mkdir -p $root"/etc/config/sing-box" 127 | echo "$json" >$root"/etc/config/sing-box/sniff.json" 128 | sed -i 's/1082/1081/g' $root"/usr/bin/nft.sh" 129 | sed -i 's/1082/1081/g' $root"/usr/bin/nft_tcp.sh" 130 | cp /sing-box $root"/usr/bin/" 131 | fi 132 | 133 | # if [ "$SNIFF" = "dns" ]; then 134 | # echo Patching sniff with dns... 135 | # mkdir -p $root"/etc/config/sing-box" 136 | # echo "$dnsjson" >$root"/etc/config/sing-box/sniff.json" 137 | # sed -i 's/1082/1081/g' $root"/usr/bin/nft.sh" 138 | # sed -i 's/1082/1081/g' $root"/usr/bin/nft_tcp.sh" 139 | # cp /sing-box $root"/usr/bin/" 140 | # touch $root"/www/sniffdns" 141 | # fi 142 | 143 | if [ -f /data/clash ]; then 144 | ls -lah /data/clash 145 | echo Patching clash... 146 | touch $root"/www/clash_core" 147 | cp /data/clash $root"/usr/bin/" 148 | chmod +x $root"/usr/bin/clash" 149 | fi 150 | if [ -f /data/network.ini ]; then 151 | ls -lah /data/network.ini 152 | echo Patching network... 153 | sed 's/\r/\n/g' "/data/network.ini" | grep -E "^[_a-zA-Z0-9]+=" >"/tmp/network.ini" 154 | . /tmp/network.ini 155 | if [ -z "$ip" ]; then 156 | echo "Error: network.ini ip not found." 157 | exit 158 | fi 159 | if [ -z "$mask" ]; then 160 | echo "Error: network.ini mask not found." 161 | exit 162 | fi 163 | if [ -z "$gw" ]; then 164 | echo "Error: network.ini gw not found." 165 | exit 166 | fi 167 | if [ "$ip" = "$gw" ]; then 168 | echo "Error: ip=gw=""$ip"" ! The network IP address should not be equal to the gateway." 169 | exit 170 | fi 171 | cat >$root"/etc/config/network" <>$root"/etc/config/network" 199 | else 200 | echo " option dns '$dns1'" >>$root"/etc/config/network" 201 | fi 202 | fi 203 | if [ -f /data/ppgwurl.ini ]; then 204 | if grep -q "ppgwurl=" /data/ppgwurl.ini; then 205 | ls -lah /data/ppgwurl.ini 206 | echo Patching ppgwurl.ini... 207 | sed 's/\r/\n/g' "/data/ppgwurl.ini" | grep "ppgwurl=" >$root"/www/ppgwurl.ini" 208 | fi 209 | fi 210 | if [ -f /data/ppgw.ini ]; then 211 | ls -lah /data/ppgw.ini 212 | echo Patching ppgw.ini... 213 | sed 's/\r/\n/g' "/data/ppgw.ini" | grep -E "^[_a-zA-Z0-9]+=" >$root"/www/ppgw.ini" 214 | fi 215 | 216 | if [ -f /data/custom.yaml ]; then 217 | ls -lah /data/custom.yaml 218 | echo Patching custom.yaml... 219 | sed 's/\r/\n/g' /data/custom.yaml >$root"/www/custom.yaml" 220 | fi 221 | 222 | if [ -f /data/custom.ovpn ]; then 223 | ls -lah /data/custom.ovpn 224 | echo Patching custom.ovpn... 225 | cp /data/custom.ovpn $root"/www/custom.ovpn" 226 | fi 227 | 228 | echo "Making iso..." 229 | cd $root || exit 230 | find . | cpio -H newc -o | gzip -9 >$cdroot/initrd.gz 231 | cd $cdroot || exit 232 | rm -rf rootfs 233 | cp -r /isolinux . 234 | xorriso -as mkisofs -o /tmp/paopao-gateway-x86-64-custom.iso \ 235 | -isohybrid-mbr isolinux/isolinux.bin \ 236 | -c isolinux/boot.cat -b isolinux/isolinux.bin \ 237 | -no-emul-boot -boot-load-size 4 -boot-info-table \ 238 | -eltorito-alt-boot -e /isolinux/efi.img \ 239 | -no-emul-boot -isohybrid-gpt-basdat -V "paopao-gateway" $cdroot >/dev/null 2>&1 240 | 241 | sha=$(sha256sum /tmp/paopao-gateway-x86-64-custom.iso | grep -Eo "^[0-9a-z]{7}") 242 | mv /tmp/paopao-gateway-x86-64-custom.iso /data/paopao-gateway-x86-64-custom-"$sha".iso 243 | ls -lah /data/paopao-gateway-x86-64-custom-"$sha".iso 244 | rm -rf /tmp/ /*sh 245 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/sha.js: -------------------------------------------------------------------------------- 1 | !function(){"use strict";function t(t,i){i?(d[0]=d[16]=d[1]=d[2]=d[3]=d[4]=d[5]=d[6]=d[7]=d[8]=d[9]=d[10]=d[11]=d[12]=d[13]=d[14]=d[15]=0,this.blocks=d):this.blocks=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],t?(this.h0=3238371032,this.h1=914150663,this.h2=812702999,this.h3=4144912697,this.h4=4290775857,this.h5=1750603025,this.h6=1694076839,this.h7=3204075428):(this.h0=1779033703,this.h1=3144134277,this.h2=1013904242,this.h3=2773480762,this.h4=1359893119,this.h5=2600822924,this.h6=528734635,this.h7=1541459225),this.block=this.start=this.bytes=this.hBytes=0,this.finalized=this.hashed=!1,this.first=!0,this.is224=t}function i(i,r,s){var e,n=typeof i;if("string"===n){var o,a=[],u=i.length,c=0;for(e=0;e>6,a[c++]=128|63&o):o<55296||o>=57344?(a[c++]=224|o>>12,a[c++]=128|o>>6&63,a[c++]=128|63&o):(o=65536+((1023&o)<<10|1023&i.charCodeAt(++e)),a[c++]=240|o>>18,a[c++]=128|o>>12&63,a[c++]=128|o>>6&63,a[c++]=128|63&o);i=a}else{if("object"!==n)throw new Error(h);if(null===i)throw new Error(h);if(f&&i.constructor===ArrayBuffer)i=new Uint8Array(i);else if(!(Array.isArray(i)||f&&ArrayBuffer.isView(i)))throw new Error(h)}i.length>64&&(i=new t(r,!0).update(i).array());var y=[],p=[];for(e=0;e<64;++e){var l=i[e]||0;y[e]=92^l,p[e]=54^l}t.call(this,r,s),this.update(p),this.oKeyPad=y,this.inner=!0,this.sharedMemory=s}var h="input is invalid type",r="object"==typeof window,s=r?window:{};s.JS_SHA256_NO_WINDOW&&(r=!1);var e=!r&&"object"==typeof self,n=!s.JS_SHA256_NO_NODE_JS&&"object"==typeof process&&process.versions&&process.versions.node;n?s=global:e&&(s=self);var o=!s.JS_SHA256_NO_COMMON_JS&&"object"==typeof module&&module.exports,a="function"==typeof define&&define.amd,f=!s.JS_SHA256_NO_ARRAY_BUFFER&&"undefined"!=typeof ArrayBuffer,u="0123456789abcdef".split(""),c=[-2147483648,8388608,32768,128],y=[24,16,8,0],p=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],l=["hex","array","digest","arrayBuffer"],d=[];!s.JS_SHA256_NO_NODE_JS&&Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)}),!f||!s.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW&&ArrayBuffer.isView||(ArrayBuffer.isView=function(t){return"object"==typeof t&&t.buffer&&t.buffer.constructor===ArrayBuffer});var A=function(i,h){return function(r){return new t(h,!0).update(r)[i]()}},w=function(i){var h=A("hex",i);n&&(h=b(h,i)),h.create=function(){return new t(i)},h.update=function(t){return h.create().update(t)};for(var r=0;r>2]|=t[n]<>2]|=s<>2]|=(192|s>>6)<>2]|=(128|63&s)<=57344?(a[e>>2]|=(224|s>>12)<>2]|=(128|s>>6&63)<>2]|=(128|63&s)<>2]|=(240|s>>18)<>2]|=(128|s>>12&63)<>2]|=(128|s>>6&63)<>2]|=(128|63&s)<=64?(this.block=a[16],this.start=e-64,this.hash(),this.hashed=!0):this.start=e}return this.bytes>4294967295&&(this.hBytes+=this.bytes/4294967296<<0,this.bytes=this.bytes%4294967296),this}},t.prototype.finalize=function(){if(!this.finalized){this.finalized=!0;var t=this.blocks,i=this.lastByteIndex;t[16]=this.block,t[i>>2]|=c[3&i],this.block=t[16],i>=56&&(this.hashed||this.hash(),t[0]=this.block,t[16]=t[1]=t[2]=t[3]=t[4]=t[5]=t[6]=t[7]=t[8]=t[9]=t[10]=t[11]=t[12]=t[13]=t[14]=t[15]=0),t[14]=this.hBytes<<3|this.bytes>>>29,t[15]=this.bytes<<3,this.hash()}},t.prototype.hash=function(){var t,i,h,r,s,e,n,o,a,f=this.h0,u=this.h1,c=this.h2,y=this.h3,l=this.h4,d=this.h5,A=this.h6,w=this.h7,b=this.blocks;for(t=16;t<64;++t)i=((s=b[t-15])>>>7|s<<25)^(s>>>18|s<<14)^s>>>3,h=((s=b[t-2])>>>17|s<<15)^(s>>>19|s<<13)^s>>>10,b[t]=b[t-16]+i+b[t-7]+h<<0;for(a=u&c,t=0;t<64;t+=4)this.first?(this.is224?(e=300032,w=(s=b[0]-1413257819)-150054599<<0,y=s+24177077<<0):(e=704751109,w=(s=b[0]-210244248)-1521486534<<0,y=s+143694565<<0),this.first=!1):(i=(f>>>2|f<<30)^(f>>>13|f<<19)^(f>>>22|f<<10),r=(e=f&u)^f&c^a,w=y+(s=w+(h=(l>>>6|l<<26)^(l>>>11|l<<21)^(l>>>25|l<<7))+(l&d^~l&A)+p[t]+b[t])<<0,y=s+(i+r)<<0),i=(y>>>2|y<<30)^(y>>>13|y<<19)^(y>>>22|y<<10),r=(n=y&f)^y&u^e,A=c+(s=A+(h=(w>>>6|w<<26)^(w>>>11|w<<21)^(w>>>25|w<<7))+(w&l^~w&d)+p[t+1]+b[t+1])<<0,i=((c=s+(i+r)<<0)>>>2|c<<30)^(c>>>13|c<<19)^(c>>>22|c<<10),r=(o=c&y)^c&f^n,d=u+(s=d+(h=(A>>>6|A<<26)^(A>>>11|A<<21)^(A>>>25|A<<7))+(A&w^~A&l)+p[t+2]+b[t+2])<<0,i=((u=s+(i+r)<<0)>>>2|u<<30)^(u>>>13|u<<19)^(u>>>22|u<<10),r=(a=u&c)^u&y^o,l=f+(s=l+(h=(d>>>6|d<<26)^(d>>>11|d<<21)^(d>>>25|d<<7))+(d&A^~d&w)+p[t+3]+b[t+3])<<0,f=s+(i+r)<<0,this.chromeBugWorkAround=!0;this.h0=this.h0+f<<0,this.h1=this.h1+u<<0,this.h2=this.h2+c<<0,this.h3=this.h3+y<<0,this.h4=this.h4+l<<0,this.h5=this.h5+d<<0,this.h6=this.h6+A<<0,this.h7=this.h7+w<<0},t.prototype.hex=function(){this.finalize();var t=this.h0,i=this.h1,h=this.h2,r=this.h3,s=this.h4,e=this.h5,n=this.h6,o=this.h7,a=u[t>>28&15]+u[t>>24&15]+u[t>>20&15]+u[t>>16&15]+u[t>>12&15]+u[t>>8&15]+u[t>>4&15]+u[15&t]+u[i>>28&15]+u[i>>24&15]+u[i>>20&15]+u[i>>16&15]+u[i>>12&15]+u[i>>8&15]+u[i>>4&15]+u[15&i]+u[h>>28&15]+u[h>>24&15]+u[h>>20&15]+u[h>>16&15]+u[h>>12&15]+u[h>>8&15]+u[h>>4&15]+u[15&h]+u[r>>28&15]+u[r>>24&15]+u[r>>20&15]+u[r>>16&15]+u[r>>12&15]+u[r>>8&15]+u[r>>4&15]+u[15&r]+u[s>>28&15]+u[s>>24&15]+u[s>>20&15]+u[s>>16&15]+u[s>>12&15]+u[s>>8&15]+u[s>>4&15]+u[15&s]+u[e>>28&15]+u[e>>24&15]+u[e>>20&15]+u[e>>16&15]+u[e>>12&15]+u[e>>8&15]+u[e>>4&15]+u[15&e]+u[n>>28&15]+u[n>>24&15]+u[n>>20&15]+u[n>>16&15]+u[n>>12&15]+u[n>>8&15]+u[n>>4&15]+u[15&n];return this.is224||(a+=u[o>>28&15]+u[o>>24&15]+u[o>>20&15]+u[o>>16&15]+u[o>>12&15]+u[o>>8&15]+u[o>>4&15]+u[15&o]),a},t.prototype.toString=t.prototype.hex,t.prototype.digest=function(){this.finalize();var t=this.h0,i=this.h1,h=this.h2,r=this.h3,s=this.h4,e=this.h5,n=this.h6,o=this.h7,a=[t>>24&255,t>>16&255,t>>8&255,255&t,i>>24&255,i>>16&255,i>>8&255,255&i,h>>24&255,h>>16&255,h>>8&255,255&h,r>>24&255,r>>16&255,r>>8&255,255&r,s>>24&255,s>>16&255,s>>8&255,255&s,e>>24&255,e>>16&255,e>>8&255,255&e,n>>24&255,n>>16&255,n>>8&255,255&n];return this.is224||a.push(o>>24&255,o>>16&255,o>>8&255,255&o),a},t.prototype.array=t.prototype.digest,t.prototype.arrayBuffer=function(){this.finalize();var t=new ArrayBuffer(this.is224?28:32),i=new DataView(t);return i.setUint32(0,this.h0),i.setUint32(4,this.h1),i.setUint32(8,this.h2),i.setUint32(12,this.h3),i.setUint32(16,this.h4),i.setUint32(20,this.h5),i.setUint32(24,this.h6),this.is224||i.setUint32(28,this.h7),t},(i.prototype=new t).finalize=function(){if(t.prototype.finalize.call(this),this.inner){this.inner=!1;var i=this.array();t.call(this,this.is224,this.sharedMemory),this.update(this.oKeyPad),this.update(i),t.prototype.finalize.call(this)}};var B=w();B.sha256=B,B.sha224=w(!0),B.sha256.hmac=v(),B.sha224.hmac=v(!0),o?module.exports=B:(s.sha256=B.sha256,s.sha224=B.sha224,a&&define(function(){return B}))}(); -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/index.esm-af95069f.js: -------------------------------------------------------------------------------- 1 | import{r as E}from"./index-969cf72a.js";function L(){return L=Object.assign?Object.assign.bind():function(n){for(var t=1;t=0)&&(r[a]=n[a]);return r}var ct=typeof performance=="object"&&typeof performance.now=="function",H=ct?function(){return performance.now()}:function(){return Date.now()};function K(n){cancelAnimationFrame(n.id)}function ut(n,t){var r=H();function i(){H()-r>=t?n.call(null):a.id=requestAnimationFrame(i)}var a={id:requestAnimationFrame(i)};return a}var N=-1;function V(n){if(n===void 0&&(n=!1),N===-1||n){var t=document.createElement("div"),r=t.style;r.width="50px",r.height="50px",r.overflow="scroll",document.body.appendChild(t),N=t.offsetWidth-t.clientWidth,document.body.removeChild(t)}return N}var _=null;function B(n){if(n===void 0&&(n=!1),_===null||n){var t=document.createElement("div"),r=t.style;r.width="50px",r.height="50px",r.overflow="scroll",r.direction="rtl";var i=document.createElement("div"),a=i.style;return a.width="100px",a.height="100px",t.appendChild(i),document.body.appendChild(t),t.scrollLeft>0?_="positive-descending":(t.scrollLeft=1,t.scrollLeft===0?_="negative":_="positive-ascending"),document.body.removeChild(t),_}return _}var ft=150,dt=function(t,r){return t};function J(n){var t,r=n.getItemOffset,i=n.getEstimatedTotalSize,a=n.getItemSize,l=n.getOffsetForIndexAndAlignment,c=n.getStartIndexForOffset,f=n.getStopIndexForStartIndex,p=n.initInstanceProps,z=n.shouldResetStyleCacheOnItemSizeChange,g=n.validateProps;return t=function(O){ot(M,O);function M(v){var e;return e=O.call(this,v)||this,e._instanceProps=p(e.props,U(e)),e._outerRef=void 0,e._resetIsScrollingTimeoutId=null,e.state={instance:U(e),isScrolling:!1,scrollDirection:"forward",scrollOffset:typeof e.props.initialScrollOffset=="number"?e.props.initialScrollOffset:0,scrollUpdateWasRequested:!1},e._callOnItemsRendered=void 0,e._callOnItemsRendered=F(function(o,s,u,m){return e.props.onItemsRendered({overscanStartIndex:o,overscanStopIndex:s,visibleStartIndex:u,visibleStopIndex:m})}),e._callOnScroll=void 0,e._callOnScroll=F(function(o,s,u){return e.props.onScroll({scrollDirection:o,scrollOffset:s,scrollUpdateWasRequested:u})}),e._getItemStyle=void 0,e._getItemStyle=function(o){var s=e.props,u=s.direction,m=s.itemSize,S=s.layout,d=e._getItemStyleCache(z&&m,z&&S,z&&u),h;if(d.hasOwnProperty(o))h=d[o];else{var y=r(e.props,o,e._instanceProps),x=a(e.props,o,e._instanceProps),T=u==="horizontal"||S==="horizontal",b=u==="rtl",R=T?y:0;d[o]=h={position:"absolute",left:b?void 0:R,right:b?R:void 0,top:T?0:y,height:T?"100%":x,width:T?x:"100%"}}return h},e._getItemStyleCache=void 0,e._getItemStyleCache=F(function(o,s,u){return{}}),e._onScrollHorizontal=function(o){var s=o.currentTarget,u=s.clientWidth,m=s.scrollLeft,S=s.scrollWidth;e.setState(function(d){if(d.scrollOffset===m)return null;var h=e.props.direction,y=m;if(h==="rtl")switch(B()){case"negative":y=-m;break;case"positive-descending":y=S-u-m;break}return y=Math.max(0,Math.min(y,S-u)),{isScrolling:!0,scrollDirection:d.scrollOffseth.clientWidth?V():0:d=h.scrollHeight>h.clientHeight?V():0}this.scrollTo(l(this.props,e,o,S,this._instanceProps,d))},I.componentDidMount=function(){var e=this.props,o=e.direction,s=e.initialScrollOffset,u=e.layout;if(typeof s=="number"&&this._outerRef!=null){var m=this._outerRef;o==="horizontal"||u==="horizontal"?m.scrollLeft=s:m.scrollTop=s}this._callPropsCallbacks()},I.componentDidUpdate=function(){var e=this.props,o=e.direction,s=e.layout,u=this.state,m=u.scrollOffset,S=u.scrollUpdateWasRequested;if(S&&this._outerRef!=null){var d=this._outerRef;if(o==="horizontal"||s==="horizontal")if(o==="rtl")switch(B()){case"negative":d.scrollLeft=-m;break;case"positive-ascending":d.scrollLeft=m;break;default:var h=d.clientWidth,y=d.scrollWidth;d.scrollLeft=y-h-m;break}else d.scrollLeft=m;else d.scrollTop=m}this._callPropsCallbacks()},I.componentWillUnmount=function(){this._resetIsScrollingTimeoutId!==null&&K(this._resetIsScrollingTimeoutId)},I.render=function(){var e=this.props,o=e.children,s=e.className,u=e.direction,m=e.height,S=e.innerRef,d=e.innerElementType,h=e.innerTagName,y=e.itemCount,x=e.itemData,T=e.itemKey,b=T===void 0?dt:T,R=e.layout,X=e.outerElementType,Y=e.outerTagName,tt=e.style,et=e.useIsScrolling,rt=e.width,A=this.state.isScrolling,P=u==="horizontal"||R==="horizontal",it=P?this._onScrollHorizontal:this._onScrollVertical,D=this._getRangeToRender(),nt=D[0],at=D[1],k=[];if(y>0)for(var w=nt;w<=at;w++)k.push(E.createElement(o,{data:x,key:b(w,x),index:w,isScrolling:et?A:void 0,style:this._getItemStyle(w)}));var $=i(this.props,this._instanceProps);return E.createElement(X||Y||"div",{className:s,onScroll:it,ref:this._outerRefSetter,style:L({position:"relative",height:m,width:rt,overflow:"auto",WebkitOverflowScrolling:"touch",willChange:"transform",direction:u},tt)},E.createElement(d||h||"div",{children:k,ref:S,style:{height:P?"100%":$,pointerEvents:A?"none":void 0,width:P?$:"100%"}}))},I._callPropsCallbacks=function(){if(typeof this.props.onItemsRendered=="function"){var e=this.props.itemCount;if(e>0){var o=this._getRangeToRender(),s=o[0],u=o[1],m=o[2],S=o[3];this._callOnItemsRendered(s,u,m,S)}}if(typeof this.props.onScroll=="function"){var d=this.state,h=d.scrollDirection,y=d.scrollOffset,x=d.scrollUpdateWasRequested;this._callOnScroll(h,y,x)}},I._getRangeToRender=function(){var e=this.props,o=e.itemCount,s=e.overscanCount,u=this.state,m=u.isScrolling,S=u.scrollDirection,d=u.scrollOffset;if(o===0)return[0,0,0,0];var h=c(this.props,d,this._instanceProps),y=f(this.props,h,d,this._instanceProps),x=!m||S==="backward"?Math.max(1,s):1,T=!m||S==="forward"?Math.max(1,s):1;return[Math.max(0,h-x),Math.max(0,Math.min(o-1,y+T)),h,y]},M}(E.PureComponent),t.defaultProps={direction:"ltr",itemData:void 0,layout:"vertical",overscanCount:2,useIsScrolling:!1},t}var mt=function(t,r){t.children,t.direction,t.height,t.layout,t.innerTagName,t.outerTagName,t.width,r.instance},ht=50,C=function(t,r,i){var a=t,l=a.itemSize,c=i.itemMetadataMap,f=i.lastMeasuredIndex;if(r>f){var p=0;if(f>=0){var z=c[f];p=z.offset+z.size}for(var g=f+1;g<=r;g++){var O=l(g);c[g]={offset:p,size:O},p+=O}i.lastMeasuredIndex=r}return c[r]},vt=function(t,r,i){var a=r.itemMetadataMap,l=r.lastMeasuredIndex,c=l>0?a[l].offset:0;return c>=i?Q(t,r,l,0,i):pt(t,r,Math.max(0,l),i)},Q=function(t,r,i,a,l){for(;a<=i;){var c=a+Math.floor((i-a)/2),f=C(t,c,r).offset;if(f===l)return c;fl&&(i=c-1)}return a>0?a-1:0},pt=function(t,r,i,a){for(var l=t.itemCount,c=1;i=i&&(c=i-1),c>=0){var p=a[c];f=p.offset+p.size}var z=i-c-1,g=z*l;return f+g},yt=J({getItemOffset:function(t,r,i){return C(t,r,i).offset},getItemSize:function(t,r,i){return i.itemMetadataMap[r].size},getEstimatedTotalSize:G,getOffsetForIndexAndAlignment:function(t,r,i,a,l,c){var f=t.direction,p=t.height,z=t.layout,g=t.width,O=f==="horizontal"||z==="horizontal",M=O?g:p,I=C(t,r,l),v=G(t,l),e=Math.max(0,Math.min(v-M,I.offset)),o=Math.max(0,I.offset-M+I.size+c);switch(i==="smart"&&(a>=o-M&&a<=e+M?i="auto":i="center"),i){case"start":return e;case"end":return o;case"center":return Math.round(o+(e-o)/2);case"auto":default:return a>=o&&a<=e?a:a=s-v&&a<=o+v?i="auto":i="center"),i){case"start":return o;case"end":return s;case"center":{var u=Math.round(s+(o-s)/2);return ue+Math.floor(v/2)?e:u}case"auto":default:return a>=s&&a<=o?a:a=0)&&Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}function Ye(e,t){if(e==null)return{};var n={},r=Object.keys(e),o,a;for(a=0;a=0)&&(n[o]=e[o]);return n}var Y=_.forwardRef(function(e,t){var n=e.color,r=n===void 0?"currentColor":n,o=e.size,a=o===void 0?24:o,l=Ke(e,["color","size"]);return G.createElement("svg",H({ref:t,xmlns:"http://www.w3.org/2000/svg",width:a,height:a,viewBox:"0 0 24 24",fill:"none",stroke:r,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"},l),G.createElement("polygon",{points:"13 2 3 14 12 14 11 22 21 10 12 10 13 2"}))});Y.propTypes={color:A.string,size:A.oneOfType([A.string,A.number])};Y.displayName="Zap";const X=Y;function ue(e){const t=e.size||24,n=w({[ve.animate]:e.animate});return s.jsx("svg",{className:n,xmlns:"http://www.w3.org/2000/svg",width:t,height:t,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:s.jsx("polygon",{points:"13 2 3 14 12 14 11 22 21 10 12 10 13 2"})})}const Ze="_FlexCenter_1380a_1",Ge={FlexCenter:Ze};function Ve({children:e}){return s.jsx("div",{className:Ge.FlexCenter,children:e})}const{useRef:Q,useEffect:We}=h;function Xe({onClickPrimaryButton:e,onClickSecondaryButton:t}){const n=Q(null),r=Q(null);We(()=>{n.current.focus()},[]);const o=a=>{a.code==="ArrowRight"?r.current.focus():a.code==="ArrowLeft"&&n.current.focus()};return s.jsxs("div",{onKeyDown:o,children:[s.jsx("h2",{children:"Close Connections?"}),s.jsx("p",{children:"Click [Yes] to close those connections that are still using the old selected proxy in this group"}),s.jsx("div",{style:{height:30}}),s.jsxs(Ve,{children:[s.jsx(v,{onClick:e,ref:n,children:"Yes"}),s.jsx("div",{style:{width:20}}),s.jsx(v,{onClick:t,ref:r,children:"No"})]})]})}const Qe="_header_1y9js_1",Je="_arrow_1y9js_8",et="_isOpen_1y9js_13",tt="_btn_1y9js_20",st="_qty_1y9js_25",C={header:Qe,arrow:Je,isOpen:et,btn:tt,qty:st};function de({name:e,type:t,toggle:n,isOpen:r,qty:o}){const a=_.useCallback(l=>{l.preventDefault(),(l.key==="Enter"||l.key===" ")&&n()},[n]);return s.jsxs("div",{className:C.header,onClick:n,style:{cursor:"pointer"},tabIndex:0,onKeyDown:a,role:"button",children:[s.jsx("div",{children:s.jsx(ge,{name:e,type:t})}),typeof o=="number"?s.jsx("span",{className:C.qty,children:o}):null,s.jsx(v,{kind:"minimal",onClick:n,className:C.btn,title:"Toggle collapsible section",children:s.jsx("span",{className:w(C.arrow,{[C.isOpen]:r}),children:s.jsx(Fe,{size:20})})})]})}const{useState:nt,useCallback:$s}=h;function xe(e){const[t,n]=nt(e);return{value:t,set:n}}const{useMemo:rt}=h;function ot(e,t){return e.filter(n=>{const r=t[n];return r===void 0?!0:!("number"in r&&r.number===0)})}const T=(e,t)=>{if(e&&"number"in e&&e.number>0)return e.number;const n=t&&t.type;return n&&re.indexOf(n)>-1?-1:999999},at={Natural:e=>e,LatencyAsc:(e,t,n)=>e.sort((r,o)=>{const a=T(t[r],n&&n[r]),l=T(t[o],n&&n[o]);return a-l}),LatencyDesc:(e,t,n)=>e.sort((r,o)=>{const a=T(t[r],n&&n[r]);return T(t[o],n&&n[o])-a}),NameAsc:e=>e.sort(),NameDesc:e=>e.sort((t,n)=>t>n?-1:tr.trim()).filter(r=>!!r);return n.length===0?e:e.filter(r=>{let o=0;for(;o-1)return!0}return!1})}function ct(e,t,n,r,o,a){let l=[...e];return n&&(l=ot(e,t)),typeof r=="string"&&r!==""&&(l=lt(l,r)),at[o](l,t,a)}function pe(e,t,n,r,o){const[a]=we(ne);return rt(()=>ct(e,t,n,a,r,o),[e,t,n,a,r,o])}const it="_header_5pmv2_1",ut="_groupHead_5pmv2_5",dt="_action_5pmv2_11",R={header:it,groupHead:ut,action:dt},xt="_proxy_5mgcm_1",pt="_now_5mgcm_25",ht="_error_5mgcm_29",mt="_selectable_5mgcm_32",ft="_proxyType_5mgcm_40",yt="_row_5mgcm_51",jt="_proxyName_5mgcm_57",_t="_proxySmall_5mgcm_66",y={proxy:xt,now:pt,error:ht,selectable:mt,proxyType:ft,row:yt,proxyName:jt,proxySmall:_t},vt="_proxyLatency_pw0sa_1",gt={proxyLatency:vt};function wt({latency:e,color:t}){let n=" ";if(e)switch(e.kind){case"Error":case"Testing":n="- ms";break;case"Result":n=(e.number!==0?e.number:"-")+" ms";break}return s.jsx("span",{className:gt.proxyLatency,style:{color:t},children:n})}const{useMemo:P}=h,g={good:"#67c23a",normal:"#d4b75c",bad:"#e67f3c",na:"#909399"};function he(e){if(!e||e.kind!=="Result")return g.na;const t=e.number;return t===0?g.na:t<200?g.good:t<400?g.normal:typeof t=="number"?g.bad:g.na}function bt(e,t){return re.indexOf(t)>-1?{border:"1px dotted #777"}:{background:he(e)}}function Ct({now:e,name:t,proxy:n,latency:r,isSelectable:o,onClick:a}){const l=P(()=>bt(r,n.type),[r,n]),u=P(()=>{let d=t;return r&&r.kind==="Result"&&typeof r.number=="number"&&(d+=" "+r.number+" ms"),d},[t,r]),c=_.useCallback(()=>{o&&a&&a(t)},[t,a,o]),x=P(()=>w(y.proxySmall,{[y.now]:e,[y.selectable]:o}),[o,e]),i=_.useCallback(d=>{d.key==="Enter"&&c()},[c]);return s.jsx("div",{title:u,className:x,style:l,onClick:c,onKeyDown:i,role:o?"menuitem":""})}function kt(e){return e==="Shadowsocks"?"SS":e}const Pt=e=>({left:e.left+window.scrollX-5,top:e.top+window.scrollY-38});function St({children:e,label:t,"aria-label":n}){const[r,o]=be();return s.jsxs(s.Fragment,{children:[_.cloneElement(e,r),s.jsx(Ce,{...o,label:t,"aria-label":n,position:Pt})]})}function Nt({now:e,name:t,proxy:n,latency:r,isSelectable:o,onClick:a}){const l=P(()=>he(r),[r]),u=_.useCallback(()=>{o&&a&&a(t)},[t,a,o]),c=_.useCallback(i=>{i.key==="Enter"&&u()},[u]),x=P(()=>w(y.proxy,{[y.now]:e,[y.selectable]:o}),[o,e]);return s.jsxs("div",{tabIndex:0,className:x,onClick:u,onKeyDown:c,role:o?"menuitem":"",children:[s.jsx("div",{className:y.proxyName,children:s.jsx(St,{label:t,"aria-label":"proxy name: "+t,children:s.jsx("span",{children:t})})}),s.jsxs("div",{className:y.row,children:[s.jsx("span",{className:y.proxyType,style:{opacity:e?.6:.2},children:kt(n.type)}),s.jsx(wt,{latency:r,color:l})]})]})}const me=(e,{name:t})=>{const n=oe(e),r=q(e);return{proxy:n[t]||{name:t,type:"Unknown",history:[]},latency:r[t]}},$t=b(me)(Nt),At=b(me)(Ct),Tt="_list_1oy7w_1",Lt="_listSummaryView_1oy7w_8",fe={list:Tt,listSummaryView:Lt};function ye({all:e,now:t,isSelectable:n,itemOnTapCallback:r}){const o=e;return s.jsx("div",{className:fe.list,children:o.map(a=>s.jsx($t,{onClick:r,isSelectable:n,name:a,now:a===t},a))})}function je({all:e,now:t,isSelectable:n,itemOnTapCallback:r}){return s.jsx("div",{className:fe.listSummaryView,children:e.map(o=>s.jsx(At,{onClick:r,isSelectable:n,name:o,now:o===t},o))})}const{createElement:Ot,useCallback:E,useMemo:Bt}=h;function Dt({name:e,all:t,delay:n,hideUnavailableProxies:r,proxySortBy:o,proxies:a,type:l,now:u,isOpen:c,apiConfig:x,dispatch:i}){const d=pe(t,n,r,o,a),f=Bt(()=>l==="Selector",[l]),{app:{updateCollapsibleIsOpen:p},proxies:{requestDelayForProxies:m}}=D(),F=E(()=>{p("proxyGroup",e,!c)},[c,p,e]),N=E(Z=>{f&&i(ke(x,e,Z))},[x,i,e,f]),{t:M}=S(),j=xe(!1),$=E(async()=>{if(!j.value){j.set(!0);try{await m(x,d)}catch{}j.set(!1)}},[d,x,m,j]);return s.jsxs("div",{className:R.group,children:[s.jsxs("div",{className:R.groupHead,children:[s.jsx(de,{name:e,type:l,toggle:F,qty:d.length,isOpen:c}),s.jsx("div",{className:R.action,children:s.jsx(B,{label:M("Test Latency"),children:s.jsx(v,{kind:"circular",onClick:$,children:s.jsx(ue,{animate:j.value,size:16})})})})]}),Ot(c?ye:je,{all:d,now:u,isSelectable:f,itemOnTapCallback:N})]})}const Ft=b((e,{name:t,delay:n})=>{const r=oe(e),o=ae(e),a=z(e),l=K(e),u=r[t],{all:c,type:x,now:i}=u;return{all:c,delay:n,hideUnavailableProxies:l,proxySortBy:a,proxies:r,type:x,now:i,isOpen:o[`proxyGroup:${t}`]}})(Dt),{useCallback:_e,useState:Mt}=h;function Rt({dispatch:e,apiConfig:t,name:n}){return _e(()=>e(Pe(t,n)),[t,e,n])}function Et({dispatch:e,apiConfig:t,names:n}){const[r,o]=Mt(!1);return[_e(async()=>{if(!r){o(!0);try{await e(Se(t,n))}catch{}o(!1)}},[t,e,n,r]),r]}const{useState:Ut,useCallback:It}=h;function Ht({isLoading:e}){return e?s.jsx(Ue,{children:s.jsx(X,{width:16,height:16})}):s.jsx(X,{width:16,height:16})}function qt({dispatch:e,apiConfig:t}){const[n,r]=Ut(!1);return[It(()=>{n||(r(!0),e(Ne(t)).then(()=>r(!1),()=>r(!1)))},[t,e,n]),n]}function zt({dispatch:e,apiConfig:t,proxyProviders:n}){const{t:r}=S(),[o,a]=qt({dispatch:e,apiConfig:t}),[l,u]=Et({apiConfig:t,dispatch:e,names:n.map(c=>c.name)});return s.jsx(Me,{icon:s.jsx(Ht,{isLoading:a}),onClick:o,text:r("Test Latency"),style:Re,children:n.length>0?s.jsx(Ee,{text:r("update_all_proxy_provider"),onClick:l,children:s.jsx(Ie,{isRotating:u})}):null})}const Kt="_updatedAt_919yi_1",Yt="_main_919yi_8",Zt="_head_919yi_17",Gt="_action_919yi_23",Vt="_refresh_919yi_31",k={updatedAt:Kt,main:Yt,head:Zt,action:Gt,refresh:Vt},{useCallback:J}=h;function L(e,t=2){if(e===0)return"0 B";const n=1024,r=t<0?0:t,o=["B","KB","MB","GB","TB","PB","EB","ZB","YB"],a=Math.floor(Math.log(e)/Math.log(n));return parseFloat((e/Math.pow(n,a)).toFixed(r))+" "+o[a]}function Wt(e,t){const n=new Date().getTime(),r=new Date(e).getTime(),o=Math.floor((n-r)/1e3);if(o<60)return t("justNow");const a=Math.floor(o/60);if(a<60)return`${a} ${t("minutesAgo")}`;const l=Math.floor(a/60);if(l<24)return`${l} ${t("hoursAgo")}`;const u=Math.floor(l/24);if(u<30)return`${u} ${t("daysAgo")}`;const c=Math.floor(u/30);return c<12?`${c} ${t("monthsAgo")}`:`${Math.floor(c/12)} ${t("yearsAgo")}`}function Xt({name:e,proxies:t,delay:n,hideUnavailableProxies:r,proxySortBy:o,vehicleType:a,updatedAt:l,isOpen:u,dispatch:c,apiConfig:x,subscriptionInfo:i}){const{t:d}=S(),f=pe(t,n,r,o),p=xe(!1),m=Rt({dispatch:c,apiConfig:x,name:e}),F=J(()=>{if(p.value)return;p.set(!0);const $=()=>p.set(!1);c($e(x,e)).then($,$)},[x,c,e,p]),{app:{updateCollapsibleIsOpen:N}}=D(),M=J(()=>{N("proxyProvider",e,!u)},[u,N,e]),j=Wt(new Date(l),d);return s.jsxs("div",{className:k.main,children:[s.jsxs("div",{className:k.head,children:[s.jsx(de,{name:e,toggle:M,type:a,isOpen:u,qty:f.length}),s.jsxs("div",{className:k.action,children:[s.jsx(B,{label:d("Update"),children:s.jsx(v,{kind:"circular",onClick:m,children:s.jsx(es,{})})}),s.jsx(B,{label:d("Test Latency"),children:s.jsx(v,{kind:"circular",onClick:F,children:s.jsx(ue,{animate:p.value,size:16})})})]})]}),s.jsx("div",{className:k.updatedAt,children:s.jsxs("small",{children:[d("Updated")," ",j,i&&s.jsxs(s.Fragment,{children:[i.Download!==void 0&&s.jsxs("span",{children:[" | ",d("Download")," ",L(i.Download)]}),i.Upload!==void 0&&s.jsxs("span",{children:[", ",d("Upload")," ",L(i.Upload)]}),i.Total!==void 0&&s.jsxs("span",{children:[", ",d("Remaining")," ",L(Math.max(0,i.Total-((i.Download!==void 0?i.Download:0)+(i.Upload!==void 0?i.Upload:0))))," / ",L(i.Total)]}),i.Expire&&s.jsxs("span",{children:[", ",d("Expires"),": ",new Date(i.Expire*1e3).toLocaleDateString()]})]})]})}),u?s.jsx(ye,{all:f}):s.jsx(je,{all:f})]})}const Qt={rest:{scale:1},pressed:{scale:.95}},Jt={rest:{rotate:0},hover:{rotate:360,transition:{duration:.3}}};function es(){const t=Ae.read().motion;return s.jsx(t.div,{className:k.refresh,variants:Qt,initial:"rest",whileHover:"hover",whileTap:"pressed",children:s.jsx(t.div,{className:"flexCenter",variants:Jt,children:s.jsx(He,{size:16})})})}const ts=(e,t)=>{const n=K(e),r=q(e),o=ae(e),a=le(e),l=z(e),c=ce(e).find(i=>i.name===t.name),x=c==null?void 0:c.subscriptionInfo;return{apiConfig:a,proxies:(c==null?void 0:c.proxies)||[],delay:r,hideUnavailableProxies:n,proxySortBy:l,isOpen:o[`proxyProvider:${t.name}`],subscriptionInfo:x,updatedAt:c==null?void 0:c.updatedAt,vehicleType:c==null?void 0:c.vehicleType}},ss=b(ts)(Xt);function ns({items:e}){return e.length===0?null:s.jsxs(s.Fragment,{children:[s.jsx(ie,{title:"Proxy Provider"}),s.jsx("div",{children:e.map(t=>s.jsx(ss,{name:t.name,proxies:t.proxies,type:t.type,vehicleType:t.vehicleType,updatedAt:t.updatedAt},t.name))})]})}const rs="_labeledInput_cmki0_1",U={labeledInput:rs},os=[["Natural","order_natural"],["LatencyAsc","order_latency_asc"],["LatencyDesc","order_latency_desc"],["NameAsc","order_name_asc"],["NameDesc","order_name_desc"]],{useCallback:ee}=h;function as({appConfig:e}){const{app:{updateAppConfig:t}}=D(),n=ee(a=>{t("proxySortBy",a.target.value)},[t]),r=ee(a=>{t("hideUnavailableProxies",a)},[t]),{t:o}=S();return s.jsxs(s.Fragment,{children:[s.jsxs("div",{className:U.labeledInput,children:[s.jsx("span",{children:o("sort_in_grp")}),s.jsx("div",{children:s.jsx(ze,{options:os.map(a=>[a[0],o(a[1])]),selected:e.proxySortBy,onChange:n})})]}),s.jsx("hr",{}),s.jsxs("div",{className:U.labeledInput,children:[s.jsx("label",{htmlFor:"hideUnavailableProxies",children:o("hide_unavail_proxies")}),s.jsx("div",{children:s.jsx(W,{id:"hideUnavailableProxies",checked:e.hideUnavailableProxies,onChange:r})})]}),s.jsxs("div",{className:U.labeledInput,children:[s.jsx("label",{htmlFor:"autoCloseOldConns",children:o("auto_close_conns")}),s.jsx("div",{children:s.jsx(W,{id:"autoCloseOldConns",checked:e.autoCloseOldConns,onChange:a=>t("autoCloseOldConns",a)})})]})]})}const ls=e=>{const t=z(e),n=K(e),r=Te(e);return{appConfig:{proxySortBy:t,hideUnavailableProxies:n,autoCloseOldConns:r}}},cs=b(ls)(as),is="_overlay_uuk3b_1",us="_cnt_uuk3b_5",ds="_afterOpen_uuk3b_16",I={overlay:is,cnt:us,afterOpen:ds},{useMemo:xs}=h;function te({isOpen:e,onRequestClose:t,children:n}){const r=xs(()=>({base:w(V.content,I.cnt),afterOpen:I.afterOpen,beforeClose:""}),[]);return s.jsx(Le,{isOpen:e,onRequestClose:t,className:r,overlayClassName:w(V.overlay,I.overlay),children:n})}function ps({color:e="currentColor",size:t=24}){return s.jsxs("svg",{fill:"none",xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",width:t,height:t,stroke:e,strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[s.jsx("path",{d:"M2 6h9M18.5 6H22"}),s.jsx("circle",{cx:"16",cy:"6",r:"2"}),s.jsx("path",{d:"M22 18h-9M6 18H2"}),s.jsx("circle",{r:"2",transform:"matrix(-1 0 0 1 8 18)"})]})}const hs="_topBar_16fpp_1",ms="_topBarRight_16fpp_13",fs="_textFilterContainer_16fpp_22",ys="_group_16fpp_29",O={topBar:hs,topBarRight:ms,textFilterContainer:fs,group:ys},{useState:js,useEffect:_s,useCallback:se,useRef:vs}=h;function gs({dispatch:e,groupNames:t,delay:n,proxyProviders:r,apiConfig:o,showModalClosePrevConns:a}){const l=vs({}),u=se(()=>{l.current.startAt=Date.now(),e(Oe(o)).then(()=>{l.current.completeAt=Date.now()})},[o,e]);_s(()=>{u();const m=()=>{l.current.startAt&&Date.now()-l.current.startAt>3e4&&u()};return window.addEventListener("focus",m,!1),()=>window.removeEventListener("focus",m,!1)},[u]);const[c,x]=js(!1),i=se(()=>{x(!1)},[]),{proxies:{closeModalClosePrevConns:d,closePrevConnsAndTheModal:f}}=D(),{t:p}=S();return s.jsxs(s.Fragment,{children:[s.jsx(te,{isOpen:c,onRequestClose:i,children:s.jsx(cs,{})}),s.jsxs("div",{className:O.topBar,children:[s.jsx(ie,{title:p("Proxies")}),s.jsxs("div",{className:O.topBarRight,children:[s.jsx("div",{className:O.textFilterContainer,children:s.jsx(qe,{textAtom:ne})}),s.jsx(B,{label:p("settings"),children:s.jsx(v,{kind:"minimal",onClick:()=>x(!0),children:s.jsx(ps,{size:16})})})]})]}),s.jsx("div",{children:t.map(m=>s.jsx("div",{className:O.group,children:s.jsx(Ft,{name:m,delay:n,apiConfig:o,dispatch:e})},m))}),s.jsx(ns,{items:r}),s.jsx("div",{style:{height:60}}),s.jsx(zt,{dispatch:e,apiConfig:o,proxyProviders:r}),s.jsx(te,{isOpen:a,onRequestClose:d,children:s.jsx(Xe,{onClickPrimaryButton:()=>f(o),onClickSecondaryButton:d})})]})}const ws=e=>({apiConfig:le(e),groupNames:Be(e),proxyProviders:ce(e),delay:q(e),showModalClosePrevConns:De(e)}),As=b(ws)(gs);export{As as default}; 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/Rules-77f1d37d.js: -------------------------------------------------------------------------------- 1 | import{aa as J,ab as $,ac as G,ad as W,ae as K,af as _,r as w,ag as Z,ah as ee,ai as te,I as j,aj as ne,ak as re,al as O,v as ae,j as u,L as ie,B as se,u as E,b as oe,g as ue,C as le,e as ce}from"./index-969cf72a.js";import{a as de,V as he}from"./index.esm-af95069f.js";import{R as A,T as fe}from"./TextFilter-78284216.js";import{F as me,p as ve}from"./Fab-e423cc40.js";import{u as ge}from"./useRemainingViewPortHeight-3d85719a.js";import"./debounce-c1ba2006.js";class pe extends J{constructor(t,n){super(),this.client=t,this.setOptions(n),this.bindMethods(),this.updateResult()}bindMethods(){this.mutate=this.mutate.bind(this),this.reset=this.reset.bind(this)}setOptions(t){var n;const r=this.options;this.options=this.client.defaultMutationOptions(t),$(r,this.options)||this.client.getMutationCache().notify({type:"observerOptionsUpdated",mutation:this.currentMutation,observer:this}),(n=this.currentMutation)==null||n.setOptions(this.options)}onUnsubscribe(){if(!this.hasListeners()){var t;(t=this.currentMutation)==null||t.removeObserver(this)}}onMutationUpdate(t){this.updateResult();const n={listeners:!0};t.type==="success"?n.onSuccess=!0:t.type==="error"&&(n.onError=!0),this.notify(n)}getCurrentResult(){return this.currentResult}reset(){this.currentMutation=void 0,this.updateResult(),this.notify({listeners:!0})}mutate(t,n){return this.mutateOptions=n,this.currentMutation&&this.currentMutation.removeObserver(this),this.currentMutation=this.client.getMutationCache().build(this.client,{...this.options,variables:typeof t<"u"?t:this.options.variables}),this.currentMutation.addObserver(this),this.currentMutation.execute()}updateResult(){const t=this.currentMutation?this.currentMutation.state:G(),n={...t,isLoading:t.status==="loading",isSuccess:t.status==="success",isError:t.status==="error",isIdle:t.status==="idle",mutate:this.mutate,reset:this.reset};this.currentResult=n}notify(t){W.batch(()=>{if(this.mutateOptions&&this.hasListeners()){if(t.onSuccess){var n,r,a,i;(n=(r=this.mutateOptions).onSuccess)==null||n.call(r,this.currentResult.data,this.currentResult.variables,this.currentResult.context),(a=(i=this.mutateOptions).onSettled)==null||a.call(i,this.currentResult.data,null,this.currentResult.variables,this.currentResult.context)}else if(t.onError){var s,l,o,c;(s=(l=this.mutateOptions).onError)==null||s.call(l,this.currentResult.error,this.currentResult.variables,this.currentResult.context),(o=(c=this.mutateOptions).onSettled)==null||o.call(c,void 0,this.currentResult.error,this.currentResult.variables,this.currentResult.context)}}t.listeners&&this.listeners.forEach(({listener:f})=>{f(this.currentResult)})})}}function F(e,t,n){const r=K(e,t,n),a=_({context:r.context}),[i]=w.useState(()=>new pe(a,r));w.useEffect(()=>{i.setOptions(r)},[i,r]);const s=Z(w.useCallback(o=>i.subscribe(W.batchCalls(o)),[i]),()=>i.getCurrentResult(),()=>i.getCurrentResult()),l=w.useCallback((o,c)=>{i.mutate(o,c).catch(be)},[i]);if(s.error&&ee(i.options.useErrorBoundary,[s.error]))throw s.error;return{...s,mutate:l,mutateAsync:s.mutate}}function be(){}function v(e,t){if(t.length1?"s":"")+" required, but only "+t.length+" present")}function d(e){v(1,arguments);var t=Object.prototype.toString.call(e);return e instanceof Date||te(e)==="object"&&t==="[object Date]"?new Date(e.getTime()):typeof e=="number"||t==="[object Number]"?new Date(e):((typeof e=="string"||t==="[object String]")&&typeof console<"u"&&(console.warn("Starting with v2.0.0-beta.1 date-fns doesn't accept strings as date arguments. Please use `parseISO` to parse strings. See: https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#string-arguments"),console.warn(new Error().stack)),new Date(NaN))}var ye={};function Me(){return ye}function C(e){var t=new Date(Date.UTC(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds()));return t.setUTCFullYear(e.getFullYear()),e.getTime()-t.getTime()}function R(e,t){v(2,arguments);var n=d(e),r=d(t),a=n.getTime()-r.getTime();return a<0?-1:a>0?1:a}function we(e,t){v(2,arguments);var n=d(e),r=d(t),a=n.getFullYear()-r.getFullYear(),i=n.getMonth()-r.getMonth();return a*12+i}function Re(e,t){return v(2,arguments),d(e).getTime()-d(t).getTime()}var N={ceil:Math.ceil,round:Math.round,floor:Math.floor,trunc:function(t){return t<0?Math.ceil(t):Math.floor(t)}},Pe="trunc";function xe(e){return e?N[e]:N[Pe]}function Se(e){v(1,arguments);var t=d(e);return t.setHours(23,59,59,999),t}function De(e){v(1,arguments);var t=d(e),n=t.getMonth();return t.setFullYear(t.getFullYear(),n+1,0),t.setHours(23,59,59,999),t}function _e(e){v(1,arguments);var t=d(e);return Se(t).getTime()===De(t).getTime()}function je(e,t){v(2,arguments);var n=d(e),r=d(t),a=R(n,r),i=Math.abs(we(n,r)),s;if(i<1)s=0;else{n.getMonth()===1&&n.getDate()>27&&n.setDate(30),n.setMonth(n.getMonth()-a*i);var l=R(n,r)===-a;_e(d(e))&&i===1&&R(e,r)===1&&(l=!1),s=a*(i-Number(l))}return s===0?0:s}function Te(e,t,n){v(2,arguments);var r=Re(e,t)/1e3;return xe(n==null?void 0:n.roundingMethod)(r)}var Ce={lessThanXSeconds:{one:"less than a second",other:"less than {{count}} seconds"},xSeconds:{one:"1 second",other:"{{count}} seconds"},halfAMinute:"half a minute",lessThanXMinutes:{one:"less than a minute",other:"less than {{count}} minutes"},xMinutes:{one:"1 minute",other:"{{count}} minutes"},aboutXHours:{one:"about 1 hour",other:"about {{count}} hours"},xHours:{one:"1 hour",other:"{{count}} hours"},xDays:{one:"1 day",other:"{{count}} days"},aboutXWeeks:{one:"about 1 week",other:"about {{count}} weeks"},xWeeks:{one:"1 week",other:"{{count}} weeks"},aboutXMonths:{one:"about 1 month",other:"about {{count}} months"},xMonths:{one:"1 month",other:"{{count}} months"},aboutXYears:{one:"about 1 year",other:"about {{count}} years"},xYears:{one:"1 year",other:"{{count}} years"},overXYears:{one:"over 1 year",other:"over {{count}} years"},almostXYears:{one:"almost 1 year",other:"almost {{count}} years"}},Ne=function(t,n,r){var a,i=Ce[t];return typeof i=="string"?a=i:n===1?a=i.one:a=i.other.replace("{{count}}",n.toString()),r!=null&&r.addSuffix?r.comparison&&r.comparison>0?"in "+a:a+" ago":a};const ke=Ne;function x(e){return function(){var t=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},n=t.width?String(t.width):e.defaultWidth,r=e.formats[n]||e.formats[e.defaultWidth];return r}}var Ie={full:"EEEE, MMMM do, y",long:"MMMM do, y",medium:"MMM d, y",short:"MM/dd/yyyy"},We={full:"h:mm:ss a zzzz",long:"h:mm:ss a z",medium:"h:mm:ss a",short:"h:mm a"},Oe={full:"{{date}} 'at' {{time}}",long:"{{date}} 'at' {{time}}",medium:"{{date}}, {{time}}",short:"{{date}}, {{time}}"},Ee={date:x({formats:Ie,defaultWidth:"full"}),time:x({formats:We,defaultWidth:"full"}),dateTime:x({formats:Oe,defaultWidth:"full"})};const Ae=Ee;var Fe={lastWeek:"'last' eeee 'at' p",yesterday:"'yesterday at' p",today:"'today at' p",tomorrow:"'tomorrow at' p",nextWeek:"eeee 'at' p",other:"P"},Le=function(t,n,r,a){return Fe[t]};const ze=Le;function b(e){return function(t,n){var r=n!=null&&n.context?String(n.context):"standalone",a;if(r==="formatting"&&e.formattingValues){var i=e.defaultFormattingWidth||e.defaultWidth,s=n!=null&&n.width?String(n.width):i;a=e.formattingValues[s]||e.formattingValues[i]}else{var l=e.defaultWidth,o=n!=null&&n.width?String(n.width):e.defaultWidth;a=e.values[o]||e.values[l]}var c=e.argumentCallback?e.argumentCallback(t):t;return a[c]}}var Xe={narrow:["B","A"],abbreviated:["BC","AD"],wide:["Before Christ","Anno Domini"]},Be={narrow:["1","2","3","4"],abbreviated:["Q1","Q2","Q3","Q4"],wide:["1st quarter","2nd quarter","3rd quarter","4th quarter"]},Ue={narrow:["J","F","M","A","M","J","J","A","S","O","N","D"],abbreviated:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],wide:["January","February","March","April","May","June","July","August","September","October","November","December"]},qe={narrow:["S","M","T","W","T","F","S"],short:["Su","Mo","Tu","We","Th","Fr","Sa"],abbreviated:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],wide:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},Ve={narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"}},Ye={narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"}},Qe=function(t,n){var r=Number(t),a=r%100;if(a>20||a<10)switch(a%10){case 1:return r+"st";case 2:return r+"nd";case 3:return r+"rd"}return r+"th"},He={ordinalNumber:Qe,era:b({values:Xe,defaultWidth:"wide"}),quarter:b({values:Be,defaultWidth:"wide",argumentCallback:function(t){return t-1}}),month:b({values:Ue,defaultWidth:"wide"}),day:b({values:qe,defaultWidth:"wide"}),dayPeriod:b({values:Ve,defaultWidth:"wide",formattingValues:Ye,defaultFormattingWidth:"wide"})};const Je=He;function y(e){return function(t){var n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=n.width,a=r&&e.matchPatterns[r]||e.matchPatterns[e.defaultMatchWidth],i=t.match(a);if(!i)return null;var s=i[0],l=r&&e.parsePatterns[r]||e.parsePatterns[e.defaultParseWidth],o=Array.isArray(l)?Ge(l,function(m){return m.test(s)}):$e(l,function(m){return m.test(s)}),c;c=e.valueCallback?e.valueCallback(o):o,c=n.valueCallback?n.valueCallback(c):c;var f=t.slice(s.length);return{value:c,rest:f}}}function $e(e,t){for(var n in e)if(e.hasOwnProperty(n)&&t(e[n]))return n}function Ge(e,t){for(var n=0;n1&&arguments[1]!==void 0?arguments[1]:{},r=t.match(e.matchPattern);if(!r)return null;var a=r[0],i=t.match(e.parsePattern);if(!i)return null;var s=e.valueCallback?e.valueCallback(i[0]):i[0];s=n.valueCallback?n.valueCallback(s):s;var l=t.slice(a.length);return{value:s,rest:l}}}var Ze=/^(\d+)(th|st|nd|rd)?/i,et=/\d+/i,tt={narrow:/^(b|a)/i,abbreviated:/^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,wide:/^(before christ|before common era|anno domini|common era)/i},nt={any:[/^b/i,/^(a|c)/i]},rt={narrow:/^[1234]/i,abbreviated:/^q[1234]/i,wide:/^[1234](th|st|nd|rd)? quarter/i},at={any:[/1/i,/2/i,/3/i,/4/i]},it={narrow:/^[jfmasond]/i,abbreviated:/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,wide:/^(january|february|march|april|may|june|july|august|september|october|november|december)/i},st={narrow:[/^j/i,/^f/i,/^m/i,/^a/i,/^m/i,/^j/i,/^j/i,/^a/i,/^s/i,/^o/i,/^n/i,/^d/i],any:[/^ja/i,/^f/i,/^mar/i,/^ap/i,/^may/i,/^jun/i,/^jul/i,/^au/i,/^s/i,/^o/i,/^n/i,/^d/i]},ot={narrow:/^[smtwf]/i,short:/^(su|mo|tu|we|th|fr|sa)/i,abbreviated:/^(sun|mon|tue|wed|thu|fri|sat)/i,wide:/^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i},ut={narrow:[/^s/i,/^m/i,/^t/i,/^w/i,/^t/i,/^f/i,/^s/i],any:[/^su/i,/^m/i,/^tu/i,/^w/i,/^th/i,/^f/i,/^sa/i]},lt={narrow:/^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,any:/^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i},ct={any:{am:/^a/i,pm:/^p/i,midnight:/^mi/i,noon:/^no/i,morning:/morning/i,afternoon:/afternoon/i,evening:/evening/i,night:/night/i}},dt={ordinalNumber:Ke({matchPattern:Ze,parsePattern:et,valueCallback:function(t){return parseInt(t,10)}}),era:y({matchPatterns:tt,defaultMatchWidth:"wide",parsePatterns:nt,defaultParseWidth:"any"}),quarter:y({matchPatterns:rt,defaultMatchWidth:"wide",parsePatterns:at,defaultParseWidth:"any",valueCallback:function(t){return t+1}}),month:y({matchPatterns:it,defaultMatchWidth:"wide",parsePatterns:st,defaultParseWidth:"any"}),day:y({matchPatterns:ot,defaultMatchWidth:"wide",parsePatterns:ut,defaultParseWidth:"any"}),dayPeriod:y({matchPatterns:lt,defaultMatchWidth:"any",parsePatterns:ct,defaultParseWidth:"any"})};const ht=dt;var ft={code:"en-US",formatDistance:ke,formatLong:Ae,formatRelative:ze,localize:Je,match:ht,options:{weekStartsOn:0,firstWeekContainsDate:1}};const mt=ft;function L(e,t){if(e==null)throw new TypeError("assign requires that input parameter not be null or undefined");for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n]);return e}function vt(e){return L({},e)}var k=1440,gt=2520,S=43200,pt=86400;function bt(e,t,n){var r,a;v(2,arguments);var i=Me(),s=(r=(a=n==null?void 0:n.locale)!==null&&a!==void 0?a:i.locale)!==null&&r!==void 0?r:mt;if(!s.formatDistance)throw new RangeError("locale must contain formatDistance property");var l=R(e,t);if(isNaN(l))throw new RangeError("Invalid time value");var o=L(vt(n),{addSuffix:!!(n!=null&&n.addSuffix),comparison:l}),c,f;l>0?(c=d(t),f=d(e)):(c=d(e),f=d(t));var m=Te(f,c),V=(C(f)-C(c))/1e3,h=Math.round((m-V)/60),p;if(h<2)return n!=null&&n.includeSeconds?m<5?s.formatDistance("lessThanXSeconds",5,o):m<10?s.formatDistance("lessThanXSeconds",10,o):m<20?s.formatDistance("lessThanXSeconds",20,o):m<40?s.formatDistance("halfAMinute",0,o):m<60?s.formatDistance("lessThanXMinutes",1,o):s.formatDistance("xMinutes",1,o):h===0?s.formatDistance("lessThanXMinutes",1,o):s.formatDistance("xMinutes",h,o);if(h<45)return s.formatDistance("xMinutes",h,o);if(h<90)return s.formatDistance("aboutXHours",1,o);if(h=0,"there is no valid rules list in the rules API response"),e.rules.map((t,n)=>({...t,id:n}))}async function Dt(e,t){let n={rules:[]};try{const{url:r,init:a}=j(t),i=await fetch(r+e,a);i.ok&&(n=await i.json())}catch(r){console.log("failed to fetch rules",r)}return St(n)}const X=re("");function _t(e,t){const n=_(),{mutate:r,isLoading:a}=F(z,{onSuccess:()=>{n.invalidateQueries(["/providers/rules"])}});return[s=>{s.preventDefault(),r({name:e,apiConfig:t})},a]}function jt(e){const t=_(),{data:n}=B(e),{mutate:r,isLoading:a}=F(wt,{onSuccess:()=>{t.invalidateQueries(["/providers/rules"])}});return[s=>{s.preventDefault(),r({names:n.names,apiConfig:e})},a]}function B(e){return O(["/providers/rules",e],()=>Mt("/providers/rules",e))}function Tt(e){const{data:t,isFetching:n}=O(["/rules",e],()=>Dt("/rules",e)),{data:r}=B(e),[a]=ae(X);if(a==="")return{rules:t,provider:r,isFetching:n};{const i=a.toLowerCase();return{rules:t.filter(s=>s.payload.toLowerCase().indexOf(i)>=0),isFetching:n,provider:{byName:r.byName,names:r.names.filter(s=>s.toLowerCase().indexOf(i)>=0)}}}}const Ct="_RuleProviderItem_12aid_1",Nt="_left_12aid_7",kt="_middle_12aid_14",It="_gray_12aid_21",Wt="_action_12aid_25",Ot="_refreshBtn_12aid_32",g={RuleProviderItem:Ct,left:Nt,middle:kt,gray:It,action:Wt,refreshBtn:Ot};function Et({idx:e,name:t,vehicleType:n,behavior:r,updatedAt:a,ruleCount:i,apiConfig:s}){const[l,o]=_t(t,s),c=bt(new Date(a),new Date);return u.jsxs("div",{className:g.RuleProviderItem,children:[u.jsx("span",{className:g.left,children:e}),u.jsxs("div",{className:g.middle,children:[u.jsx(ie,{name:t,type:`${n} / ${r}`}),u.jsx("div",{className:g.gray,children:i<2?`${i} rule`:`${i} rules`}),u.jsxs("div",{className:g.action,children:[u.jsxs(se,{onClick:l,disabled:o,className:g.refreshBtn,children:[u.jsx(A,{isRotating:o,size:13}),u.jsx("span",{className:"visually-hidden",children:"Refresh"})]}),u.jsxs("small",{className:g.gray,children:["Updated ",c," ago"]})]})]})]})}function At({apiConfig:e}){const[t,n]=jt(e),{t:r}=E();return u.jsx(me,{icon:u.jsx(A,{isRotating:n}),text:r("update_all_rule_provider"),style:ve,onClick:t})}const Ft="_rule_1kxgd_1",Lt="_left_1kxgd_12",zt="_a_1kxgd_19",Xt="_b_1kxgd_26",Bt="_type_1kxgd_37",M={rule:Ft,left:Lt,a:zt,b:Xt,type:Bt},D={_default:"#59caf9",DIRECT:"#f5bc41",REJECT:"#cb3166"};function Ut({proxy:e}){let t=D._default;return D[e]&&(t=D[e]),{color:t}}function qt({type:e,payload:t,proxy:n,id:r}){const a=Ut({proxy:n});return u.jsxs("div",{className:M.rule,children:[u.jsx("div",{className:M.left,children:r}),u.jsxs("div",{children:[u.jsx("div",{className:M.b,children:t}),u.jsxs("div",{className:M.a,children:[u.jsx("div",{className:M.type,children:e}),u.jsx("div",{style:a,children:n})]})]})]})}const Vt="_header_n1m95_1",Yt="_RuleProviderItemWrapper_n1m95_17",U={header:Vt,RuleProviderItemWrapper:Yt},{memo:Qt}=ce,I=30;function Ht(e,{rules:t,provider:n}){const r=n.names.length;return e{const{rules:r,provider:a,apiConfig:i}=n,s=a.names.length;if(e({apiConfig:ue(e)}),an=oe($t)(Gt);function Gt({apiConfig:e}){const[t,n]=ge(),{rules:r,provider:a}=Tt(e),i=Jt({provider:a}),{t:s}=E();return u.jsxs("div",{children:[u.jsxs("div",{className:U.header,children:[u.jsx(le,{title:s("Rules")}),u.jsx(fe,{placeholder:"Filter",textAtom:X})]}),u.jsx("div",{ref:t,style:{paddingBottom:I},children:u.jsx(he,{height:n-I,width:"100%",itemCount:r.length+a.names.length,itemSize:i,itemData:{rules:r,provider:a,apiConfig:e},itemKey:Ht,children:q})}),a&&a.names&&a.names.length>0?u.jsx(At,{apiConfig:e}):null]})}export{an as default}; 2 | -------------------------------------------------------------------------------- /FILES/etc/config/clash/clash-dashboard/assets/index-454097a7.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";.relative,.border-left,.border-top,.border-bottom{position:relative}.border-bottom:after,.border-top:before{position:absolute;content:"";height:1px;width:100%;transform:scaleY(.5) translateZ(0);left:0;right:0;background:#555}.border-left:before{position:absolute;content:"";height:100%;width:1px;transform:scaleX(.5) translateZ(0);top:0;bottom:0;background:#555}.border-top:before{top:0}.border-bottom:after{bottom:0}.border-left:before{left:0}*,*:before,*:after{box-sizing:border-box}:root{--font-mono: "Roboto Mono", Menlo, monospace;--font-normal: Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica, Apple Color Emoji, Twemoji Country Flags, Segoe UI Emoji, Segoe UI Symbol, "PingFang SC", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;--color-focus-blue: #1a73e8;--btn-bg: #387cec}body{font-family:var(--font-normal);-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-text-size-adjust:100%;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;margin:0;padding:0}@media (prefers-color-scheme: dark){:root[data-theme=auto]{--color-background: #202020;--color-background2: rgba(32, 32, 32, .3);--color-bg-card: #2d2d2d;--card-hover-border-lightness: 30%;--color-text: #ddd;--color-text-secondary: #ccc;--color-text-highlight: #fff;--color-bg-sidebar: #2d2d30;--color-input-bg: #2d2d30;--color-input-border: #3f3f3f;--color-toggle-bg: #353535;--color-toggle-selected: #181818;--color-icon: #c7c7c7;--color-separator: #333;--color-btn-bg: #232323;--color-btn-fg: #bebebe;--color-bg-proxy: #303030;--color-row-odd: #333;--bg-log-info-tag: #454545;--bg-modal: #1f1f20;--bg-near-transparent: rgba(255, 255, 255, .1);--bg-tooltip: #111;--bc-tooltip: #555;--select-border-color: #040404;--select-bg-hover: url(data:image/svg+xml,%0A%20%20%20%20%3Csvg%20width%3D%228%22%20height%3D%2224%22%20viewBox%3D%220%200%208%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%207L7%2011H1L4%207Z%22%20fill%3D%22%23ffffff%22%20%2F%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%2017L1%2013L7%2013L4%2017Z%22%20fill%3D%22%23ffffff%22%20%2F%3E%0A%20%20%20%20%3C%2Fsvg%3E%0A%20%20);--color-proxy-dot-selected-ind-bo: transparent;--bg-toggle-track: #393939;color-scheme:dark}}@media (prefers-color-scheme: light){:root[data-theme=auto]{--color-background: #eee;--color-background2: rgba(240, 240, 240, .3);--color-bg-card: #fafafa;--card-hover-border-lightness: 80%;--color-text: #222;--color-text-secondary: #646464;--color-text-highlight: #040404;--color-bg-sidebar: #f8f8f8;--color-input-bg: #f0f0f0;--color-input-border: #c0c0c0;--color-toggle-bg: #ffffff;--color-toggle-selected: #d7d7d7;--color-icon: #5b5b5b;--color-separator: #ccc;--color-btn-bg: #f4f4f4;--color-btn-fg: #101010;--color-bg-proxy: #fafafa;--color-row-odd: #e1e1e1;--bg-log-info-tag: #888;--bg-modal: #fbfbfb;--bg-near-transparent: rgba(0, 0, 0, .1);--bg-tooltip: #f0f0f0;--bc-tooltip: #ccc;--select-border-color: #999999;--select-bg-hover: url(data:image/svg+xml,%0A%20%20%20%20%3Csvg%20width%3D%228%22%20height%3D%2224%22%20viewBox%3D%220%200%208%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%207L7%2011H1L4%207Z%22%20fill%3D%22%23222222%22%20%2F%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%2017L1%2013L7%2013L4%2017Z%22%20fill%3D%22%23222222%22%20%2F%3E%0A%20%20%20%20%3C%2Fsvg%3E%0A%20%20);--color-proxy-dot-selected-ind-bo: #888;--bg-toggle-track: #d0d0d0;color-scheme:light}}:root[data-theme=dark]{--color-background: #202020;--color-background2: rgba(32, 32, 32, .3);--color-bg-card: #2d2d2d;--card-hover-border-lightness: 30%;--color-text: #ddd;--color-text-secondary: #ccc;--color-text-highlight: #fff;--color-bg-sidebar: #2d2d30;--color-input-bg: #2d2d30;--color-input-border: #3f3f3f;--color-toggle-bg: #353535;--color-toggle-selected: #181818;--color-icon: #c7c7c7;--color-separator: #333;--color-btn-bg: #232323;--color-btn-fg: #bebebe;--color-bg-proxy: #303030;--color-row-odd: #333;--bg-log-info-tag: #454545;--bg-modal: #1f1f20;--bg-near-transparent: rgba(255, 255, 255, .1);--bg-tooltip: #111;--bc-tooltip: #555;--select-border-color: #040404;--select-bg-hover: url(data:image/svg+xml,%0A%20%20%20%20%3Csvg%20width%3D%228%22%20height%3D%2224%22%20viewBox%3D%220%200%208%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%207L7%2011H1L4%207Z%22%20fill%3D%22%23ffffff%22%20%2F%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%2017L1%2013L7%2013L4%2017Z%22%20fill%3D%22%23ffffff%22%20%2F%3E%0A%20%20%20%20%3C%2Fsvg%3E%0A%20%20);--color-proxy-dot-selected-ind-bo: transparent;--bg-toggle-track: #393939;color-scheme:dark}:root[data-theme=light]{--color-background: #eee;--color-background2: rgba(240, 240, 240, .3);--color-bg-card: #fafafa;--card-hover-border-lightness: 80%;--color-text: #222;--color-text-secondary: #646464;--color-text-highlight: #040404;--color-bg-sidebar: #f8f8f8;--color-input-bg: #f0f0f0;--color-input-border: #c0c0c0;--color-toggle-bg: #ffffff;--color-toggle-selected: #d7d7d7;--color-icon: #5b5b5b;--color-separator: #ccc;--color-btn-bg: #f4f4f4;--color-btn-fg: #101010;--color-bg-proxy: #fafafa;--color-row-odd: #e1e1e1;--bg-log-info-tag: #888;--bg-modal: #fbfbfb;--bg-near-transparent: rgba(0, 0, 0, .1);--bg-tooltip: #f0f0f0;--bc-tooltip: #ccc;--select-border-color: #999999;--select-bg-hover: url(data:image/svg+xml,%0A%20%20%20%20%3Csvg%20width%3D%228%22%20height%3D%2224%22%20viewBox%3D%220%200%208%2024%22%20fill%3D%22none%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%207L7%2011H1L4%207Z%22%20fill%3D%22%23222222%22%20%2F%3E%0A%20%20%20%20%20%20%3Cpath%20d%3D%22M4%2017L1%2013L7%2013L4%2017Z%22%20fill%3D%22%23222222%22%20%2F%3E%0A%20%20%20%20%3C%2Fsvg%3E%0A%20%20);--color-proxy-dot-selected-ind-bo: #888;--bg-toggle-track: #d0d0d0;color-scheme:light}:root[data-theme=dark] .pureBlackDark{--color-background: #000000;--color-input-bg: #111111;--color-background2: rgba(0, 0, 0, .3);--color-bg-card: #1c1c1c}@media (prefers-color-scheme: dark){:root[data-theme=auto] .pureBlackDark{--color-background: #000000;--color-input-bg: #111111;--color-background2: rgba(0, 0, 0, .3);--color-bg-card: #1c1c1c}}.flexCenter{display:flex;align-items:center;justify-content:center}.fabgrp{position:fixed;z-index:3;right:20px;bottom:20px}.visually-hidden{position:absolute;overflow:hidden;clip:rect(0 0 0 0);width:1px;height:1px;margin:-1px;border:0;padding:0}:root{--reach-tooltip: 1}[data-reach-tooltip]{z-index:1;pointer-events:none;position:absolute;padding:.25em .5em;box-shadow:2px 2px 10px #0000001a;white-space:nowrap;font-size:85%;background:var(--bg-tooltip);color:var(--color-text);border:solid 1px var(--bc-tooltip);border-radius:4px}._root_5bosw_1{height:76px;display:flex;align-items:center}._h1_5bosw_7{padding:0 15px;font-size:1.7em;text-align:left;margin:0}@media screen and (min-width: 30em){._h1_5bosw_7{padding:0 40px;font-size:2em}}._root_1392e_1{padding:6px 15px}@media screen and (min-width: 30em){._root_1392e_1{padding:10px 40px}}._mono_1392e_10{font-family:var(--font-mono)}._link_1392e_14{color:var(--color-text-secondary);display:inline-flex}._link_1392e_14:hover{color:var(--color-text-highlight)}._loading_74j3j_1{width:100%;height:100%;display:flex;justify-content:center;align-items:center}._spinner_74j3j_9{width:20px;height:20px;display:inline-block;vertical-align:middle;animation:_rotate_74j3j_1 1s steps(12,end) infinite;background:transparent url("data:image/svg+xml;charset=utf8, %3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 100 100'%3E%3Cpath fill='none' d='M0 0h100v100H0z'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23E9E9E9' rx='5' ry='5' transform='translate(0 -30)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23989697' rx='5' ry='5' transform='rotate(30 105.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%239B999A' rx='5' ry='5' transform='rotate(60 75.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23A3A1A2' rx='5' ry='5' transform='rotate(90 65 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23ABA9AA' rx='5' ry='5' transform='rotate(120 58.66 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23B2B2B2' rx='5' ry='5' transform='rotate(150 54.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23BAB8B9' rx='5' ry='5' transform='rotate(180 50 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23C2C0C1' rx='5' ry='5' transform='rotate(-150 45.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23CBCBCB' rx='5' ry='5' transform='rotate(-120 41.34 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23D2D2D2' rx='5' ry='5' transform='rotate(-90 35 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23DADADA' rx='5' ry='5' transform='rotate(-60 24.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='%23E2E2E2' rx='5' ry='5' transform='rotate(-30 -5.98 65)'/%3E%3C/svg%3E") no-repeat;background-size:100%}@keyframes _rotate_74j3j_1{0%{transform:rotate3d(0,0,1,0)}to{transform:rotate3d(0,0,1,360deg)}}._root_4m2cd_1{position:fixed;top:0;bottom:0;left:0;right:0;overflow:hidden;padding:20px;background:var(--color-background);color:var(--color-text);text-align:center}._yacd_4m2cd_14{color:#2a477a;opacity:.6;display:flex;justify-content:center;align-items:center;padding:40px}._link_4m2cd_23{display:inline-flex;align-items:center;color:var(--color-text-secondary)}._link_4m2cd_23:hover,._link_4m2cd_23:active{color:#387cec}._link_4m2cd_23 svg{margin-right:5px}._path_r8pm3_1{stroke-dasharray:890;stroke-dashoffset:890;animation:_dash_r8pm3_1 3s ease-in-out forwards normal infinite}@keyframes _dash_r8pm3_1{0%{stroke-dashoffset:890}to{stroke-dashoffset:0}}._root_4oasi_1{padding:6px 15px}@media screen and (min-width: 30em){._root_4oasi_1{padding:10px 40px}}._chart_4oasi_10{margin-top:15px}._TrafficNow_hzna1_1{color:var(--color-text);display:flex;align-items:center;flex-wrap:wrap;display:grid;grid-template-columns:repeat(auto-fit,180px);grid-gap:10px}._TrafficNow_hzna1_1 ._sec_hzna1_10{padding:10px;background-color:var(--color-bg-card);border-radius:10px;box-shadow:0 1px 5px #0000001a}._TrafficNow_hzna1_1 ._sec_hzna1_10 div:nth-child(1){color:var(--color-text-secondary);font-size:.7em}._TrafficNow_hzna1_1 ._sec_hzna1_10 div:nth-child(2){padding:10px 0 0;font-size:1.8em}._lo_pmly2_1{opacity:.5;width:100%;height:100%;display:flex;justify-content:center;align-items:center}._app_1s3k7_1{position:fixed;top:0;bottom:0;left:0;right:0;display:flex;align-items:stretch;background:var(--color-background);color:var(--color-text)}@media (max-width: 768px){._app_1s3k7_1{flex-direction:column}}._content_1s3k7_18{flex-grow:1;overflow:auto}[data-reach-menu-button]{--sz: 40px;width:var(--sz);height:var(--sz);display:inline-flex;align-items:center;justify-content:center;-webkit-appearance:none;outline:none;-webkit-user-select:none;user-select:none;cursor:pointer;color:var(--color-btn-fg);background:none;border:1px solid transparent;border-radius:20px}[data-reach-menu-button]:hover{opacity:.6}[data-reach-menu-button]:focus{border-color:var(--color-focus-blue)}[data-reach-menu-list]{background:var(--bg-tooltip);color:var(--color-text);border:1px solid #555;padding:4px;border-radius:8px}[data-reach-menu-item]{padding:5px 16px 5px 6px;border-radius:7px;cursor:pointer;display:flex;align-items:center}[data-reach-menu-item][data-selected]{background:var(--color-focus-blue);color:#f7f7f7}._checkWrapper_1nrct_45{display:inline-flex;align-items:center;margin-right:2px;visibility:hidden}._checkWrapper_1nrct_45._active_1nrct_51{visibility:visible}._root_r8ke8_1{display:flex;flex-direction:column;padding:8px}@media (max-width: 768px){._root_r8ke8_1{padding:0}}._logoPlaceholder_r8ke8_12{height:15px}@media (max-width: 768px){._logoPlaceholder_r8ke8_12{display:none}}._rows_r8ke8_21{flex:1}@media (max-width: 768px){._rows_r8ke8_21{display:flex;justify-content:space-between;overflow:auto}}._row_r8ke8_21{color:var(--color-text);text-decoration:none;border-radius:1000px;display:flex;align-items:center;padding:6px 16px}@media screen and (min-width: 30em){._row_r8ke8_21{padding:8px 20px}}@media (max-width: 768px){._row_r8ke8_21{border-radius:0}}@media (max-width: 768px){._row_r8ke8_21{flex-direction:column}}._row_r8ke8_21 svg{color:var(--color-icon);width:22px;height:22px}@media screen and (min-width: 30em){._row_r8ke8_21 svg{width:24px;height:24px}}._rowActive_r8ke8_68{--bg: hsla(217deg, 83%, 57%, .2);--fg: hsl(217deg 83% 57%);color:var(--fg);background:var(--bg)}@media (max-width: 768px){._rowActive_r8ke8_68{background:none}}._label_r8ke8_80{padding-left:14px;font-size:.75em;white-space:nowrap}@media (max-width: 768px){._label_r8ke8_80{padding-left:0;padding-top:5px}}@media screen and (min-width: 30em){._label_r8ke8_80{font-size:1em}}._footer_r8ke8_97{display:flex;flex-direction:column;align-items:center}@media (max-width: 768px){._footer_r8ke8_97{display:none}}._iconWrapper_r8ke8_108{--sz: 40px;width:var(--sz);height:var(--sz);display:flex;justify-content:center;align-items:center;outline:none;padding:5px;color:var(--color-text);border-radius:100%;border:1px solid transparent}._iconWrapper_r8ke8_108:hover{opacity:.6}._iconWrapper_r8ke8_108:focus{border-color:var(--color-focus-blue)}._btn_lzu00_1{-webkit-appearance:none;outline:none;-webkit-user-select:none;user-select:none;position:relative;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;color:var(--color-btn-fg);background:var(--color-btn-bg);border:1px solid #555;border-radius:100px;padding:10px 13px}._btn_lzu00_1:focus{border-color:var(--color-focus-blue)}._btn_lzu00_1:hover{background:#387cec;border:1px solid #387cec;color:#fff}._btn_lzu00_1:active{transform:scale(.97)}._btn_lzu00_1._circular_lzu00_27{padding:8px}._btn_lzu00_1._minimal_lzu00_30{border-color:transparent;background:none;padding:6px 12px}._btn_lzu00_1._minimal_lzu00_30:focus{border-color:var(--color-focus-blue)}._btn_lzu00_1._minimal_lzu00_30:hover{color:#fff;background:#387cec;border:1px solid #387cec}._btn_lzu00_1:disabled{opacity:.5}._btnStart_lzu00_48{margin-right:5px;display:inline-flex;align-items:center;justify-content:center}._loadingContainer_lzu00_55{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);display:inline-flex}h2._sectionNameType_1b9pp_1{margin:0;font-size:1.3em}@media screen and (min-width: 30em){h2._sectionNameType_1b9pp_1{font-size:1.5em}}h2._sectionNameType_1b9pp_1 span:nth-child(2){font-size:12px;color:#777;font-weight:400;margin:0 .3em}:root[data-theme=light]{--loading-dot-1-1: rgba(0, 0, 0, .1);--loading-dot-1-2: rgba(0, 0, 0, .5);--loading-dot-1-3: rgba(0, 0, 0, .3);--loading-dot-2-1: rgba(0, 0, 0, .3);--loading-dot-2-2: rgba(0, 0, 0, .1);--loading-dot-2-3: rgba(0, 0, 0, .5);--loading-dot-3-1: rgba(0, 0, 0, .5);--loading-dot-3-2: rgba(0, 0, 0, .3);--loading-dot-3-3: rgba(0, 0, 0, .1)}:root[data-theme=dark]{--loading-dot-1-1: rgba(255, 255, 255, .5);--loading-dot-1-2: rgba(255, 255, 255, .1);--loading-dot-1-3: rgba(255, 255, 255, .3);--loading-dot-2-1: rgba(255, 255, 255, .3);--loading-dot-2-2: rgba(255, 255, 255, .5);--loading-dot-2-3: rgba(255, 255, 255, .1);--loading-dot-3-1: rgba(255, 255, 255, .1);--loading-dot-3-2: rgba(255, 255, 255, .3);--loading-dot-3-3: rgba(255, 255, 255, .5)}._loadingDot_1b9pp_66,._loadingDot_1b9pp_66:before,._loadingDot_1b9pp_66:after{display:inline-block;vertical-align:middle;width:6px;height:6px;border-radius:50%;font-size:0}._loadingDot_1b9pp_66{position:relative;background-color:var(--loading-dot-2-1);animation:_dot2_1b9pp_1 1s step-start infinite}._loadingDot_1b9pp_66:before{content:"";position:absolute;left:-12px;background-color:var(--loading-dot-1-1);animation:_dot1_1b9pp_1 1s step-start infinite}._loadingDot_1b9pp_66:after{content:"";position:absolute;right:-12px;background-color:var(--loading-dot-3-1);animation:_dot3_1b9pp_1 1s step-start infinite}@keyframes _dot1_1b9pp_1{0%,to{background-color:var(--loading-dot-1-1)}33%{background-color:var(--loading-dot-1-2)}66%{background-color:var(--loading-dot-1-3)}}@keyframes _dot2_1b9pp_1{0%,to{background-color:var(--loading-dot-2-1)}33%{background-color:var(--loading-dot-2-2)}66%{background-color:var(--loading-dot-2-3)}}@keyframes _dot3_1b9pp_1{0%,to{background-color:var(--loading-dot-3-1)}33%{background-color:var(--loading-dot-3-2)}66%{background-color:var(--loading-dot-3-3)}}._toggle_g6vyf_1{--height: 28px;--width: 44px;--knob-size: 24px;display:inline-flex;align-items:center;cursor:pointer;position:relative;width:var(--width);height:var(--height)}._toggle_g6vyf_1 ._input_g6vyf_12{opacity:0;width:0}._toggle_g6vyf_1 ._input_g6vyf_12:checked+._track_g6vyf_16{background-color:#047aff}._toggle_g6vyf_1 ._input_g6vyf_12:checked+._track_g6vyf_16:before{transform:translate(calc(var(--width) - var(--height)))}._toggle_g6vyf_1 ._input_g6vyf_12:disabled+._track_g6vyf_16{opacity:.8;cursor:not-allowed}._toggle_g6vyf_1 ._input_g6vyf_12:focus-visible+._track_g6vyf_16{outline:solid 1px var(--color-focus-blue);outline-offset:2px}._toggle_g6vyf_1 ._track_g6vyf_16{width:var(--width);height:var(--height);position:absolute;cursor:pointer;top:0;left:0;bottom:0;transition:transform .15s,background-color .15s;background:var(--bg-toggle-track);border-radius:100px;border-width:1px}._toggle_g6vyf_1 ._track_g6vyf_16:before{position:absolute;content:"";width:var(--knob-size);height:var(--knob-size);background-color:#fff;transition:all .4s;border-radius:100%;top:calc((var(--height) - var(--knob-size)) / 2);left:calc((var(--height) - var(--knob-size)) / 2)}._input_1hkb4_1{-moz-appearance:none;appearance:none;-webkit-appearance:none;background-color:var(--color-input-bg);background-image:none;border-radius:4px;border:1px solid var(--color-input-border);box-sizing:border-box;color:inherit;display:inline-block;font-size:inherit;height:40px;outline:none;padding:0 8px;width:100%}._input_1hkb4_1:focus{box-shadow:#4299e199 0 0 0 3px}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}._animate_1w0e8_1{--saturation: 70%;stroke:hsl(46deg,var(--saturation),45%);transform:scale(1);animation:_zap-pulse_1w0e8_1 .7s 0s ease-in-out none normal infinite}@keyframes _zap-pulse_1w0e8_1{0%{stroke:hsl(46deg,var(--saturation),45%);transform:scale(1)}50%{stroke:hsl(46deg,var(--saturation),95%);transform:scale(1.1)}to{stroke:hsl(46deg,var(--saturation),45%);transform:scale(1)}}._ToggleSwitch_10mtp_1{-webkit-user-select:none;user-select:none;border-radius:4px;border:1px solid #525252;color:var(--color-text);background:var(--color-toggle-bg);display:flex;position:relative;outline:none}._ToggleSwitch_10mtp_1:focus{border-color:var(--color-focus-blue)}._ToggleSwitch_10mtp_1 input{position:absolute;left:0;opacity:0}._ToggleSwitch_10mtp_1 label{z-index:2;display:flex;align-items:center;justify-content:center;padding:10px 0;cursor:pointer}._slider_10mtp_28{z-index:1;position:absolute;display:block;left:0;height:100%;transition:left .2s ease-out;background:var(--color-toggle-selected)} 2 | -------------------------------------------------------------------------------- /ppgw.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "crypto/tls" 7 | "encoding/csv" 8 | "encoding/json" 9 | "flag" 10 | "fmt" 11 | "hash/fnv" 12 | "io" 13 | "net" 14 | "net/http" 15 | "net/url" 16 | "os" 17 | "os/exec" 18 | "sort" 19 | "strconv" 20 | "strings" 21 | "sync" 22 | "time" 23 | 24 | "gopkg.in/yaml.v2" 25 | "nhooyr.io/websocket" 26 | "nhooyr.io/websocket/wsjson" 27 | ) 28 | 29 | var ( 30 | server string 31 | domain string 32 | rawURL string 33 | downURL string 34 | port int 35 | maxSystemCommandDelay int 36 | waitdelay string 37 | resolver *net.Resolver 38 | inputFiles inputFlags 39 | inputFile string 40 | outputFile string 41 | yamlhashFile string 42 | interval string 43 | sleeptime string 44 | apiURL string 45 | secret string 46 | reckey string 47 | testNodeURL string 48 | extNodeStr string 49 | testProxy string 50 | dnslist string 51 | reload bool 52 | closeall bool 53 | wsPort string 54 | net_rec_num string 55 | now_node bool 56 | spec_node string 57 | ) 58 | 59 | var orange = "\033[38;5;208m" 60 | var green = "\033[32m" 61 | var red = "\033[31m" 62 | var reset = "\033[0m" 63 | 64 | type inputFlags []string 65 | 66 | type ClashNode struct { 67 | Node string `json:"name"` 68 | Type string `json:"type"` 69 | Now string `json:"now,omitempty"` 70 | } 71 | 72 | type ClashAPIResponse struct { 73 | Proxies map[string]ClashNode `json:"proxies"` 74 | } 75 | 76 | type ConfigResponse struct { 77 | Mode string `json:"mode"` 78 | } 79 | 80 | type PingResult struct { 81 | Node string 82 | Duration time.Duration 83 | } 84 | 85 | type PingResponse struct { 86 | Delay int `json:"delay"` 87 | } 88 | 89 | type Downloader struct { 90 | URL string 91 | OutputFile string 92 | UserAgent string 93 | Timeout time.Duration 94 | } 95 | 96 | // ws catch 97 | type ConnectionInfo struct { 98 | DownloadTotal int64 `json:"downloadTotal"` 99 | UploadTotal int64 `json:"uploadTotal"` 100 | Connections []Connection `json:"connections"` 101 | } 102 | 103 | type Connection struct { 104 | ID string `json:"id"` 105 | Metadata Metadata `json:"metadata"` 106 | Upload int `json:"upload"` 107 | Download int `json:"download"` 108 | } 109 | 110 | type Metadata struct { 111 | Network string `json:"network"` 112 | Type string `json:"type"` 113 | SourceIP string `json:"sourceIP"` 114 | DestinationIP string `json:"destinationIP"` 115 | SourcePort string `json:"sourcePort"` 116 | DestinationPort string `json:"destinationPort"` 117 | Host string `json:"host"` 118 | DNSMode string `json:"dnsMode"` 119 | ProcessPath string `json:"processPath"` 120 | SpecialProxy string `json:"specialProxy"` 121 | } 122 | 123 | type DomainInfo struct { 124 | Domain string 125 | Download int64 126 | Upload int64 127 | ClientIP string 128 | } 129 | 130 | type DomainInfoList []DomainInfo 131 | 132 | type LastConnectionInfo struct { 133 | LastDownloadTotal int64 134 | LastUploadTotal int64 135 | } 136 | 137 | func main() { 138 | 139 | flag.Var(&inputFiles, "input", "Input YAML files") 140 | flag.StringVar(&outputFile, "output", "output.yaml", "Output YAML file") 141 | flag.StringVar(&inputFile, "dnsinput", "", "dns input YAML file") 142 | flag.StringVar(&yamlhashFile, "yamlhashFile", "", "Hash YAML file") 143 | flag.StringVar(&domain, "domain", "", "domain") 144 | flag.StringVar(&rawURL, "rawURL", "", "rawURL") 145 | flag.StringVar(&downURL, "downURL", "", "downURL") 146 | flag.StringVar(&server, "server", "", "DNS server to use") 147 | flag.StringVar(&interval, "interval", "", "sub interval") 148 | flag.StringVar(&sleeptime, "sleeptime", "", "sleeptime") 149 | flag.StringVar(&testProxy, "testProxy", "", "http testProxy") 150 | flag.StringVar(&dnslist, "dnslist", "", "dnslist") 151 | flag.IntVar(&port, "port", 53, "DNS port") 152 | 153 | //clashapi 154 | flag.StringVar(&apiURL, "apiurl", "", "Clash API") 155 | flag.StringVar(&secret, "secret", "", "Clash secret") 156 | flag.StringVar(&spec_node, "spec_node", "", "specified node by name") 157 | flag.StringVar(&reckey, "reckey", "", "netrec reckey") 158 | flag.StringVar(&testNodeURL, "test_node_url", "", "test_node_url") 159 | flag.StringVar(&extNodeStr, "ext_node", "", "ext_node") 160 | flag.StringVar(&waitdelay, "waitdelay", "1000", "node delay") 161 | flag.IntVar(&maxSystemCommandDelay, "cpudelay", 300, "CPU delay") 162 | flag.BoolVar(&reload, "reload", false, "reload yaml") 163 | flag.BoolVar(&closeall, "closeall", false, "close all connections.") 164 | flag.BoolVar(&now_node, "now_node", false, "now_node.") 165 | //ws catch 166 | flag.StringVar(&wsPort, "wsPort", "", "wsPort") 167 | flag.StringVar(&net_rec_num, "net_rec_num", "", "net_rec_num") 168 | 169 | flag.Parse() 170 | //net_rec 171 | if wsPort != "" && secret != "" && reckey != "" { 172 | max_rec, err := strconv.Atoi(net_rec_num) 173 | if err != nil { 174 | max_rec = 5000 175 | } 176 | wsURL := "ws://127.0.0.1:" + wsPort + "/connections?token=" + secret 177 | fmt.Printf("\n" + green + "[PaoPaoGW REC]" + reset + "Start NET REC :" + wsPort + " \n") 178 | 179 | ctx, cancel := context.WithCancel(context.Background()) 180 | defer cancel() 181 | 182 | domainInfoMap := make(map[string]*DomainInfo) 183 | lastConnectionInfoMap := make(map[string]LastConnectionInfo) 184 | var domainInfoList DomainInfoList 185 | var mutex sync.Mutex 186 | 187 | go func() { 188 | for { 189 | conn, _, err := websocket.Dial(ctx, wsURL, nil) 190 | if err != nil { 191 | fmt.Printf("\n" + red + "[PaoPaoGW REC]" + reset + "Failed to dial WebSocket.\n") 192 | time.Sleep(5 * time.Second) 193 | continue 194 | } 195 | defer conn.Close(websocket.StatusInternalError, "PPGW NET_REC ERR") 196 | 197 | // Increase the read limit 198 | conn.SetReadLimit(10 * 1024 * 1024) 199 | 200 | for { 201 | var connectionInfo ConnectionInfo 202 | err := wsjson.Read(ctx, conn, &connectionInfo) 203 | if err != nil { 204 | fmt.Printf("\n" + red + "[PaoPaoGW REC]" + reset + "Failed to read WebSocket message.\n") 205 | break 206 | } 207 | 208 | mutex.Lock() 209 | for _, connection := range connectionInfo.Connections { 210 | destination := connection.Metadata.Host 211 | if destination == "" { 212 | destination = connection.Metadata.DestinationIP 213 | } 214 | 215 | lastInfo, exists := lastConnectionInfoMap[connection.ID] 216 | if !exists { 217 | lastConnectionInfoMap[connection.ID] = LastConnectionInfo{ 218 | LastDownloadTotal: int64(connection.Download), 219 | LastUploadTotal: int64(connection.Upload), 220 | } 221 | } else { 222 | download := int64(connection.Download) - lastInfo.LastDownloadTotal 223 | upload := int64(connection.Upload) - lastInfo.LastUploadTotal 224 | 225 | if domainInfo, ok := domainInfoMap[destination]; ok { 226 | domainInfo.Download += download 227 | domainInfo.Upload += upload 228 | } else { 229 | domainInfoMap[destination] = &DomainInfo{ 230 | Domain: destination, 231 | Download: download, 232 | Upload: upload, 233 | ClientIP: connection.Metadata.SourceIP, 234 | } 235 | } 236 | 237 | lastConnectionInfoMap[connection.ID] = LastConnectionInfo{ 238 | LastDownloadTotal: int64(connection.Download), 239 | LastUploadTotal: int64(connection.Upload), 240 | } 241 | } 242 | } 243 | 244 | if len(domainInfoMap) > max_rec*2 { 245 | var trimmedList []DomainInfo 246 | for _, info := range domainInfoMap { 247 | trimmedList = append(trimmedList, *info) 248 | } 249 | sort.Slice(trimmedList, func(i, j int) bool { 250 | return trimmedList[i].Download+trimmedList[i].Upload > trimmedList[j].Download+trimmedList[j].Upload 251 | }) 252 | if len(trimmedList) > max_rec { 253 | trimmedList = trimmedList[:max_rec] 254 | } 255 | domainInfoMap = make(map[string]*DomainInfo) 256 | for i := range trimmedList { 257 | domainInfoMap[trimmedList[i].Domain] = &trimmedList[i] 258 | } 259 | } 260 | mutex.Unlock() 261 | } 262 | } 263 | }() 264 | for range time.Tick(3 * time.Second) { 265 | mutex.Lock() 266 | domainInfoList = nil 267 | for _, info := range domainInfoMap { 268 | domainInfoList = append(domainInfoList, *info) 269 | } 270 | sort.Sort(domainInfoList) 271 | recPath := "/etc/config/clash/clash-dashboard/rec_data/" + reckey 272 | os.MkdirAll(recPath, 0755) 273 | newFilePath := recPath + "/data.csv.new" 274 | oldFilePath := recPath + "/data.csv.old" 275 | currentFilePath := recPath + "/data.csv" 276 | file, err := os.Create(newFilePath) 277 | if err != nil { 278 | fmt.Printf("\n" + red + "[PaoPaoGW REC]" + reset + "Failed to create CSV file.\n") 279 | mutex.Unlock() 280 | continue 281 | } 282 | defer file.Close() 283 | writer := csv.NewWriter(file) 284 | if err := writer.Write([]string{"Domain", "Download", "Upload", "ClientIP"}); err != nil { 285 | fmt.Printf("\n" + red + "[PaoPaoGW REC]" + reset + "Error writing CSV header.\n") 286 | continue 287 | } 288 | for _, info := range domainInfoList { 289 | row := []string{info.Domain, formatBytes(info.Download), formatBytes(info.Upload), info.ClientIP} 290 | if err := writer.Write(row); err != nil { 291 | fmt.Printf("\n" + red + "[PaoPaoGW REC]" + reset + "Error writing CSV data.\n") 292 | continue 293 | } 294 | } 295 | writer.Flush() 296 | if err := writer.Error(); err != nil { 297 | fmt.Printf("\n" + red + "[PaoPaoGW REC]" + reset + "Error flushing CSV data.\n") 298 | } 299 | file.Close() 300 | if _, err := os.Stat(currentFilePath); err == nil { 301 | os.Rename(currentFilePath, oldFilePath) 302 | } 303 | 304 | if err := os.Rename(newFilePath, currentFilePath); err != nil { 305 | fmt.Printf("\n" + red + "[PaoPaoGW REC]" + reset + "Failed to replace CSV file.\n") 306 | os.Rename(oldFilePath, currentFilePath) 307 | } 308 | if _, err := os.Stat(oldFilePath); err == nil { 309 | os.Remove(oldFilePath) 310 | } 311 | mutex.Unlock() 312 | } 313 | os.Exit(0) 314 | } 315 | //clash_yaml reload 316 | if reload { 317 | err := reloadYaml(apiURL, secret) 318 | if err != nil { 319 | fmt.Printf(red+"[PaoPaoGW Reload]"+reset+"ERR:%s\n", err) 320 | os.Exit(1) 321 | } 322 | fmt.Printf("\n" + green + "[PaoPaoGW Reload]" + reset + "Yaml reload OK. \n") 323 | os.Exit(0) 324 | } 325 | //test_http_code 326 | if testProxy != "" { 327 | if testNodeURL == "" || testProxy == "" { 328 | fmt.Println("Please provide URL and HTTP proxy parameters") 329 | flag.Usage() 330 | os.Exit(1) 331 | } 332 | 333 | proxyURL, err := url.Parse(testProxy) 334 | if err != nil { 335 | fmt.Println("invalid proxy address:", err) 336 | os.Exit(1) 337 | } 338 | 339 | tr := &http.Transport{ 340 | Proxy: http.ProxyURL(proxyURL), 341 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 342 | DialContext: (&net.Dialer{ 343 | Resolver: &net.Resolver{ 344 | PreferGo: true, 345 | Dial: func(ctx context.Context, network, address string) (net.Conn, error) { 346 | dialer := net.Dialer{} 347 | proxyConn, err := dialer.Dial("tcp", proxyURL.Host) 348 | if err != nil { 349 | return nil, err 350 | } 351 | return proxyConn, nil 352 | }, 353 | }, 354 | }).DialContext, 355 | } 356 | 357 | client := &http.Client{ 358 | Transport: tr, 359 | Timeout: 10 * time.Second, 360 | } 361 | 362 | resp, err := client.Get(testNodeURL) 363 | if err != nil { 364 | fmt.Println("Request error:", err) 365 | os.Exit(1) 366 | } 367 | defer resp.Body.Close() 368 | fmt.Println("Node Check OK. HTTP CODE:", resp.StatusCode) 369 | os.Exit(0) 370 | } 371 | 372 | //clashapi ./ppgw -apiurl="http://10.10.10.3:9090" -secret="clashpass" -test_node_url="https://www.google.com" -ext_node="ong|Traffic|Expire| GB" 373 | //closeall conn 374 | if closeall { 375 | if secret == "" || apiURL == "" { 376 | os.Exit(1) 377 | } 378 | err := deleteConnections(apiURL, secret) 379 | if err != nil { 380 | fmt.Printf(red+"[PaoPaoGW Close]"+reset+"Unable to close connections %s:%v\n", err) 381 | os.Exit(1) 382 | } 383 | os.Exit(0) 384 | } 385 | if now_node { 386 | if secret == "" || apiURL == "" { 387 | os.Exit(1) 388 | } 389 | mode, _ := getMode(apiURL, secret) 390 | if mode != "global" { 391 | os.Exit(1) 392 | } 393 | _, now, err := getNodes(apiURL, secret) 394 | if err != nil { 395 | fmt.Print("Unable to get the now node.\n") 396 | } else { 397 | fmt.Print(now) 398 | } 399 | if now != "" { 400 | os.Exit(0) 401 | } 402 | os.Exit(1) 403 | } 404 | if apiURL != "" && secret != "" && spec_node != "" { 405 | err := selectNode(apiURL, secret, spec_node) 406 | if err != nil { 407 | fmt.Printf(red+"[PaoPaoGW SOCKS]"+reset+"Unable to select ppgwsocks :%v\n", err) 408 | os.Exit(1) 409 | } 410 | fmt.Printf("\n" + green + "[PaoPaoGW SOCKS]" + reset + "The ppgwsocks node selected.") 411 | // deleteConnections(apiURL, secret) 412 | os.Exit(0) 413 | } 414 | //fast_node 415 | if apiURL != "" { 416 | if secret == "" || testNodeURL == "" { 417 | os.Exit(1) 418 | } 419 | 420 | nodes, _, err := getNodes(apiURL, secret) 421 | if err != nil { 422 | fmt.Printf(red+"[PaoPaoGW Fast]"+reset+"Unable to get node list:%v\n", err) 423 | return 424 | } 425 | 426 | excludedNodes := parseExcludedNodes(extNodeStr) 427 | nodes = filterNodes(nodes, excludedNodes) 428 | 429 | pingResults := make([]PingResult, 0) 430 | waitdelaynum, err := strconv.Atoi(waitdelay) 431 | if err != nil { 432 | fmt.Println(err) 433 | return 434 | } 435 | for i := 0; i < len(nodes); i += 2 { 436 | go func(index int) { 437 | if index < len(nodes) { 438 | node1 := nodes[index] 439 | duration1, err1 := pingNode(apiURL, secret, node1.Node, testNodeURL) 440 | if err1 == nil { 441 | pingResults = append(pingResults, PingResult{Node: node1.Node, Duration: duration1}) 442 | } else { 443 | fmt.Printf(red+"[PaoPaoGW Fast]"+reset+"Node %s:%v\n", node1.Node, err1) 444 | time.Sleep(time.Duration(1+waitdelaynum/1000) * time.Second) 445 | } 446 | if index+1 < len(nodes) { 447 | node2 := nodes[index+1] 448 | duration2, err2 := pingNode(apiURL, secret, node2.Node, testNodeURL) 449 | if err2 == nil { 450 | pingResults = append(pingResults, PingResult{Node: node2.Node, Duration: duration2}) 451 | } else { 452 | fmt.Printf(red+"[PaoPaoGW Fast]"+reset+"Node %s:%v\n", node2.Node, err2) 453 | time.Sleep(time.Duration(1+waitdelaynum/1000) * time.Second) 454 | } 455 | } 456 | } 457 | 458 | }(i) 459 | } 460 | time.Sleep(time.Duration(waitdelaynum/1000+3) * time.Second) 461 | sort.Slice(pingResults, func(i, j int) bool { 462 | return pingResults[i].Duration < pingResults[j].Duration 463 | }) 464 | 465 | printPingResults(pingResults) 466 | 467 | if len(pingResults) > 0 { 468 | fastestNode := pingResults[0].Node 469 | err := selectNode(apiURL, secret, fastestNode) 470 | if err != nil { 471 | fmt.Printf(red+"[PaoPaoGW Fast]"+reset+"Unable to select node %s:%v\n", fastestNode, err) 472 | os.Exit(1) 473 | } 474 | fmt.Printf("\n"+green+"[PaoPaoGW Fast]"+reset+"The fastest node selected:%s\n", fastestNode) 475 | // deleteConnections(apiURL, secret) 476 | os.Exit(0) 477 | } else { 478 | fmt.Println("\n" + red + "[PaoPaoGW Fast]" + reset + "All nodes failed !") 479 | } 480 | os.Exit(1) 481 | } 482 | //gen_host 483 | if rawURL != "" { 484 | parsedURL, err := url.Parse(rawURL) 485 | if err != nil { 486 | fmt.Printf("Failed to parse URL: %v\n", err) 487 | os.Exit(1) 488 | } 489 | host := parsedURL.Hostname() 490 | initDNS() 491 | ipString := nslookup(host) 492 | constructedURL := fmt.Sprintf("%s %s", ipString, host) 493 | fmt.Println(constructedURL) 494 | os.Exit(0) 495 | } 496 | //wget 497 | if downURL != "" { 498 | downloader := NewDownloader(downURL, outputFile) 499 | err := downloader.Download() 500 | if err != nil { 501 | fmt.Printf("%v\n", err) 502 | os.Exit(1) 503 | } else { 504 | fmt.Println(green + "[PaoPaoGW Get]" + reset + "Download: OK!") 505 | os.Exit(0) 506 | } 507 | } 508 | //gen_cron 509 | if interval != "" && sleeptime != "" { 510 | result := parseSubtime(interval, sleeptime) 511 | fmt.Printf("%d", result) 512 | os.Exit(0) 513 | } 514 | //gen yaml hash 515 | if yamlhashFile != "" { 516 | content, err := os.ReadFile(yamlhashFile) 517 | if err != nil { 518 | fmt.Println("Cannot read", err) 519 | os.Exit(1) 520 | } 521 | 522 | var data map[interface{}]interface{} 523 | err = yaml.Unmarshal(content, &data) 524 | if err != nil { 525 | fmt.Println("Cannot Unmarshal YAML", err) 526 | os.Exit(1) 527 | } 528 | 529 | keys := make([]string, 0, len(data)) 530 | for key := range data { 531 | keys = append(keys, fmt.Sprintf("%v", key)) 532 | } 533 | sort.Strings(keys) 534 | 535 | var sb strings.Builder 536 | for _, key := range keys { 537 | value := fmt.Sprintf("%v", data[key]) 538 | sb.WriteString(key) 539 | sb.WriteString(value) 540 | } 541 | 542 | hash := fnv.New32a() 543 | hash.Write([]byte(sb.String())) 544 | fmt.Printf("%x", hash.Sum32()) 545 | os.Exit(0) 546 | } 547 | //dns_burn 548 | if dnslist != "" { 549 | if inputFile == "" { 550 | fmt.Println("Please provide an input YAML file using the -input flag") 551 | } 552 | 553 | data, err := os.ReadFile(inputFile) 554 | if err != nil { 555 | fmt.Println("Error reading input file:", err) 556 | } 557 | 558 | var config map[string]interface{} 559 | if err := yaml.Unmarshal(data, &config); err != nil { 560 | fmt.Println("Error unmarshalling YAML: ", err) 561 | } 562 | 563 | proxies, ok := config["proxies"].([]interface{}) 564 | if !ok { 565 | fmt.Println("No 'proxies' found in the YAML file") 566 | } 567 | dnsServers := strings.Split(dnslist, ",") 568 | 569 | var newProxies []interface{} 570 | var wg sync.WaitGroup 571 | var mu sync.Mutex 572 | 573 | for _, proxy := range proxies { 574 | p, ok := proxy.(map[interface{}]interface{}) 575 | if !ok { 576 | fmt.Printf("Skipping invalid proxy: %+v\n", proxy) 577 | continue 578 | } 579 | 580 | server, ok := p["server"].(string) 581 | if !ok { 582 | fmt.Printf("Skipping proxy without a 'server' field: %+v\n", p) 583 | continue 584 | } 585 | 586 | wg.Add(1) 587 | go func(name, server string) { 588 | defer wg.Done() 589 | 590 | serverList := dnsRes(server, dnsServers) 591 | 592 | mu.Lock() 593 | defer mu.Unlock() 594 | 595 | for _, serverAddr := range serverList { 596 | newProxy := make(map[interface{}]interface{}) 597 | for key, value := range p { 598 | newProxy[key] = value 599 | } 600 | newProxy["name"] = fmt.Sprintf("%s-%s", name, serverAddr) 601 | newProxy["server"] = serverAddr 602 | newProxies = append(newProxies, newProxy) 603 | } 604 | }(p["name"].(string), server) 605 | } 606 | 607 | wg.Wait() 608 | 609 | config["proxies"] = append(proxies, newProxies...) 610 | 611 | newData, err := yaml.Marshal(&config) 612 | if err != nil { 613 | fmt.Println("Error marshalling new YAML:", err) 614 | } 615 | 616 | if err := os.WriteFile(outputFile, newData, 0644); err != nil { 617 | fmt.Println("Error writing output file: ", err) 618 | } 619 | 620 | fmt.Printf("New configuration written to %s\n", outputFile) 621 | 622 | os.Exit(0) 623 | } 624 | //combine yaml 625 | if inputFiles != nil { 626 | result := make(map[interface{}]interface{}) 627 | 628 | for _, inputFile := range inputFiles { 629 | data, err := os.ReadFile(inputFile) 630 | if err != nil { 631 | fmt.Println("Failed to read file : ", inputFile, err) 632 | os.Exit(1) 633 | } 634 | 635 | m := make(map[interface{}]interface{}) 636 | err = yaml.Unmarshal(data, &m) 637 | if err != nil { 638 | fmt.Println("Failed to unmarshal YAML from file : ", inputFile, err) 639 | os.Exit(1) 640 | } 641 | 642 | for k, v := range m { 643 | result[k] = v 644 | } 645 | } 646 | 647 | data, err := yaml.Marshal(result) 648 | if err != nil { 649 | fmt.Println("Failed to marshal result to YAML: ", err) 650 | os.Exit(1) 651 | } 652 | 653 | err = os.WriteFile(outputFile, data, 0644) 654 | if err != nil { 655 | fmt.Println("Failed to write result to file : ", outputFile, err) 656 | os.Exit(1) 657 | } 658 | 659 | fmt.Printf("Merged YAML written to %s\n", outputFile) 660 | os.Exit(0) 661 | } 662 | flag.CommandLine.Usage() 663 | } 664 | 665 | // net rec func 666 | func (d DomainInfoList) Len() int { 667 | return len(d) 668 | } 669 | 670 | func (d DomainInfoList) Less(i, j int) bool { 671 | return d[i].Download+d[i].Upload > d[j].Download+d[j].Upload 672 | } 673 | 674 | func (d DomainInfoList) Swap(i, j int) { 675 | d[i], d[j] = d[j], d[i] 676 | } 677 | 678 | func formatBytes(bytes int64) string { 679 | const ( 680 | KB = 1024 681 | MB = KB * 1024 682 | GB = MB * 1024 683 | ) 684 | 685 | switch { 686 | case bytes >= GB: 687 | return fmt.Sprintf("%.3fGB", float64(bytes)/GB) 688 | case bytes >= MB: 689 | return fmt.Sprintf("%.3fMB", float64(bytes)/MB) 690 | case bytes >= KB: 691 | return fmt.Sprintf("%.3fKB", float64(bytes)/KB) 692 | default: 693 | return fmt.Sprintf("%dB", bytes) 694 | } 695 | } 696 | func dnsRes(domain string, dnsServers []string) []string { 697 | var wg sync.WaitGroup 698 | var mu sync.Mutex 699 | ipSet := make(map[string]struct{}) 700 | for _, dnsServer := range dnsServers { 701 | wg.Add(1) 702 | go func(server string) { 703 | defer wg.Done() 704 | ipAddrs, err := QueryARecords(context.Background(), &domain, server) 705 | if err == nil { 706 | mu.Lock() 707 | for _, ipAddr := range ipAddrs { 708 | ipSet[ipAddr.String()] = struct{}{} 709 | } 710 | mu.Unlock() 711 | } 712 | }(dnsServer) 713 | } 714 | 715 | wg.Wait() 716 | 717 | uniqueIPs := make([]string, 0, len(ipSet)) 718 | for ip := range ipSet { 719 | uniqueIPs = append(uniqueIPs, ip) 720 | } 721 | 722 | return uniqueIPs 723 | } 724 | 725 | func QueryARecords(ctx context.Context, domain *string, dnsServer string) ([]net.IP, error) { 726 | dnsResolver := &net.Resolver{ 727 | PreferGo: true, 728 | Dial: func(ctx context.Context, network, address string) (net.Conn, error) { 729 | dialer := net.Dialer{} 730 | return dialer.DialContext(ctx, "udp", dnsServer) 731 | }, 732 | } 733 | 734 | ips, err := dnsResolver.LookupIP(ctx, "ip4", *domain) 735 | if err != nil { 736 | return nil, err 737 | } 738 | 739 | if len(ips) == 0 { 740 | return nil, fmt.Errorf("no A records found for domain: %s", *domain) 741 | } 742 | 743 | return ips, nil 744 | } 745 | 746 | func NewDownloader(url, outputFile string) *Downloader { 747 | userAgent := "ClashforWindows/clash-verge/Clash/clash" 748 | if _, err := os.Stat("/www/clash_core"); err == nil { 749 | userAgent = "clash-verge/v1.6.6" //auto update, do not change 750 | } 751 | return &Downloader{ 752 | URL: url, 753 | OutputFile: outputFile, 754 | UserAgent: userAgent, 755 | Timeout: 10 * time.Second, 756 | } 757 | } 758 | 759 | func (d *Downloader) Download() error { 760 | client := d.createClient() 761 | req, err := http.NewRequest("GET", d.URL, nil) 762 | if err != nil { 763 | return fmt.Errorf("failed to create request: %v", err) 764 | } 765 | req.Header.Set("User-Agent", d.UserAgent) 766 | 767 | host := req.URL.Hostname() 768 | addrs, err := net.LookupHost(host) 769 | if err != nil { 770 | return fmt.Errorf(red+"[PaoPaoGW Get]"+reset+host+"failed to perform DNS lookup: %v", err) 771 | } 772 | fmt.Println(orange+"[PaoPaoGW Get]"+reset+"HOST:"+host+" IP:", strings.Join(addrs, ", ")) 773 | 774 | resp, err := client.Do(req) 775 | if err != nil { 776 | return fmt.Errorf(red+"[PaoPaoGW Get]"+reset+"request failed: %v", err) 777 | } 778 | defer resp.Body.Close() 779 | 780 | if resp.StatusCode >= 400 { 781 | return fmt.Errorf(red+"[PaoPaoGW Get]"+reset+host+" request failed with status code %d", resp.StatusCode) 782 | } 783 | 784 | finalURL := resp.Request.URL.String() 785 | fmt.Println(orange+"[PaoPaoGW Get]"+reset+"URL:", finalURL) 786 | 787 | file, err := os.Create(d.OutputFile) 788 | if err != nil { 789 | return fmt.Errorf(red+"[PaoPaoGW Get]"+reset+"failed to create output file: %v", err) 790 | } 791 | defer file.Close() 792 | 793 | _, err = io.Copy(file, resp.Body) 794 | if err != nil { 795 | return fmt.Errorf(red+"[PaoPaoGW Get]"+reset+host+" download failed: %v", err) 796 | } 797 | 798 | return nil 799 | } 800 | 801 | func (d *Downloader) createClient() *http.Client { 802 | transport := &http.Transport{ 803 | TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, 804 | } 805 | return &http.Client{ 806 | Transport: transport, 807 | Timeout: d.Timeout, 808 | } 809 | } 810 | 811 | func nslookup(domain string) string { 812 | ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) 813 | defer cancel() 814 | r, err := resolver.LookupIPAddr(ctx, domain) 815 | if err != nil { 816 | os.Exit(1) 817 | } 818 | if len(r) == 0 { 819 | os.Exit(1) 820 | } 821 | ip := r[0].IP.String() 822 | return ip 823 | } 824 | 825 | func parseSubtime(subtime, sleeptime string) int { 826 | duration := 86400 827 | if subtime != "" { 828 | if strings.HasSuffix(subtime, "d") { 829 | nStr := strings.TrimSuffix(subtime, "d") 830 | n, err := strconv.Atoi(nStr) 831 | if err == nil { 832 | duration = n * 86400 833 | } 834 | } else if strings.HasSuffix(subtime, "h") { 835 | nStr := strings.TrimSuffix(subtime, "h") 836 | n, err := strconv.Atoi(nStr) 837 | if err == nil { 838 | duration = n * 3600 839 | } 840 | } else if strings.HasSuffix(subtime, "m") { 841 | nStr := strings.TrimSuffix(subtime, "m") 842 | n, err := strconv.Atoi(nStr) 843 | if err == nil { 844 | duration = n * 60 845 | } 846 | } 847 | } 848 | sleeptimeInt, err := strconv.Atoi(sleeptime) 849 | if err != nil { 850 | sleeptimeInt = 30 851 | } 852 | result := duration / sleeptimeInt 853 | return result 854 | } 855 | 856 | func initDNS() { 857 | if server != "" { 858 | resolver = &net.Resolver{ 859 | PreferGo: true, 860 | Dial: func(ctx context.Context, network, address string) (net.Conn, error) { 861 | d := net.Dialer{} 862 | return d.DialContext(ctx, network, net.JoinHostPort(server, strconv.Itoa(port))) 863 | }, 864 | } 865 | } else { 866 | resolver = net.DefaultResolver 867 | } 868 | } 869 | 870 | func (i *inputFlags) String() string { 871 | return fmt.Sprint(*i) 872 | } 873 | 874 | func (i *inputFlags) Set(value string) error { 875 | *i = append(*i, value) 876 | return nil 877 | } 878 | 879 | // clashapi 880 | func printPingResults(results []PingResult) { 881 | for _, result := range results { 882 | fmt.Printf("| %-60s | %-10s |\n", result.Node, result.Duration.String()) 883 | } 884 | } 885 | 886 | func getNodes(apiURL, secret string) ([]ClashNode, string, error) { 887 | client := &http.Client{ 888 | Transport: &http.Transport{ 889 | Proxy: nil, 890 | }, 891 | } 892 | req, err := http.NewRequest("GET", apiURL+"/proxies", nil) 893 | if err != nil { 894 | return nil, "", err 895 | } 896 | req.Header.Set("Authorization", "Bearer "+secret) 897 | 898 | resp, err := client.Do(req) 899 | if err != nil { 900 | return nil, "", err 901 | } 902 | defer resp.Body.Close() 903 | 904 | body, err := io.ReadAll(resp.Body) 905 | if err != nil { 906 | return nil, "", err 907 | } 908 | var apiResponse ClashAPIResponse 909 | err = json.Unmarshal(body, &apiResponse) 910 | if err != nil { 911 | return nil, "", fmt.Errorf(resp.Status + ":" + err.Error()) 912 | 913 | } 914 | nodes := make([]ClashNode, 0, len(apiResponse.Proxies)) 915 | for _, node := range apiResponse.Proxies { 916 | if !isSystemNode(node.Type) { 917 | nodes = append(nodes, node) 918 | } 919 | } 920 | globalProxy, ok := apiResponse.Proxies["GLOBAL"] 921 | if ok { 922 | return nodes, globalProxy.Now, nil 923 | } 924 | return nodes, "", nil 925 | } 926 | 927 | func getMode(apiURL, secret string) (string, error) { 928 | client := &http.Client{ 929 | Transport: &http.Transport{ 930 | Proxy: nil, 931 | }, 932 | } 933 | req, err := http.NewRequest("GET", apiURL+"/configs", nil) 934 | if err != nil { 935 | return "", err 936 | } 937 | req.Header.Set("Authorization", "Bearer "+secret) 938 | 939 | resp, err := client.Do(req) 940 | if err != nil { 941 | return "", err 942 | } 943 | defer resp.Body.Close() 944 | 945 | body, err := io.ReadAll(resp.Body) 946 | if err != nil { 947 | return "", err 948 | } 949 | 950 | var configResponse ConfigResponse 951 | err = json.Unmarshal(body, &configResponse) 952 | if err != nil { 953 | return "", fmt.Errorf(resp.Status + ":" + err.Error()) 954 | } 955 | 956 | return configResponse.Mode, nil 957 | } 958 | 959 | func parseExcludedNodes(extNodeStr string) []string { 960 | if extNodeStr == "" { 961 | return nil 962 | } 963 | 964 | excludedNodes := strings.Split(extNodeStr, "|") 965 | return excludedNodes 966 | } 967 | 968 | func filterNodes(nodes []ClashNode, excludedNodes []string) []ClashNode { 969 | filteredNodes := make([]ClashNode, 0) 970 | 971 | for _, node := range nodes { 972 | if !containsExcludedKeyword(node.Node, excludedNodes) && !isSystemNode(node.Node) { 973 | filteredNodes = append(filteredNodes, node) 974 | } 975 | } 976 | 977 | return filteredNodes 978 | } 979 | 980 | func isSystemNode(nodeName string) bool { 981 | systemNodes := []string{"REJECT", "DIRECT", "GLOBAL", "UNKNOWN"} 982 | nodeName = strings.ToUpper(nodeName) 983 | for _, sysNode := range systemNodes { 984 | if nodeName == sysNode { 985 | return true 986 | } 987 | } 988 | 989 | return false 990 | } 991 | 992 | func containsExcludedKeyword(nodeName string, excludedNodes []string) bool { 993 | for _, keyword := range excludedNodes { 994 | if strings.Contains(nodeName, keyword) { 995 | return true 996 | } 997 | } 998 | return false 999 | } 1000 | 1001 | func systemLoadDealy() int64 { 1002 | startTime := time.Now() 1003 | cmd := exec.Command("ps") 1004 | err := cmd.Run() 1005 | if err != nil { 1006 | return 10000 1007 | } 1008 | executionTime := time.Since(startTime).Milliseconds() 1009 | return executionTime 1010 | } 1011 | 1012 | func pingNode(apiURL, secret, nodeName, testNodeURL string) (time.Duration, error) { 1013 | delay := systemLoadDealy() 1014 | if delay > int64(maxSystemCommandDelay) { 1015 | return 0, fmt.Errorf("High CPU load: %d", delay) 1016 | } 1017 | 1018 | client := &http.Client{} 1019 | 1020 | requestURL := fmt.Sprintf("%s/proxies/%s/delay?timeout=%s&url=%s", apiURL, nodeName, waitdelay, testNodeURL) 1021 | // fmt.Println(requestURL) 1022 | req, err := http.NewRequest("GET", requestURL, nil) 1023 | if err != nil { 1024 | return 0, err 1025 | } 1026 | req.Header.Set("Content-Type", "application/json") 1027 | req.Header.Set("Authorization", "Bearer "+secret) 1028 | 1029 | resp, err := client.Do(req) 1030 | if err != nil { 1031 | return 0, err 1032 | } 1033 | defer resp.Body.Close() 1034 | 1035 | if resp.StatusCode >= 200 && resp.StatusCode < 300 { 1036 | var pingResp PingResponse 1037 | err = json.NewDecoder(resp.Body).Decode(&pingResp) 1038 | if err != nil { 1039 | return 0, err 1040 | } 1041 | 1042 | if pingResp.Delay > 0 { 1043 | return time.Duration(pingResp.Delay) * time.Millisecond, nil 1044 | } 1045 | 1046 | return 0, fmt.Errorf("The delay value does not exist") 1047 | } 1048 | 1049 | return 0, fmt.Errorf("%s", resp.Status) 1050 | } 1051 | 1052 | func selectNode(apiURL, secret, nodeName string) error { 1053 | setGlobalMode(apiURL, secret) 1054 | client := &http.Client{} 1055 | 1056 | data := []byte(fmt.Sprintf(`{"name":"%s"}`, nodeName)) 1057 | 1058 | req, err := http.NewRequest("PUT", apiURL+"/proxies/GLOBAL", strings.NewReader(string(data))) 1059 | if err != nil { 1060 | return err 1061 | } 1062 | req.Header.Set("Content-Type", "application/json") 1063 | req.Header.Set("Authorization", "Bearer "+secret) 1064 | 1065 | resp, err := client.Do(req) 1066 | if err != nil { 1067 | return err 1068 | } 1069 | defer resp.Body.Close() 1070 | 1071 | if resp.StatusCode >= 200 && resp.StatusCode < 300 { 1072 | return nil 1073 | } 1074 | 1075 | return fmt.Errorf("The node selection request failed:%s", resp.Status) 1076 | } 1077 | 1078 | func reloadYaml(apiURL, secret string) error { 1079 | client := &http.Client{} 1080 | data := []byte(fmt.Sprintf(`{"path":"/tmp/clash.yaml"}`)) 1081 | req, err := http.NewRequest("PUT", apiURL+"/configs", strings.NewReader(string(data))) 1082 | if err != nil { 1083 | return err 1084 | } 1085 | req.Header.Set("Content-Type", "application/json") 1086 | req.Header.Set("Authorization", "Bearer "+secret) 1087 | resp, err := client.Do(req) 1088 | if err != nil { 1089 | return err 1090 | } 1091 | defer resp.Body.Close() 1092 | 1093 | if resp.StatusCode >= 200 && resp.StatusCode < 300 { 1094 | return nil 1095 | } 1096 | 1097 | bodyBytes, err := io.ReadAll(resp.Body) 1098 | if err != nil { 1099 | return fmt.Errorf("Failed to reload configuration: %s, unable to read response body", resp.Status) 1100 | } 1101 | 1102 | errorMessage := fmt.Sprintf("Failed to reload configuration: %s, response body: %s", resp.Status, string(bodyBytes)) 1103 | return fmt.Errorf(errorMessage) 1104 | } 1105 | 1106 | func setGlobalMode(apiURL, secret string) error { 1107 | url := fmt.Sprintf("%s/configs", apiURL) 1108 | payload := []byte(`{"mode":"Global"}`) 1109 | 1110 | req, err := http.NewRequest("PATCH", url, bytes.NewBuffer(payload)) 1111 | if err != nil { 1112 | return err 1113 | } 1114 | 1115 | req.Header.Set("Content-Type", "application/json") 1116 | req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", secret)) 1117 | 1118 | client := &http.Client{} 1119 | resp, err := client.Do(req) 1120 | if err != nil { 1121 | return err 1122 | } 1123 | defer resp.Body.Close() 1124 | 1125 | if resp.StatusCode >= 200 && resp.StatusCode < 300 { 1126 | return nil 1127 | } 1128 | 1129 | return fmt.Errorf("Failed to set Global mode, response status code :%d", resp.StatusCode) 1130 | } 1131 | 1132 | func deleteConnections(apiURL, secret string) error { 1133 | url := fmt.Sprintf("%s/connections", apiURL) 1134 | 1135 | req, err := http.NewRequest("DELETE", url, nil) 1136 | if err != nil { 1137 | return err 1138 | } 1139 | 1140 | req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", secret)) 1141 | 1142 | client := &http.Client{} 1143 | resp, err := client.Do(req) 1144 | if err != nil { 1145 | return err 1146 | } 1147 | defer resp.Body.Close() 1148 | 1149 | if resp.StatusCode >= 200 && resp.StatusCode < 300 { 1150 | return nil 1151 | } 1152 | 1153 | return fmt.Errorf("Failed to delete connections, response status code: %d", resp.StatusCode) 1154 | } 1155 | --------------------------------------------------------------------------------