Compare commits

..

30 Commits

Author SHA1 Message Date
zu1k
2c4a6a833d update html 2020-08-21 10:21:11 +08:00
zu1k
9f6ae0cb9b add type len 2020-08-21 09:53:08 +08:00
zu1k
6262f510e9 mod html 2020-08-21 09:48:05 +08:00
zu1k
eea6a692e6 fix trojan provider 2020-08-21 09:38:10 +08:00
zu1k
f9d2dbbed9 remoe fanqiangdang num limit 2020-08-21 09:05:17 +08:00
zu1k
6f70ee0b7b update web fanqiangdang 2020-08-21 09:00:26 +08:00
zu1k
bb6600cdd6 fix trojan 2020-08-21 08:31:45 +08:00
zu1k
5a2b0a4188 comment on source.yaml 2020-08-21 08:16:24 +08:00
zu1k
5c2b14f836 update readme 2020-08-20 22:44:15 +08:00
zu1k
345c6f89b6 add trojan link grep 2020-08-20 22:42:40 +08:00
zu1k
097c2d2241 add trojan support 2020-08-20 22:30:59 +08:00
zu1k
023de15f0e config file not found 2020-08-20 20:32:03 +08:00
zu1k
70dea95241 remove config test 2020-08-20 19:25:30 +08:00
zu1k
1a713ed8e4 use local config source default 2020-08-20 19:21:51 +08:00
zu1k
d92cd20d88 add config file path param 2020-08-20 19:06:25 +08:00
zu1k
17c051cee3 add proxies count show 2020-08-20 18:32:41 +08:00
zu1k
07a91fd647 fix for github action 2020-08-20 18:25:23 +08:00
zu1k
c6c5a4c707 can modify domain 2020-08-20 18:23:32 +08:00
zu1k
008183b40e change source url 2020-08-20 15:58:31 +08:00
zu1k
21551f7a67 update readme 2020-08-20 15:44:01 +08:00
zu1k
35c6d1348b add google analytics 2020-08-20 09:39:17 +08:00
zu1k
1e10be9153 update readme 2020-08-20 09:29:27 +08:00
zu1k
8d988f0f5b add more tgchannel 2020-08-19 22:54:10 +08:00
zu1k
a7a8a9ff8b vmess identifier add uuid 2020-08-19 21:20:08 +08:00
zu1k
a9fa94c8c1 opti 2020-08-19 21:12:49 +08:00
zu1k
4cfb143f88 crowl sub in tgchannel‘ 2020-08-19 21:06:19 +08:00
zu1k
3fbdb91e7d update index.html 2020-08-19 09:28:24 +08:00
zu1k
6b462f6310 update readme 2020-08-19 08:34:52 +08:00
zu1k
32c1c7c127 update readme 2020-08-19 08:10:11 +08:00
zu1k
be46f914de add heroku app.json 2020-08-19 08:05:19 +08:00
48 changed files with 719 additions and 644 deletions

View File

@@ -12,6 +12,5 @@ FROM alpine:latest
RUN apk add --no-cache ca-certificates
WORKDIR /proxypool-src
COPY ./assets /proxypool-src/assets
COPY ./source.yaml /proxypool-src
COPY --from=builder /proxypool /proxypool-src/
ENTRYPOINT ["/proxypool-src/proxypool"]

View File

@@ -2,7 +2,7 @@
<br>proxypool<br>
</h1>
<h5 align="center">自动抓取tg频道、订阅地址、公开互联网上的ss、ssr、vmess节点信息聚合去重测试可用性后提供节点列表</h5>
<h5 align="center">自动抓取tg频道、订阅地址、公开互联网上的ss、ssr、vmess、trojan节点信息,聚合去重测试可用性后提供节点列表</h5>
<p align="center">
<a href="https://github.com/zu1k/proxypool/actions">
@@ -20,7 +20,7 @@
## 支持
- 支持ss、ssr、vmess节点链接与订阅
- 支持ss、ssr、vmess、trojan节点链接与订阅
- 任意 Telegram 频道抓取
- 机场订阅地址抓取解析
- 公开互联网页面模糊抓取
@@ -32,6 +32,15 @@
## 安装
### 使用Heroku
点击按钮进入部署页面,填写基本信息然后运行
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy)
> 因为爬虫程序需要持续运行,所以至少选择 $7/月 的配置
> 免费配置长时间无人访问会被heroku强制停止
### 从源码编译
需要安装Golang
@@ -52,30 +61,30 @@ docker pull docker.pkg.github.com/zu1k/proxypool/proxypool:latest
## 使用
### 共享抓取配置文件
### 修改配置文件
每一次抓取前会自动从github下载最新的抓取配置文件
首先修改 source.yaml 中的必要配置信息其中域名修改为你自己的域名cf开头的配置信息可以留空
直接运行 `proxypool` 程序即可
### 自定义抓取配置文件
### 启动程序
```shell
proxypool -c source.yaml
```
### 帮助更新配置文件
可以在 https://github.com/zu1k/proxypool/issues/3 进行留言
### 用户使用
目前公开版本: https://proxy.tgbot.co
直接在clash添加配置文件即可使用 https://proxy.tgbot.co/clash/config
访问页面,按照相关指导进行使用
## 截图
![Speedtest](docs/speedtest.png)
![Fast](docs/fast.png)
## 声明
本项目遵循 GNU General Public License v3.0 开源,在此基础上,所有使用本项目提供服务者都必须在网站首页保留指向本项目的链接
禁止使用本项目进行营利和做其他违法事情,产生的一切后果本项目概不负责

View File

@@ -1,24 +1,63 @@
package api
import (
"fmt"
"net/http"
"os"
"github.com/gin-gonic/gin"
_ "github.com/heroku/x/hmetrics/onload"
"github.com/zu1k/proxypool/app/cache"
"github.com/zu1k/proxypool/provider"
"github.com/zu1k/proxypool/config"
"github.com/zu1k/proxypool/internal/cache"
"github.com/zu1k/proxypool/pkg/provider"
)
var router *gin.Engine
var domain = "proxy.tgbot.co"
func setupRouter() {
router = gin.Default()
domain = config.SourceConfig.Domain
fmt.Println("Domain:", domain)
router = gin.Default()
router.LoadHTMLGlob("assets/html/*")
router.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{
"domain": domain,
"all_proxies_count": cache.AllProxiesCount,
"ss_proxies_count": cache.SSProxiesCount,
"ssr_proxies_count": cache.SSRProxiesCount,
"vmess_proxies_count": cache.VmessProxiesCount,
"trojan_proxies_count": cache.TrojanProxiesCount,
"useful_proxies_count": cache.UsefullProxiesCount,
})
})
router.GET("/clash", func(c *gin.Context) {
c.HTML(http.StatusOK, "clash.html", gin.H{
"domain": domain,
})
})
router.GET("/surge", func(c *gin.Context) {
c.HTML(http.StatusOK, "surge.html", gin.H{
"domain": domain,
})
})
router.GET("/clash/config", func(c *gin.Context) {
c.HTML(http.StatusOK, "clash-config.yaml", gin.H{
"domain": domain,
})
})
router.GET("/surge/config", func(c *gin.Context) {
c.HTML(http.StatusOK, "surge.conf", gin.H{
"domain": domain,
})
})
router.StaticFile("/", "assets/index.html")
router.StaticFile("/clash", "assets/clash.html")
router.StaticFile("/surge", "assets/surge.html")
router.StaticFile("/clash/config", "assets/clash-config.yaml")
router.StaticFile("/surge/config", "assets/surge.conf")
router.GET("/clash/proxies", func(c *gin.Context) {
proxyTypes := c.DefaultQuery("type", "")
text := ""

25
app.json Normal file
View File

@@ -0,0 +1,25 @@
{
"name": "proxypool",
"description": "自动抓取tg频道、订阅地址、公开互联网上的ss、ssr、vmess节点信息聚合去重测试可用性后提供节点列表",
"website": "https://proxy.tgbot.co/",
"repository": "https://github.com/zu1k/proxypool",
"success_url": "/",
"logo": "https://raw.githubusercontent.com/zu1k/proxypool/master/assets/proxy.jpg",
"keywords": ["golang", "ss", "ssr", "vmess", "shadowsocks", "shadowsocksr"],
"env": {
"CONFIG_FILE": {
"description": "Path to config file, could be a url."
},
"DOMAIN": {
"description": "Domain to use."
},
"CF_API_EMAIL": {
"description": "Cloudflare Email.",
"required": false
},
"CF_API_KEY": {
"description": "Cloudflare API key.",
"required": false
}
}
}

View File

@@ -1,36 +0,0 @@
package app
import (
"errors"
"fmt"
"strconv"
"testing"
"github.com/zu1k/proxypool/config"
"github.com/zu1k/proxypool/getter"
)
func TestConfigFile(t *testing.T) {
c, err := config.Parse("../source.yaml")
if err != nil {
t.Error(err)
return
}
if c == nil {
t.Error(errors.New("no sources"))
return
}
for idx, source := range c.Sources {
g, err := getter.NewGetter(source.Type, source.Options)
if err != nil {
t.Error(err, idx)
fmt.Println(source)
return
}
if g == nil {
t.Error(errors.New("getter is nil:" + strconv.Itoa(idx)))
fmt.Println(source)
return
}
}
}

View File

@@ -1,10 +0,0 @@
package app
import (
"github.com/jasonlvhit/gocron"
)
func Cron() {
_ = gocron.Every(10).Minutes().Do(CrawlGo)
<-gocron.Start()
}

View File

@@ -54,7 +54,7 @@ proxy-groups:
proxy-providers:
provider:
type: http
url: "https://proxy.tgbot.co/clash/proxies"
url: "https://{{ .domain }}/clash/proxies"
interval: 3600
path: ./provider.yaml
health-check:

View File

@@ -103,17 +103,26 @@
<div class='section friendly'>
<h1><strong>免费Clash节点</strong></h1>
<div class='article'>
<p>自动抓取tg频道、订阅地址、公开互联网上的ss、ssr、vmess节点信息聚合去重后提供clash配置每10分钟更新</p>
<p>自动抓取tg频道、订阅地址、公开互联网上的ss、ssr、vmess、trojan节点信息聚合去重后提供clash配置每15分钟更新</p>
<br>
<p>Clash配置文件<a href="https://proxy.tgbot.co/clash/config">https://proxy.tgbot.co/clash/config</a> <a href="clash://install-config?url=https://proxy.tgbot.co/clash/config">一键导入</a></p>
<p>Clash proxy-provider(Shadowrocket添加订阅方式可用)<a href="https://proxy.tgbot.co/clash/proxies">https://proxy.tgbot.co/clash/proxies</a></p>
<p>Clash配置文件https://{{ .domain }}/clash/config <a href="clash://install-config?url=https://{{ .domain }}/clash/config">一键导入</a></p>
<p>Clash proxy-provider(Shadowrocket添加订阅方式可用)<a href="https://{{ .domain }}/clash/proxies">https://{{ .domain }}/clash/proxies</a></p>
<br>
<p>筛选代理类型(此种方式你只能自己维护配置文件)https://proxy.tgbot.co/clash/proxies?type=ss,ssr,vmess</p>
<p>所有节点的Provider(不是都可以用)<a href="https://proxy.tgbot.co/clash/proxies?type=all">https://proxy.tgbot.co/clash/proxies?type=all</a></p>
<p>筛选代理类型(此种方式你只能自己维护配置文件)https://{{ .domain }}/clash/proxies?type=ss,ssr,vmess</p>
<p>所有节点的Provider(不是都可以用)<a href="https://{{ .domain }}/clash/proxies?type=all">https://{{ .domain }}/clash/proxies?type=all</a></p>
<br>
<p>抓取程序已开源:<a href="https://github.com/zu1k/proxypool">https://github.com/zu1k/proxypool</a></p>
</div>
</div>
</div>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-DC6CR61FHE"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-DC6CR61FHE');
</script>
</body>
</html>

146
assets/html/index.html Normal file
View File

@@ -0,0 +1,146 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="HandheldFriendly" content="True">
<title>免费节点</title>
<meta property="og:site_name" content="免费节点">
<meta property="og:description" content="免费ss,免费ssr,免费v2ray,免费vmess,免费vless,免费shadowsocks,免费shadowsocksr,免费shadowsocksrr,免费shadowrocket,免费quan,免费quanx,免费surge,免费小火箭,白嫖ss,白嫖ssr,白嫖v2ray,白嫖vmess,白嫖vless,白嫖shadowsocks,白嫖shadowsocksr,白嫖shadowsocksrr,白嫖shadowrocket,白嫖quan,白嫖quanx,白嫖surge,白嫖小火箭,高速ss,高速ssr,高速v2ray,高速vmess,高速vless,高速shadowsocks,高速shadowsocksr,高速shadowsocksrr,高速shadowrocket,高速quan,高速quanx,高速surge,高速小火箭,公益ss,公益ssr,公益v2ray,公益vmess,公益vless,公益shadowsocks,公益shadowsocksr,公益shadowsocksrr,公益shadowrocket,公益quan,公益quanx,公益surge,公益小火箭,windowsss,windowsssr,windowsv2ray,windowsvmess,windowsvless,windowsshadowsocks,windowsshadowsocksr,windowsshadowsocksrr,windowsshadowrocket,windowsquan,windowsquanx,windowssurge,windows小火箭,androidss,androidssr,androidv2ray,androidvmess,androidvless,androidshadowsocks,androidshadowsocksr,androidshadowsocksrr,androidshadowrocket,androidquan,androidquanx,androidsurge,android小火箭,iosss,iosssr,iosv2ray,iosvmess,iosvless,iosshadowsocks,iosshadowsocksr,iosshadowsocksrr,iosshadowrocket,iosquan,iosquanx,iossurge,ios小火箭,macss,macssr,macv2ray,macvmess,macvless,macshadowsocks,macshadowsocksr,macshadowsocksrr,macshadowrocket,macquan,macquanx,macsurge,mac小火箭,苹果ss,苹果ssr,苹果v2ray,苹果vmess,苹果vless,苹果shadowsocks,苹果shadowsocksr,苹果shadowsocksrr,苹果shadowrocket,苹果quan,苹果quanx,苹果surge,苹果小火箭,安卓ss,安卓ssr,安卓v2ray,安卓vmess,安卓vless,安卓shadowsocks,安卓shadowsocksr,安卓shadowsocksrr,安卓shadowrocket,安卓quan,安卓quanx,安卓surge,安卓小火箭">
<meta name="keywords" content="免费ss,免费ssr,免费v2ray,免费vmess,免费vless,免费shadowsocks,免费shadowsocksr,免费shadowsocksrr,免费shadowrocket,免费quan,免费quanx,免费surge,免费小火箭,白嫖ss,白嫖ssr,白嫖v2ray,白嫖vmess,白嫖vless,白嫖shadowsocks,白嫖shadowsocksr,白嫖shadowsocksrr,白嫖shadowrocket,白嫖quan,白嫖quanx,白嫖surge,白嫖小火箭,高速ss,高速ssr,高速v2ray,高速vmess,高速vless,高速shadowsocks,高速shadowsocksr,高速shadowsocksrr,高速shadowrocket,高速quan,高速quanx,高速surge,高速小火箭,公益ss,公益ssr,公益v2ray,公益vmess,公益vless,公益shadowsocks,公益shadowsocksr,公益shadowsocksrr,公益shadowrocket,公益quan,公益quanx,公益surge,公益小火箭,windowsss,windowsssr,windowsv2ray,windowsvmess,windowsvless,windowsshadowsocks,windowsshadowsocksr,windowsshadowsocksrr,windowsshadowrocket,windowsquan,windowsquanx,windowssurge,windows小火箭,androidss,androidssr,androidv2ray,androidvmess,androidvless,androidshadowsocks,androidshadowsocksr,androidshadowsocksrr,androidshadowrocket,androidquan,androidquanx,androidsurge,android小火箭,iosss,iosssr,iosv2ray,iosvmess,iosvless,iosshadowsocks,iosshadowsocksr,iosshadowsocksrr,iosshadowrocket,iosquan,iosquanx,iossurge,ios小火箭,macss,macssr,macv2ray,macvmess,macvless,macshadowsocks,macshadowsocksr,macshadowsocksrr,macshadowrocket,macquan,macquanx,macsurge,mac小火箭,苹果ss,苹果ssr,苹果v2ray,苹果vmess,苹果vless,苹果shadowsocks,苹果shadowsocksr,苹果shadowsocksrr,苹果shadowrocket,苹果quan,苹果quanx,苹果surge,苹果小火箭,安卓ss,安卓ssr,安卓v2ray,安卓vmess,安卓vless,安卓shadowsocks,安卓shadowsocksr,安卓shadowsocksrr,安卓shadowrocket,安卓quan,安卓quanx,安卓surge,安卓小火箭">
<style type='text/css'>
body {
background-color: white;
color: #333333;
font-family: Arial, sans-serif;
margin: 0;
padding: 36px;
line-height: 1;
font-size: 14px;
}
.section {
margin-bottom: 36px;
}
.section.friendly {
color: #222222;
}
.section.friendly h1 {
font-size: 26px;
background-color: #dad8e4;
padding: 18px 22px 15px 22px;
margin: 0;
overflow: hidden;
}
.section.friendly h1 strong {
display: inline-block;
float: left;
}
.section.friendly h1 small {
display: inline-block;
float: right;
text-align: right;
font-size: 18px;
padding-top: 4px;
color: #333333;
}
.section.friendly .article {
border: 4px solid #dad8e4;
padding: 24px 18px 18px 18px;
}
.section.friendly .article h3 {
font-size: 20px;
margin: 0 0 18px 0;
}
.section.friendly .article a {
color: #6b6ceb;
}
.section.friendly .article a:visited {
color: #1d1d3b;
}
.section.friendly .article p {
font-size: 14px;
}
.section.friendly .article ul {
list-style-type: square;
}
.section.original {
background-color: #eeeeee;
color: #444444;
}
.section.original h2 {
background-color: #dddddd;
margin: 0;
padding: 18px 22px 18px 22px;
font-size: 20px;
}
.section.original pre {
margin: 0;
padding: 18px 22px 18px 22px;
overflow: auto;
font-family: monaco, monospaced;
}
.section.original pre code {
display: block;
font-size: 11px;
width: 100%;
}
</style>
</head>
<body>
<div class='container'>
<div class='section friendly'>
<h1><strong>免费节点</strong></h1>
<div class='article'>
<p>自动抓取tg频道、订阅地址、公开互联网上的ss、ssr、vmess、trojan节点信息聚合去重后提供节点列表每15分钟更新</p>
<p>汇总节点数量:{{ .all_proxies_count }}</p>
<p>ss节点数量{{ .ss_proxies_count }}</p>
<p>ssr节点数量{{ .ssr_proxies_count }}</p>
<p>vmess节点数量{{ .vmess_proxies_count }}</p>
<p>trojan节点数量{{ .trojan_proxies_count }}</p>
<p>可用节点数量:{{ .useful_proxies_count }}</p>
<br>
<h5><a href="/clash">Clash</a></h5>
<p>Clash配置文件https://{{ .domain }}/clash/config <a
href="clash://install-config?url=https://{{ .domain }}/clash/config">一键导入</a></p>
<p>Clash proxy-provider(Shadowrocket添加订阅方式可用)<a href="https://{{ .domain }}/clash/proxies">https://{{ .domain }}/clash/proxies</a>
</p>
<p>所有节点的Provider(不是都可以用)<a href="https://{{ .domain }}/clash/proxies?type=all">https://{{ .domain }}/clash/proxies?type=all</a>
</p>
<br>
<h5><a href="/surge">Surge</a></h5>
<p>Surge配置文件https://{{ .domain }}/surge/config <a
href="surge3:///install-config?url=https://{{ .domain }}/surge/config">一键导入</a></p>
<p>Surge proxy list<a href="https://{{ .domain }}/surge/proxies">https://{{ .domain }}/surge/proxies</a>
</p>
<br>
{{- /* 所有使用本代码提供服务的禁止删除该行*/}}
<p>抓取程序已开源:<a href="https://github.com/zu1k/proxypool">https://github.com/zu1k/proxypool</a></p>
</div>
</div>
</div>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-DC6CR61FHE"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-DC6CR61FHE');
</script>
</body>
</html>

View File

@@ -3,9 +3,9 @@ Direct = direct
[Proxy Group]
Proxy = select, 延迟最低, 失败切换, 手动选择
延迟最低 = url-test, policy-path=https://proxy.tgbot.co/surge/proxies, url=http://www.qualcomm.cn/generate_204, update-interval=3600, interval = 600s, tolerance = 100ms, timeout = 5s, evaluate-before-use = true
失败切换 = fallback, policy-path=https://proxy.tgbot.co/surge/proxies, url=http://www.qualcomm.cn/generate_204, update-interval=3600, interval = 600s, tolerance = 100ms, timeout = 5s, evaluate-before-use = true
手动选择 = select, policy-path=https://proxy.tgbot.co/surge/proxies, url=http://www.qualcomm.cn/generate_204, update-interval=3600, interval = 600s, tolerance = 100ms, timeout = 5s, evaluate-before-use = true
延迟最低 = url-test, policy-path=https://{{ .domain }}/surge/proxies, url=http://www.qualcomm.cn/generate_204, update-interval=3600, interval = 600s, tolerance = 100ms, timeout = 5s, evaluate-before-use = true
失败切换 = fallback, policy-path=https://{{ .domain }}/surge/proxies, url=http://www.qualcomm.cn/generate_204, update-interval=3600, interval = 600s, tolerance = 100ms, timeout = 5s, evaluate-before-use = true
手动选择 = select, policy-path=https://{{ .domain }}/surge/proxies, url=http://www.qualcomm.cn/generate_204, update-interval=3600, interval = 600s, tolerance = 100ms, timeout = 5s, evaluate-before-use = true
Apple = select, Direct, Proxy
Adblock = select, Direct, REJECT, REJECT-TINYGIF

View File

@@ -73,14 +73,23 @@
<div class='section friendly'>
<h1><strong>免费Surge节点</strong></h1>
<div class='article'>
<p>自动抓取tg频道、订阅地址、公开互联网上的ss、vmess节点信息聚合去重后提供Surge节点列表每10分钟更新</p>
<p>自动抓取tg频道、订阅地址、公开互联网上的ss、vmess节点信息聚合去重后提供Surge节点列表每15分钟更新</p>
<br>
<p>Surge配置文件<a href="https://proxy.tgbot.co/surge/config">https://proxy.tgbot.co/surge/config</a> <a href="surge3:///install-config?url=https://proxy.tgbot.co/surge/config">一键导入</a></p>
<p>Surge proxy list<a href="https://proxy.tgbot.co/surge/proxies">https://proxy.tgbot.co/surge/proxies</a></p>
<p>Surge配置文件https://{{ .domain }}/surge/config <a href="surge3:///install-config?url=https://{{ .domain }}/surge/config">一键导入</a></p>
<p>Surge proxy list<a href="https://{{ .domain }}/surge/proxies">https://{{ .domain }}/surge/proxies</a></p>
<br>
<p>抓取程序已开源:<a href="https://github.com/zu1k/proxypool">https://github.com/zu1k/proxypool</a></p>
</div>
</div>
</div>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-DC6CR61FHE"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-DC6CR61FHE');
</script>
</body>
</html>

View File

@@ -1,127 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="HandheldFriendly" content="True">
<title>免费节点</title>
<style type='text/css'>
body {
background-color: white;
color: #333333;
font-family: Arial, sans-serif;
margin: 0;
padding: 36px;
line-height: 1;
font-size: 14px;
}
.section {
margin-bottom: 36px;
}
.section.friendly {
color: #222222;
}
.section.friendly h1 {
font-size: 26px;
background-color: #dad8e4;
padding: 18px 22px 15px 22px;
margin: 0;
overflow: hidden;
}
.section.friendly h1 strong {
display: inline-block;
float: left;
}
.section.friendly h1 small {
display: inline-block;
float: right;
text-align: right;
font-size: 18px;
padding-top: 4px;
color: #333333;
}
.section.friendly .article {
border: 4px solid #dad8e4;
padding: 24px 18px 18px 18px;
}
.section.friendly .article h3 {
font-size: 20px;
margin: 0 0 18px 0;
}
.section.friendly .article a {
color: #6b6ceb;
}
.section.friendly .article a:visited {
color: #1d1d3b;
}
.section.friendly .article p {
font-size: 14px;
}
.section.friendly .article ul {
list-style-type: square;
}
.section.original {
background-color: #eeeeee;
color: #444444;
}
.section.original h2 {
background-color: #dddddd;
margin: 0;
padding: 18px 22px 18px 22px;
font-size: 20px;
}
.section.original pre {
margin: 0;
padding: 18px 22px 18px 22px;
overflow: auto;
font-family: monaco, monospaced;
}
.section.original pre code {
display: block;
font-size: 11px;
width: 100%;
}
</style>
</head>
<body>
<div class='container'>
<div class='section friendly'>
<h1><strong>免费节点</strong></h1>
<div class='article'>
<p>自动抓取tg频道、订阅地址、公开互联网上的ss、ssr、vmess节点信息聚合去重后提供节点列表每10分钟更新</p>
<br>
<h5><a href="/clash">Clash</a></h5>
<p>Clash配置文件<a href="https://proxy.tgbot.co/clash/config">https://proxy.tgbot.co/clash/config</a> <a
href="clash://install-config?url=https://proxy.tgbot.co/clash/config">一键导入</a></p>
<p>Clash proxy-provider(Shadowrocket添加订阅方式可用)<a href="https://proxy.tgbot.co/clash/proxies">https://proxy.tgbot.co/clash/proxies</a>
</p>
<p>所有节点的Provider(不是都可以用)<a href="https://proxy.tgbot.co/clash/proxies?type=all">https://proxy.tgbot.co/clash/proxies?type=all</a>
</p>
<br>
<h5><a href="/surge">Surge</a></h5>
<p>Surge配置文件<a href="https://proxy.tgbot.co/surge/config">https://proxy.tgbot.co/surge/config</a> <a
href="surge3:///install-config?url=https://proxy.tgbot.co/surge/config">一键导入</a></p>
<p>Surge proxy list<a href="https://proxy.tgbot.co/surge/proxies">https://proxy.tgbot.co/surge/proxies</a>
</p>
<br>
<p>抓取程序已开源:<a href="https://github.com/zu1k/proxypool">https://github.com/zu1k/proxypool</a></p>
</div>
</div>
</div>
</body>
</html>

BIN
assets/proxy.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@@ -6,7 +6,12 @@ import (
"os"
"github.com/ghodss/yaml"
"github.com/zu1k/proxypool/tool"
"github.com/zu1k/proxypool/pkg/tool"
)
var (
NeedFetch = true
Url = "source.yaml"
)
type Source struct {
@@ -15,6 +20,9 @@ type Source struct {
}
type Config struct {
Domain string `json:"domain" yaml:"domain"`
CFEmail string `json:"cf_email" yaml:"cf_email"`
CFKey string `json:"cf_key" yaml:"cf_key"`
Sources []Source `json:"sources" yaml:"sources"`
}
@@ -30,6 +38,15 @@ func Parse(path string) (*Config, error) {
if err != nil {
return nil, err
}
if domain := os.Getenv("DOMAIN"); domain != "" {
SourceConfig.Domain = domain
}
if cfEmail := os.Getenv("CF_API_EMAIL"); cfEmail != "" {
SourceConfig.CFEmail = cfEmail
}
if cfKey := os.Getenv("CF_API_KEY"); cfKey != "" {
SourceConfig.CFKey = cfKey
}
return &SourceConfig, nil
}

View File

@@ -1,25 +1,33 @@
domain: proxy.tgbot.co
cf_email: ""
cf_key: ""
sources:
# 模糊抓取订阅链接
- type: webfuzzsub
options:
url: https://raw.githubusercontent.com/du5/free/master/sub.list
# 订阅链接
- type: subscribe
options:
url: https://raw.githubusercontent.com/ssrsub/ssr/master/v2ray
# 网页模糊抓取
- type: webfuzz
options:
url: https://merlinblog.xyz/wiki/freess.html
# tg频道抓取
- type: tgchannel
options:
channel: ssrList
num: 200
- type: web-fanqiangdang
# 翻墙党论坛抓取
- type: web-fanqiangdang-rss
options:
url: https://fanqiangdang.com/forum.php?mod=rss&fid=50&auth=0
num: 200
# 某个网站抓取
- type: web-freessrxyz
options:

View File

@@ -1,81 +0,0 @@
package getter
import (
"fmt"
"sync"
"github.com/gocolly/colly"
"github.com/zu1k/proxypool/proxy"
"github.com/zu1k/proxypool/tool"
)
func init() {
Register("web-fanqiangdang", NewWebFanqiangdangGetter)
}
type WebFanqiangdang struct {
c *colly.Collector
NumNeeded int
Url string
results []string
}
func NewWebFanqiangdangGetter(options tool.Options) (getter Getter, err error) {
num, found := options["num"]
t := 200
switch num.(type) {
case int:
t = num.(int)
case float64:
t = int(num.(float64))
}
if !found || t <= 0 {
t = 200
}
urlInterface, found := options["url"]
if found {
url, err := AssertTypeStringNotNull(urlInterface)
if err != nil {
return nil, err
}
return &WebFanqiangdang{
c: colly.NewCollector(),
NumNeeded: t,
Url: url,
}, nil
}
return nil, ErrorUrlNotFound
}
func (w *WebFanqiangdang) Get() proxy.ProxyList {
w.results = make([]string, 0)
// 找到所有的文字消息
w.c.OnHTML("td.t_f", func(e *colly.HTMLElement) {
w.results = append(w.results, GrepLinksFromString(e.Text)...)
})
// 从订阅中取出每一页,因为是订阅,所以都比较新
w.c.OnXML("//item//link", func(e *colly.XMLElement) {
if len(w.results) < w.NumNeeded {
_ = e.Request.Visit(e.Text)
}
})
w.results = make([]string, 0)
err := w.c.Visit(w.Url)
if err != nil {
_ = fmt.Errorf("%s", err.Error())
}
return StringArray2ProxyArray(w.results)
}
func (w *WebFanqiangdang) Get2Chan(pc chan proxy.Proxy, wg *sync.WaitGroup) {
defer wg.Done()
nodes := w.Get()
for _, node := range nodes {
pc <- node
}
}

1
go.mod
View File

@@ -9,6 +9,7 @@ require (
github.com/antchfx/htmlquery v1.2.3 // indirect
github.com/antchfx/xmlquery v1.2.4 // indirect
github.com/antchfx/xpath v1.1.8 // indirect
github.com/cloudflare/cloudflare-go v0.13.0
github.com/ghodss/yaml v1.0.0
github.com/gin-gonic/gin v1.6.3
github.com/go-playground/validator/v10 v10.3.0 // indirect

14
go.sum
View File

@@ -28,7 +28,10 @@ github.com/aws/aws-sdk-go v1.13.10/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41Zo
github.com/axiomhq/hyperloglog v0.0.0-20180317131949-fe9507de0228/go.mod h1:IOXAcuKIFq/mDyuQ4wyJuJ79XLMsmLM+5RdQ+vWrL7o=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/cloudflare-go v0.13.0 h1:Mx2gNz/r4H0eHETENq5ZPtc/kOX/uzEfT2UFuA+/XAU=
github.com/cloudflare/cloudflare-go v0.13.0/go.mod h1:6rZ6s/XWxP8WIWMATgDM7aUop0Z0ZOAfcm/4rEd0lOY=
github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -163,6 +166,7 @@ github.com/lstoll/grpce v1.7.0/go.mod h1:XiCWl3R+avNCT7KsTjv3qCblgsSqd0SC4ymySrH
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/miekg/dns v1.1.29 h1:xHBEhR+t5RzcFJjBLJlax2daXOrTYtr9z4WdKEfWFzg=
github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615 h1:/mD+ABZyXD39BzJI2XyRJlqdZG11gXFo0SSynL+OFeU=
@@ -176,6 +180,7 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
@@ -190,6 +195,8 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.2-0.20190227000051-27936f6d90f9/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -198,6 +205,7 @@ github.com/rcrowley/go-metrics v0.0.0-20160613154715-cfa5a85e9f0a/go.mod h1:bCqn
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rollbar/rollbar-go v1.0.2/go.mod h1:AcFs5f0I+c71bpHlXNNDbOWJiKwjFDtISeXco0L5PKQ=
github.com/rollbar/rollbar-go v1.2.0/go.mod h1:czC86b8U4xdUH7W2C6gomi2jutLm8qK0OtrF5WMvpcc=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
@@ -207,6 +215,7 @@ github.com/shirou/gopsutil v2.20.7+incompatible h1:Ymv4OD12d6zm+2yONe39VSmp2XooJ
github.com/shirou/gopsutil v2.20.7+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
@@ -231,6 +240,8 @@ github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/unrolled/secure v1.0.1/go.mod h1:R6rugAuzh4TQpbFAq69oqZggyBQxFRFQIewtz5z7Jsc=
github.com/urfave/cli v1.21.0/go.mod h1:lxDj6qX9Q6lWQxIrbrT0nwecwUtRnhVZAJjJZrVUZZQ=
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ=
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@@ -277,6 +288,7 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4=
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -317,6 +329,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@@ -5,7 +5,7 @@ import (
"fmt"
"github.com/zu1k/proxypool/config"
"github.com/zu1k/proxypool/getter"
"github.com/zu1k/proxypool/pkg/getter"
)
var Getters = make([]getter.Getter, 0)

View File

@@ -6,18 +6,16 @@ import (
"log"
"sync"
"github.com/zu1k/proxypool/app/cache"
"github.com/zu1k/proxypool/config"
"github.com/zu1k/proxypool/provider"
"github.com/zu1k/proxypool/proxy"
"github.com/zu1k/proxypool/tool"
"github.com/zu1k/proxypool/internal/cache"
"github.com/zu1k/proxypool/pkg/provider"
"github.com/zu1k/proxypool/pkg/proxy"
"github.com/zu1k/proxypool/pkg/tool"
"gopkg.in/yaml.v2"
)
var NeedFetchNewConfigFile = false
func CrawlGo() {
if NeedFetchNewConfigFile {
if config.NeedFetch {
FetchNewConfigFileThenInit()
}
wg := &sync.WaitGroup{}
@@ -42,12 +40,18 @@ func CrawlGo() {
proxies = provider.Clash{Proxies: proxies}.CleanProxies()
proxies.NameAddCounrty().Sort().NameAddIndex()
cache.SetProxies("allproxies", proxies)
cache.AllProxiesCount = proxies.Len()
cache.SSProxiesCount = proxies.TypeLen("ss")
cache.SSRProxiesCount = proxies.TypeLen("ssr")
cache.VmessProxiesCount = proxies.TypeLen("vmess")
cache.TrojanProxiesCount = proxies.TypeLen("trojan")
// 可用性检测
proxies = proxy.CleanBadProxies(proxies)
log.Println("CrawlGo clash useable node count:", len(proxies))
proxies.NameAddCounrty().Sort().NameAddIndex()
cache.SetProxies("proxies", proxies)
cache.UsefullProxiesCount = proxies.Len()
cache.SetString("clashproxies", provider.Clash{Proxies: proxies}.Provide())
cache.SetString("surgeproxies", provider.Surge{Proxies: proxies}.Provide())
@@ -55,7 +59,7 @@ func CrawlGo() {
func FetchNewConfigFileThenInit() {
fmt.Println("fetch new config file...")
resp, err := tool.GetHttpClient().Get("https://raw.githubusercontent.com/zu1k/proxypool/master/source.yaml")
resp, err := tool.GetHttpClient().Get(config.Url)
if err != nil {
return
}

View File

@@ -5,7 +5,7 @@ import (
"time"
"github.com/patrickmn/go-cache"
"github.com/zu1k/proxypool/proxy"
"github.com/zu1k/proxypool/pkg/proxy"
)
var c = cache.New(cache.NoExpiration, 10*time.Minute)

11
internal/cache/vars.go vendored Normal file
View File

@@ -0,0 +1,11 @@
package cache
var (
AllProxiesCount = 0
SSRProxiesCount = 0
SSProxiesCount = 0
VmessProxiesCount = 0
TrojanProxiesCount = 0
UsefullProxiesCount = 0
)

View File

@@ -0,0 +1,30 @@
package cloudflare
import (
"fmt"
"log"
"github.com/cloudflare/cloudflare-go"
"github.com/zu1k/proxypool/config"
)
func test() {
api, err := cloudflare.New(config.SourceConfig.CFKey, config.SourceConfig.CFKey)
if err != nil {
log.Fatal(err)
}
// Fetch the zone ID
id, err := api.ZoneIDByName(config.SourceConfig.Domain)
if err != nil {
log.Fatal(err)
}
// Fetch zone details
zone, err := api.ZoneDetails(id)
if err != nil {
log.Fatal(err)
}
// Print zone details
fmt.Println(zone)
}

11
internal/cron/cron.go Normal file
View File

@@ -0,0 +1,11 @@
package cron
import (
"github.com/jasonlvhit/gocron"
"github.com/zu1k/proxypool/internal/app"
)
func Cron() {
_ = gocron.Every(15).Minutes().Do(app.CrawlGo)
<-gocron.Start()
}

43
main.go
View File

@@ -5,11 +5,17 @@ import (
"fmt"
"net/http"
_ "net/http/pprof"
"os"
"strings"
"github.com/zu1k/proxypool/config"
"github.com/zu1k/proxypool/internal/cron"
_ "github.com/mkevac/debugcharts"
"github.com/zu1k/proxypool/api"
"github.com/zu1k/proxypool/app"
"github.com/zu1k/proxypool/proxy"
"github.com/zu1k/proxypool/internal/app"
"github.com/zu1k/proxypool/pkg/proxy"
)
var (
@@ -26,22 +32,39 @@ func main() {
go pprof()
}
if configFilePath == "" {
app.NeedFetchNewConfigFile = true
} else {
err := app.InitConfigAndGetters(configFilePath)
if err != nil {
fmt.Println(err)
}
envConfigFilePath := os.Getenv("CONFIG_FILE")
if envConfigFilePath == "" {
envConfigFilePath = "source.yaml"
}
if configFilePath != "" {
initConfigFile(configFilePath)
} else {
initConfigFile(envConfigFilePath)
}
proxy.InitGeoIpDB()
go app.Cron()
go cron.Cron()
fmt.Println("Do the first crawl...")
go app.CrawlGo()
api.Run()
}
func initConfigFile(path string) {
if strings.HasPrefix(path, "http") {
config.Url = path
config.NeedFetch = true
app.FetchNewConfigFileThenInit()
} else {
err := app.InitConfigAndGetters(configFilePath)
if err != nil {
fmt.Errorf("Config file not found")
os.Exit(2)
}
}
}
func pprof() {
ip := "127.0.0.1:6060"
if err := http.ListenAndServe(ip, nil); err != nil {

View File

@@ -5,8 +5,8 @@ import (
"strings"
"sync"
"github.com/zu1k/proxypool/proxy"
"github.com/zu1k/proxypool/tool"
"github.com/zu1k/proxypool/pkg/proxy"
"github.com/zu1k/proxypool/pkg/tool"
)
type Getter interface {
@@ -39,6 +39,8 @@ func String2Proxy(link string) proxy.Proxy {
data, err = proxy.ParseVmessLink(link)
} else if strings.HasPrefix(link, "ss://") {
data, err = proxy.ParseSSLink(link)
} else if strings.HasPrefix(link, "trojan://") {
data, err = proxy.ParseTrojanLink(link)
}
if err != nil {
return nil
@@ -58,6 +60,7 @@ func GrepLinksFromString(text string) []string {
results := proxy.GrepSSRLinkFromString(text)
results = append(results, proxy.GrepVmessLinkFromString(text)...)
results = append(results, proxy.GrepSSLinkFromString(text)...)
results = append(results, proxy.GrepTrojanLinkFromString(text)...)
return results
}

View File

@@ -5,8 +5,8 @@ import (
"strings"
"sync"
"github.com/zu1k/proxypool/proxy"
"github.com/zu1k/proxypool/tool"
"github.com/zu1k/proxypool/pkg/proxy"
"github.com/zu1k/proxypool/pkg/tool"
)
func init() {

View File

@@ -5,8 +5,8 @@ import (
"sync"
"github.com/gocolly/colly"
"github.com/zu1k/proxypool/proxy"
"github.com/zu1k/proxypool/tool"
"github.com/zu1k/proxypool/pkg/proxy"
"github.com/zu1k/proxypool/pkg/tool"
)
func init() {
@@ -49,10 +49,16 @@ func NewTGChannelGetter(options tool.Options) (getter Getter, err error) {
}
func (g *TGChannelGetter) Get() proxy.ProxyList {
result := make(proxy.ProxyList, 0)
g.results = make([]string, 0)
// 找到所有的文字消息
g.c.OnHTML("div.tgme_widget_message_text", func(e *colly.HTMLElement) {
g.results = append(g.results, GrepLinksFromString(e.Text)...)
// 抓取到http链接有可能是订阅链接或其他链接无论如何试一下
subUrls := urlRe.FindAllString(e.Text, -1)
for _, url := range subUrls {
result = append(result, (&Subscribe{Url: url}).Get()...)
}
})
// 找到之前消息页面的链接,加入访问队列
@@ -67,8 +73,7 @@ func (g *TGChannelGetter) Get() proxy.ProxyList {
if err != nil {
_ = fmt.Errorf("%s", err.Error())
}
return StringArray2ProxyArray(g.results)
return append(result, StringArray2ProxyArray(g.results)...)
}
func (g *TGChannelGetter) Get2Chan(pc chan proxy.Proxy, wg *sync.WaitGroup) {

View File

@@ -0,0 +1,120 @@
package getter
import (
"fmt"
"strings"
"sync"
"github.com/gocolly/colly"
"github.com/zu1k/proxypool/pkg/proxy"
"github.com/zu1k/proxypool/pkg/tool"
)
func init() {
Register("web-fanqiangdang-rss", NewWebFanqiangdangRSSGetter)
Register("web-fanqiangdang", NewWebFanqiangdangGetter)
}
type WebFanqiangdang struct {
c *colly.Collector
Url string
results proxy.ProxyList
}
func NewWebFanqiangdangGetter(options tool.Options) (getter Getter, err error) {
urlInterface, found := options["url"]
if found {
url, err := AssertTypeStringNotNull(urlInterface)
if err != nil {
return nil, err
}
return &WebFanqiangdang{
c: colly.NewCollector(),
Url: url,
}, nil
}
return nil, ErrorUrlNotFound
}
func (w *WebFanqiangdang) Get() proxy.ProxyList {
w.results = make(proxy.ProxyList, 0)
w.c.OnHTML("td.t_f", func(e *colly.HTMLElement) {
w.results = append(w.results, FuzzParseProxyFromString(e.Text)...)
subUrls := urlRe.FindAllString(e.Text, -1)
for _, url := range subUrls {
w.results = append(w.results, (&Subscribe{Url: url}).Get()...)
}
})
w.c.OnHTML("th.new>a[href]", func(e *colly.HTMLElement) {
url := e.Attr("href")
if strings.HasPrefix(url, "https://fanqiangdang.com/thread") {
_ = e.Request.Visit(url)
}
})
w.results = make(proxy.ProxyList, 0)
err := w.c.Visit(w.Url)
if err != nil {
_ = fmt.Errorf("%s", err.Error())
}
return w.results
}
func (w *WebFanqiangdang) Get2Chan(pc chan proxy.Proxy, wg *sync.WaitGroup) {
defer wg.Done()
nodes := w.Get()
for _, node := range nodes {
pc <- node
}
}
type WebFanqiangdangRSS struct {
c *colly.Collector
Url string
results []string
}
func NewWebFanqiangdangRSSGetter(options tool.Options) (getter Getter, err error) {
urlInterface, found := options["url"]
if found {
url, err := AssertTypeStringNotNull(urlInterface)
if err != nil {
return nil, err
}
return &WebFanqiangdangRSS{
c: colly.NewCollector(),
Url: url,
}, nil
}
return nil, ErrorUrlNotFound
}
func (w *WebFanqiangdangRSS) Get() proxy.ProxyList {
w.results = make([]string, 0)
w.c.OnHTML("td.t_f", func(e *colly.HTMLElement) {
w.results = append(w.results, GrepLinksFromString(e.Text)...)
})
w.c.OnXML("//item//link", func(e *colly.XMLElement) {
_ = e.Request.Visit(e.Text)
})
w.results = make([]string, 0)
err := w.c.Visit(w.Url)
if err != nil {
_ = fmt.Errorf("%s", err.Error())
}
return StringArray2ProxyArray(w.results)
}
func (w *WebFanqiangdangRSS) Get2Chan(pc chan proxy.Proxy, wg *sync.WaitGroup) {
defer wg.Done()
nodes := w.Get()
for _, node := range nodes {
pc <- node
}
}

View File

@@ -5,8 +5,8 @@ import (
"io/ioutil"
"sync"
"github.com/zu1k/proxypool/proxy"
"github.com/zu1k/proxypool/tool"
"github.com/zu1k/proxypool/pkg/proxy"
"github.com/zu1k/proxypool/pkg/tool"
)
func init() {

View File

@@ -4,8 +4,8 @@ import (
"io/ioutil"
"sync"
"github.com/zu1k/proxypool/proxy"
"github.com/zu1k/proxypool/tool"
"github.com/zu1k/proxypool/pkg/proxy"
"github.com/zu1k/proxypool/pkg/tool"
)
func init() {

View File

@@ -5,8 +5,8 @@ import (
"regexp"
"sync"
"github.com/zu1k/proxypool/proxy"
"github.com/zu1k/proxypool/tool"
"github.com/zu1k/proxypool/pkg/proxy"
"github.com/zu1k/proxypool/pkg/tool"
)
func init() {
@@ -80,7 +80,7 @@ const (
domainPattern = `[a-zA-Z0-9][a-zA-Z0-9_-]{0,62}(\.[a-zA-Z0-9][a-zA-Z0-9_-]{0,62})*(\.[a-zA-Z][a-zA-Z0-9]{0,10}){1}`
// 匹配 URL
urlPattern = `((https|http|ftp|rtsp|mms)?://)?` + // 协议
urlPattern = `((https|http)?://)?` + // 协议
`(([0-9a-zA-Z]+:)?[0-9a-zA-Z_-]+@)?` + // pwd:user@
"(" + ipPattern + "|(" + domainPattern + "))" + // IP 或域名
`(:\d{1,5})?` + // 端口

View File

@@ -3,7 +3,7 @@ package provider
import (
"strings"
"github.com/zu1k/proxypool/proxy"
"github.com/zu1k/proxypool/pkg/proxy"
)
type Clash struct {
@@ -64,6 +64,8 @@ func checkClashSupport(p proxy.Proxy) bool {
if checkInList(ssCipherList, ss.Cipher) {
return true
}
case "trojan":
return true
default:
return false
}

View File

@@ -3,7 +3,7 @@ package provider
import (
"strings"
"github.com/zu1k/proxypool/proxy"
"github.com/zu1k/proxypool/pkg/proxy"
)
type Surge struct {

View File

@@ -11,6 +11,16 @@ func (ps ProxyList) Len() int {
return len(ps)
}
func (ps ProxyList) TypeLen(t string) int {
l := 0
for _, p := range ps {
if p.TypeName() == t {
l++
}
}
return l
}
func (ps ProxyList) Less(i, j int) bool {
return ps[i].BaseInfo().Name < ps[j].BaseInfo().Name
}

View File

@@ -11,7 +11,7 @@ import (
"strconv"
"strings"
"github.com/zu1k/proxypool/tool"
"github.com/zu1k/proxypool/pkg/tool"
)
var (

View File

@@ -10,7 +10,7 @@ import (
"strconv"
"strings"
"github.com/zu1k/proxypool/tool"
"github.com/zu1k/proxypool/pkg/tool"
)
var (

147
pkg/proxy/trojan.go Normal file
View File

@@ -0,0 +1,147 @@
package proxy
import (
"encoding/json"
"errors"
"math/rand"
"net"
"net/url"
"regexp"
"strconv"
"strings"
)
var (
ErrorNotTrojanink = errors.New("not a correct trojan link")
)
type Trojan struct {
Base
Password string `yaml:"password" json:"password"`
ALPN []string `yaml:"alpn,omitempty" json:"alpn,omitempty"`
SNI string `yaml:"sni,omitempty" json:"sni,omitempty"`
SkipCertVerify bool `yaml:"skip-cert-verify,omitempty" json:"skip-cert-verify,omitempty"`
UDP bool `yaml:"udp,omitempty" json:"udp,omitempty"`
}
/**
- name: "trojan"
type: trojan
server: server
port: 443
password: yourpsk
# udp: true
# sni: example.com # aka server name
# alpn:
# - h2
# - http/1.1
# skip-cert-verify: true
*/
func (t Trojan) Identifier() string {
return net.JoinHostPort(t.Server, strconv.Itoa(t.Port)) + t.Password
}
func (t Trojan) String() string {
data, err := json.Marshal(t)
if err != nil {
return ""
}
return string(data)
}
func (t Trojan) ToClash() string {
data, err := json.Marshal(t)
if err != nil {
return ""
}
return "- " + string(data)
}
func (t Trojan) ToSurge() string {
return ""
}
func (t Trojan) Clone() Proxy {
return &t
}
func ParseTrojanLink(link string) (*Trojan, error) {
if !strings.HasPrefix(link, "trojan://") && !strings.HasPrefix(link, "trojan-go://") {
return nil, ErrorNotTrojanink
}
/**
trojan-go://
$(trojan-password)
@
trojan-host
:
port
/?
sni=$(tls-sni.com)&
type=$(original|ws|h2|h2+ws)&
host=$(websocket-host.com)&
path=$(/websocket/path)&
encryption=$(ss;aes-256-gcm;ss-password)&
plugin=$(...)
#$(descriptive-text)
*/
uri, err := url.Parse(link)
if err != nil {
return nil, ErrorNotSSLink
}
password := uri.User.Username()
password, _ = url.QueryUnescape(password)
server := uri.Hostname()
port, _ := strconv.Atoi(uri.Port())
moreInfos := uri.Query()
sni := moreInfos.Get("sni")
sni, _ = url.QueryUnescape(sni)
transformType := moreInfos.Get("type")
transformType, _ = url.QueryUnescape(transformType)
host := moreInfos.Get("host")
host, _ = url.QueryUnescape(host)
path := moreInfos.Get("path")
path, _ = url.QueryUnescape(path)
alpn := make([]string, 0)
if transformType == "h2" {
alpn = append(alpn, "h2")
}
if port == 0 {
return nil, ErrorNotTrojanink
}
return &Trojan{
Base: Base{
Name: strconv.Itoa(rand.Int()),
Server: server,
Port: port,
Type: "trojan",
},
Password: password,
ALPN: alpn,
UDP: true,
SNI: host,
SkipCertVerify: true,
}, nil
}
var (
trojanPlainRe = regexp.MustCompile("trojan(-go)?://([A-Za-z0-9+/_&?=@:%.-])+")
)
func GrepTrojanLinkFromString(text string) []string {
results := make([]string, 0)
texts := strings.Split(text, "trojan://")
for _, text := range texts {
results = append(results, trojanPlainRe.FindAllString("trojan://"+text, -1)...)
}
return results
}

View File

@@ -11,7 +11,7 @@ import (
"strconv"
"strings"
"github.com/zu1k/proxypool/tool"
"github.com/zu1k/proxypool/pkg/tool"
)
var (
@@ -40,7 +40,7 @@ type HTTPOptions struct {
}
func (v Vmess) Identifier() string {
return net.JoinHostPort(v.Server, strconv.Itoa(v.Port)) + v.Cipher
return net.JoinHostPort(v.Server, strconv.Itoa(v.Port)) + v.Cipher + v.UUID
}
func (v Vmess) String() string {

View File

@@ -1,313 +0,0 @@
sources:
- type: webfuzzsub
options:
url: https://raw.githubusercontent.com/du5/free/master/sub.list
# 订阅链接
- type: subscribe
options:
url: https://suda.sub.koicloud.pw/link/K9vz0uFPe9ULfdqX?sub=3
- type: subscribe
options:
url: https://raw.githubusercontent.com/Pcrab/Dotfiles/912c1104b3f8121f72f7ee11590f52bc9c44dde7/.config/electron-ssr/gui-config.json
- type: subscribe
options:
url: https://v2.fit/modules/servers/V2raySocks/osubscribe.php?sid=7063&token=lKJwbO2onxIr
- type: subscribe
options:
url: https://www.liesauer.net/yogurt/subscribe?ACCESS_TOKEN=d309c6921bbd7d0d
- type: subscribe
options:
url: https://neurotoxinw.coding.net/p/qifei/d/qifei/git/raw/master/README.md
- type: subscribe
options:
url: https://sbnmsl.co/link/2cpTGUGJtHBXUK7d?sub=3
- type: subscribe
options:
url: https://extrm.info/link/uirPjznB7esOezjr?sub=1
- type: subscribe
options:
url: http://www.sksla.pro/api/v1/client/subscribe?token=99c3fa86424539bd3bd34a893bc6dee8
- type: subscribe
options:
url: https://vvsub.xyz/api/al/19786-xDX1SCq61Ymi
- type: subscribe
options:
url: https://rss-node.com/link/vqOaWFJRfbYxpAhY?mu=1
- type: subscribe
options:
url: https://tm2w.live/link/EqICUlKXmn1EJwaw?sub=3
- type: subscribe
options:
url: https://dingyue.suying666.info/link/o7j43Aykx8CWBehE?sub=3
- type: subscribe
options:
url: https://dingyue.suying666.info/link/o7j43Aykx8CWBehE?sub=1
- type: subscribe
options:
url: https://www.haidaobot.xyz/link/QwdUmWolPN0LkThW?mu=2
- type: subscribe
options:
url: https://pptp.cloud/sub/cXHG9wqUpQbhHr7b.html
- type: subscribe
options:
url: https://suda.sub.koicloud.pw/link/JgULLCNkImsJ6Ibh?sub=3
- type: subscribe
options:
url: https://jiyou.world/modules/servers/V2raySocks/osubscribetest.php?sid=57394&token=V3GM60lgqZL9
- type: subscribe
options:
url: https://aero.moe/link/kxdbKdopH3paUqUf?sub=3
- type: subscribe
options:
url: http://dy.tntv2.xyz/link/pTL0RgiVblXLIQjS?sub=3&extend=1
- type: subscribe
options:
url: https://719401146.online//link/oHPA3bXVc2zeqGGq?mu=2
- type: subscribe
options:
url: https://www.v2ray.pw/link/b5e255KbnnATXc60?mu=2+&extend=1
- type: subscribe
options:
url: http://ssrdingyue.ueuo.com/v2/8y12r
- type: subscribe
options:
url: https://www.suncloud.fun/link/Su683BQEyUdxtyuY?mu=1&extend=1
- type: subscribe
options:
url: https://sub88.xyz/link/egy4oyqok9aavpcy?sub=3
- type: subscribe
options:
url: https://qiaomenzhuanfx.netlify.com/
- type: subscribe
options:
url: https://sub88.xyz/link/lkY8Jt5Q3SHlffra?mu=2
- type: subscribe
options:
url: https://raw.githubusercontent.com/hotsymbol/vpnsetting/master/v2rayopen
- type: subscribe
options:
url: https://raw.githubusercontent.com/satrom/V2SSR/master/V2RAY/Sub.txt
- type: subscribe
options:
url: https://raw.githubusercontent.com/ssrsub/ssr/master/v2ray
- type: subscribe
options:
url: http://qe83xk711.sabkt.gdipper.com/freev2ray.txt
- type: subscribe
options:
url: https://iwxf.netlify.app/
- type: subscribe
options:
url: https://rss.getfree.win/link/w9ted9eZq1zbC3gx?sub=1
- type: subscribe
options:
url: https://youlianboshi.netlify.com/
- type: subscribe
options:
url: https://raw.githubusercontent.com/ssrsub/ssr/master/ss-sub
- type: subscribe
options:
url: https://bujidao302.com/link/IJ6wKEt96Otboilb?mu=2
- type: subscribe
options:
url: https://raw.githubusercontent.com/satrom/V2SSR/master/SSR/Day.txt
- type: subscribe
options:
url: https://raw.githubusercontent.com/ntkernel/lantern/master/vmess_base64.txt
- type: subscribe
options:
url: https://lei-su.me//link/Dw3lmyXXJJTnvsBA?sub=3&extend=1
- type: subscribe
options:
url: https://raw.githubusercontent.com/cdp2020/v2ray/master/README.md
- type: subscribe
options:
url: https://raw.githubusercontent.com/ssrsub/ssr/master/ssrsub
- type: subscribe
options:
url: https://www.liesauer.net/yogurt/subscribe?ACCESS_TOKEN=DAYxR3mMaZAsaqUb
- type: subscribe
options:
url: https://rss.cnrss.xyz/link/Rcr8h8fvZIWE001U?mu=2
- type: subscribe
options:
url: https://12o.ooo/link/JLisT80gOhRkiFnX?sub=1
- type: subscribe
options:
url: https://sub1.m87sub.xyz/link/pZDgnxhgL6Poh1GQ?sub=3
- type: subscribe
options:
url: https://raw.githubusercontent.com/satrom/V2SSR/master/SSR/Sub.txt
- type: subscribe
options:
url: https://sub88.xyz/link/lkY8Jt5Q3SHlffra?mu=2
- type: subscribe
options:
url: https://s.sublank.xyz/subscribe/66056/0yzuMVawjpr/ssr/
- type: subscribe
options:
url: https://sub1.m87sub.xyz/link/pZDgnxhgL6Poh1GQ?sub=1
- type: subscribe
options:
url: http://qe83xk711.sabkt.gdipper.com/freess.txt
- type: subscribe
options:
url: https://raw.githubusercontent.com/pojiezhiyuanjun/freev2/master/20200808.txt
- type: subscribe
options:
url: https://sub1.m87sub.xyz/link/2488O6IM4n4nksMG?sub=3
- type: subscribe
options:
url: http://103.72.166.89/v2ray.php
- type: subscribe
options:
url: https://fly.lo-lita.ru/api/v1/client/subscribe?token=94be7fa3d65791197dd10c6a0b757571
- type: subscribe
options:
url: https://raw.githubusercontent.com/RaymondHarris971/ssrsub/master/9a075bdee5.txt
- type: subscribe
options:
url: https://bit.ly/2D5fWhX
- type: subscribe
options:
url: https://www.suncloud.fun/link/ja3OIcMTrky6VhN6?mu=1&extend=1
- type: subscribe
options:
url: https://raw.githubusercontent.com/voken100g/AutoSSR/master/recent
- type: subscribe
options:
url: https://jiang.netlify.com/
- type: subscribe
options:
url: https://raw.githubusercontent.com/ssrsub/ssr/master/v2ray
- type: subscribe
options:
url: https://raw.githubusercontent.com/ssrsub/ssr/master/ssrsub
- type: subscribe
options:
url: https://raw.githubusercontent.com/ssrsub/ssr/master/ss-sub
- type: subscribe
options:
url: https://heikejilaila.xyz/keji.php?id=22c7b9fdda20bb7405b270cd75971f66
- type: subscribe
options:
url: https://youlianboshi.netlify.app/
- type: subscribe
options:
url: https://raw.githubusercontent.com/umelabs/node.umelabs.dev/master/Subscribe/SS.md
- type: subscribe
options:
url: https://raw.githubusercontent.com/umelabs/node.umelabs.dev/master/Subscribe/SSR.md
- type: subscribe
options:
url: https://raw.githubusercontent.com/umelabs/node.umelabs.dev/master/Subscribe/v2ray.md
- type: subscribe
options:
url: https://www.3kla.cn/subscribe/txt/Anranray.txt
# 网页模糊抓取
- type: webfuzz
options:
url: https://zfjvpn.gitbook.io/
- type: webfuzz
options:
url: https://www.freefq.com/d/file/free-ssr/20200811/1f3e9d0d0064f662457062712dcf1b66.txt
- type: webfuzz
options:
url: https://merlinblog.xyz/wiki/freess.html
- type: webfuzz
options:
url: https://zfjvpn.gitbook.io/123/
- type: webfuzz
options:
url: https://raw.githubusercontent.com/ruanfei/ShadowsocksRRShare/master/ss/ss.txt
- type: webfuzz
options:
url: https://raw.githubusercontent.com/ruanfei/ShadowsocksRRShare/master/ssr/ssr.txt
- type: webfuzz
options:
url: https://raw.githubusercontent.com/pojiezhiyuanjun/freev2/master/all.txt
- type: webfuzz
options:
url: https://raw.githubusercontent.com/zu1k/ssrtool-crawler/master/data/ssr.txt
- type: webfuzz
options:
url: https://raw.githubusercontent.com/freefq/free/master/README.md
- type: webfuzz
options:
url: https://raw.githubusercontent.com/52bp/52bp.github.io/master/freesite.html
# tg频道
- type: tgchannel
options:
channel: ssrList
num: 200
- type: tgchannel
options:
channel: ssList
num: 200
- type: tgchannel
options:
channel: SSRSUB
num: 200
- type: tgchannel
options:
channel: FreeSSRNode
num: 200
- type: tgchannel
options:
channel: ssrlists
num: 200
- type: tgchannel
options:
channel: ssrshares
num: 200
- type: tgchannel
options:
channel: V2List
num: 200
- type: tgchannel
options:
channel: ssrtool
num: 100
- type: tgchannel
options:
channel: ssrtool_crack
num: 100
- type: tgchannel
options:
channel: vmessr
num: 200
- type: tgchannel
options:
channel: FreeSSR666
num: 200
- type: tgchannel
options:
channel: fanqiang666
num: 200
- type: tgchannel
options:
channel: jiedianfenxiang
num: 200
- type: tgchannel
options:
channel: freeshadowsock
num: 200
# 翻墙党,后面的东西都无需修改
- type: web-fanqiangdang
options:
url: https://fanqiangdang.com/forum.php?mod=rss&fid=50&auth=0
num: 200
- type: web-fanqiangdang
options:
url: https://fanqiangdang.com/forum.php?mod=rss&fid=2&auth=0
num: 200
- type: web-fanqiangdang
options:
url: https://fanqiangdang.com/forum.php?mod=rss&fid=36&auth=0
num: 200
- type: web-freessrxyz
options: