mirror of
https://github.com/asdlokj1qpi233/subconverter.git
synced 2025-10-26 02:42:25 +00:00
Compare commits
178 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
add52ec9cb | ||
|
|
d22cd9b50a | ||
|
|
d22cba4c69 | ||
|
|
dfa8188739 | ||
|
|
4bd91f89d8 | ||
|
|
57c18b0c69 | ||
|
|
d95995a807 | ||
|
|
add0e6da1a | ||
|
|
80363459f2 | ||
|
|
1624d0f10d | ||
|
|
36229fc2ad | ||
|
|
aa721c5b06 | ||
|
|
60d20e42c8 | ||
|
|
645361a07e | ||
|
|
9947eebbfc | ||
|
|
11bc5c7236 | ||
|
|
4b4d227603 | ||
|
|
383deb54a7 | ||
|
|
766434b771 | ||
|
|
cc9e3b77d4 | ||
|
|
4ae0d1b0bd | ||
|
|
a428c844a2 | ||
|
|
3a0784f1f6 | ||
|
|
4787d821bd | ||
|
|
97192f9e5d | ||
|
|
b0b04a0130 | ||
|
|
4e73f5695e | ||
|
|
dd59d514bd | ||
|
|
57ed33f96c | ||
|
|
eab18a9568 | ||
|
|
c242e631ba | ||
|
|
b649fdc253 | ||
|
|
5759f52ebc | ||
|
|
e4b3ee816d | ||
|
|
ebf6a08449 | ||
|
|
638137e1db | ||
|
|
ea49fe862d | ||
|
|
3971468034 | ||
|
|
75a7b1c84c | ||
|
|
4ee3e11950 | ||
|
|
68f2f3bb56 | ||
|
|
79b2e31096 | ||
|
|
d5e6159fbd | ||
|
|
eec5113947 | ||
|
|
695f5eb6d7 | ||
|
|
a0ad2b46e0 | ||
|
|
2b0011a127 | ||
|
|
f69597efb7 | ||
|
|
ffbd262aae | ||
|
|
3ea867e4b8 | ||
|
|
090c2def1d | ||
|
|
e88f8fd485 | ||
|
|
292850818a | ||
|
|
92f66bf5b5 | ||
|
|
b39de30db9 | ||
|
|
223d75a10a | ||
|
|
691193731f | ||
|
|
05959b09b4 | ||
|
|
3f5ed82672 | ||
|
|
05910ac5dd | ||
|
|
1d56f44696 | ||
|
|
c207bfc1f0 | ||
|
|
3a8762c307 | ||
|
|
bc7e2c2e94 | ||
|
|
ad47d18a23 | ||
|
|
79a7e888b1 | ||
|
|
a1f919eafb | ||
|
|
33f32deb32 | ||
|
|
258a64ed4f | ||
|
|
7e16236595 | ||
|
|
644b9040b9 | ||
|
|
3f2281e284 | ||
|
|
0c11565cc9 | ||
|
|
4e6e25c710 | ||
|
|
7dec83d529 | ||
|
|
c4aa8c5b5e | ||
|
|
e22f043213 | ||
|
|
e9c39481df | ||
|
|
6854ea4923 | ||
|
|
dc5c13c76c | ||
|
|
5f644b0b08 | ||
|
|
73352ecb43 | ||
|
|
34adb36029 | ||
|
|
311c696c1d | ||
|
|
33660d7f1b | ||
|
|
0844ebcae7 | ||
|
|
27e82ca60c | ||
|
|
bd06896454 | ||
|
|
72ea8a098f | ||
|
|
456fc328d5 | ||
|
|
19fcccf7f8 | ||
|
|
e3101cfa5e | ||
|
|
198fe253d1 | ||
|
|
3589cfd615 | ||
|
|
c204199477 | ||
|
|
dbba931701 | ||
|
|
ee9b239e21 | ||
|
|
c56685fd40 | ||
|
|
3b2a2632d9 | ||
|
|
c359424242 | ||
|
|
4d0ed9a105 | ||
|
|
63eee92062 | ||
|
|
b9b864cf51 | ||
|
|
bdd6bbf67a | ||
|
|
8a18d3564b | ||
|
|
2ee7c3aa04 | ||
|
|
598f6ac414 | ||
|
|
6c296bfbf2 | ||
|
|
43fc751a2d | ||
|
|
99c1ef8b1a | ||
|
|
53b561bce7 | ||
|
|
469feaf0f5 | ||
|
|
0895a16876 | ||
|
|
6974910734 | ||
|
|
0c8574755a | ||
|
|
b9ad0c2ee2 | ||
|
|
04ac98725c | ||
|
|
6af2c56fc8 | ||
|
|
fb6a830d7b | ||
|
|
b82d49200d | ||
|
|
40ba3fd970 | ||
|
|
1f57413025 | ||
|
|
b228255d3b | ||
|
|
55e765e7f9 | ||
|
|
535d1d01e1 | ||
|
|
7fdba81f2c | ||
|
|
6c38710312 | ||
|
|
eeffa0f544 | ||
|
|
73da1a87ad | ||
|
|
670544cfb1 | ||
|
|
4864a6b13c | ||
|
|
cb15d568c0 | ||
|
|
0f2cefd537 | ||
|
|
9e66b07251 | ||
|
|
624f5cd120 | ||
|
|
c711f1ad05 | ||
|
|
88635b6ed8 | ||
|
|
0cb4053f8d | ||
|
|
fb2aca3237 | ||
|
|
37c4e13071 | ||
|
|
623ffbb23f | ||
|
|
be2de49360 | ||
|
|
a8292b1fc6 | ||
|
|
1ff018c47b | ||
|
|
6227eb4e7d | ||
|
|
54c8e65c70 | ||
|
|
b90e63b506 | ||
|
|
185e3893bf | ||
|
|
5a4049af89 | ||
|
|
c842defea8 | ||
|
|
e26eaf0bf5 | ||
|
|
766bdcd6e1 | ||
|
|
897dc5ed43 | ||
|
|
7bd6670448 | ||
|
|
7af3bf1794 | ||
|
|
359d9794a8 | ||
|
|
089f782177 | ||
|
|
75023b028e | ||
|
|
322924f24a | ||
|
|
04a2c24904 | ||
|
|
e80ce5833c | ||
|
|
31ba5373f0 | ||
|
|
d3801b7951 | ||
|
|
31775a91a8 | ||
|
|
af4dd857a8 | ||
|
|
686f6b3517 | ||
|
|
ebad0e96f7 | ||
|
|
927c828a27 | ||
|
|
13a372511b | ||
|
|
eef5328506 | ||
|
|
119df56f35 | ||
|
|
0672bd11cd | ||
|
|
f4de5097a6 | ||
|
|
cb36b431ce | ||
|
|
d5b3f920b8 | ||
|
|
69e35d6657 | ||
|
|
936ff011e9 | ||
|
|
0cda1641d3 |
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -7,6 +7,7 @@ body:
|
||||
value: |
|
||||
遇到问题请先尝试使用[Action](https://github.com/tindy2013/subconverter/actions)中的最新版本
|
||||
如果是使用公共转换服务中遇到的问题,请先联系服务的提供者。
|
||||
Please note that if the bug report does not include reproduction steps, configuration files, or relevant URL content, it will not be considered.
|
||||
- type: checkboxes
|
||||
id: version-check
|
||||
attributes:
|
||||
|
||||
327
.github/workflows/build.yml
vendored
327
.github/workflows/build.yml
vendored
@@ -1,5 +1,5 @@
|
||||
name: GitHub CI
|
||||
on:
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
tags:
|
||||
@@ -7,215 +7,144 @@ on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
concurrency:
|
||||
group: ${{ github.ref }}-${{ github.workflow }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
linux32_build:
|
||||
name: Linux x86 Build
|
||||
runs-on: ubuntu-latest
|
||||
linux_build:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86
|
||||
artifact: subconverter_linux32
|
||||
os: ubuntu-latest
|
||||
- arch: amd64
|
||||
artifact: subconverter_linux64
|
||||
os: ubuntu-latest
|
||||
- arch: armv7
|
||||
artifact: subconverter_armv7
|
||||
os: ubuntu-latest
|
||||
- arch: aarch64
|
||||
artifact: subconverter_aarch64
|
||||
os: ubuntu-latest
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Linux ${{ matrix.arch }} Build
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Add commit id into version
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h
|
||||
- name: Build
|
||||
run: docker run --rm -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:x86-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh"
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: subconverter_linux32
|
||||
path: subconverter/
|
||||
- name: Package Release
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
run: tar czf subconverter_linux32.tar.gz subconverter
|
||||
- name: Draft Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
with:
|
||||
files: subconverter_linux32.tar.gz
|
||||
draft: true
|
||||
|
||||
linux64_build:
|
||||
name: Linux x86_64 Build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Add commit id into version
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h
|
||||
- name: Build
|
||||
run: docker run --rm -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:amd64-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh"
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: subconverter_linux64
|
||||
path: subconverter/
|
||||
- name: Package Release
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
run: tar czf subconverter_linux64.tar.gz subconverter
|
||||
- name: Draft Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
with:
|
||||
files: subconverter_linux64.tar.gz
|
||||
draft: true
|
||||
|
||||
# armv7_build:
|
||||
# name: Linux armv7 Build
|
||||
# runs-on: [self-hosted, linux, ARM]
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# - name: Add commit id into version
|
||||
# if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
# run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h
|
||||
# - name: Build
|
||||
# run: docker run --rm -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:armv7-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh"
|
||||
# - name: Upload
|
||||
# uses: actions/upload-artifact@v3
|
||||
# with:
|
||||
# name: subconverter_armv7
|
||||
# path: subconverter/
|
||||
# - name: Package Release
|
||||
# if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
# run: tar czf subconverter_armv7.tar.gz subconverter
|
||||
# - name: Draft Release
|
||||
# uses: softprops/action-gh-release@v1
|
||||
# if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
# with:
|
||||
# files: subconverter_armv7.tar.gz
|
||||
# draft: true
|
||||
#
|
||||
# aarch64_build:
|
||||
# name: Linux aarch64 Build
|
||||
# runs-on: [self-hosted, linux, ARM64]
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# - name: Add commit id into version
|
||||
# if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
# run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h
|
||||
# - name: Build
|
||||
# run: docker run --rm -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:aarch64-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh"
|
||||
# - name: Upload
|
||||
# uses: actions/upload-artifact@v3
|
||||
# with:
|
||||
# name: subconverter_aarch64
|
||||
# path: subconverter/
|
||||
# - name: Package Release
|
||||
# if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
# run: tar czf subconverter_aarch64.tar.gz subconverter
|
||||
# - name: Draft Release
|
||||
# uses: softprops/action-gh-release@v1
|
||||
# if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
# with:
|
||||
# files: subconverter_aarch64.tar.gz
|
||||
# draft: true
|
||||
- name: Checkout base
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Add commit id into version
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h
|
||||
- name: Build
|
||||
run: docker run --rm -v $GITHUB_WORKSPACE:/root/workdir multiarch/alpine:${{ matrix.arch }}-latest-stable /bin/sh -c "apk add bash git nodejs npm && cd /root/workdir && chmod +x scripts/build.alpine.release.sh && bash scripts/build.alpine.release.sh"
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}
|
||||
path: subconverter/
|
||||
- name: Package Release
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
run: tar czf ${{ matrix.artifact }}.tar.gz subconverter
|
||||
- name: Draft Release
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: ${{ matrix.artifact }}.tar.gz
|
||||
draft: true
|
||||
|
||||
macos_build:
|
||||
name: macOS Build
|
||||
runs-on: macos-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86
|
||||
artifact: subconverter_darwin64
|
||||
os: macos-13
|
||||
- arch: arm
|
||||
artifact: subconverter_darwinarm
|
||||
os: macos-14
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: macOS ${{ matrix.arch }} Build
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Add commit id into version
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
run: SHA=$(git rev-parse --short HEAD) && sed -i -e 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h
|
||||
- name: Build
|
||||
run: bash scripts/build.macos.release.sh
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: subconverter_darwin64
|
||||
path: subconverter/
|
||||
- name: Package Release
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
run: tar czf subconverter_darwin64.tar.gz subconverter
|
||||
- name: Draft Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
with:
|
||||
files: subconverter_darwin64.tar.gz
|
||||
draft: true
|
||||
- name: Checkout base
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Add commit id into version
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
run: SHA=$(git rev-parse --short HEAD) && sed -i -e 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h
|
||||
- name: Build
|
||||
run: bash scripts/build.macos.release.sh
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}
|
||||
path: subconverter/
|
||||
- name: Package Release
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
run: tar czf ${{ matrix.artifact }}.tar.gz subconverter
|
||||
- name: Draft Release
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: ${{ matrix.artifact }}.tar.gz
|
||||
draft: true
|
||||
|
||||
windows64_build:
|
||||
name: Windows x86_64 Build
|
||||
windows_build:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86
|
||||
artifact: subconverter_win32
|
||||
env: i686
|
||||
msystem: MINGW32
|
||||
- arch: amd64
|
||||
artifact: subconverter_win64
|
||||
env: x86_64
|
||||
msystem: MINGW64
|
||||
runs-on: windows-latest
|
||||
name: Windows ${{ matrix.arch }} Build
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16'
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
update: true
|
||||
install: base-devel git mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-pcre2 patch
|
||||
msystem: MINGW64
|
||||
path-type: inherit
|
||||
- name: Add commit id into version
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h
|
||||
- name: Build
|
||||
run: bash scripts/build.windows.release.sh
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: subconverter_win64
|
||||
path: subconverter/
|
||||
- name: Package Release
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
run: 7z a subconverter_win64.7z subconverter/
|
||||
- name: Draft Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
with:
|
||||
files: subconverter_win64.7z
|
||||
draft: true
|
||||
|
||||
windows32_build:
|
||||
name: Windows x86 Build
|
||||
runs-on: windows-latest
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16'
|
||||
- uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
update: true
|
||||
install: base-devel git mingw-w64-i686-gcc mingw-w64-i686-cmake mingw-w64-i686-pcre2 patch
|
||||
msystem: MINGW32
|
||||
path-type: inherit
|
||||
- name: Add commit id into version
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h
|
||||
- name: Build
|
||||
run: bash scripts/build.windows.release.sh
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: subconverter_win32
|
||||
path: subconverter/
|
||||
- name: Package Release
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
run: 7z a subconverter_win32.7z subconverter/
|
||||
- name: Draft Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
with:
|
||||
files: subconverter_win32.7z
|
||||
draft: true
|
||||
- name: Checkout base
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11'
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '16'
|
||||
- name: Setup MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
update: true
|
||||
install: base-devel git mingw-w64-${{ matrix.env }}-gcc mingw-w64-${{ matrix.env }}-cmake mingw-w64-${{ matrix.env }}-pcre2 patch
|
||||
msystem: ${{ matrix.msystem }}
|
||||
path-type: inherit
|
||||
- name: Add commit id into version
|
||||
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
|
||||
run: SHA=$(git rev-parse --short HEAD) && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h
|
||||
- name: Build
|
||||
run: bash scripts/build.windows.release.sh
|
||||
- name: Upload
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.artifact }}
|
||||
path: subconverter/
|
||||
- name: Package Release
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
run: 7z a ${{ matrix.artifact }}.7z subconverter/
|
||||
- name: Draft Release
|
||||
if: ${{ github.event_name != 'pull_request' && startsWith(github.ref, 'refs/tags/') }}
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: ${{ matrix.artifact }}.7z
|
||||
draft: true
|
||||
406
.github/workflows/docker.yml
vendored
406
.github/workflows/docker.yml
vendored
@@ -9,328 +9,122 @@ concurrency:
|
||||
group: ${{ github.ref }}-${{ github.workflow }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
REGISTRY_IMAGE: asdlokj1qpi23/subconverter
|
||||
|
||||
jobs:
|
||||
amd64_build:
|
||||
name: Build AMD64 Image
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout base
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Docker login
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Get commit SHA
|
||||
id: vars
|
||||
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build and export
|
||||
id: build
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
platforms: linux/amd64
|
||||
context: scripts/
|
||||
tags: asdlokj1qpi23/subconverter:latest
|
||||
build-args: |
|
||||
SHA=${{ steps.vars.outputs.sha_short }}
|
||||
outputs: type=image,push=true
|
||||
|
||||
- name: Replace tag without `v`
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: actions/github-script@v6
|
||||
id: version
|
||||
with:
|
||||
script: |
|
||||
return context.payload.ref.replace(/\/?refs\/tags\/v/, '')
|
||||
result-encoding: string
|
||||
|
||||
- name: Build release and export
|
||||
id: build_rel
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
platforms: linux/amd64
|
||||
context: scripts/
|
||||
tags: asdlokj1qpi23/subconverter:${{steps.version.outputs.result}}
|
||||
outputs: type=image,push=true
|
||||
|
||||
- name: Save digest
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: echo ${{ steps.build.outputs.digest }} > /tmp/digest.txt
|
||||
|
||||
- name: Save release digest
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: echo ${{ steps.build_rel.outputs.digest }} > /tmp/digest.txt
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: digest_amd64
|
||||
path: /tmp/digest.txt
|
||||
|
||||
x86_build:
|
||||
name: Build x86 Image
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout base
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Docker login
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Get commit SHA
|
||||
id: vars
|
||||
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build and export
|
||||
id: build
|
||||
if: github.ref == 'refs/heads/master'
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
platforms: linux/386
|
||||
context: scripts/
|
||||
tags: asdlokj1qpi23/subconverter:latest-x86
|
||||
build-args: |
|
||||
SHA=${{ steps.vars.outputs.sha_short }}
|
||||
outputs: type=image,push=true
|
||||
|
||||
- name: Replace tag without `v`
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: actions/github-script@v6
|
||||
id: version
|
||||
with:
|
||||
script: |
|
||||
return context.payload.ref.replace(/\/?refs\/tags\/v/, '')
|
||||
result-encoding: string
|
||||
|
||||
- name: Build release and export
|
||||
id: build_rel
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
platforms: linux/386
|
||||
context: scripts/
|
||||
tags: asdlokj1qpi23/subconverter:${{steps.version.outputs.result}}-x86
|
||||
outputs: type=image,push=true
|
||||
|
||||
- name: Save digest
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: echo ${{ steps.build.outputs.digest }} > /tmp/digest.txt
|
||||
|
||||
- name: Save release digest
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: echo ${{ steps.build_rel.outputs.digest }} > /tmp/digest.txt
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: digest_386
|
||||
path: /tmp/digest.txt
|
||||
|
||||
# armv7_build:
|
||||
# name: Build ARMv7 Image
|
||||
# runs-on: [self-hosted, linux, ARM]
|
||||
# steps:
|
||||
# - name: Checkout base
|
||||
# uses: actions/checkout@v3
|
||||
# with:
|
||||
# fetch-depth: 0
|
||||
#
|
||||
# - name: Set up Docker Buildx
|
||||
# uses: docker/setup-buildx-action@v2
|
||||
#
|
||||
# - name: Docker login
|
||||
# uses: docker/login-action@v2
|
||||
# with:
|
||||
# username: ${{ secrets.DOCKER_USERNAME }}
|
||||
# password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
#
|
||||
# - name: Get commit SHA
|
||||
# id: vars
|
||||
# run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
#
|
||||
# - name: Build and export
|
||||
# id: build
|
||||
# if: github.ref == 'refs/heads/master'
|
||||
# uses: docker/build-push-action@v3
|
||||
# with:
|
||||
# platforms: linux/arm/v7
|
||||
# context: scripts/
|
||||
# tags: asdlokj1qpi23/subconverter:latest-armv7
|
||||
# build-args: |
|
||||
# SHA=${{ steps.vars.outputs.sha_short }}
|
||||
# THREADS=4
|
||||
# outputs: type=image,push=true
|
||||
#
|
||||
# - name: Replace tag without `v`
|
||||
# if: startsWith(github.ref, 'refs/tags/')
|
||||
# uses: actions/github-script@v6
|
||||
# id: version
|
||||
# with:
|
||||
# script: |
|
||||
# return context.payload.ref.replace(/\/?refs\/tags\/v/, '')
|
||||
# result-encoding: string
|
||||
#
|
||||
# - name: Build release and export
|
||||
# id: build_rel
|
||||
# if: startsWith(github.ref, 'refs/tags/')
|
||||
# uses: docker/build-push-action@v3
|
||||
# with:
|
||||
# platforms: linux/arm/v7
|
||||
# context: scripts/
|
||||
# tags: asdlokj1qpi23/subconverter:${{steps.version.outputs.result}}-armv7
|
||||
# build-args: |
|
||||
# THREADS=4
|
||||
# outputs: type=image,push=true
|
||||
#
|
||||
# - name: Save digest
|
||||
# if: github.ref == 'refs/heads/master'
|
||||
# run: echo ${{ steps.build.outputs.digest }} > /tmp/digest.txt
|
||||
#
|
||||
# - name: Save release digest
|
||||
# if: startsWith(github.ref, 'refs/tags/')
|
||||
# run: echo ${{ steps.build_rel.outputs.digest }} > /tmp/digest.txt
|
||||
#
|
||||
# - name: Upload artifact
|
||||
# uses: actions/upload-artifact@v3
|
||||
# with:
|
||||
# name: digest_armv7
|
||||
# path: /tmp/digest.txt
|
||||
#
|
||||
# arm64_build:
|
||||
# name: Build ARM64 Image
|
||||
# runs-on: [self-hosted, linux, ARM64]
|
||||
# steps:
|
||||
# - name: Checkout base
|
||||
# uses: actions/checkout@v3
|
||||
# with:
|
||||
# fetch-depth: 0
|
||||
#
|
||||
# - name: Set up Docker Buildx
|
||||
# uses: docker/setup-buildx-action@v2
|
||||
#
|
||||
# - name: Docker login
|
||||
# uses: docker/login-action@v2
|
||||
# with:
|
||||
# username: ${{ secrets.DOCKER_USERNAME }}
|
||||
# password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
#
|
||||
# - name: Get commit SHA
|
||||
# id: vars
|
||||
# run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
#
|
||||
# - name: Build and export
|
||||
# id: build
|
||||
# if: github.ref == 'refs/heads/master'
|
||||
# uses: docker/build-push-action@v3
|
||||
# with:
|
||||
# platforms: linux/arm64
|
||||
# context: scripts/
|
||||
# tags: asdlokj1qpi23/subconverter:latest-arm64
|
||||
# build-args: |
|
||||
# SHA=${{ steps.vars.outputs.sha_short }}
|
||||
# THREADS=4
|
||||
# outputs: type=image,push=true
|
||||
#
|
||||
# - name: Replace tag without `v`
|
||||
# if: startsWith(github.ref, 'refs/tags/')
|
||||
# uses: actions/github-script@v6
|
||||
# id: version
|
||||
# with:
|
||||
# script: |
|
||||
# return context.payload.ref.replace(/\/?refs\/tags\/v/, '')
|
||||
# result-encoding: string
|
||||
#
|
||||
# - name: Build release and export
|
||||
# id: build_rel
|
||||
# if: startsWith(github.ref, 'refs/tags/')
|
||||
# uses: docker/build-push-action@v3
|
||||
# with:
|
||||
# platforms: linux/arm64
|
||||
# context: scripts/
|
||||
# tags: asdlokj1qpi23/subconverter:${{steps.version.outputs.result}}-arm64
|
||||
# build-args: |
|
||||
# THREADS=4
|
||||
# outputs: type=image,push=true
|
||||
#
|
||||
# - name: Save digest
|
||||
# if: github.ref == 'refs/heads/master'
|
||||
# run: echo ${{ steps.build.outputs.digest }} > /tmp/digest.txt
|
||||
#
|
||||
# - name: Save release digest
|
||||
# if: startsWith(github.ref, 'refs/tags/')
|
||||
# run: echo ${{ steps.build_rel.outputs.digest }} > /tmp/digest.txt
|
||||
#
|
||||
# - name: Upload artifact
|
||||
# uses: actions/upload-artifact@v3
|
||||
# with:
|
||||
# name: digest_arm64
|
||||
# path: /tmp/digest.txt
|
||||
|
||||
build:
|
||||
name: Build
|
||||
# needs: [amd64_build, x86_build, armv7_build, arm64_build]
|
||||
needs: [amd64_build, x86_build]
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
os: ubuntu-latest
|
||||
- platform: linux/386
|
||||
os: ubuntu-latest
|
||||
- platform: linux/arm/v7
|
||||
os: ubuntu-latest
|
||||
- platform: linux/arm64
|
||||
os: ubuntu-latest
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: Build ${{ matrix.platform }} Image
|
||||
steps:
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
|
||||
- name: Checkout base
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# https://github.com/docker/setup-qemu-action
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
# https://github.com/docker/setup-buildx-action
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
config-inline: |
|
||||
[worker.oci]
|
||||
max-parallelism = 1
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Download artifact
|
||||
uses: actions/download-artifact@v3
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
path: /tmp/images/
|
||||
images: ${{ env.REGISTRY_IMAGE }}
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Docker login
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Replace tag without `v`
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: actions/github-script@v6
|
||||
id: version
|
||||
with:
|
||||
script: |
|
||||
return context.payload.ref.replace(/\/?refs\/tags\/v/, '')
|
||||
result-encoding: string
|
||||
|
||||
- name: Merge and push manifest on master branch
|
||||
- name: Get commit SHA
|
||||
if: github.ref == 'refs/heads/master'
|
||||
run: python scripts/merge_manifest.py
|
||||
id: vars
|
||||
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Merge and push manifest on release
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
run: python scripts/merge_manifest.py ${{steps.version.outputs.result}}
|
||||
- name: Build and export
|
||||
id: build
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
platforms: ${{ matrix.platform }}
|
||||
context: scripts/
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
SHA=${{ steps.vars.outputs.sha_short }}
|
||||
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
||||
|
||||
- name: Export digest
|
||||
run: |
|
||||
rm -rf /tmp/digests
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digest-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
merge:
|
||||
name: Merge
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digest-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY_IMAGE }}
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Docker login
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
|
||||
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -3,3 +3,9 @@ subconverter.exe
|
||||
cmake-build-debug
|
||||
.idea
|
||||
base/cache
|
||||
scripts/quickjspp
|
||||
scripts/yaml-cpp
|
||||
.DS_Store
|
||||
src/.DS_Store
|
||||
|
||||
build
|
||||
@@ -1,9 +1,13 @@
|
||||
PROJECT(subconverter LANGUAGES CXX)
|
||||
SET(BUILD_TARGET_NAME ${PROJECT_NAME})
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.4)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
|
||||
INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include/")
|
||||
|
||||
if (MINGW)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--allow-multiple-definition")
|
||||
endif()
|
||||
|
||||
IF(NOT CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE Release)
|
||||
ENDIF()
|
||||
|
||||
14
README.md
14
README.md
@@ -2,10 +2,12 @@
|
||||
|
||||
Utility to convert between various proxy subscription formats.
|
||||
|
||||
[](https://github.com/asdlokj1qpi23/subconverter/actions)
|
||||
[](https://github.com/asdlokj1qpi23/subconverter/tags)
|
||||
[](https://github.com/asdlokj1qpi23/subconverter/releases)
|
||||
[](https://github.com/tindy2013/subconverter/blob/master/LICENSE)
|
||||
original git: https://github.com/asdlokj1qpi23/subconverter
|
||||
|
||||
[](https://github.com/asdlokj1qpi233/subconverter/actions)
|
||||
[](https://github.com/asdlokj1qpi23/subconverter/tags)
|
||||
[](https://github.com/asdlokj1qpi233/subconverter/releases)
|
||||
[](https://github.com/tindy2013/subconverter/blob/master/LICENSE)
|
||||
|
||||
[Docker README](https://github.com/asdlokj1qpi23/subconverter/blob/master/README-docker.md)
|
||||
|
||||
@@ -59,9 +61,11 @@ services:
|
||||
| Surge 2 | ✓ | ✓ | surge&ver=2 |
|
||||
| Surge 3 | ✓ | ✓ | surge&ver=3 |
|
||||
| Surge 4 | ✓ | ✓ | surge&ver=4 |
|
||||
| Surge 5 | ✓ | ✓ | surge&ver=5 |
|
||||
| V2Ray | ✓ | ✓ | v2ray |
|
||||
| Telegram-liked HTTP/Socks 5 links | ✓ | × | Only as source |
|
||||
| Singbox | × | ✓ | singbox |
|
||||
| Singbox | ✓ | ✓ | singbox |
|
||||
|
||||
Notice:
|
||||
|
||||
1. Shadowrocket users should use `ss`, `ssr` or `v2ray` as target.
|
||||
|
||||
@@ -5,7 +5,7 @@ socks-port: {{ default(global.clash.socks_port, "7891") }}
|
||||
allow-lan: {{ default(global.clash.allow_lan, "true") }}
|
||||
mode: Rule
|
||||
log-level: {{ default(global.clash.log_level, "info") }}
|
||||
external-controller: :9090
|
||||
external-controller: {{ default(global.clash.external_controller, "127.0.0.1:9090") }}
|
||||
{% if default(request.clash.dns, "") == "1" %}
|
||||
dns:
|
||||
enable: true
|
||||
@@ -378,7 +378,16 @@ enhanced-mode-by-rule = true
|
||||
"rules": [],
|
||||
"auto_detect_interface": true
|
||||
},
|
||||
"experimental": {}
|
||||
"experimental": {
|
||||
"cache_file": {
|
||||
"enabled": true,
|
||||
"store_fakeip": true
|
||||
},
|
||||
"clash_api": {
|
||||
"external_controller": "{{ default(global.clash.external_controller, "127.0.0.1:9090") }}",
|
||||
"external_ui": "dashboard"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{% endif %}
|
||||
|
||||
@@ -100,5 +100,14 @@
|
||||
"rules": [],
|
||||
"auto_detect_interface": true
|
||||
},
|
||||
"experimental": {}
|
||||
"experimental": {
|
||||
"cache_file": {
|
||||
"enabled": true,
|
||||
"store_fakeip": true
|
||||
},
|
||||
"clash_api": {
|
||||
"external_controller": "127.0.0.1:9090",
|
||||
"external_ui": "dashboard"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,13 +109,14 @@ filter_deprecated_nodes=false
|
||||
append_sub_userinfo=true
|
||||
clash_use_new_field_name=true
|
||||
|
||||
;Generate style of the proxies section of Clash subscriptions.
|
||||
;Generate style of the proxies and proxy groups section of Clash subscriptions.
|
||||
;Supported styles: block, flow, compact
|
||||
;Block: - name: name1 Flow: - {name: name1, key: value} Compact: [{name: name1, key: value},{name: name2, key: value}]
|
||||
; key: value - {name: name2, key: value}
|
||||
; - name: name2
|
||||
; key: value
|
||||
clash_proxies_style=flow
|
||||
clash_proxy_groups_style=block
|
||||
|
||||
;add Clash mode to sing-box rules, and add a GLOBAL group to end of outbounds
|
||||
singbox_add_clash_modes=true
|
||||
@@ -232,6 +233,7 @@ clash.http_port=7890
|
||||
clash.socks_port=7891
|
||||
clash.allow_lan=true
|
||||
clash.log_level=info
|
||||
clash.external_controller=127.0.0.1:9090
|
||||
singbox.allow_lan=true
|
||||
singbox.mixed_port=2080
|
||||
|
||||
|
||||
@@ -117,10 +117,10 @@ match = '^Smart Access expire: (\d+)/(\d+)/(\d+)$'
|
||||
replace = '$1:$2:$3:0:0:0'
|
||||
|
||||
[node_pref]
|
||||
udp_flag = true
|
||||
tcp_fast_open_flag = false
|
||||
skip_cert_verify_flag = true
|
||||
tls13_flag = false
|
||||
#udp_flag = false
|
||||
#tcp_fast_open_flag = false
|
||||
#skip_cert_verify_flag = false
|
||||
#tls13_flag = false
|
||||
|
||||
sort_flag = false
|
||||
# Script used for sorting nodes. A "compare" function with 2 arguments which are the 2 nodes to be compared should be defined in the script. Supports inline script and script path.
|
||||
@@ -135,13 +135,14 @@ filter_deprecated_nodes = false
|
||||
append_sub_userinfo = true
|
||||
clash_use_new_field_name = true
|
||||
|
||||
# Generate style of the proxies section of Clash subscriptions.
|
||||
# Generate style of the proxies and proxy groups section of Clash subscriptions.
|
||||
# Supported styles: block, flow, compact
|
||||
# Block: - name: name1 Flow: - {name: name1, key: value} Compact: [{name: name1, key: value},{name: name2, key: value}]
|
||||
# key: value - {name: name2, key: value}
|
||||
# - name: name2
|
||||
# key: value
|
||||
clash_proxies_style = "flow"
|
||||
clash_proxy_groups_style = "block"
|
||||
|
||||
# add Clash mode to sing-box rules, and add a GLOBAL group to end of outbounds
|
||||
singbox_add_clash_modes = true
|
||||
@@ -243,6 +244,10 @@ value = "true"
|
||||
key = "clash.log_level"
|
||||
value = "info"
|
||||
|
||||
[[template.globals]]
|
||||
key = "clash.external_controller"
|
||||
value = "127.0.0.1:9090"
|
||||
|
||||
[[template.globals]]
|
||||
key = "singbox.allow_lan"
|
||||
value = "true"
|
||||
|
||||
@@ -50,6 +50,7 @@ node_pref:
|
||||
append_sub_userinfo: true
|
||||
clash_use_new_field_name: true
|
||||
clash_proxies_style: flow
|
||||
clash_proxy_groups_style: block
|
||||
singbox_add_clash_modes: true
|
||||
rename_node:
|
||||
# - {match: "\\(?((x|X)?(\\d+)(\\.?\\d+)?)((\\s?倍率?)|(x|X))\\)?", replace: "$1x"}
|
||||
@@ -108,9 +109,10 @@ template:
|
||||
- {key: clash.socks_port, value: 7891}
|
||||
- {key: clash.allow_lan, value: true}
|
||||
- {key: clash.log_level, value: info}
|
||||
- {key: clash.external_controller, value: '127.0.0.1:9090'}
|
||||
- {key: singbox.allow_lan, value: true}
|
||||
- {key: singbox.mixed_port, value: 2080}
|
||||
|
||||
|
||||
aliases:
|
||||
- {uri: /v, target: /version}
|
||||
- {uri: /clash, target: "/sub?target=clash"}
|
||||
|
||||
@@ -3,15 +3,15 @@ match = "(?i:Bandwidth|expire|流量|时间|应急|过期)"
|
||||
emoji = "🏳️🌈"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bHK[G]?\\b|Hong.*?Kong|\\bHKT\\b|\\bHKBN\\b|\\bHGC\\b|\\bWTT\\b|\\bCMI\\b|[^-]港)"
|
||||
match = "(?i:\\bHK[G]?\\d*\\b|Hong.*?Kong|\\bHKT\\b|\\bHKBN\\b|\\bHGC\\b|\\bWTT\\b|\\bCMI\\b|[^-]港)"
|
||||
emoji = "🇭🇰"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bTW[N]?\\b|Taiwan|新北|彰化|\\bCHT\\b|台湾|[^-]台|\\bHINET\\b)"
|
||||
match = "(?i:\\bTW[N]?\\d*\\b|Taiwan|新北|彰化|\\bCHT\\b|台湾|[^-]台|\\bHINET\\b)"
|
||||
emoji = "🇨🇳"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bSG[P]?\\b|Singapore|新加坡|狮城|[^-]新)"
|
||||
match = "(?i:\\bSG[P]?\\d*\\b|Singapore|新加坡|狮城|[^-]新)"
|
||||
emoji = "🇸🇬"
|
||||
|
||||
[[emoji]]
|
||||
@@ -19,15 +19,15 @@ match = "(尼日利亚|Nigeria)"
|
||||
emoji = "🇳🇬"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bJP[N]?\\b|Japan|Tokyo|Osaka|Saitama|日本|东京|大阪|埼玉|[^-]日)"
|
||||
match = "(?i:\\bJP[N]?\\d*\\b|Japan|Tokyo|Osaka|Saitama|日本|东京|大阪|埼玉|[^-]日)"
|
||||
emoji = "🇯🇵"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bK[O]?R\\b|Korea|首尔|韩|韓)"
|
||||
match = "(?i:(?<!North\\s)(\\bK[O]?R\\d*\\b|Korea|首尔|韩|韓))"
|
||||
emoji = "🇰🇷"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bUS[A]?\\b|America|United.*?States|美国|[^-]美|波特兰|达拉斯|俄勒冈|凤凰城|费利蒙|硅谷|拉斯维加斯|洛杉矶|圣何塞|圣克拉拉|西雅图|芝加哥)"
|
||||
match = "(?i:\\bUS[A]?\\d*\\b|America|United.*?States|美国|[^-]美|波特兰|达拉斯|俄勒冈|凤凰城|费利蒙|硅谷|拉斯维加斯|洛杉矶|圣何塞|圣克拉拉|西雅图|芝加哥)"
|
||||
emoji = "🇺🇸"
|
||||
|
||||
[[emoji]]
|
||||
@@ -42,6 +42,10 @@ emoji = "🇦🇪"
|
||||
match = "(阿尔巴尼亚|Albania)"
|
||||
emoji = "🇦🇱"
|
||||
|
||||
[[emoji]]
|
||||
match = "(南极|Antarctica)"
|
||||
emoji = "🇦🇶"
|
||||
|
||||
[[emoji]]
|
||||
match = "(Argentina|阿根廷)"
|
||||
emoji = "🇦🇷"
|
||||
@@ -51,7 +55,7 @@ match = "(Austria|Vienna|奥地利|维也纳)"
|
||||
emoji = "🇦🇹"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bAU[S]?\\b|Australia|Sydney|澳大利亚|澳洲|悉尼)"
|
||||
match = "(?i:\\bAU[S]?\\d*\\b|Australia|Sydney|澳大利亚|澳洲|悉尼)"
|
||||
emoji = "🇦🇺"
|
||||
|
||||
[[emoji]]
|
||||
@@ -75,7 +79,7 @@ match = "(Brazil|Paulo|巴西|圣保罗)"
|
||||
emoji = "🇧🇷"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bCA[N]?\\b|Canada|Toronto|Montreal|Vancouver|加拿大|蒙特利尔|温哥华|楓葉|枫叶)"
|
||||
match = "(?i:\\bCA[N]?\\d*\\b|Canada|Toronto|Montreal|Vancouver|加拿大|蒙特利尔|温哥华|楓葉|枫叶)"
|
||||
emoji = "🇨🇦"
|
||||
|
||||
[[emoji]]
|
||||
@@ -103,7 +107,7 @@ match = "(Czech|捷克)"
|
||||
emoji = "🇨🇿"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bDE[U]?\\b|Germany|法兰克福|德(国|意志)|中德|^德$)"
|
||||
match = "(?i:\\bDE[U]?\\d*\\b|Germany|法兰克福|德(国|意志)|中德|^德$)"
|
||||
emoji = "🇩🇪"
|
||||
|
||||
[[emoji]]
|
||||
@@ -119,7 +123,7 @@ match = "(埃及|Egypt)"
|
||||
emoji = "🇪🇬"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bES[P]?\\b|Spain|西班牙)"
|
||||
match = "(?i:\\bES[P]?\\d*\\b|Spain|西班牙)"
|
||||
emoji = "🇪🇸"
|
||||
|
||||
[[emoji]]
|
||||
@@ -131,11 +135,11 @@ match = "(Finland|Helsinki|芬兰|赫尔辛基)"
|
||||
emoji = "🇫🇮"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bFR[A]?\\b|France|Paris|法国|巴黎)"
|
||||
match = "(?i:\\bFR[A]?\\d*\\b|France|Paris|法国|巴黎)"
|
||||
emoji = "🇫🇷"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bUK\\b|\\bGB[R]?\\b|England|United.*?Kingdom|London|英国|[^-]英|伦敦)"
|
||||
match = "(?i:\\bUK\\d*\\b|\\bGB[R]?\\d*\\b|England|United.*?Kingdom|London|英国|[^-]英|伦敦)"
|
||||
emoji = "🇬🇧"
|
||||
|
||||
[[emoji]]
|
||||
@@ -171,7 +175,7 @@ match = "(马恩岛|Mann)"
|
||||
emoji = "🇮🇲"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bIN[D]?\\b|India|Mumbai|印度|孟买|加尔各答|贾坎德|泰米尔纳德)"
|
||||
match = "(?i:\\bIN[D]?\\d*\\b|India|Mumbai|印度|孟买|加尔各答|贾坎德|泰米尔纳德)"
|
||||
emoji = "🇮🇳"
|
||||
|
||||
[[emoji]]
|
||||
@@ -179,11 +183,11 @@ match = "(伊朗|Iran)"
|
||||
emoji = "🇮🇷"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bIS[L]?\\b|Iceland|冰岛)"
|
||||
match = "(?i:\\bIS[L]?\\d*\\b|Iceland|冰岛)"
|
||||
emoji = "🇮🇸"
|
||||
|
||||
[[emoji]]
|
||||
match = "(Italy|Milan|意大利|米兰)"
|
||||
match = "(Italy|Italia|Milan|意大利|米兰)"
|
||||
emoji = "🇮🇹"
|
||||
|
||||
[[emoji]]
|
||||
@@ -202,7 +206,6 @@ emoji = "🇰🇬"
|
||||
match = "(柬埔寨|Cambodia)"
|
||||
emoji = "🇰🇭"
|
||||
|
||||
|
||||
[[emoji]]
|
||||
match = "(North.*?Korea|朝鲜)"
|
||||
emoji = "🇰🇵"
|
||||
@@ -231,6 +234,10 @@ emoji = "🇲🇩"
|
||||
match = "(北马其顿|Macedonia)"
|
||||
emoji = "🇲🇰"
|
||||
|
||||
[[emoji]]
|
||||
match = "(缅甸|Myanmar)"
|
||||
emoji = "🇲🇲"
|
||||
|
||||
[[emoji]]
|
||||
match = "(蒙古|Монголулс|Mongolia)"
|
||||
emoji = "🇲🇳"
|
||||
@@ -248,7 +255,7 @@ match = "(Malaysia|马来|MY)"
|
||||
emoji = "🇲🇾"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bNL[D]?\\b|Netherlands|荷兰|阿姆斯特丹)"
|
||||
match = "(?i:\\bNL[D]?\\d*\\b|Netherlands|荷兰|阿姆斯特丹)"
|
||||
emoji = "🇳🇱"
|
||||
|
||||
[[emoji]]
|
||||
@@ -260,7 +267,7 @@ match = "(新西兰|纽西兰|New Zealand)"
|
||||
emoji = "🇳🇿"
|
||||
|
||||
[[emoji]]
|
||||
match = "(Philippines|菲律宾)"
|
||||
match = "(?i:\\bP[O]?H\\d*\\b|Philippines|菲律宾)"
|
||||
emoji = "🇵🇭"
|
||||
|
||||
[[emoji]]
|
||||
@@ -292,7 +299,7 @@ match = "(塞尔维亚|Serbia)"
|
||||
emoji = "🇷🇸"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bRU[S]?\\b|Russia|Moscow|Petersburg|Siberia|伯力|莫斯科|圣彼得堡|西伯利亚|新西伯利亚|哈巴罗夫斯克|俄罗斯|[^-]俄)"
|
||||
match = "(?i:\\bRU[S]?\\d*\\b|Russia|Moscow|Petersburg|Siberia|伯力|莫斯科|圣彼得堡|西伯利亚|新西伯利亚|哈巴罗夫斯克|俄罗斯|[^-]俄)"
|
||||
emoji = "🇷🇺"
|
||||
|
||||
[[emoji]]
|
||||
@@ -320,7 +327,7 @@ match = "(突尼斯|Tunisia)"
|
||||
emoji = "🇹🇳"
|
||||
|
||||
[[emoji]]
|
||||
match = "(Turkey|土耳其|伊斯坦布尔)"
|
||||
match = "(Turkey|Türkiye|土耳其|伊斯坦布尔)"
|
||||
emoji = "🇹🇷"
|
||||
|
||||
[[emoji]]
|
||||
@@ -364,4 +371,4 @@ emoji = "🇧🇩"
|
||||
|
||||
[[emoji]]
|
||||
match = "(?i:\\bC[H]?N\\b|China|back|回国|中国[^-]|江苏[^-]|北京[^-]|上海[^-]|广州[^-]|深圳[^-]|杭州[^-]|常州[^-]|徐州[^-]|青岛[^-]|宁波[^-]|镇江[^-]|成都[^-]|河北[^-]|山西[^-]|辽宁[^-]|吉林[^-]|黑龙江[^-]|江苏[^-]|浙江[^-]|安徽[^-]|福建[^-]|江西[^-]|山东[^-]|河南[^-]|湖北[^-]|湖南[^-]|广东[^-]|海南[^-]|四川[^-]|贵州[^-]|云南[^-]|陕西[^-]|甘肃[^-]|青海[^-]|内蒙古[^-]|广西[^-]|西藏[^-]|宁夏[^-]|新疆[^-])"
|
||||
emoji = "🇨🇳"
|
||||
emoji = "🇨🇳"
|
||||
@@ -1,38 +1,39 @@
|
||||
(?i:Bandwidth|expire|流量|时间|应急|过期),🏳️🌈
|
||||
(?i:\bHK[G]?\b|Hong.*?Kong|\bHKT\b|\bHKBN\b|\bHGC\b|\bWTT\b|\bCMI\b|[^-]港),🇭🇰
|
||||
(?i:\bTW[N]?\b|Taiwan|新北|彰化|\bCHT\b|台湾|[^-]台|\bHINET\b),🇨🇳
|
||||
(?i:\bSG[P]?\b|Singapore|新加坡|狮城|[^-]新),🇸🇬
|
||||
(?i:\bHK[G]?\d*\b|Hong.*?Kong|\bHKT\b|\bHKBN\b|\bHGC\b|\bWTT\b|\bCMI\b|[^-]港),🇭🇰
|
||||
(?i:\bTW[N]?\d*\b|Taiwan|新北|彰化|\bCHT\b|台湾|[^-]台|\bHINET\b),🇨🇳
|
||||
(?i:\bSG[P]?\d*\b|Singapore|新加坡|狮城|[^-]新),🇸🇬
|
||||
(尼日利亚|Nigeria),🇳🇬
|
||||
(?i:\bJP[N]?\b|Japan|Tokyo|Osaka|Saitama|日本|东京|大阪|埼玉|[^-]日),🇯🇵
|
||||
(?i:\bK[O]?R\b|Korea|首尔|韩|韓),🇰🇷
|
||||
(?i:\bUS[A]?\b|America|United.*?States|美国|[^-]美|波特兰|达拉斯|俄勒冈|凤凰城|费利蒙|硅谷|拉斯维加斯|洛杉矶|圣何塞|圣克拉拉|西雅图|芝加哥),🇺🇸
|
||||
(?i:\bJP[N]?\d*\b|Japan|Tokyo|Osaka|Saitama|日本|东京|大阪|埼玉|[^-]日),🇯🇵
|
||||
(?i:(?<!North\s)(\bK[O]?R\d*\b|Korea|首尔|韩|韓)),🇰🇷
|
||||
(?i:\bUS[A]?\d*\b|America|United.*?States|美国|[^-]美|波特兰|达拉斯|俄勒冈|凤凰城|费利蒙|硅谷|拉斯维加斯|洛杉矶|圣何塞|圣克拉拉|西雅图|芝加哥),🇺🇸
|
||||
(Ascension|阿森松),🇦🇨
|
||||
(?i:\bUAE\b|Dubai|阿联酋|迪拜),🇦🇪
|
||||
(阿尔巴尼亚|Albania),🇦🇱
|
||||
(南极|Antarctica),🇦🇶
|
||||
(Argentina|阿根廷),🇦🇷
|
||||
(Austria|Vienna|奥地利|维也纳),🇦🇹
|
||||
(?i:\bAU[S]?\b|Australia|Sydney|澳大利亚|澳洲|悉尼),🇦🇺
|
||||
(?i:\bAU[S]?\d*\b|Australia|Sydney|澳大利亚|澳洲|悉尼),🇦🇺
|
||||
(阿塞拜疆|Azerbaijan),🇦🇿
|
||||
(波黑共和国|波士尼亚与赫塞哥维纳|Bosnia|Herzegovina),🇧🇦
|
||||
(Belgium|比利时),🇧🇪
|
||||
(保加利亚|Bulgaria),🇧🇬
|
||||
(Brazil|Paulo|巴西|圣保罗),🇧🇷
|
||||
(?i:\bCA[N]?\b|Canada|Toronto|Montreal|Vancouver|加拿大|蒙特利尔|温哥华|楓葉|枫叶),🇨🇦
|
||||
(?i:\bCA[N]?\d*\b|Canada|Toronto|Montreal|Vancouver|加拿大|蒙特利尔|温哥华|楓葉|枫叶),🇨🇦
|
||||
(Switzerland|Zurich|瑞士|苏黎世),🇨🇭
|
||||
(智利|Chile),🇨🇱
|
||||
(Colombia|哥伦比亚),🇨🇴
|
||||
(Costa Rica|哥斯达黎加),🇨🇷
|
||||
(塞浦路斯|Cyprus),🇨🇾
|
||||
(Czech|捷克),🇨🇿
|
||||
(?i:\bDE[U]?\b|Germany|法兰克福|德(国|意志)|中德|^德$),🇩🇪
|
||||
(?i:\bDE[U]?\d*\b|Germany|法兰克福|德(国|意志)|中德|^德$),🇩🇪
|
||||
(?i:\bD[N]?K\b|Denmark|丹麦),🇩🇰
|
||||
(爱沙尼亚|Estonia),🇪🇪
|
||||
(埃及|Egypt),🇪🇬
|
||||
(?i:\bES[P]?\b|Spain|西班牙),🇪🇸
|
||||
(?i:\bES[P]?\d*\b|Spain|西班牙),🇪🇸
|
||||
(Europe|欧洲),🇪🇺
|
||||
(Finland|Helsinki|芬兰|赫尔辛基),🇫🇮
|
||||
(?i:\bFR[A]?\b|France|Paris|法国|巴黎),🇫🇷
|
||||
(?i:\bUK\b|\bGB[R]?\b|England|United.*?Kingdom|London|英国|[^-]英|伦敦),🇬🇧
|
||||
(?i:\bFR[A]?\d*\b|France|Paris|法国|巴黎),🇫🇷
|
||||
(?i:\bUK\d*\b|\bGB[R]?\d*\b|England|United.*?Kingdom|London|英国|[^-]英|伦敦),🇬🇧
|
||||
(希腊|Greece),🇬🇷
|
||||
(格鲁吉亚|Georgia),🇬🇪
|
||||
(克罗地亚|Croatia),🇭🇷
|
||||
@@ -41,10 +42,10 @@
|
||||
(Ireland|Dublin|爱尔兰|都柏林),🇮🇪
|
||||
(Israel|以色列),🇮🇱
|
||||
(马恩岛|Mann),🇮🇲
|
||||
(?i:\bIN[D]?\b|India|Mumbai|印度|孟买|加尔各答|贾坎德|泰米尔纳德),🇮🇳
|
||||
(?i:\bIN[D]?\d*\b|India|Mumbai|印度|孟买|加尔各答|贾坎德|泰米尔纳德),🇮🇳
|
||||
(伊朗|Iran),🇮🇷
|
||||
(?i:\bIS[L]?\b|Iceland|冰岛),🇮🇸
|
||||
(Italy|Milan|意大利|米兰),🇮🇹
|
||||
(?i:\bIS[L]?\d*\b|Iceland|冰岛),🇮🇸
|
||||
(Italy|Italia|Milan|意大利|米兰),🇮🇹
|
||||
(约旦|Jordan),🇯🇴
|
||||
(肯尼亚|Kenya),🇰🇪
|
||||
(吉尔吉斯斯坦|Kyrgyzstan),🇰🇬
|
||||
@@ -56,14 +57,15 @@
|
||||
(拉脱维亚|Latvia),🇱🇻
|
||||
(Moldova|摩尔多瓦),🇲🇩
|
||||
(北马其顿|Macedonia),🇲🇰
|
||||
(缅甸|Myanmar),🇲🇲
|
||||
(蒙古|Монголулс|Mongolia),🇲🇳
|
||||
(Macao|澳门|\bCTM\b),🇲🇴
|
||||
(墨西哥|Mexico),🇲🇽
|
||||
(Malaysia|马来|MY),🇲🇾
|
||||
(?i:\bNL[D]?\b|Netherlands|荷兰|阿姆斯特丹),🇳🇱
|
||||
(?i:\bNL[D]?\d*\b|Netherlands|荷兰|阿姆斯特丹),🇳🇱
|
||||
(挪威|Norway),🇳🇴
|
||||
(新西兰|纽西兰|New Zealand),🇳🇿
|
||||
(Philippines|菲律宾),🇵🇭
|
||||
(?i:\bP[O]?H\d*\b|Philippines|菲律宾),🇵🇭
|
||||
(Pakistan|巴基斯坦),🇵🇰
|
||||
(?i:\bP[O]?L\b|Poland|波兰),🇵🇱
|
||||
(巴拿马|Panama),🇵🇦
|
||||
@@ -71,15 +73,16 @@
|
||||
(葡萄牙|Portugal),🇵🇹
|
||||
(Romania|罗马尼亚),🇷🇴
|
||||
(塞尔维亚|Serbia),🇷🇸
|
||||
(?i:\bRU[S]?\b|Russia|Moscow|Petersburg|Siberia|伯力|莫斯科|圣彼得堡|西伯利亚|新西伯利亚|哈巴罗夫斯克|俄罗斯|[^-]俄),🇷🇺
|
||||
(?i:\bRU[S]?\d*\b|Russia|Moscow|Petersburg|Siberia|伯力|莫斯科|圣彼得堡|西伯利亚|新西伯利亚|哈巴罗夫斯克|俄罗斯|[^-]俄),🇷🇺
|
||||
(Arabia|沙特),🇸🇦
|
||||
(Sweden|瑞典),🇸🇪
|
||||
(斯洛文尼亚|Slovenia),🇸🇮
|
||||
(斯洛伐克|Slovensko),🇸🇰
|
||||
(Thailand|泰国|曼谷),🇹🇭
|
||||
(突尼斯|Tunisia),🇹🇳
|
||||
(Turkey|土耳其|伊斯坦布尔),🇹🇷
|
||||
(Turkey|Türkiye|土耳其|伊斯坦布尔),🇹🇷
|
||||
(乌拉圭|Uruguay),🇺🇾
|
||||
(梵蒂冈|Vatican),🇻🇦
|
||||
(Vietnam|越南),🇻🇳
|
||||
(Africa|南非),🇿🇦
|
||||
(Ukraine|UA|乌克兰),🇺🇦
|
||||
|
||||
@@ -8,8 +8,10 @@ WORKDIR /
|
||||
RUN set -xe && \
|
||||
apk add --no-cache --virtual .build-tools git g++ build-base linux-headers cmake python3 && \
|
||||
apk add --no-cache --virtual .build-deps curl-dev rapidjson-dev pcre2-dev yaml-cpp-dev && \
|
||||
git clone https://github.com/ftk/quickjspp --depth=1 && \
|
||||
git clone --no-checkout https://github.com/ftk/quickjspp.git && \
|
||||
cd quickjspp && \
|
||||
git fetch origin 0c00c48895919fc02da3f191a2da06addeb07f09 && \
|
||||
git checkout 0c00c48895919fc02da3f191a2da06addeb07f09 && \
|
||||
git submodule update --init && \
|
||||
cmake -DCMAKE_BUILD_TYPE=Release . && \
|
||||
make quickjs -j $THREADS && \
|
||||
@@ -30,12 +32,12 @@ RUN set -xe && \
|
||||
install -d /usr/include/date/ && \
|
||||
install -m644 libcron/externals/date/include/date/* /usr/include/date/ && \
|
||||
cd .. && \
|
||||
git clone https://github.com/ToruNiina/toml11 --branch="v3.7.1" --depth=1 && \
|
||||
git clone https://github.com/ToruNiina/toml11 --branch="v4.3.0" --depth=1 && \
|
||||
cd toml11 && \
|
||||
cmake -DCMAKE_CXX_STANDARD=11 . && \
|
||||
make install -j $THREADS && \
|
||||
cd .. && \
|
||||
git clone https://github.com/asdlokj1qpi23/subconverter --depth=1 && \
|
||||
git clone https://github.com/asdlokj1qpi233/subconverter --depth=1 && \
|
||||
cd subconverter && \
|
||||
[ -n "$SHA" ] && sed -i 's/\(v[0-9]\.[0-9]\.[0-9]\)/\1-'"$SHA"'/' src/version.h;\
|
||||
python3 -m ensurepip && \
|
||||
@@ -53,6 +55,10 @@ RUN apk add --no-cache --virtual subconverter-deps pcre2 libcurl yaml-cpp
|
||||
COPY --from=builder /subconverter/subconverter /usr/bin/
|
||||
COPY --from=builder /subconverter/base /base/
|
||||
|
||||
ENV TZ=Africa/Abidjan
|
||||
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime
|
||||
RUN echo $TZ > /etc/timezone
|
||||
|
||||
# set entry
|
||||
WORKDIR /base
|
||||
CMD subconverter
|
||||
|
||||
@@ -4,7 +4,7 @@ set -xe
|
||||
apk add gcc g++ build-base linux-headers cmake make autoconf automake libtool python2 python3
|
||||
apk add mbedtls-dev mbedtls-static zlib-dev rapidjson-dev zlib-static pcre2-dev
|
||||
|
||||
git clone https://github.com/curl/curl --depth=1 --branch curl-8_4_0
|
||||
git clone https://github.com/curl/curl --depth=1 --branch curl-8_6_0
|
||||
cd curl
|
||||
cmake -DCURL_USE_MBEDTLS=ON -DHTTP_ONLY=ON -DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=OFF -DCMAKE_USE_LIBSSH2=OFF -DBUILD_CURL_EXE=OFF . > /dev/null
|
||||
make install -j2 > /dev/null
|
||||
@@ -16,8 +16,10 @@ cmake -DCMAKE_BUILD_TYPE=Release -DYAML_CPP_BUILD_TESTS=OFF -DYAML_CPP_BUILD_TOO
|
||||
make install -j3 > /dev/null
|
||||
cd ..
|
||||
|
||||
git clone https://github.com/ftk/quickjspp --depth=1
|
||||
git clone --no-checkout https://github.com/ftk/quickjspp.git
|
||||
cd quickjspp
|
||||
git fetch origin 0c00c48895919fc02da3f191a2da06addeb07f09
|
||||
git checkout 0c00c48895919fc02da3f191a2da06addeb07f09
|
||||
cmake -DCMAKE_BUILD_TYPE=Release .
|
||||
make quickjs -j3 > /dev/null
|
||||
install -d /usr/lib/quickjs/
|
||||
@@ -34,7 +36,7 @@ cmake -DCMAKE_BUILD_TYPE=Release .
|
||||
make libcron install -j3
|
||||
cd ..
|
||||
|
||||
git clone https://github.com/ToruNiina/toml11 --branch="v3.7.1" --depth=1
|
||||
git clone https://github.com/ToruNiina/toml11 --branch="v4.3.0" --depth=1
|
||||
cd toml11
|
||||
cmake -DCMAKE_CXX_STANDARD=11 .
|
||||
make install -j4
|
||||
|
||||
@@ -14,49 +14,49 @@ brew reinstall rapidjson zlib pcre2 pkgconfig
|
||||
git clone https://github.com/jbeder/yaml-cpp --depth=1
|
||||
cd yaml-cpp
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DYAML_CPP_BUILD_TESTS=OFF -DYAML_CPP_BUILD_TOOLS=OFF . > /dev/null
|
||||
make install -j8 > /dev/null
|
||||
make -j6 > /dev/null
|
||||
sudo make install > /dev/null
|
||||
cd ..
|
||||
|
||||
git clone https://github.com/ftk/quickjspp --depth=1
|
||||
git clone --no-checkout https://github.com/ftk/quickjspp.git
|
||||
cd quickjspp
|
||||
git fetch origin 0c00c48895919fc02da3f191a2da06addeb07f09
|
||||
git checkout 0c00c48895919fc02da3f191a2da06addeb07f09
|
||||
cmake -DCMAKE_BUILD_TYPE=Release .
|
||||
make quickjs -j8
|
||||
install -d /usr/local/lib/quickjs/
|
||||
install -m644 quickjs/libquickjs.a /usr/local/lib/quickjs/
|
||||
install -d /usr/local/include/quickjs/
|
||||
install -m644 quickjs/quickjs.h quickjs/quickjs-libc.h /usr/local/include/quickjs/
|
||||
install -m644 quickjspp.hpp /usr/local/include/
|
||||
make quickjs -j6 > /dev/null
|
||||
sudo install -d /usr/local/lib/quickjs/
|
||||
sudo install -m644 quickjs/libquickjs.a /usr/local/lib/quickjs/
|
||||
sudo install -d /usr/local/include/quickjs/
|
||||
sudo install -m644 quickjs/quickjs.h quickjs/quickjs-libc.h /usr/local/include/quickjs/
|
||||
sudo install -m644 quickjspp.hpp /usr/local/include/
|
||||
cd ..
|
||||
|
||||
git clone https://github.com/PerMalmberg/libcron --depth=1
|
||||
cd libcron
|
||||
git submodule update --init
|
||||
cmake -DCMAKE_BUILD_TYPE=Release .
|
||||
make libcron install -j8
|
||||
install -m644 libcron/out/Release/liblibcron.a /usr/local/lib/
|
||||
install -d /usr/local/include/libcron/
|
||||
install -m644 libcron/include/libcron/* /usr/local/include/libcron/
|
||||
install -d /usr/local/include/date/
|
||||
install -m644 libcron/externals/date/include/date/* /usr/local/include/date/
|
||||
make libcron -j6
|
||||
sudo install -m644 libcron/out/Release/liblibcron.a /usr/local/lib/
|
||||
sudo install -d /usr/local/include/libcron/
|
||||
sudo install -m644 libcron/include/libcron/* /usr/local/include/libcron/
|
||||
sudo install -d /usr/local/include/date/
|
||||
sudo install -m644 libcron/externals/date/include/date/* /usr/local/include/date/
|
||||
cd ..
|
||||
|
||||
git clone https://github.com/ToruNiina/toml11 --depth=1
|
||||
git clone https://github.com/ToruNiina/toml11 --branch="v4.3.0" --depth=1
|
||||
cd toml11
|
||||
cmake -DCMAKE_CXX_STANDARD=11 .
|
||||
make install -j4
|
||||
sudo make install -j6 > /dev/null
|
||||
cd ..
|
||||
|
||||
cp /usr/local/opt/zlib/lib/libz.a .
|
||||
cp /usr/local/lib/libpcre2-8.a .
|
||||
|
||||
cmake -DCMAKE_BUILD_TYPE=Release .
|
||||
make -j8
|
||||
make -j6
|
||||
rm subconverter
|
||||
# shellcheck disable=SC2046
|
||||
c++ -Xlinker -unexported_symbol -Xlinker "*" -o base/subconverter -framework CoreFoundation -framework Security $(find CMakeFiles/subconverter.dir/src/ -name "*.o") $(find . -name "*.a") -lcurl -O3
|
||||
c++ -Xlinker -unexported_symbol -Xlinker "*" -o base/subconverter -framework CoreFoundation -framework Security $(find CMakeFiles/subconverter.dir/src/ -name "*.o") "$(brew --prefix zlib)/lib/libz.a" "$(brew --prefix pcre2)/lib/libpcre2-8.a" $(find . -name "*.a") -lcurl -O3
|
||||
|
||||
python -m ensurepip
|
||||
python -m pip install gitpython
|
||||
sudo python -m pip install gitpython
|
||||
python scripts/update_rules.py -c scripts/rules_config.conf
|
||||
|
||||
cd base
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
set -xe
|
||||
|
||||
git clone https://github.com/curl/curl --depth=1 --branch curl-8_4_0
|
||||
git clone https://github.com/curl/curl --depth=1 --branch curl-8_6_0
|
||||
cd curl
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCURL_USE_LIBSSH2=OFF -DHTTP_ONLY=ON -DCURL_USE_SCHANNEL=ON -DBUILD_SHARED_LIBS=OFF -DBUILD_CURL_EXE=OFF -DCMAKE_INSTALL_PREFIX="$MINGW_PREFIX" -G "Unix Makefiles" -DHAVE_LIBIDN2=OFF -DCURL_USE_LIBPSL=OFF .
|
||||
make install -j4
|
||||
@@ -13,11 +13,16 @@ cmake -DCMAKE_BUILD_TYPE=Release -DYAML_CPP_BUILD_TESTS=OFF -DYAML_CPP_BUILD_TOO
|
||||
make install -j4
|
||||
cd ..
|
||||
|
||||
git clone https://github.com/ftk/quickjspp --depth=1
|
||||
git clone --no-checkout https://github.com/ftk/quickjspp.git
|
||||
cd quickjspp
|
||||
git fetch origin 0c00c48895919fc02da3f191a2da06addeb07f09
|
||||
git checkout 0c00c48895919fc02da3f191a2da06addeb07f09
|
||||
patch quickjs/quickjs-libc.c -i ../scripts/patches/0001-quickjs-libc-add-realpath-for-Windows.patch
|
||||
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release .
|
||||
cmake -G "Unix Makefiles" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_C_FLAGS="-D__MINGW_FENV_DEFINED" .
|
||||
make quickjs -j4
|
||||
|
||||
install -d "$MINGW_PREFIX/lib/quickjs/"
|
||||
install -m644 quickjs/libquickjs.a "$MINGW_PREFIX/lib/quickjs/"
|
||||
install -d "$MINGW_PREFIX/include/quickjs"
|
||||
@@ -38,7 +43,7 @@ cmake -DRAPIDJSON_BUILD_DOC=OFF -DRAPIDJSON_BUILD_EXAMPLES=OFF -DRAPIDJSON_BUILD
|
||||
make install -j4
|
||||
cd ..
|
||||
|
||||
git clone https://github.com/ToruNiina/toml11 --depth=1
|
||||
git clone https://github.com/ToruNiina/toml11 --branch "v4.3.0" --depth=1
|
||||
cd toml11
|
||||
cmake -DCMAKE_INSTALL_PREFIX="$MINGW_PREFIX" -G "Unix Makefiles" -DCMAKE_CXX_STANDARD=11 .
|
||||
make install -j4
|
||||
@@ -53,5 +58,5 @@ cmake -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" .
|
||||
make -j4
|
||||
rm subconverter.exe
|
||||
# shellcheck disable=SC2046
|
||||
g++ $(find CMakeFiles/subconverter.dir/src -name "*.obj") curl/lib/libcurl.a -o base/subconverter.exe -static -lbcrypt -lpcre2-8 -l:quickjs/libquickjs.a -llibcron -lyaml-cpp -liphlpapi -lcrypt32 -lws2_32 -lwsock32 -lz -s
|
||||
g++ $(find CMakeFiles/subconverter.dir/src -name "*.obj") curl/lib/libcurl.a -o base/subconverter.exe -static -Wl,--allow-multiple-definition -lbcrypt -lpcre2-8 -llibcron -lyaml-cpp -liphlpapi -lcrypt32 -lws2_32 -lwsock32 -lz -Lquickjspp/quickjs -lquickjs -s
|
||||
mv base subconverter
|
||||
|
||||
@@ -16,8 +16,10 @@ cd rapidjson
|
||||
cp -r include/* $PREFIX/include/
|
||||
cd ..
|
||||
|
||||
git clone https://github.com/ftk/quickjspp --depth=1
|
||||
git clone --no-checkout https://github.com/ftk/quickjspp.git
|
||||
cd quickjspp
|
||||
git fetch origin 0c00c48895919fc02da3f191a2da06addeb07f09
|
||||
git checkout 0c00c48895919fc02da3f191a2da06addeb07f09
|
||||
cmake -DCMAKE_BUILD_TYPE=Release .
|
||||
make quickjs -j3
|
||||
install -d $PREFIX/lib/quickjs/
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
[ACL4SSR]
|
||||
name=ACL4SSR
|
||||
url=https://github.com/ACL4SSR/ACL4SSR
|
||||
checkout=1dc5c92b0c8ceaaecbc66530c309961f53e52c8c
|
||||
branch=master
|
||||
match=Clash/*.list|Clash/Ruleset/**
|
||||
|
||||
[ACL4SSR_config]
|
||||
name=ACL4SSR
|
||||
url=https://github.com/ACL4SSR/ACL4SSR
|
||||
checkout=1dc5c92b0c8ceaaecbc66530c309961f53e52c8c
|
||||
branch=master
|
||||
match=Clash/config/**
|
||||
dest=base/config/
|
||||
keep_tree=false
|
||||
|
||||
[DivineEngine]
|
||||
url=https://github.com/DivineEngine/Profiles
|
||||
checkout=f4d75f7d48a3f42129e030bef751d4d22bca02da
|
||||
match=Surge/Ruleset/**
|
||||
|
||||
[NobyDa]
|
||||
url=https://github.com/NobyDa/Script
|
||||
checkout=ae4c12f23de8078e02c373c9969b19af28257fcb
|
||||
branch=master
|
||||
match=Surge/*.list
|
||||
|
||||
[lhie1]
|
||||
url=https://github.com/dler-io/Rules
|
||||
branch=main
|
||||
match=Surge/Surge 3/Provider/**
|
||||
|
||||
23
scripts/rules_config_bak.conf
Normal file
23
scripts/rules_config_bak.conf
Normal file
@@ -0,0 +1,23 @@
|
||||
[ACL4SSR]
|
||||
name=ACL4SSR
|
||||
url=https://github.com/ACL4SSR/ACL4SSR
|
||||
checkout=1dc5c92b0c8ceaaecbc66530c309961f53e52c8c
|
||||
match=Clash/*.list|Clash/Ruleset/**
|
||||
|
||||
[ACL4SSR_config]
|
||||
name=ACL4SSR
|
||||
url=https://github.com/ACL4SSR/ACL4SSR
|
||||
checkout=1dc5c92b0c8ceaaecbc66530c309961f53e52c8c
|
||||
match=Clash/config/**
|
||||
dest=base/config/
|
||||
keep_tree=false
|
||||
|
||||
[DivineEngine]
|
||||
url=https://github.com/DivineEngine/Profiles
|
||||
checkout=f4d75f7d48a3f42129e030bef751d4d22bca02da
|
||||
match=Surge/Ruleset/**
|
||||
|
||||
[NobyDa]
|
||||
url=https://github.com/NobyDa/Script
|
||||
checkout=ae4c12f23de8078e02c373c9969b19af28257fcb
|
||||
match=Surge/*.list
|
||||
@@ -22,10 +22,13 @@ def open_repo(path: str):
|
||||
return None
|
||||
|
||||
|
||||
def update_rules(repo_path, save_path, commit, matches, keep_tree):
|
||||
def update_rules(repo_path: str, save_path: str, matches: list[str], keep_tree: bool):
|
||||
os.makedirs(save_path, exist_ok=True)
|
||||
for pattern in matches:
|
||||
files = glob.glob(os.path.join(repo_path, pattern), recursive=True)
|
||||
if len(files) == 0:
|
||||
logging.warn(f"no files found for pattern {pattern}")
|
||||
continue
|
||||
for file in files:
|
||||
if os.path.isdir(file):
|
||||
continue
|
||||
@@ -51,12 +54,13 @@ def main():
|
||||
for section in config.sections():
|
||||
repo = config.get(section, "name", fallback=section)
|
||||
url = config.get(section, "url")
|
||||
commit = config.get(section, "checkout")
|
||||
commit = config.get(section, "commit", fallback=None)
|
||||
branch = config.get(section, "branch", fallback=None)
|
||||
matches = config.get(section, "match").split("|")
|
||||
save_path = config.get(section, "dest", fallback=f"base/rules/{repo}")
|
||||
keep_tree = config.getboolean(section, "keep_tree", fallback=True)
|
||||
|
||||
logging.info(f"reading files from url {url} with commit {commit} and matches {matches}, save to {save_path} keep_tree {keep_tree}")
|
||||
logging.info(f"reading files from url {url}, matches {matches}, save to {save_path} keep_tree {keep_tree}")
|
||||
|
||||
repo_path = os.path.join("./tmp/repo/", repo)
|
||||
|
||||
@@ -67,8 +71,21 @@ def main():
|
||||
else:
|
||||
logging.info(f"repo {repo_path} exists")
|
||||
|
||||
r.git.checkout(commit)
|
||||
update_rules(repo_path, save_path, commit, matches, keep_tree)
|
||||
try:
|
||||
if commit is not None:
|
||||
logging.info(f"checking out to commit {commit}")
|
||||
r.git.checkout(commit)
|
||||
elif branch is not None:
|
||||
logging.info(f"checking out to branch {branch}")
|
||||
r.git.checkout(branch)
|
||||
else:
|
||||
logging.info(f"checking out to default branch")
|
||||
r.active_branch.checkout()
|
||||
except Exception as e:
|
||||
logging.error(f"checkout failed {e}")
|
||||
continue
|
||||
|
||||
update_rules(repo_path, save_path, matches, keep_tree)
|
||||
|
||||
shutil.rmtree("./tmp", ignore_errors=True)
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@ namespace toml
|
||||
static ProxyGroupConfig from_toml(const value& v)
|
||||
{
|
||||
ProxyGroupConfig conf;
|
||||
conf.Name = toml::find<String>(v, "name");
|
||||
String type = toml::find<String>(v, "type");
|
||||
String strategy = toml::find_or<String>(v, "strategy", "");
|
||||
conf.Name = find<String>(v, "name");
|
||||
String type = find<String>(v, "type");
|
||||
String strategy = find_or<String>(v, "strategy", "");
|
||||
switch(hash_(type))
|
||||
{
|
||||
case "select"_hash:
|
||||
@@ -27,18 +27,18 @@ namespace toml
|
||||
break;
|
||||
case "url-test"_hash:
|
||||
conf.Type = ProxyGroupType::URLTest;
|
||||
conf.Url = toml::find<String>(v, "url");
|
||||
conf.Interval = toml::find<Integer>(v, "interval");
|
||||
conf.Tolerance = toml::find_or<Integer>(v, "tolerance", 0);
|
||||
conf.Url = find<String>(v, "url");
|
||||
conf.Interval = find<Integer>(v, "interval");
|
||||
conf.Tolerance = find_or<Integer>(v, "tolerance", 0);
|
||||
if(v.contains("lazy"))
|
||||
conf.Lazy = toml::find_or<bool>(v, "lazy", false);
|
||||
conf.Lazy = find_or<bool>(v, "lazy", false);
|
||||
if(v.contains("evaluate-before-use"))
|
||||
conf.EvaluateBeforeUse = toml::find_or(v, "evaluate-before-use", conf.EvaluateBeforeUse.get());
|
||||
conf.EvaluateBeforeUse = find_or(v, "evaluate-before-use", conf.EvaluateBeforeUse.get());
|
||||
break;
|
||||
case "load-balance"_hash:
|
||||
conf.Type = ProxyGroupType::LoadBalance;
|
||||
conf.Url = toml::find<String>(v, "url");
|
||||
conf.Interval = toml::find<Integer>(v, "interval");
|
||||
conf.Url = find<String>(v, "url");
|
||||
conf.Interval = find<Integer>(v, "interval");
|
||||
switch(hash_(strategy))
|
||||
{
|
||||
case "consistent-hashing"_hash:
|
||||
@@ -49,14 +49,14 @@ namespace toml
|
||||
break;
|
||||
}
|
||||
if(v.contains("persistent"))
|
||||
conf.Persistent = toml::find_or(v, "persistent", conf.Persistent.get());
|
||||
conf.Persistent = find_or(v, "persistent", conf.Persistent.get());
|
||||
break;
|
||||
case "fallback"_hash:
|
||||
conf.Type = ProxyGroupType::Fallback;
|
||||
conf.Url = toml::find<String>(v, "url");
|
||||
conf.Interval = toml::find<Integer>(v, "interval");
|
||||
conf.Url = find<String>(v, "url");
|
||||
conf.Interval = find<Integer>(v, "interval");
|
||||
if(v.contains("evaluate-before-use"))
|
||||
conf.EvaluateBeforeUse = toml::find_or(v, "evaluate-before-use", conf.EvaluateBeforeUse.get());
|
||||
conf.EvaluateBeforeUse = find_or(v, "evaluate-before-use", conf.EvaluateBeforeUse.get());
|
||||
break;
|
||||
case "relay"_hash:
|
||||
conf.Type = ProxyGroupType::Relay;
|
||||
@@ -64,16 +64,26 @@ namespace toml
|
||||
case "ssid"_hash:
|
||||
conf.Type = ProxyGroupType::SSID;
|
||||
break;
|
||||
case "smart"_hash:
|
||||
conf.Type = ProxyGroupType::Smart;
|
||||
conf.Url = find<String>(v, "url");
|
||||
conf.Interval = find<Integer>(v, "interval");
|
||||
conf.Tolerance = find_or<Integer>(v, "tolerance", 0);
|
||||
if(v.contains("lazy"))
|
||||
conf.Lazy = find_or<bool>(v, "lazy", false);
|
||||
if(v.contains("evaluate-before-use"))
|
||||
conf.EvaluateBeforeUse = find_or(v, "evaluate-before-use", conf.EvaluateBeforeUse.get());
|
||||
break;
|
||||
default:
|
||||
throw toml::syntax_error("Proxy Group has incorrect type, should be one of following:\n select, url-test, load-balance, fallback, relay, ssid", v.at("type").location());
|
||||
throw serialization_error(format_error("Proxy Group has unsupported type!", v.at("type").location(), "should be one of following: select, url-test, load-balance, fallback, relay, ssid"), v.at("type").location());
|
||||
}
|
||||
conf.Timeout = toml::find_or(v, "timeout", 5);
|
||||
conf.Proxies = toml::find_or<StrArray>(v, "rule", {});
|
||||
conf.UsingProvider = toml::find_or<StrArray>(v, "use", {});
|
||||
conf.Timeout = find_or(v, "timeout", 5);
|
||||
conf.Proxies = find_or<StrArray>(v, "rule", {});
|
||||
conf.UsingProvider = find_or<StrArray>(v, "use", {});
|
||||
if(conf.Proxies.empty() && conf.UsingProvider.empty())
|
||||
throw toml::syntax_error("Proxy Group must contains at least one of proxy match rule or provider", v.location());
|
||||
throw serialization_error(format_error("Proxy Group must contains at least one of proxy match rule or provider!", v.location(), "here"), v.location());
|
||||
if(v.contains("disable-udp"))
|
||||
conf.DisableUdp = toml::find_or(v, "disable-udp", conf.DisableUdp.get());
|
||||
conf.DisableUdp = find_or(v, "disable-udp", conf.DisableUdp.get());
|
||||
return conf;
|
||||
}
|
||||
};
|
||||
@@ -84,8 +94,8 @@ namespace toml
|
||||
static RulesetConfig from_toml(const value& v)
|
||||
{
|
||||
RulesetConfig conf;
|
||||
conf.Group = toml::find<String>(v, "group");
|
||||
String type = toml::find_or<String>(v, "type", "surge-ruleset");
|
||||
conf.Group = find<String>(v, "group");
|
||||
String type = find_or<String>(v, "type", "surge-ruleset");
|
||||
switch(hash_(type))
|
||||
{
|
||||
/*
|
||||
@@ -122,10 +132,10 @@ namespace toml
|
||||
conf.Url = type + ":";
|
||||
break;
|
||||
default:
|
||||
throw toml::syntax_error("Ruleset has incorrect type, should be one of following:\n surge-ruleset, quantumultx, clash-domain, clash-ipcidr, clash-classic", v.at("type").location());
|
||||
throw serialization_error(format_error("Ruleset has unsupported type!", v.at("type").location(), "should be one of following: surge-ruleset, quantumultx, clash-domain, clash-ipcidr, clash-classic"), v.at("type").location());
|
||||
}
|
||||
conf.Url += toml::find<String>(v, "ruleset");
|
||||
conf.Interval = toml::find_or<Integer>(v, "interval", 86400);
|
||||
conf.Url += find<String>(v, "ruleset");
|
||||
conf.Interval = find_or<Integer>(v, "interval", 86400);
|
||||
return conf;
|
||||
}
|
||||
};
|
||||
@@ -138,14 +148,14 @@ namespace toml
|
||||
RegexMatchConfig conf;
|
||||
if(v.contains("script"))
|
||||
{
|
||||
conf.Script = toml::find<String>(v, "script");
|
||||
conf.Script = find<String>(v, "script");
|
||||
return conf;
|
||||
}
|
||||
conf.Match = toml::find<String>(v, "match");
|
||||
conf.Match = find<String>(v, "match");
|
||||
if(v.contains("emoji"))
|
||||
conf.Replace = toml::find<String>(v, "emoji");
|
||||
conf.Replace = find<String>(v, "emoji");
|
||||
else
|
||||
conf.Replace = toml::find<String>(v, "replace");
|
||||
conf.Replace = find<String>(v, "replace");
|
||||
return conf;
|
||||
}
|
||||
};
|
||||
@@ -156,10 +166,10 @@ namespace toml
|
||||
static CronTaskConfig from_toml(const value& v)
|
||||
{
|
||||
CronTaskConfig conf;
|
||||
conf.Name = toml::find<String>(v, "name");
|
||||
conf.CronExp = toml::find<String>(v, "cronexp");
|
||||
conf.Path = toml::find<String>(v, "path");
|
||||
conf.Timeout = toml::find_or<Integer>(v, "timeout", 0);
|
||||
conf.Name = find<String>(v, "name");
|
||||
conf.CronExp = find<String>(v, "cronexp");
|
||||
conf.Path = find<String>(v, "path");
|
||||
conf.Timeout = find_or<Integer>(v, "timeout", 0);
|
||||
return conf;
|
||||
}
|
||||
};
|
||||
@@ -220,6 +230,9 @@ namespace INIBinding
|
||||
case "ssid"_hash:
|
||||
conf.Type = ProxyGroupType::SSID;
|
||||
break;
|
||||
case "smart"_hash:
|
||||
conf.Type = ProxyGroupType::Smart;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3,17 +3,18 @@
|
||||
|
||||
#include "def.h"
|
||||
|
||||
enum ProxyGroupType
|
||||
enum class ProxyGroupType
|
||||
{
|
||||
Select,
|
||||
URLTest,
|
||||
Fallback,
|
||||
LoadBalance,
|
||||
Relay,
|
||||
SSID
|
||||
SSID,
|
||||
Smart
|
||||
};
|
||||
|
||||
enum BalanceStrategy
|
||||
enum class BalanceStrategy
|
||||
{
|
||||
ConsistentHashing,
|
||||
RoundRobin
|
||||
@@ -45,6 +46,7 @@ struct ProxyGroupConfig
|
||||
case ProxyGroupType::Fallback: return "fallback";
|
||||
case ProxyGroupType::Relay: return "relay";
|
||||
case ProxyGroupType::SSID: return "ssid";
|
||||
case ProxyGroupType::Smart: return "smart";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
#include "def.h"
|
||||
|
||||
enum RulesetType
|
||||
enum class RulesetType
|
||||
{
|
||||
SurgeRuleset,
|
||||
QuantumultX,
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
|
||||
/// rule type lists
|
||||
#define basic_types "DOMAIN", "DOMAIN-SUFFIX", "DOMAIN-KEYWORD", "IP-CIDR", "SRC-IP-CIDR", "GEOIP", "MATCH", "FINAL"
|
||||
string_array ClashRuleTypes = {basic_types, "IP-CIDR6", "SRC-PORT", "DST-PORT", "PROCESS-NAME"};
|
||||
// 新增meta路由规则
|
||||
//string_array ClashRuleTypes = {basic_types, "IP-CIDR6", "SRC-PORT", "DST-PORT", "PROCESS-NAME"};
|
||||
string_array ClashRuleTypes = {basic_types, "IP-CIDR6", "SRC-PORT", "DST-PORT", "PROCESS-NAME", "DOMAIN-REGEX", "GEOSITE", "IP-SUFFIX", "IP-ASN", "SRC-GEOIP", "SRC-IP-ASN", "SRC-IP-SUFFIX", "IN-PORT", "IN-TYPE", "IN-USER", "IN-NAME", "PROCESS-PATH-REGEX", "PROCESS-PATH", "PROCESS-NAME-REGEX", "UID", "NETWORK", "DSCP", "SUB-RULE", "RULE-SET", "AND", "OR", "NOT"};
|
||||
string_array Surge2RuleTypes = {basic_types, "IP-CIDR6", "USER-AGENT", "URL-REGEX", "PROCESS-NAME", "IN-PORT", "DEST-PORT", "SRC-IP"};
|
||||
string_array SurgeRuleTypes = {basic_types, "IP-CIDR6", "USER-AGENT", "URL-REGEX", "AND", "OR", "NOT", "PROCESS-NAME", "IN-PORT", "DEST-PORT", "SRC-IP"};
|
||||
string_array QuanXRuleTypes = {basic_types, "USER-AGENT", "HOST", "HOST-SUFFIX", "HOST-KEYWORD"};
|
||||
@@ -248,8 +250,26 @@ std::string rulesetToClashStr(YAML::Node &base_rule, std::vector<RulesetContent>
|
||||
strLine.erase(strLine.find("//"));
|
||||
strLine = trimWhitespace(strLine);
|
||||
}
|
||||
strLine = transformRuleToCommon(temp, strLine, rule_group);
|
||||
output_content += " - " + strLine + "\n";
|
||||
|
||||
//AND & OR & NOT
|
||||
if(startsWith(strLine, "AND") || startsWith(strLine, "OR") || startsWith(strLine, "NOT"))
|
||||
{
|
||||
output_content += " - " + strLine + "," + rule_group + "\n";
|
||||
}
|
||||
//SUB-RULE & RULE-SET
|
||||
else if (startsWith(strLine, "SUB-RULE") || startsWith(strLine, "RULE-SET"))
|
||||
{
|
||||
output_content += " - " + strLine + "\n";
|
||||
}
|
||||
else
|
||||
//OTHER
|
||||
{
|
||||
strLine = transformRuleToCommon(temp, strLine, rule_group);
|
||||
output_content += " - " + strLine + "\n";
|
||||
}
|
||||
|
||||
//strLine = transformRuleToCommon(temp, strLine, rule_group);
|
||||
//output_content += " - " + strLine + "\n";
|
||||
total_rules++;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,6 +40,7 @@ struct extra_settings
|
||||
bool clash_classical_ruleset = false;
|
||||
std::string sort_script;
|
||||
std::string clash_proxies_style = "flow";
|
||||
std::string clash_proxy_groups_style = "flow";
|
||||
bool authorized = false;
|
||||
|
||||
extra_settings() = default;
|
||||
|
||||
@@ -357,10 +357,10 @@ int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &rulese
|
||||
if(x.rule_type == RULESET_CLASH_IPCIDR || x.rule_type == RULESET_CLASH_DOMAIN || x.rule_type == RULESET_CLASH_CLASSICAL)
|
||||
{
|
||||
//rule_name = std::to_string(hash_(rule_group + rule_path));
|
||||
rule_name = old_rule_name = findFileName(rule_path);
|
||||
rule_name = old_rule_name = urlDecode(findFileName(rule_path));
|
||||
int idx = 2;
|
||||
while(std::find(groups.begin(), groups.end(), rule_name) != groups.end())
|
||||
rule_name = old_rule_name + "_" + std::to_string(idx++);
|
||||
rule_name = old_rule_name + " " + std::to_string(idx++);
|
||||
names[rule_name] = rule_group;
|
||||
urls[rule_name] = "*" + rule_path;
|
||||
rule_type[rule_name] = x.rule_type;
|
||||
@@ -386,10 +386,10 @@ int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &rulese
|
||||
if(fileExist(rule_path, true) || isLink(rule_path))
|
||||
{
|
||||
//rule_name = std::to_string(hash_(rule_group + rule_path));
|
||||
rule_name = old_rule_name = findFileName(rule_path);
|
||||
rule_name = old_rule_name = urlDecode(findFileName(rule_path));
|
||||
int idx = 2;
|
||||
while(std::find(groups.begin(), groups.end(), rule_name) != groups.end())
|
||||
rule_name = old_rule_name + "_" + std::to_string(idx++);
|
||||
rule_name = old_rule_name + " " + std::to_string(idx++);
|
||||
names[rule_name] = rule_group;
|
||||
urls[rule_name] = rule_path_typed;
|
||||
rule_type[rule_name] = x.rule_type;
|
||||
@@ -436,9 +436,9 @@ int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &rulese
|
||||
if(vArray.size() < 2)
|
||||
continue;
|
||||
if(keywords.find(rule_name) == keywords.end())
|
||||
keywords[rule_name] = "\"" + vArray[1] + "\"";
|
||||
keywords[rule_name] = "\"" + trim(vArray[1]) + "\"";
|
||||
else
|
||||
keywords[rule_name] += ",\"" + vArray[1] + "\"";
|
||||
keywords[rule_name] += ",\"" + trim(vArray[1]) + "\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -449,7 +449,7 @@ int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &rulese
|
||||
}
|
||||
else
|
||||
{
|
||||
strLine = vArray[0] + "," + vArray[1] + "," + rule_group;
|
||||
strLine = vArray[0] + "," + trim(vArray[1]) + "," + rule_group;
|
||||
if(vArray.size() > 2)
|
||||
strLine += "," + vArray[2];
|
||||
}
|
||||
@@ -466,14 +466,16 @@ int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &rulese
|
||||
}
|
||||
}
|
||||
if(has_domain[rule_name] && !script)
|
||||
rules.emplace_back("RULE-SET," + rule_name + "_domain," + rule_group);
|
||||
rules.emplace_back("RULE-SET," + rule_name + " (Domain)," + rule_group);
|
||||
if(has_ipcidr[rule_name] && !script)
|
||||
{
|
||||
if(has_no_resolve)
|
||||
rules.emplace_back("RULE-SET," + rule_name + "_ipcidr," + rule_group + ",no-resolve");
|
||||
rules.emplace_back("RULE-SET," + rule_name + " (IP-CIDR)," + rule_group + ",no-resolve");
|
||||
else
|
||||
rules.emplace_back("RULE-SET," + rule_name + "_ipcidr," + rule_group);
|
||||
rules.emplace_back("RULE-SET," + rule_name + " (IP-CIDR)," + rule_group);
|
||||
}
|
||||
if(!has_domain[rule_name] && !has_ipcidr[rule_name] && !script)
|
||||
rules.emplace_back("RULE-SET," + rule_name + "," + rule_group);
|
||||
if(std::find(groups.begin(), groups.end(), rule_name) == groups.end())
|
||||
groups.emplace_back(rule_name);
|
||||
}
|
||||
@@ -488,14 +490,14 @@ int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &rulese
|
||||
{
|
||||
std::string yaml_key = x;
|
||||
if(rule_type[x] != RULESET_CLASH_DOMAIN)
|
||||
yaml_key += "_domain";
|
||||
yaml_key += " (Domain)";
|
||||
base_rule["rule-providers"][yaml_key]["type"] = "http";
|
||||
base_rule["rule-providers"][yaml_key]["behavior"] = "domain";
|
||||
if(url[0] == '*')
|
||||
base_rule["rule-providers"][yaml_key]["url"] = url.substr(1);
|
||||
else
|
||||
base_rule["rule-providers"][yaml_key]["url"] = remote_path_prefix + "/getruleset?type=3&url=" + urlSafeBase64Encode(url);
|
||||
base_rule["rule-providers"][yaml_key]["path"] = "./providers/rule-provider_" + yaml_key + ".yaml";
|
||||
base_rule["rule-providers"][yaml_key]["path"] = "./providers/" + std::to_string(hash_(url)) + "_domain.yaml";
|
||||
if(interval)
|
||||
base_rule["rule-providers"][yaml_key]["interval"] = interval;
|
||||
}
|
||||
@@ -503,14 +505,14 @@ int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &rulese
|
||||
{
|
||||
std::string yaml_key = x;
|
||||
if(rule_type[x] != RULESET_CLASH_IPCIDR)
|
||||
yaml_key += "_ipcidr";
|
||||
yaml_key += " (IP-CIDR)";
|
||||
base_rule["rule-providers"][yaml_key]["type"] = "http";
|
||||
base_rule["rule-providers"][yaml_key]["behavior"] = "ipcidr";
|
||||
if(url[0] == '*')
|
||||
base_rule["rule-providers"][yaml_key]["url"] = url.substr(1);
|
||||
else
|
||||
base_rule["rule-providers"][yaml_key]["url"] = remote_path_prefix + "/getruleset?type=4&url=" + urlSafeBase64Encode(url);
|
||||
base_rule["rule-providers"][yaml_key]["path"] = "./providers/rule-provider_" + yaml_key + ".yaml";
|
||||
base_rule["rule-providers"][yaml_key]["path"] = "./providers/" + std::to_string(hash_(url)) + "_ipcidr.yaml";
|
||||
if(interval)
|
||||
base_rule["rule-providers"][yaml_key]["interval"] = interval;
|
||||
}
|
||||
@@ -523,7 +525,7 @@ int renderClashScript(YAML::Node &base_rule, std::vector<RulesetContent> &rulese
|
||||
base_rule["rule-providers"][yaml_key]["url"] = url.substr(1);
|
||||
else
|
||||
base_rule["rule-providers"][yaml_key]["url"] = remote_path_prefix + "/getruleset?type=6&url=" + urlSafeBase64Encode(url);
|
||||
base_rule["rule-providers"][yaml_key]["path"] = "./providers/rule-provider_" + yaml_key + ".yaml";
|
||||
base_rule["rule-providers"][yaml_key]["path"] = "./providers/" + std::to_string(hash_(url)) + ".yaml";
|
||||
if(interval)
|
||||
base_rule["rule-providers"][yaml_key]["interval"] = interval;
|
||||
}
|
||||
|
||||
@@ -58,31 +58,33 @@ struct UAProfile {
|
||||
};
|
||||
|
||||
const std::vector<UAProfile> UAMatchList = {
|
||||
{"ClashForAndroid", "\\/([0-9.]+)", "2.0", "clash", true},
|
||||
{"ClashForAndroid", "\\/([0-9.]+)R", "", "clashr", false},
|
||||
{"ClashForAndroid", "", "", "clash", false},
|
||||
{"ClashforWindows", "\\/([0-9.]+)", "0.11", "clash", true},
|
||||
{"ClashforWindows", "", "", "clash", false},
|
||||
{"ClashX Pro", "", "", "clash", true},
|
||||
{"ClashX", "\\/([0-9.]+)", "0.13", "clash", true},
|
||||
{"Clash", "", "", "clash", true},
|
||||
{"Kitsunebi", "", "", "v2ray"},
|
||||
{"Loon", "", "", "loon"},
|
||||
{"Pharos", "", "", "mixed"},
|
||||
{"Potatso", "", "", "mixed"},
|
||||
{"Quantumult%20X", "", "", "quanx"},
|
||||
{"Quantumult", "", "", "quan"},
|
||||
{"Qv2ray", "", "", "v2ray"},
|
||||
{"Shadowrocket", "", "", "mixed"},
|
||||
{"Surfboard", "", "", "surfboard"},
|
||||
{"Surge", "\\/([0-9.]+).*x86", "906", "surge", false, 4}, /// Surge for Mac (supports VMess)
|
||||
{"Surge", "\\/([0-9.]+).*x86", "368", "surge", false, 3}, /// Surge for Mac (supports new rule types and Shadowsocks without plugin)
|
||||
{"Surge", "\\/([0-9.]+)", "1419", "surge", false, 4}, /// Surge iOS 4 (first version)
|
||||
{"Surge", "\\/([0-9.]+)", "900", "surge", false, 3}, /// Surge iOS 3 (approx)
|
||||
{"Surge", "", "", "surge", false, 2}, /// any version of Surge as fallback
|
||||
{"Trojan-Qt5", "", "", "trojan"},
|
||||
{"V2rayU", "", "", "v2ray"},
|
||||
{"V2RayX", "", "", "v2ray"}
|
||||
{"ClashForAndroid", "\\/([0-9.]+)", "2.0", "clash", true},
|
||||
{"ClashForAndroid", "\\/([0-9.]+)R", "", "clashr", false},
|
||||
{"ClashForAndroid", "", "", "clash", false},
|
||||
{"ClashforWindows", "\\/([0-9.]+)", "0.11", "clash", true},
|
||||
{"ClashforWindows", "", "", "clash", false},
|
||||
{"clash-verge", "", "", "clash", true},
|
||||
{"ClashX Pro", "", "", "clash", true},
|
||||
{"ClashX", "\\/([0-9.]+)", "0.13", "clash", true},
|
||||
{"Clash", "", "", "clash", true},
|
||||
{"Kitsunebi", "", "", "v2ray"},
|
||||
{"Loon", "", "", "loon"},
|
||||
{"Pharos", "", "", "mixed"},
|
||||
{"Potatso", "", "", "mixed"},
|
||||
{"Quantumult%20X", "", "", "quanx"},
|
||||
{"Quantumult", "", "", "quan"},
|
||||
{"Qv2ray", "", "", "v2ray"},
|
||||
{"Shadowrocket", "", "", "mixed"},
|
||||
{"Surfboard", "", "", "surfboard"},
|
||||
{"Surge", "\\/([0-9.]+).*x86", "906", "surge", false, 4}, /// Surge for Mac (supports VMess)
|
||||
{"Surge", "\\/([0-9.]+).*x86", "368", "surge", false, 3},
|
||||
/// Surge for Mac (supports new rule types and Shadowsocks without plugin)
|
||||
{"Surge", "\\/([0-9.]+)", "1419", "surge", false, 4}, /// Surge iOS 4 (first version)
|
||||
{"Surge", "\\/([0-9.]+)", "900", "surge", false, 3}, /// Surge iOS 3 (approx)
|
||||
{"Surge", "", "", "surge", false, 2}, /// any version of Surge as fallback
|
||||
{"Trojan-Qt5", "", "", "trojan"},
|
||||
{"V2rayU", "", "", "v2ray"},
|
||||
{"V2RayX", "", "", "v2ray"}
|
||||
};
|
||||
|
||||
bool verGreaterEqual(const std::string &src_ver, const std::string &target_ver) {
|
||||
@@ -134,8 +136,8 @@ std::string getRuleset(RESPONSE_CALLBACK_ARGS) {
|
||||
int *status_code = &response.status_code;
|
||||
/// type: 1 for Surge, 2 for Quantumult X, 3 for Clash domain rule-provider, 4 for Clash ipcidr rule-provider, 5 for Surge DOMAIN-SET, 6 for Clash classical ruleset
|
||||
std::string url = urlSafeBase64Decode(getUrlArg(argument, "url")), type = getUrlArg(argument,
|
||||
"type"), group = urlSafeBase64Decode(
|
||||
getUrlArg(argument, "group"));
|
||||
"type"), group = urlSafeBase64Decode(
|
||||
getUrlArg(argument, "group"));
|
||||
std::string output_content, dummy;
|
||||
int type_int = to_int(type, 0);
|
||||
|
||||
@@ -332,26 +334,26 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) {
|
||||
std::string argGroupName = getUrlArg(argument, "group"), argUploadPath = getUrlArg(argument, "upload_path");
|
||||
std::string argIncludeRemark = getUrlArg(argument, "include"), argExcludeRemark = getUrlArg(argument, "exclude");
|
||||
std::string argCustomGroups = urlSafeBase64Decode(
|
||||
getUrlArg(argument, "groups")), argCustomRulesets = urlSafeBase64Decode(
|
||||
getUrlArg(argument, "ruleset")), argExternalConfig = getUrlArg(argument, "config");
|
||||
getUrlArg(argument, "groups")), argCustomRulesets = urlSafeBase64Decode(
|
||||
getUrlArg(argument, "ruleset")), argExternalConfig = getUrlArg(argument, "config");
|
||||
std::string argDeviceID = getUrlArg(argument, "dev_id"), argFilename = getUrlArg(argument,
|
||||
"filename"), argUpdateInterval = getUrlArg(
|
||||
argument, "interval"), argUpdateStrict = getUrlArg(argument, "strict");
|
||||
"filename"), argUpdateInterval = getUrlArg(
|
||||
argument, "interval"), argUpdateStrict = getUrlArg(argument, "strict");
|
||||
std::string argRenames = getUrlArg(argument, "rename"), argFilterScript = getUrlArg(argument, "filter_script");
|
||||
|
||||
/// switches with default value
|
||||
tribool argUpload = getUrlArg(argument, "upload"), argEmoji = getUrlArg(argument, "emoji"), argAddEmoji = getUrlArg(
|
||||
argument, "add_emoji"), argRemoveEmoji = getUrlArg(argument, "remove_emoji");
|
||||
argument, "add_emoji"), argRemoveEmoji = getUrlArg(argument, "remove_emoji");
|
||||
tribool argAppendType = getUrlArg(argument, "append_type"), argTFO = getUrlArg(argument, "tfo"), argUDP = getUrlArg(
|
||||
argument, "udp"), argGenNodeList = getUrlArg(argument, "list");
|
||||
argument, "udp"), argGenNodeList = getUrlArg(argument, "list");
|
||||
tribool argSort = getUrlArg(argument, "sort"), argUseSortScript = getUrlArg(argument, "sort_script");
|
||||
tribool argGenClashScript = getUrlArg(argument, "script"), argEnableInsert = getUrlArg(argument, "insert");
|
||||
tribool argSkipCertVerify = getUrlArg(argument, "scv"), argFilterDeprecated = getUrlArg(argument,
|
||||
"fdn"), argExpandRulesets = getUrlArg(
|
||||
argument, "expand"), argAppendUserinfo = getUrlArg(argument, "append_info");
|
||||
"fdn"), argExpandRulesets = getUrlArg(
|
||||
argument, "expand"), argAppendUserinfo = getUrlArg(argument, "append_info");
|
||||
tribool argPrependInsert = getUrlArg(argument, "prepend"), argGenClassicalRuleProvider = getUrlArg(argument,
|
||||
"classic"), argTLS13 = getUrlArg(
|
||||
argument, "tls13");
|
||||
"classic"), argTLS13 = getUrlArg(
|
||||
argument, "tls13");
|
||||
|
||||
std::string base_content, output_content;
|
||||
ProxyGroupConfigs lCustomProxyGroups = global.customProxyGroups;
|
||||
@@ -360,20 +362,23 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) {
|
||||
std::vector<RulesetContent> lRulesetContent;
|
||||
extra_settings ext;
|
||||
std::string subInfo, dummy;
|
||||
int interval = !argUpdateInterval.empty() ? to_int(argUpdateInterval, global.updateInterval)
|
||||
: global.updateInterval;
|
||||
int interval = !argUpdateInterval.empty()
|
||||
? to_int(argUpdateInterval, global.updateInterval)
|
||||
: global.updateInterval;
|
||||
bool authorized =
|
||||
!global.APIMode || getUrlArg(argument, "token") == global.accessToken, strict = !argUpdateStrict.empty() ?
|
||||
argUpdateStrict == "true"
|
||||
: global.updateStrict;
|
||||
!global.APIMode || getUrlArg(argument, "token") == global.accessToken, strict = !argUpdateStrict.empty()
|
||||
? argUpdateStrict == "true"
|
||||
: global.updateStrict;
|
||||
|
||||
if (std::find(gRegexBlacklist.cbegin(), gRegexBlacklist.cend(), argIncludeRemark) != gRegexBlacklist.cend() ||
|
||||
std::find(gRegexBlacklist.cbegin(), gRegexBlacklist.cend(), argExcludeRemark) != gRegexBlacklist.cend())
|
||||
return "Invalid request!";
|
||||
|
||||
/// for external configuration
|
||||
std::string lClashBase = global.clashBase, lSurgeBase = global.surgeBase, lMellowBase = global.mellowBase, lSurfboardBase = global.surfboardBase;
|
||||
std::string lQuanBase = global.quanBase, lQuanXBase = global.quanXBase, lLoonBase = global.loonBase, lSSSubBase = global.SSSubBase;
|
||||
std::string lClashBase = global.clashBase, lSurgeBase = global.surgeBase, lMellowBase = global.mellowBase,
|
||||
lSurfboardBase = global.surfboardBase;
|
||||
std::string lQuanBase = global.quanBase, lQuanXBase = global.quanXBase, lLoonBase = global.loonBase, lSSSubBase =
|
||||
global.SSSubBase;
|
||||
std::string lSingBoxBase = global.singBoxBase;
|
||||
|
||||
/// validate urls
|
||||
@@ -386,20 +391,20 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) {
|
||||
}
|
||||
|
||||
/// load request arguments as template variables
|
||||
// string_array req_args = split(argument, "&");
|
||||
// string_map req_arg_map;
|
||||
// for(std::string &x : req_args)
|
||||
// {
|
||||
// string_size pos = x.find("=");
|
||||
// if(pos == x.npos)
|
||||
// {
|
||||
// req_arg_map[x] = "";
|
||||
// continue;
|
||||
// }
|
||||
// if(x.substr(0, pos) == "token")
|
||||
// continue;
|
||||
// req_arg_map[x.substr(0, pos)] = x.substr(pos + 1);
|
||||
// }
|
||||
// string_array req_args = split(argument, "&");
|
||||
// string_map req_arg_map;
|
||||
// for(std::string &x : req_args)
|
||||
// {
|
||||
// string_size pos = x.find("=");
|
||||
// if(pos == x.npos)
|
||||
// {
|
||||
// req_arg_map[x] = "";
|
||||
// continue;
|
||||
// }
|
||||
// if(x.substr(0, pos) == "token")
|
||||
// continue;
|
||||
// req_arg_map[x.substr(0, pos)] = x.substr(pos + 1);
|
||||
// }
|
||||
string_map req_arg_map;
|
||||
for (auto &x: argument) {
|
||||
if (x.first == "token")
|
||||
@@ -424,6 +429,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) {
|
||||
argExpandRulesets.define(true);
|
||||
|
||||
ext.clash_proxies_style = global.clashProxiesStyle;
|
||||
ext.clash_proxy_groups_style = global.clashProxyGroupsStyle;
|
||||
|
||||
/// read preference from argument, assign global var if not in argument
|
||||
ext.tfo.define(argTFO).define(global.TFOFlag);
|
||||
@@ -652,8 +658,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) {
|
||||
ctx.eval(filterScript);
|
||||
auto filter = (std::function<bool(const Proxy &)>) ctx.eval("filter");
|
||||
nodes.erase(std::remove_if(nodes.begin(), nodes.end(), filter), nodes.end());
|
||||
}
|
||||
catch (qjs::exception) {
|
||||
} catch (qjs::exception) {
|
||||
script_print_stack(ctx);
|
||||
}
|
||||
}, global.scriptCleanContext);
|
||||
@@ -686,7 +691,7 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) {
|
||||
std::string managed_url = base64Decode(getUrlArg(argument, "profile_data"));
|
||||
if (managed_url.empty())
|
||||
managed_url = global.managedConfigPrefix + "/sub?" + joinArguments(argument);
|
||||
size_t found;
|
||||
|
||||
//std::cerr<<"Generate target: ";
|
||||
proxy = parseProxy(global.proxyConfig);
|
||||
switch (hash_(argTarget)) {
|
||||
@@ -734,9 +739,10 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) {
|
||||
uploadGist("surge" + argSurgeVer, argUploadPath, output_content, true);
|
||||
|
||||
if (global.writeManagedConfig && !global.managedConfigPrefix.empty())
|
||||
output_content = "#!MANAGED-CONFIG " + managed_url +
|
||||
(interval ? " interval=" + std::to_string(interval) : "") \
|
||||
+ " strict=" + std::string(strict ? "true" : "false") + "\n\n" + output_content;
|
||||
output_content = "#!MANAGED-CONFIG " + managed_url + (interval
|
||||
? " interval=" + std::to_string(interval)
|
||||
: "")
|
||||
+ " strict=" + std::string(strict ? "true" : "false") + "\n\n" + output_content;
|
||||
}
|
||||
break;
|
||||
case "surfboard"_hash:
|
||||
@@ -752,9 +758,10 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) {
|
||||
uploadGist("surfboard", argUploadPath, output_content, true);
|
||||
|
||||
if (global.writeManagedConfig && !global.managedConfigPrefix.empty())
|
||||
output_content =
|
||||
"#!MANAGED-CONFIG " + managed_url + (interval ? " interval=" + std::to_string(interval) : "") \
|
||||
+ " strict=" + std::string(strict ? "true" : "false") + "\n\n" + output_content;
|
||||
output_content = "#!MANAGED-CONFIG " + managed_url + (interval
|
||||
? " interval=" + std::to_string(interval)
|
||||
: "")
|
||||
+ " strict=" + std::string(strict ? "true" : "false") + "\n\n" + output_content;
|
||||
break;
|
||||
case "mellow"_hash:
|
||||
writeLog(0, "Generate target: Mellow", LOG_LEVEL_INFO);
|
||||
@@ -805,9 +812,21 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) {
|
||||
if (argUpload)
|
||||
uploadGist("trojan", argUploadPath, output_content, false);
|
||||
break;
|
||||
case "vless"_hash:
|
||||
writeLog(0, "Generate target: vless", LOG_LEVEL_INFO);
|
||||
output_content = proxyToSingle(nodes, 16, ext);
|
||||
if (argUpload)
|
||||
uploadGist("vless", argUploadPath, output_content, false);
|
||||
break;
|
||||
case "hysteria2"_hash:
|
||||
writeLog(0, "Generate target: hysteria2", LOG_LEVEL_INFO);
|
||||
output_content = proxyToSingle(nodes, 32, ext);
|
||||
if (argUpload)
|
||||
uploadGist("hysteria2", argUploadPath, output_content, false);
|
||||
break;
|
||||
case "mixed"_hash:
|
||||
writeLog(0, "Generate target: Standard Subscription", LOG_LEVEL_INFO);
|
||||
output_content = proxyToSingle(nodes, 15, ext);
|
||||
output_content = proxyToSingle(nodes, 63, ext);
|
||||
if (argUpload)
|
||||
uploadGist("sub", argUploadPath, output_content, false);
|
||||
break;
|
||||
@@ -873,11 +892,6 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) {
|
||||
}
|
||||
|
||||
output_content = proxyToSingBox(nodes, base_content, lRulesetContent, lCustomProxyGroups, ext);
|
||||
found = output_content.find('\u0000');
|
||||
while (found != std::string::npos) {
|
||||
output_content.erase(found, 1);
|
||||
found = output_content.find('\u0000', found);
|
||||
}
|
||||
|
||||
if (argUpload)
|
||||
uploadGist("singbox", argUploadPath, output_content, false);
|
||||
@@ -890,12 +904,11 @@ std::string subconverter(RESPONSE_CALLBACK_ARGS) {
|
||||
writeLog(0, "Generate completed.", LOG_LEVEL_INFO);
|
||||
if (!argFilename.empty())
|
||||
response.headers.emplace("Content-Disposition",
|
||||
"attachment; filename=\"" + argFilename + "\"; filename*=utf-8''" +
|
||||
urlEncode(argFilename));
|
||||
"attachment; filename=\"" + argFilename + "\"; filename*=utf-8''" + urlEncode(
|
||||
argFilename));
|
||||
return output_content;
|
||||
}
|
||||
|
||||
|
||||
std::string simpleToClashR(RESPONSE_CALLBACK_ARGS) {
|
||||
auto argument = joinArguments(request.argument);
|
||||
int *status_code = &response.status_code;
|
||||
@@ -922,9 +935,8 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS) {
|
||||
string_array dummy_str_array;
|
||||
std::vector<Proxy> nodes;
|
||||
std::string base_content, url = argument.size() <= 5 ? "" : argument.substr(5);
|
||||
const std::string proxygroup_name = global.clashUseNewField ? "proxy-groups"
|
||||
: "Proxy Group", rule_name = global.clashUseNewField
|
||||
? "rules" : "Rule";
|
||||
const std::string proxygroup_name = global.clashUseNewField ? "proxy-groups" : "Proxy Group", rule_name =
|
||||
global.clashUseNewField ? "rules" : "Rule";
|
||||
|
||||
ini.store_any_line = true;
|
||||
|
||||
@@ -987,8 +999,8 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS) {
|
||||
if (dummy_str_array.empty())
|
||||
continue;
|
||||
type = dummy_str_array[0];
|
||||
if (!(type == "select" || type == "url-test" || type == "fallback" ||
|
||||
type == "load-balance")) //remove unsupported types
|
||||
if (!(type == "select" || type == "url-test" || type == "fallback" || type == "load-balance"))
|
||||
//remove unsupported types
|
||||
continue;
|
||||
singlegroup["name"] = name;
|
||||
singlegroup["type"] = type;
|
||||
@@ -1100,8 +1112,8 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS) {
|
||||
lineSize = strLine.size();
|
||||
if (lineSize && strLine[lineSize - 1] == '\r') //remove line break
|
||||
strLine.erase(--lineSize);
|
||||
if (!lineSize || strLine[0] == ';' || strLine[0] == '#' ||
|
||||
(lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/')) //empty lines and comments are ignored
|
||||
if (!lineSize || strLine[0] == ';' || strLine[0] == '#' || (
|
||||
lineSize >= 2 && strLine[0] == '/' && strLine[1] == '/')) //empty lines and comments are ignored
|
||||
continue;
|
||||
else if (!std::any_of(ClashRuleTypes.begin(), ClashRuleTypes.end(),
|
||||
[&strLine](const std::string &type) {
|
||||
@@ -1115,8 +1127,9 @@ std::string surgeConfToClash(RESPONSE_CALLBACK_ARGS) {
|
||||
}
|
||||
ss.clear();
|
||||
continue;
|
||||
} else if (!std::any_of(ClashRuleTypes.begin(), ClashRuleTypes.end(),
|
||||
[&strLine](const std::string &type) { return startsWith(strLine, type); }))
|
||||
} else if (!std::any_of(ClashRuleTypes.begin(), ClashRuleTypes.end(), [&strLine](const std::string &type) {
|
||||
return startsWith(strLine, type);
|
||||
}))
|
||||
continue;
|
||||
rule.push_back(x);
|
||||
}
|
||||
@@ -1244,8 +1257,8 @@ std::string subInfoToMessage(std::string subinfo) {
|
||||
using ull = unsigned long long;
|
||||
subinfo = replaceAllDistinct(subinfo, "; ", "&");
|
||||
std::string retdata, useddata = "N/A", totaldata = "N/A", expirydata = "N/A";
|
||||
std::string upload = getUrlArg(subinfo, "upload"), download = getUrlArg(subinfo, "download"), total = getUrlArg(
|
||||
subinfo, "total"), expire = getUrlArg(subinfo, "expire");
|
||||
std::string upload = getUrlArg(subinfo, "upload"), download = getUrlArg(subinfo, "download"), total =
|
||||
getUrlArg(subinfo, "total"), expire = getUrlArg(subinfo, "expire");
|
||||
ull used = to_number<ull>(upload, 0) + to_number<ull>(download, 0), tot = to_number<ull>(total, 0);
|
||||
auto expiry = to_number<time_t>(expire, 0);
|
||||
if (used != 0)
|
||||
@@ -1302,7 +1315,7 @@ int simpleGenerator() {
|
||||
sections = new_targets;
|
||||
sections.shrink_to_fit();
|
||||
} else
|
||||
//std::cerr<<"Generating all artifacts...\n";
|
||||
//std::cerr<<"Generating all artifacts...\n";
|
||||
writeLog(0, "Generating all artifacts...", LOG_LEVEL_INFO);
|
||||
|
||||
string_multimap allItems;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <toml.hpp>
|
||||
|
||||
#include "config/binding.h"
|
||||
#include "handler/webget.h"
|
||||
@@ -566,13 +565,13 @@ void readYAMLConf(YAML::Node &node)
|
||||
}
|
||||
|
||||
template <class T, class... U>
|
||||
void find_if_exist(const toml::value &v, const toml::key &k, T& target, U&&... args)
|
||||
void find_if_exist(const toml::value &v, const toml::value::key_type &k, T& target, U&&... args)
|
||||
{
|
||||
if(v.contains(k)) target = toml::find<T>(v, k);
|
||||
if constexpr (sizeof...(args) > 0) find_if_exist(v, std::forward<U>(args)...);
|
||||
}
|
||||
|
||||
void operate_toml_kv_table(const std::vector<toml::table> &arr, const toml::key &key_name, const toml::key &value_name, std::function<void (const toml::value&, const toml::value&)> binary_op)
|
||||
void operate_toml_kv_table(const std::vector<toml::table> &arr, const toml::value::key_type &key_name, const toml::value::key_type &value_name, std::function<void (const toml::value&, const toml::value&)> binary_op)
|
||||
{
|
||||
for(const toml::table &table : arr)
|
||||
{
|
||||
@@ -801,7 +800,7 @@ void readConf()
|
||||
return readYAMLConf(yaml);
|
||||
}
|
||||
toml::value conf = parseToml(prefdata, global.prefPath);
|
||||
if(!conf.is_uninitialized() && toml::find_or<int>(conf, "version", 0))
|
||||
if(!conf.is_empty() && toml::find_or<int>(conf, "version", 0))
|
||||
return readTOMLConf(conf);
|
||||
}
|
||||
catch (YAML::Exception &e)
|
||||
@@ -1210,7 +1209,7 @@ int loadExternalConfig(std::string &path, ExternalConfig &ext)
|
||||
if(yaml.size() && yaml["custom"].IsDefined())
|
||||
return loadExternalYAML(yaml, ext);
|
||||
toml::value conf = parseToml(base_content, path);
|
||||
if(!conf.is_uninitialized() && toml::find_or<int>(conf, "version", 0))
|
||||
if(!conf.is_empty() && toml::find_or<int>(conf, "version", 0))
|
||||
return loadExternalTOML(conf, ext);
|
||||
}
|
||||
catch (YAML::Exception &e)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "utils/string.h"
|
||||
#include "utils/stl_extra.h"
|
||||
#include "utils/tribool.h"
|
||||
#include <toml.hpp>
|
||||
|
||||
struct Settings
|
||||
{
|
||||
@@ -48,7 +49,7 @@ struct Settings
|
||||
tribool UDPFlag, TFOFlag, skipCertVerify, TLS13Flag, enableInsert;
|
||||
bool enableSort = false, updateStrict = false;
|
||||
bool clashUseNewField = false, singBoxAddClashModes = true;
|
||||
std::string clashProxiesStyle = "flow";
|
||||
std::string clashProxiesStyle = "flow", clashProxyGroupsStyle = "block";
|
||||
std::string proxyConfig, proxyRuleset, proxySubscription;
|
||||
int updateInterval = 0;
|
||||
std::string sortScript, filterScript;
|
||||
@@ -100,7 +101,12 @@ extern Settings global;
|
||||
|
||||
int importItems(string_array &target, bool scope_limit = true);
|
||||
int loadExternalConfig(std::string &path, ExternalConfig &ext);
|
||||
|
||||
//template <class T, class... U>
|
||||
//void find_if_exist(const toml::value &v, const toml::key &k, T& target, U&&... args)
|
||||
//{
|
||||
// if(v.contains(k)) target = toml::find<T>(v, k);
|
||||
// if constexpr (sizeof...(args) > 0) find_if_exist(v, std::forward<U>(args)...);
|
||||
//}
|
||||
template <class... Args>
|
||||
void parseGroupTimes(const std::string &src, Args... args)
|
||||
{
|
||||
|
||||
@@ -87,11 +87,13 @@ static int logger(CURL *handle, curl_infotype type, char *data, size_t size, voi
|
||||
switch(type)
|
||||
{
|
||||
case CURLINFO_TEXT:
|
||||
prefix = "CURL_INFO";
|
||||
prefix = "CURL_INFO: ";
|
||||
break;
|
||||
case CURLINFO_HEADER_IN:
|
||||
prefix = "CURL_HEADER: < ";
|
||||
break;
|
||||
case CURLINFO_HEADER_OUT:
|
||||
prefix = "CURL_HEADER";
|
||||
prefix = "CURL_HEADER: > ";
|
||||
break;
|
||||
case CURLINFO_DATA_IN:
|
||||
case CURLINFO_DATA_OUT:
|
||||
@@ -105,7 +107,6 @@ static int logger(CURL *handle, curl_infotype type, char *data, size_t size, voi
|
||||
for(auto &x : lines)
|
||||
{
|
||||
std::string log_content = prefix;
|
||||
log_content += ": ";
|
||||
log_content += x;
|
||||
writeLog(0, log_content, LOG_LEVEL_VERBOSE);
|
||||
}
|
||||
@@ -113,7 +114,6 @@ static int logger(CURL *handle, curl_infotype type, char *data, size_t size, voi
|
||||
else
|
||||
{
|
||||
std::string log_content = prefix;
|
||||
log_content += ": ";
|
||||
log_content += trimWhitespace(content);
|
||||
writeLog(0, log_content, LOG_LEVEL_VERBOSE);
|
||||
}
|
||||
@@ -172,7 +172,8 @@ static int curlGet(const FetchArgument &argument, FetchResult &result)
|
||||
{
|
||||
for(auto &x : *argument.request_headers)
|
||||
{
|
||||
header_list = curl_slist_append(header_list, (x.first + ": " + x.second).data());
|
||||
auto header = x.first + ": " + x.second;
|
||||
header_list = curl_slist_append(header_list, header.data());
|
||||
}
|
||||
if(!argument.request_headers->contains("User-Agent"))
|
||||
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, user_agent_str);
|
||||
@@ -233,7 +234,7 @@ static int curlGet(const FetchArgument &argument, FetchResult &result)
|
||||
while(true)
|
||||
{
|
||||
retVal = curl_easy_perform(curl_handle);
|
||||
if(retVal == CURLE_OK || max_fails <= fail_count)
|
||||
if(retVal == CURLE_OK || max_fails <= fail_count || global.APIMode)
|
||||
break;
|
||||
else
|
||||
fail_count++;
|
||||
|
||||
@@ -233,10 +233,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
std::string type = getUrlArg(request.argument, "type");
|
||||
if(type == "form")
|
||||
fileWrite(global.prefPath, getFormData(request.postdata), true);
|
||||
else if(type == "direct")
|
||||
if(type == "form" || type == "direct")
|
||||
{
|
||||
fileWrite(global.prefPath, request.postdata, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
response.status_code = 501;
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
using String = std::string;
|
||||
using StringArray = std::vector<String>;
|
||||
|
||||
enum class ProxyType {
|
||||
enum class ProxyType
|
||||
{
|
||||
Unknown,
|
||||
Shadowsocks,
|
||||
ShadowsocksR,
|
||||
@@ -22,7 +23,10 @@ enum class ProxyType {
|
||||
WireGuard,
|
||||
VLESS,
|
||||
Hysteria,
|
||||
Hysteria2
|
||||
Hysteria2,
|
||||
TUIC,
|
||||
AnyTLS,
|
||||
Mieru
|
||||
};
|
||||
|
||||
inline String getProxyTypeName(ProxyType type) {
|
||||
@@ -51,6 +55,10 @@ inline String getProxyTypeName(ProxyType type) {
|
||||
return "Hysteria";
|
||||
case ProxyType::Hysteria2:
|
||||
return "Hysteria2";
|
||||
case ProxyType::TUIC:
|
||||
return "Tuic";
|
||||
case ProxyType::AnyTLS:
|
||||
return "AnyTLS";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
@@ -64,7 +72,7 @@ struct Proxy {
|
||||
String Remark;
|
||||
String Hostname;
|
||||
uint16_t Port = 0;
|
||||
|
||||
String CongestionControl;
|
||||
String Username;
|
||||
String Password;
|
||||
String EncryptMethod;
|
||||
@@ -79,7 +87,10 @@ struct Proxy {
|
||||
String TransferProtocol;
|
||||
String FakeType;
|
||||
String AuthStr;
|
||||
|
||||
uint16_t IdleSessionCheckInterval=30;
|
||||
uint16_t IdleSessionTimeout=30;
|
||||
uint16_t MinIdleSession=0;
|
||||
String TLSStr;
|
||||
bool TLSSecure = false;
|
||||
|
||||
String Host;
|
||||
@@ -109,7 +120,7 @@ struct Proxy {
|
||||
uint16_t KeepAlive = 0;
|
||||
String TestUrl;
|
||||
String ClientId;
|
||||
|
||||
String Ports;
|
||||
String Auth;
|
||||
String Alpn;
|
||||
String UpMbps;
|
||||
@@ -122,6 +133,19 @@ struct Proxy {
|
||||
String ShortId;
|
||||
String Flow;
|
||||
bool FlowShow = false;
|
||||
tribool DisableSni;
|
||||
uint32_t UpSpeed;
|
||||
uint32_t DownSpeed;
|
||||
String SNI;
|
||||
tribool ReduceRtt;
|
||||
String UdpRelayMode = "native";
|
||||
uint16_t RequestTimeout = 15000;
|
||||
String token;
|
||||
String UnderlyingProxy;
|
||||
std::vector<String> AlpnList;
|
||||
String PacketEncoding;
|
||||
String Multiplexing;
|
||||
tribool V2rayHttpUpgrade;
|
||||
};
|
||||
|
||||
#define SS_DEFAULT_GROUP "SSProvider"
|
||||
@@ -135,5 +159,7 @@ struct Proxy {
|
||||
#define XRAY_DEFAULT_GROUP "XRayProvider"
|
||||
#define HYSTERIA_DEFAULT_GROUP "HysteriaProvider"
|
||||
#define HYSTERIA2_DEFAULT_GROUP "Hysteria2Provider"
|
||||
|
||||
#define TUIC_DEFAULT_GROUP "TuicProvider"
|
||||
#define ANYTLS_DEFAULT_GROUP "AnyTLSProvider"
|
||||
#define MIERU_DEFAULT_GROUP "MieruProvider"
|
||||
#endif // PROXY_H_INCLUDED
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,8 +5,7 @@
|
||||
|
||||
#include "config/proxy.h"
|
||||
|
||||
enum class ConfType
|
||||
{
|
||||
enum class ConfType {
|
||||
Unknow,
|
||||
SS,
|
||||
SSR,
|
||||
@@ -19,36 +18,129 @@ enum class ConfType
|
||||
SUB,
|
||||
Local
|
||||
};
|
||||
void hysteriaConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &auth, const std::string &auth_str, const std::string &host, const std::string &up, const std::string &down, const std::string &alpn, const std::string &obfsParam, const std::string &insecure ,tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
|
||||
void hysteria2Construct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &password, const std::string &host, const std::string &up, const std::string &down, const std::string &alpn, const std::string &obfsParam, const std::string &obfsPassword, const std::string &insecure ,tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
|
||||
void vlessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &flow, const std::string &mode, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls,const std::string &pkd, const std::string &sid, const std::string &fp, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
|
||||
void vmessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add, const std::string &port, const std::string &type, const std::string &id, const std::string &aid, const std::string &net, const std::string &cipher, const std::string &path, const std::string &host, const std::string &edge, const std::string &tls, const std::string &sni, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
|
||||
void ssrConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &protocol, const std::string &method, const std::string &obfs, const std::string &password, const std::string &obfsparam, const std::string &protoparam, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool());
|
||||
void ssConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &method, const std::string &plugin, const std::string &pluginopts, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
|
||||
void socksConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool());
|
||||
void httpConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &username, const std::string &password, bool tls, tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
|
||||
void trojanConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &network, const std::string &host, const std::string &path,const std::string &fp, bool tlssecure, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool());
|
||||
void snellConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server, const std::string &port, const std::string &password, const std::string &obfs, const std::string &host, uint16_t version = 0, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool());
|
||||
|
||||
void hysteriaConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add,
|
||||
const std::string &port, const std::string &type, const std::string &auth,
|
||||
const std::string &auth_str, const std::string &host, const std::string &up,
|
||||
const std::string &down, const std::string &alpn, const std::string &obfsParam,
|
||||
const std::string &insecure, const std::string &ports, const std::string &sni,
|
||||
tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(),
|
||||
tribool tls13 = tribool(),const std::string& underlying_proxy="");
|
||||
|
||||
void hysteria2Construct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add,
|
||||
const std::string &port, const std::string &password, const std::string &host,
|
||||
const std::string &up, const std::string &down, const std::string &alpn,
|
||||
const std::string &obfsParam, const std::string &obfsPassword, const std::string &sni,
|
||||
const std::string &publicKey, const std::string &ports,
|
||||
tribool udp, tribool tfo,
|
||||
tribool scv,const std::string& underlying_proxy="");
|
||||
|
||||
void vlessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add,
|
||||
const std::string &port, const std::string &type, const std::string &id, const std::string &aid,
|
||||
const std::string &net, const std::string &cipher, const std::string &flow, const std::string &mode,
|
||||
const std::string &path, const std::string &host, const std::string &edge, const std::string &tls,
|
||||
const std::string &pkd, const std::string &sid, const std::string &fp, const std::string &sni,
|
||||
const std::vector<std::string> &alpnList,const std::string &packet_encoding,
|
||||
tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(),
|
||||
tribool tls13 = tribool(),const std::string& underlying_proxy="",tribool v2ray_http_upgrade=tribool());
|
||||
|
||||
void vmessConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add,
|
||||
const std::string &port, const std::string &type, const std::string &id, const std::string &aid,
|
||||
const std::string &net, const std::string &cipher, const std::string &path, const std::string &host,
|
||||
const std::string &edge, const std::string &tls, const std::string &sni,
|
||||
const std::vector<std::string> &alpnList, tribool udp = tribool(),
|
||||
tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool(),const std::string& underlying_proxy="");
|
||||
|
||||
void ssrConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server,
|
||||
const std::string &port, const std::string &protocol, const std::string &method,
|
||||
const std::string &obfs, const std::string &password, const std::string &obfsparam,
|
||||
const std::string &protoparam, tribool udp = tribool(), tribool tfo = tribool(),
|
||||
tribool scv = tribool(),const std::string& underlying_proxy="");
|
||||
|
||||
void ssConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server,
|
||||
const std::string &port, const std::string &password, const std::string &method,
|
||||
const std::string &plugin, const std::string &pluginopts, tribool udp = tribool(),
|
||||
tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool(),const std::string& underlying_proxy="");
|
||||
|
||||
void socksConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server,
|
||||
const std::string &port, const std::string &username, const std::string &password,
|
||||
tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(),const std::string& underlying_proxy="");
|
||||
|
||||
void httpConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server,
|
||||
const std::string &port, const std::string &username, const std::string &password, bool tls,
|
||||
tribool tfo = tribool(), tribool scv = tribool(), tribool tls13 = tribool(),const std::string& underlying_proxy="");
|
||||
|
||||
void trojanConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server,
|
||||
const std::string &port, const std::string &password, const std::string &network,
|
||||
const std::string &host, const std::string &path, const std::string &fp, const std::string &sni,
|
||||
const std::vector<std::string> &alpnList,
|
||||
bool tlssecure, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(),
|
||||
tribool tls13 = tribool(),const std::string& underlying_proxy="");
|
||||
void anyTlSConstruct(Proxy &node, const std::string &group, const std::string &remarks,
|
||||
const std::string &port, const std::string &password,
|
||||
const std::string &host, const std::vector<String> &AlpnList,
|
||||
const std::string &fingerprint,
|
||||
const std::string &sni, tribool udp = tribool(), tribool tfo = tribool(), tribool scv = tribool(),
|
||||
tribool tls13 = tribool(),const std::string& underlying_proxy="",uint16_t idleSessionCheckInterval=30,uint16_t idleSessionTimeout=30,uint16_t minIdleSession=0);
|
||||
void snellConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &server,
|
||||
const std::string &port, const std::string &password, const std::string &obfs,
|
||||
const std::string &host, uint16_t version = 0, tribool udp = tribool(), tribool tfo = tribool(),
|
||||
tribool scv = tribool(),const std::string& underlying_proxy="");
|
||||
|
||||
void tuicConstruct(Proxy &node, const std::string &group, const std::string &remarks, const std::string &add,
|
||||
const std::string &port, const std::string &password, const std::string &congestion_control,
|
||||
const std::string &alpn,
|
||||
const std::string &sni, const std::string &uuid, const std::string &udpRelayMode,
|
||||
const std::string &token,
|
||||
tribool udp = tribool(), tribool tfo = tribool(),
|
||||
tribool scv = tribool(), tribool reduceRtt = tribool(), tribool disableSni = tribool(),
|
||||
uint16_t request_timeout = 15000,const std::string& underlying_proxy="");
|
||||
void mieruConstruct(Proxy &node, const std::string &group, const std::string &remarks,
|
||||
const std::string &port, const std::string &password,
|
||||
const std::string &host, const std::string &ports,
|
||||
const std::string &username,const std::string &multiplexing,
|
||||
const std::string &transfer_protocol, tribool udp,
|
||||
tribool tfo, tribool scv,
|
||||
tribool tls13, const std::string &underlying_proxy);
|
||||
void explodeVmess(std::string vmess, Proxy &node);
|
||||
|
||||
void explodeSSR(std::string ssr, Proxy &node);
|
||||
|
||||
void explodeSS(std::string ss, Proxy &node);
|
||||
|
||||
void explodeTrojan(std::string trojan, Proxy &node);
|
||||
|
||||
void explodeQuan(const std::string &quan, Proxy &node);
|
||||
void explodeMierus(std::string mieru, Proxy &node);
|
||||
void explodeStdVMess(std::string vmess, Proxy &node);
|
||||
|
||||
void explodeStdVless(std::string vless, Proxy &node);
|
||||
void explodeStdMieru(std::string mieru, Proxy &node);
|
||||
void explodeStdHysteria(std::string hysteria, Proxy &node);
|
||||
|
||||
void explodeStdHysteria2(std::string hysteria2, Proxy &node);
|
||||
|
||||
void explodeShadowrocket(std::string kit, Proxy &node);
|
||||
|
||||
void explodeKitsunebi(std::string kit, Proxy &node);
|
||||
|
||||
void explodeVless(std::string vless, Proxy &node);
|
||||
|
||||
void explodeHysteria(std::string hysteria, Proxy &node);
|
||||
|
||||
void explodeHysteria2(std::string hysteria2, Proxy &node);
|
||||
|
||||
void explodeAnyTLS(std::string anytls, Proxy &node);
|
||||
|
||||
/// Parse a link
|
||||
void explode(const std::string &link, Proxy &node);
|
||||
|
||||
void explodeSSD(std::string link, std::vector<Proxy> &nodes);
|
||||
|
||||
void explodeSub(std::string sub, std::vector<Proxy> &nodes);
|
||||
|
||||
int explodeConf(const std::string &filepath, std::vector<Proxy> &nodes);
|
||||
|
||||
int explodeConfContent(const std::string &content, std::vector<Proxy> &nodes);
|
||||
|
||||
#endif // SUBPARSER_H_INCLUDED
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <quickjspp.hpp>
|
||||
#include <utility>
|
||||
#include <quickjs/quickjs-libc.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -226,7 +227,7 @@ public:
|
||||
qjs_fetch_Headers headers;
|
||||
std::string cookies;
|
||||
std::string postdata;
|
||||
explicit qjs_fetch_Request(const std::string &url) : url(url) {}
|
||||
explicit qjs_fetch_Request(std::string url) : url(std::move(url)) {}
|
||||
};
|
||||
|
||||
class qjs_fetch_Response
|
||||
@@ -389,7 +390,7 @@ void script_runtime_init(qjs::Runtime &runtime)
|
||||
js_std_init_handlers(runtime.rt);
|
||||
}
|
||||
|
||||
int ShowMsgbox(const std::string &title, std::string content, uint16_t type = 0)
|
||||
int ShowMsgbox(const std::string &title, const std::string &content, uint16_t type = 0)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if(!type)
|
||||
@@ -424,7 +425,7 @@ struct Lambda {
|
||||
|
||||
uint32_t currentTime()
|
||||
{
|
||||
return time(NULL);
|
||||
return time(nullptr);
|
||||
}
|
||||
|
||||
int script_context_init(qjs::Context &context)
|
||||
@@ -525,7 +526,7 @@ int script_context_init(qjs::Context &context)
|
||||
)", "<import>", JS_EVAL_TYPE_MODULE);
|
||||
return 0;
|
||||
}
|
||||
catch(qjs::exception)
|
||||
catch(qjs::exception&)
|
||||
{
|
||||
script_print_stack(context);
|
||||
return 1;
|
||||
|
||||
@@ -47,16 +47,23 @@ static httplib::Server::Handler makeHandler(const responseRoute &rr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
req.headers[h.first] = h.second;
|
||||
req.headers.emplace(h.first.data(), h.second.data());
|
||||
}
|
||||
req.argument = request.params;
|
||||
if (request.get_header_value("Content-Type") == "application/x-www-form-urlencoded")
|
||||
if (request.method == "POST" || request.method == "PUT" || request.method == "PATCH")
|
||||
{
|
||||
req.postdata = urlDecode(request.body);
|
||||
}
|
||||
else
|
||||
{
|
||||
req.postdata = request.body;
|
||||
if (request.is_multipart_form_data() && !request.files.empty())
|
||||
{
|
||||
req.postdata = request.files.begin()->second.content;
|
||||
}
|
||||
else if (request.get_header_value("Content-Type") == "application/x-www-form-urlencoded")
|
||||
{
|
||||
req.postdata = urlDecode(request.body);
|
||||
}
|
||||
else
|
||||
{
|
||||
req.postdata = request.body;
|
||||
}
|
||||
}
|
||||
auto result = rr.rc(req, resp);
|
||||
response.status = resp.status_code;
|
||||
@@ -163,6 +170,7 @@ int WebServer::start_web_server_multi(listener_args *args)
|
||||
{
|
||||
res.set_header("Access-Control-Allow-Headers", req.get_header_value("Access-Control-Request-Headers"));
|
||||
}
|
||||
res.set_header("Access-Control-Allow-Origin", "*");
|
||||
return httplib::Server::HandlerResponse::Unhandled;
|
||||
});
|
||||
for (auto &x : redirect_map)
|
||||
@@ -187,7 +195,7 @@ int WebServer::start_web_server_multi(listener_args *args)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::rethrow_exception(e);
|
||||
if (e) std::rethrow_exception(e);
|
||||
}
|
||||
catch (const httplib::Error &err)
|
||||
{
|
||||
@@ -212,6 +220,9 @@ int WebServer::start_web_server_multi(listener_args *args)
|
||||
{
|
||||
server.set_mount_point("/", serve_file_root);
|
||||
}
|
||||
server.new_task_queue = [args] {
|
||||
return new httplib::ThreadPool(args->max_workers);
|
||||
};
|
||||
server.bind_to_port(args->listen_address, args->port, 0);
|
||||
|
||||
std::thread thread([&]()
|
||||
|
||||
@@ -26,7 +26,8 @@ std::string getTime(int type)
|
||||
format = "%Y%m%d-%H%M%S";
|
||||
break;
|
||||
case 2:
|
||||
format = "%Y/%m/%d %a %H:%M:%S." + std::string(cMillis);
|
||||
format = "%Y/%m/%d %a %H:%M:%S.";
|
||||
format += cMillis;
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
|
||||
@@ -9,7 +9,12 @@ struct strICaseComp
|
||||
{
|
||||
bool operator() (const std::string &lhs, const std::string &rhs) const
|
||||
{
|
||||
return strcasecmp(lhs.c_str(), rhs.c_str());
|
||||
return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(),
|
||||
rhs.end(),
|
||||
[](unsigned char c1, unsigned char c2)
|
||||
{
|
||||
return ::tolower(c1) < ::tolower(c2);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -3,88 +3,38 @@
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <random>
|
||||
|
||||
#include "string.h"
|
||||
#include "map_extra.h"
|
||||
|
||||
std::vector<std::string> split(const std::string &s, const std::string &separator)
|
||||
{
|
||||
string_size bpos = 0, epos = s.find(separator);
|
||||
std::vector<std::string> result;
|
||||
string_size i = 0;
|
||||
|
||||
while(i != s.size())
|
||||
while(bpos < s.size())
|
||||
{
|
||||
int flag = 0;
|
||||
while(i != s.size() && flag == 0)
|
||||
{
|
||||
flag = 1;
|
||||
for(char x : separator)
|
||||
if(s[i] == x)
|
||||
{
|
||||
++i;
|
||||
flag = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
flag = 0;
|
||||
string_size j = i;
|
||||
while(j != s.size() && flag == 0)
|
||||
{
|
||||
for(char x : separator)
|
||||
if(s[j] == x)
|
||||
{
|
||||
flag = 1;
|
||||
break;
|
||||
}
|
||||
if(flag == 0)
|
||||
++j;
|
||||
}
|
||||
if(i != j)
|
||||
{
|
||||
result.push_back(s.substr(i, j-i));
|
||||
i = j;
|
||||
}
|
||||
if(epos == std::string::npos)
|
||||
epos = s.size();
|
||||
result.push_back(s.substr(bpos, epos - bpos));
|
||||
bpos = epos + separator.size();
|
||||
epos = s.find(separator, bpos);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void split(std::vector<std::string_view> &result, std::string_view s, char separator)
|
||||
{
|
||||
string_size i = 0;
|
||||
|
||||
while (i != s.size())
|
||||
string_size bpos = 0, epos = s.find(separator);
|
||||
while(bpos < s.size())
|
||||
{
|
||||
int flag = 0;
|
||||
while(i != s.size() && flag == 0)
|
||||
{
|
||||
flag = 1;
|
||||
if(s[i] == separator)
|
||||
{
|
||||
++i;
|
||||
flag = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
flag = 0;
|
||||
string_size j = i;
|
||||
while(j != s.size() && flag == 0)
|
||||
{
|
||||
if(s[j] == separator)
|
||||
{
|
||||
flag = 1;
|
||||
break;
|
||||
}
|
||||
++j;
|
||||
}
|
||||
if (i != j)
|
||||
{
|
||||
result.push_back(s.substr(i, j-i));
|
||||
i = j;
|
||||
}
|
||||
if(epos == std::string_view::npos)
|
||||
epos = s.size();
|
||||
result.push_back(s.substr(bpos, epos - bpos));
|
||||
bpos = epos + 1;
|
||||
epos = s.find(separator, bpos);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +91,7 @@ std::string toUpper(const std::string &str)
|
||||
void processEscapeChar(std::string &str)
|
||||
{
|
||||
string_size pos = str.find('\\');
|
||||
while(pos != str.npos)
|
||||
while(pos != std::string::npos)
|
||||
{
|
||||
if(pos == str.size())
|
||||
break;
|
||||
@@ -191,7 +141,7 @@ void processEscapeCharReverse(std::string &str)
|
||||
|
||||
int parseCommaKeyValue(const std::string &input, const std::string &separator, string_pair_array &result)
|
||||
{
|
||||
string_size bpos = 0, epos = input.find(',');
|
||||
string_size bpos = 0, epos = input.find(separator);
|
||||
std::string kv;
|
||||
while(bpos < input.size())
|
||||
{
|
||||
@@ -200,9 +150,9 @@ int parseCommaKeyValue(const std::string &input, const std::string &separator, s
|
||||
else if(epos && input[epos - 1] == '\\')
|
||||
{
|
||||
kv += input.substr(bpos, epos - bpos - 1);
|
||||
kv += ',';
|
||||
kv += separator;
|
||||
bpos = epos + 1;
|
||||
epos = input.find(',', bpos);
|
||||
epos = input.find(separator, bpos);
|
||||
continue;
|
||||
}
|
||||
kv += input.substr(bpos, epos - bpos);
|
||||
@@ -213,9 +163,9 @@ int parseCommaKeyValue(const std::string &input, const std::string &separator, s
|
||||
result.emplace_back(kv.substr(0, eqpos), kv.substr(eqpos + 1));
|
||||
kv.clear();
|
||||
bpos = epos + 1;
|
||||
epos = input.find(',', bpos);
|
||||
epos = input.find(separator, bpos);
|
||||
}
|
||||
if(kv.size())
|
||||
if(!kv.empty())
|
||||
{
|
||||
string_size eqpos = kv.find('=');
|
||||
if(eqpos == std::string::npos)
|
||||
@@ -328,12 +278,12 @@ std::string getUrlArg(const std::string &url, const std::string &request)
|
||||
while(pos)
|
||||
{
|
||||
pos = url.rfind(pattern, pos);
|
||||
if(pos != url.npos)
|
||||
if(pos != std::string::npos)
|
||||
{
|
||||
if(pos == 0 || url[pos - 1] == '&' || url[pos - 1] == '?')
|
||||
{
|
||||
pos += pattern.size();
|
||||
return url.substr(pos, url.find("&", pos) - pos);
|
||||
return url.substr(pos, url.find('&', pos) - pos);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -410,23 +360,24 @@ bool isStrUTF8(const std::string &data)
|
||||
std::string randomStr(int len)
|
||||
{
|
||||
std::string retData;
|
||||
srand(time(NULL));
|
||||
int cnt = 0;
|
||||
while(cnt < len)
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_int_distribution<> dis(0, 61);
|
||||
for(int i = 0; i < len; i++)
|
||||
{
|
||||
switch((rand() % 3))
|
||||
int r = dis(gen);
|
||||
if (r < 26)
|
||||
{
|
||||
case 1:
|
||||
retData += ('A' + rand() % 26);
|
||||
break;
|
||||
case 2:
|
||||
retData += ('a' + rand() % 26);
|
||||
break;
|
||||
default:
|
||||
retData += ('0' + rand() % 10);
|
||||
break;
|
||||
retData.push_back('a' + r);
|
||||
}
|
||||
else if (r < 52)
|
||||
{
|
||||
retData.push_back('A' + r - 26);
|
||||
}
|
||||
else
|
||||
{
|
||||
retData.push_back('0' + r - 52);
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
return retData;
|
||||
}
|
||||
@@ -451,7 +402,7 @@ int to_int(const std::string &str, int def_value)
|
||||
|
||||
std::string join(const string_array &arr, const std::string &delimiter)
|
||||
{
|
||||
if(arr.size() == 0)
|
||||
if(arr.empty())
|
||||
return "";
|
||||
if(arr.size() == 1)
|
||||
return arr[0];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#ifndef VERSION_H_INCLUDED
|
||||
#define VERSION_H_INCLUDED
|
||||
|
||||
#define VERSION "v0.8.2"
|
||||
#define VERSION "v0.9.9"
|
||||
|
||||
#endif // VERSION_H_INCLUDED
|
||||
|
||||
Reference in New Issue
Block a user