mirror of
https://github.com/nitezs/sub2clash.git
synced 2024-12-24 11:14:41 -05:00
Reordered import statements across multiple files
for consistency
This commit is contained in:
parent
d0696aad5b
commit
73e94ad856
13
.vscode/launch.json
vendored
Normal file
13
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Debug",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "debug",
|
||||||
|
"program": "${workspaceFolder}/main.go",
|
||||||
|
"output": "${workspaceFolder}/dist/main.exe",
|
||||||
|
"buildFlags": "-ldflags '-X sub2clash/config.Dev=true -X sub2clash/config.Version=dev'"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
获取 Clash/Clash.Meta 配置链接
|
获取 Clash/Clash.Meta 配置链接
|
||||||
|
|
||||||
| Query 参数 | 类型 | 是否必须 | 默认值 | 说明 |
|
| Query 参数 | 类型 | 是否必须 | 默认值 | 说明 |
|
||||||
|--------------|--------|-------------------|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
| ------------ | ------ | ------------------------ | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- |
|
||||||
| sub | string | sub/proxy 至少有一项存在 | - | 订阅链接,可以在链接结尾加上`#名称`,来给订阅中的节点加上统一前缀(可以输入多个,用 `,` 分隔) |
|
| sub | string | sub/proxy 至少有一项存在 | - | 订阅链接,可以在链接结尾加上`#名称`,来给订阅中的节点加上统一前缀(可以输入多个,用 `,` 分隔) |
|
||||||
| proxy | string | sub/proxy 至少有一项存在 | - | 节点分享链接(可以输入多个,用 `,` 分隔) |
|
| proxy | string | sub/proxy 至少有一项存在 | - | 节点分享链接(可以输入多个,用 `,` 分隔) |
|
||||||
| refresh | bool | 否 | `false` | 强制刷新配置(默认缓存 5 分钟) |
|
| refresh | bool | 否 | `false` | 强制刷新配置(默认缓存 5 分钟) |
|
||||||
@ -23,7 +23,7 @@
|
|||||||
具体参考使用可以参考 [api\templates\index.html](api/static/index.html)
|
具体参考使用可以参考 [api\templates\index.html](api/static/index.html)
|
||||||
|
|
||||||
| Body 参数 | 类型 | 是否必须 | 默认值 | 说明 |
|
| Body 参数 | 类型 | 是否必须 | 默认值 | 说明 |
|
||||||
|----------|--------|------|-----|------------------|
|
| --------- | ------ | -------- | ------ | ------------------------- |
|
||||||
| url | string | 是 | - | 需要转换的 Query 参数部分 |
|
| url | string | 是 | - | 需要转换的 Query 参数部分 |
|
||||||
| password | string | 否 | - | 短链密码 |
|
| password | string | 否 | - | 短链密码 |
|
||||||
|
|
||||||
@ -33,5 +33,5 @@
|
|||||||
`hash` 为动态路由参数,可以通过 `/short` 接口获取
|
`hash` 为动态路由参数,可以通过 `/short` 接口获取
|
||||||
|
|
||||||
| Query 参数 | 类型 | 是否必须 | 默认值 | 说明 |
|
| Query 参数 | 类型 | 是否必须 | 默认值 | 说明 |
|
||||||
|----------|--------|------|-----|------|
|
| ---------- | ------ | -------- | ------ | -------- |
|
||||||
| password | string | 否 | - | 短链密码 |
|
| password | string | 否 | - | 短链密码 |
|
||||||
|
@ -1,18 +1,21 @@
|
|||||||
# sub2clash
|
# sub2clash
|
||||||
|
|
||||||
将订阅链接转换为 Clash、Clash.Meta 配置
|
将订阅链接转换为 Clash、Clash.Meta 配置
|
||||||
|
[Demo](https://www.nite07.com/sub)
|
||||||
|
|
||||||
## 特性
|
## 特性
|
||||||
|
|
||||||
- 开箱即用的规则、策略组配置
|
- 开箱即用的规则、策略组配置
|
||||||
- 自动根据节点名称按国家划分策略组
|
- 自动根据节点名称按国家划分策略组
|
||||||
- 支持多订阅合并
|
- 支持多订阅合并
|
||||||
|
- 支持添加自定义 Rule Provider、Rule
|
||||||
- 支持多种协议
|
- 支持多种协议
|
||||||
- Shadowsocks
|
- Shadowsocks
|
||||||
- ShadowsocksR
|
- ShadowsocksR
|
||||||
- Vmess
|
- Vmess
|
||||||
- Vless
|
- Vless (Clash.Meta)
|
||||||
- Trojan
|
- Trojan
|
||||||
|
- Hysteria2 (Clash.Meta)
|
||||||
|
|
||||||
## 使用
|
## 使用
|
||||||
|
|
||||||
@ -26,7 +29,7 @@
|
|||||||
可以通过编辑 .env 文件来修改默认配置,docker 直接添加环境变量
|
可以通过编辑 .env 文件来修改默认配置,docker 直接添加环境变量
|
||||||
|
|
||||||
| 变量名 | 说明 | 默认值 |
|
| 变量名 | 说明 | 默认值 |
|
||||||
|-----------------------|-----------------------------------------------------------|-----------------------|
|
| --------------------- | ---------------------------------------------- | --------------------- |
|
||||||
| PORT | 端口 | `8011` |
|
| PORT | 端口 | `8011` |
|
||||||
| META_TEMPLATE | meta 模板文件名 | `template_meta.yaml` |
|
| META_TEMPLATE | meta 模板文件名 | `template_meta.yaml` |
|
||||||
| CLASH_TEMPLATE | clash 模板文件名 | `template_clash.yaml` |
|
| CLASH_TEMPLATE | clash 模板文件名 | `template_clash.yaml` |
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sub2clash/config"
|
"sub2clash/config"
|
||||||
"sub2clash/model"
|
"sub2clash/model"
|
||||||
"sub2clash/validator"
|
"sub2clash/validator"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SubmodHandler(c *gin.Context) {
|
func SubmodHandler(c *gin.Context) {
|
||||||
|
@ -4,8 +4,6 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"go.uber.org/zap"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
@ -16,6 +14,9 @@ import (
|
|||||||
"sub2clash/parser"
|
"sub2clash/parser"
|
||||||
"sub2clash/utils"
|
"sub2clash/utils"
|
||||||
"sub2clash/validator"
|
"sub2clash/validator"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func BuildSub(clashType model.ClashType, query validator.SubValidator, template string) (
|
func BuildSub(clashType model.ClashType, query validator.SubValidator, template string) (
|
||||||
|
@ -2,12 +2,13 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sub2clash/config"
|
"sub2clash/config"
|
||||||
"sub2clash/model"
|
"sub2clash/model"
|
||||||
"sub2clash/validator"
|
"sub2clash/validator"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SubHandler(c *gin.Context) {
|
func SubHandler(c *gin.Context) {
|
||||||
|
@ -2,9 +2,6 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
@ -16,6 +13,10 @@ import (
|
|||||||
"sub2clash/utils/database"
|
"sub2clash/utils/database"
|
||||||
"sub2clash/validator"
|
"sub2clash/validator"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ShortLinkGenHandler(c *gin.Context) {
|
func ShortLinkGenHandler(c *gin.Context) {
|
||||||
|
@ -2,13 +2,14 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"html/template"
|
"html/template"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sub2clash/api/controller"
|
"sub2clash/api/controller"
|
||||||
"sub2clash/config"
|
"sub2clash/config"
|
||||||
"sub2clash/middleware"
|
"sub2clash/middleware"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed static
|
//go:embed static
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
@ -117,7 +117,9 @@
|
|||||||
name="refresh"
|
name="refresh"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
/>
|
/>
|
||||||
<label class="form-check-label" for="refresh">强制重新获取订阅</label>
|
<label class="form-check-label" for="refresh"
|
||||||
|
>强制重新获取订阅</label
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<!-- Node List -->
|
<!-- Node List -->
|
||||||
<div class="form-check mb-3">
|
<div class="form-check mb-3">
|
||||||
@ -127,7 +129,9 @@
|
|||||||
name="nodeList"
|
name="nodeList"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
/>
|
/>
|
||||||
<label class="form-check-label" for="nodeList">输出为 Node List</label>
|
<label class="form-check-label" for="nodeList"
|
||||||
|
>输出为 Node List</label
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<!-- Auto Test -->
|
<!-- Auto Test -->
|
||||||
<div class="form-check mb-3">
|
<div class="form-check mb-3">
|
||||||
@ -143,7 +147,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- Lazy -->
|
<!-- Lazy -->
|
||||||
<div class="form-check mb-3">
|
<div class="form-check mb-3">
|
||||||
<input class="form-check-input" id="lazy" name="lazy" type="checkbox" />
|
<input
|
||||||
|
class="form-check-input"
|
||||||
|
id="lazy"
|
||||||
|
name="lazy"
|
||||||
|
type="checkbox"
|
||||||
|
/>
|
||||||
<label class="form-check-label" for="lazy"
|
<label class="form-check-label" for="lazy"
|
||||||
>自动测速启用 lazy 模式</label
|
>自动测速启用 lazy 模式</label
|
||||||
>
|
>
|
||||||
@ -207,8 +216,17 @@
|
|||||||
<div class="form-group mb-5">
|
<div class="form-group mb-5">
|
||||||
<label for="apiLink">配置链接:</label>
|
<label for="apiLink">配置链接:</label>
|
||||||
<div class="input-group mb-2">
|
<div class="input-group mb-2">
|
||||||
<input class="form-control" id="apiLink" readonly type="text" />
|
<input
|
||||||
<button class="btn btn-primary" onclick="generateURL()" type="button">
|
class="form-control"
|
||||||
|
id="apiLink"
|
||||||
|
readonly
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
class="btn btn-primary"
|
||||||
|
onclick="generateURL()"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
生成链接
|
生成链接
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
@ -220,7 +238,12 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input class="form-control" id="apiShortLink" readonly type="text" />
|
<input
|
||||||
|
class="form-control"
|
||||||
|
id="apiShortLink"
|
||||||
|
readonly
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
<input
|
<input
|
||||||
class="form-control"
|
class="form-control"
|
||||||
id="password"
|
id="password"
|
||||||
@ -247,7 +270,9 @@
|
|||||||
<footer>
|
<footer>
|
||||||
<p class="text-center">
|
<p class="text-center">
|
||||||
Powered by
|
Powered by
|
||||||
<a class="link-primary" href="https://github.com/nitezs/sub2clash"
|
<a
|
||||||
|
class="link-primary"
|
||||||
|
href="https://github.com/nitezs/sub2clash"
|
||||||
>sub2clash</a
|
>sub2clash</a
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
|
@ -114,7 +114,11 @@ function generateURI() {
|
|||||||
let prepend = rules[i * 3 + 1].value;
|
let prepend = rules[i * 3 + 1].value;
|
||||||
let group = rules[i * 3 + 2].value;
|
let group = rules[i * 3 + 2].value;
|
||||||
// 是否存在空值
|
// 是否存在空值
|
||||||
if (rule.trim() === "" || prepend.trim() === "" || group.trim() === "") {
|
if (
|
||||||
|
rule.trim() === "" ||
|
||||||
|
prepend.trim() === "" ||
|
||||||
|
group.trim() === ""
|
||||||
|
) {
|
||||||
alert("Rule 中存在空值,请检查后重试!");
|
alert("Rule 中存在空值,请检查后重试!");
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
@ -189,14 +193,16 @@ function parseInputURL() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (params.has("sub")) {
|
if (params.has("sub")) {
|
||||||
document.getElementById("sub").value = decodeURIComponent(params.get("sub"))
|
document.getElementById("sub").value = decodeURIComponent(
|
||||||
|
params.get("sub")
|
||||||
|
)
|
||||||
.split(",")
|
.split(",")
|
||||||
.join("\n");
|
.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.has("proxy")) {
|
if (params.has("proxy")) {
|
||||||
document.getElementById("proxy").value = decodeURIComponent(
|
document.getElementById("proxy").value = decodeURIComponent(
|
||||||
params.get("proxy"),
|
params.get("proxy")
|
||||||
)
|
)
|
||||||
.split(",")
|
.split(",")
|
||||||
.join("\n");
|
.join("\n");
|
||||||
@ -218,7 +224,7 @@ function parseInputURL() {
|
|||||||
|
|
||||||
if (params.has("template")) {
|
if (params.has("template")) {
|
||||||
document.getElementById("template").value = decodeURIComponent(
|
document.getElementById("template").value = decodeURIComponent(
|
||||||
params.get("template"),
|
params.get("template")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +234,7 @@ function parseInputURL() {
|
|||||||
|
|
||||||
if (params.has("remove")) {
|
if (params.has("remove")) {
|
||||||
document.getElementById("remove").value = decodeURIComponent(
|
document.getElementById("remove").value = decodeURIComponent(
|
||||||
params.get("remove"),
|
params.get("remove")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +244,7 @@ function parseInputURL() {
|
|||||||
|
|
||||||
if (params.has("ruleProvider")) {
|
if (params.has("ruleProvider")) {
|
||||||
parseAndFillRuleProviderParams(
|
parseAndFillRuleProviderParams(
|
||||||
decodeURIComponent(params.get("ruleProvider")),
|
decodeURIComponent(params.get("ruleProvider"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,7 +409,7 @@ function generateShortLink() {
|
|||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
apiShortLink.value = `${window.location.origin}${window.location.pathname}s/${response.data}`;
|
apiShortLink.value = `${window.location.origin}${window.location.pathname}s/${response.data}`;
|
||||||
|
@ -2,9 +2,10 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/joho/godotenv"
|
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/joho/godotenv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
version: '3'
|
version: "3"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
sub2clash:
|
sub2clash:
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package logger
|
package logger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go.uber.org/zap"
|
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"go.uber.org/zap/zapcore"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
5
main.go
5
main.go
@ -2,8 +2,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sub2clash/api"
|
"sub2clash/api"
|
||||||
@ -11,6 +9,9 @@ import (
|
|||||||
"sub2clash/logger"
|
"sub2clash/logger"
|
||||||
"sub2clash/utils"
|
"sub2clash/utils"
|
||||||
"sub2clash/utils/database"
|
"sub2clash/utils/database"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed templates/template_meta.yaml
|
//go:embed templates/template_meta.yaml
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"sub2clash/logger"
|
"sub2clash/logger"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ZapLogger() gin.HandlerFunc {
|
func ZapLogger() gin.HandlerFunc {
|
||||||
|
@ -45,6 +45,7 @@ func ParseHysteria2(proxy string) (model.Proxy, error) {
|
|||||||
Obfs: params.Get("obfs"),
|
Obfs: params.Get("obfs"),
|
||||||
ObfsParam: params.Get("obfs-password"),
|
ObfsParam: params.Get("obfs-password"),
|
||||||
Sni: params.Get("sni"),
|
Sni: params.Get("sni"),
|
||||||
|
SkipCertVerify: params.Get("insecure") == "1",
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
package database
|
package database
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/glebarez/sqlite"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sub2clash/logger"
|
"sub2clash/logger"
|
||||||
"sub2clash/model"
|
"sub2clash/model"
|
||||||
"sub2clash/utils"
|
"sub2clash/utils"
|
||||||
|
|
||||||
|
"github.com/glebarez/sqlite"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
var DB *gorm.DB
|
var DB *gorm.DB
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go.uber.org/zap"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sub2clash/logger"
|
"sub2clash/logger"
|
||||||
"sub2clash/model"
|
"sub2clash/model"
|
||||||
"sub2clash/parser"
|
"sub2clash/parser"
|
||||||
|
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetContryName(countryKey string) string {
|
func GetContryName(countryKey string) string {
|
||||||
|
@ -4,11 +4,12 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SubValidator struct {
|
type SubValidator struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user