Skip to content

Commit

Permalink
improve impersonate feature
Browse files Browse the repository at this point in the history
  • Loading branch information
sagan committed Jan 2, 2024
1 parent 2c0c105 commit 3e16163
Show file tree
Hide file tree
Showing 16 changed files with 445 additions and 343 deletions.
281 changes: 143 additions & 138 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ func init() {
configFiles := []string{
configFile,
filepath.Join(UserHomeDir, ".config/ptool/ptool.yaml"),
"ptool.toml",
"ptool.yaml",
filepath.Join(".", "ptool.toml"),
filepath.Join(".", "ptool.yaml"),
}
for _, cf := range configFiles {
_, err := os.Stat(cf)
Expand Down
18 changes: 10 additions & 8 deletions cmd/cookiecloud/importsites/importsites.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@ import (
)

var (
doAction = false
noCheck = false
profile = ""
siteProxy = ""
siteUa = ""
siteJa3 = ""
doAction = false
noCheck = false
profile = ""
siteProxy = ""
siteImpersonate = ""
siteUa = ""
siteJa3 = ""
)

var command = &cobra.Command{
Expand All @@ -42,6 +43,7 @@ func init() {
command.Flags().BoolVarP(&noCheck, "no-check", "", false, "Do not check the cookies validity before importing new sites")
command.Flags().StringVarP(&profile, "profile", "", "", "Comma-separated string, Set the used cookiecloud profile name(s). If not set, All cookiecloud profiles in config will be used")
command.Flags().StringVarP(&siteProxy, "site-proxy", "", "", "Set the proxy for imported sites")
command.Flags().StringVarP(&siteImpersonate, "site-impersonate", "", "", "Set the impersonate for imported sites")
command.Flags().StringVarP(&siteUa, "site-ua", "", "", "Set the user-agent for imported sites")
command.Flags().StringVarP(&siteJa3, "site-ja3", "", "", "Set the client TLS ja3 fingerprint for imported sites")
cookiecloud.Command.AddCommand(command)
Expand Down Expand Up @@ -98,8 +100,8 @@ func importsites(cmd *cobra.Command, args []string) error {
if cookie == "" {
continue
}
newsiteconfig := &config.SiteConfigStruct{Type: tplname, Cookie: cookie,
Proxy: siteProxy, UserAgent: siteUa, Ja3: siteJa3}
newsiteconfig := &config.SiteConfigStruct{Type: tplname, Cookie: cookie, Proxy: siteProxy,
Impersonate: siteImpersonate, UserAgent: siteUa, Ja3: siteJa3}
if !noCheck {
siteInstance, err := site.CreateSiteInternal(tplname, newsiteconfig, config.Get())
if err != nil {
Expand Down
40 changes: 29 additions & 11 deletions cmd/versioncmd/versioncmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package versioncmd

import (
"fmt"
"path/filepath"
"runtime"
"strings"

"github.com/spf13/cobra"

Expand All @@ -20,25 +22,41 @@ var command = &cobra.Command{
RunE: versioncmd,
}

var (
impersonate string
)

func init() {
command.Flags().StringVarP(&impersonate, "show-impersonate", "", "", "Show details of specified impersonate and exit")
cmd.RootCmd.AddCommand(command)
}

func versioncmd(cmd *cobra.Command, args []string) error {
if impersonate != "" {
impersonateProfile := util.ImpersonateProfiles[impersonate]
if impersonateProfile == nil {
return fmt.Errorf("impersonate '%s' not supported", impersonate)
}
fmt.Printf("Impersonate '%s'\n", impersonate)
fmt.Printf("- navigator: %s\n", impersonateProfile.Navigator)
fmt.Printf("- tls_ja3: %s\n", impersonateProfile.Ja3)
fmt.Printf("- h2_fingerprint: %s\n", impersonateProfile.H2fingerpring)
fmt.Printf("- http_request_headers:\n")
for _, header := range impersonateProfile.Headers {
value := header[1]
if value == util.HTTP_HEADER_PLACEHOLDER {
value = ""
}
fmt.Printf(" %s: %s\n", header[0], value)
}
return nil
}
fmt.Printf("ptool %s\n", version.Version)
fmt.Printf("- os/type: %s\n", runtime.GOOS)
fmt.Printf("- os/arch: %s\n", runtime.GOARCH)
fmt.Printf("- go/version: %s\n", runtime.Version())
fmt.Printf("- config_file: %s\n", config.DefaultConfigFile)
fmt.Printf("- config/default_tls_ja3: %s\n", util.CHROME_JA3)
fmt.Printf("- config/default_h2_fingerprint: %s\n", util.CHROME_H2FINGERPRINT)
fmt.Printf("- config/default_http_request_headers:\n")
for _, header := range util.CHROME_HTTP_REQUEST_HEADERS {
value := header[1]
if value == util.HTTP_HEADER_PLACEHOLDER {
value = ""
}
fmt.Printf(" %s: %s\n", header[0], value)
}
fmt.Printf("- config_file: %s%c%s\n", config.ConfigDir, filepath.Separator, config.ConfigFile)
fmt.Printf("- config_dir: %s\n", config.ConfigDir)
fmt.Printf("- config/supported_impersonates: %s\n", strings.Join(util.Impersonates, ", "))
return nil
}
44 changes: 22 additions & 22 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ type SiteConfigStruct struct {
TorrentsExtraUrls []string `yaml:"torrentsExtraUrls"`
Cookie string `yaml:"cookie"`
UserAgent string `yaml:"userAgent"`
Impersonate string `yaml:"impersonate"`
HttpHeaders [][]string `yaml:"httpHeaders"`
NoDefaultHttpHeaders bool `yaml:"noDefaultHttpHeaders"`
Ja3 string `yaml:"ja3"`
Timeoout int64 `yaml:"timeout"`
H2Fingerprint string `yaml:"h2Fingerprint"`
Expand Down Expand Up @@ -156,27 +156,27 @@ type SiteConfigStruct struct {
}

type ConfigStruct struct {
Hushshell bool `yaml:"hushshell"`
ShellMaxSuggestions int64 `yaml:"shellMaxSuggestions"`
ShellMaxHistory int64 `yaml:"shellMaxHistory"`
IyuuToken string `yaml:"iyuuToken"`
SiteProxy string `yaml:"siteProxy"`
SiteUserAgent string `yaml:"siteUserAgent"`
SiteNoDefaultHttpHeaders bool `yaml:"siteNoDefaultHttpHeaders"`
SiteHttpHeaders [][]string `yaml:"siteHttpHeaders"`
SiteJa3 string `yaml:"siteJa3"`
SiteTimeout int64 `yaml:"siteTimeout"` // 访问网站超时时间(秒)
SiteSecure bool `yaml:"siteSecure"` // 强制开启所有站点 TLS 证书校验。
SiteH2Fingerprint string `yaml:"siteH2Fingerprint"`
BrushEnableStats bool `yaml:"brushEnableStats"`
Clients []*ClientConfigStruct `yaml:"clients"`
Sites []*SiteConfigStruct `yaml:"sites"`
Groups []*GroupConfigStruct `yaml:"groups"`
Aliases []*AliasConfigStruct `yaml:"aliases"`
Cookieclouds []*CookiecloudConfigStruct `yaml:"cookieclouds"`
Comment string `yaml:"comment"`
ClientsEnabled []*ClientConfigStruct
SitesEnabled []*SiteConfigStruct
Hushshell bool `yaml:"hushshell"`
ShellMaxSuggestions int64 `yaml:"shellMaxSuggestions"`
ShellMaxHistory int64 `yaml:"shellMaxHistory"`
IyuuToken string `yaml:"iyuuToken"`
SiteProxy string `yaml:"siteProxy"`
SiteUserAgent string `yaml:"siteUserAgent"`
SiteImpersonate string `yaml:"siteImpersonate"`
SiteHttpHeaders [][]string `yaml:"siteHttpHeaders"`
SiteJa3 string `yaml:"siteJa3"`
SiteTimeout int64 `yaml:"siteTimeout"` // 访问网站超时时间(秒)
SiteSecure bool `yaml:"siteSecure"` // 强制开启所有站点 TLS 证书校验。
SiteH2Fingerprint string `yaml:"siteH2Fingerprint"`
BrushEnableStats bool `yaml:"brushEnableStats"`
Clients []*ClientConfigStruct `yaml:"clients"`
Sites []*SiteConfigStruct `yaml:"sites"`
Groups []*GroupConfigStruct `yaml:"groups"`
Aliases []*AliasConfigStruct `yaml:"aliases"`
Cookieclouds []*CookiecloudConfigStruct `yaml:"cookieclouds"`
Comment string `yaml:"comment"`
ClientsEnabled []*ClientConfigStruct
SitesEnabled []*SiteConfigStruct
}

var (
Expand Down
11 changes: 1 addition & 10 deletions ptool.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,12 @@ iyuuToken = '' # iyuu token。用于自动辅种功能
# 注释掉的配置项值为默认值
#siteSecure = false # 启用访问站点时的 TLS 证书校验
#siteTimeout = 5 # 访问网站超时时间(秒)
#siteJa3 = "" # 设置访问站点时使用的 TLS ja3 指纹。默认使用最新稳定版 Chrome on Windows x64 en-US 的
#siteH2Fingerprint = "" # 设置访问站点时使用的 HTTP2 指纹(akamai_fingerprint)。默认使用 Chrome 的
#siteImpersonate = "" # 设置访问站点时模仿的浏览器,ptool 会使用该浏览器的 TLS ja3 指纹、H2 指纹、http headers。默认模仿最新稳定版 Chrome on Windows x64 en-US
#siteProxy = '' # 使用代理访问 PT 站点(不适用于访问 BT 客户端)。格式为 'http://127.0.0.1:1080'。所有支持的代理协议: https://github.com/Noooste/azuretls-client?tab=readme-ov-file#proxy . 也支持通过 HTTP_PROXY & HTTPS_PROXY 环境变量设置代理
#siteUserAgent = '' # 所有站点默认使用的 ua。默认使用 Chrome 的
#brushEnableStats = false # 启用刷流统计功能
#hushshell = false # 如果设为 true, 启动 ptool shell 时将不显示欢迎信息
#shellMaxSuggestions = 5 # ptool shell 自动补全显示建议数量。设为 0 禁用
#shellMaxHistory = 500 # ptool shell 命令历史记录保存数量。设为 0 禁用
#siteNoDefaultHttpHeaders = false # 如果设为 true, 访问站点时禁用默认设置的模仿 Chrome 的 http 请求头

# 自定义访问站点时设置的 http 请求头。如果值设为空,删除对应 header
#siteHttpHeaders = [
# ['Cache-Control', 'no-cache']
#]

# 完整支持 qBittorrent v4.1+ (推荐使用 qb v4.4+)
[[clients]]
Expand Down Expand Up @@ -59,7 +51,6 @@ password = 'password'
type = 'mteam'
cookie = 'cookie_here'
#proxy = '' # 访问该站点使用的代理。优先级高于全局的 siteProxy 配置。格式为 'http://127.0.0.1:1080'
#userAgent = '' # 部分站点 cookie 绑定 ua。优先级高于全局的 siteUserAgent 配置
#torrentUploadSpeedLimit = '10MiB' # 站点单个种子上传速度限制(/s)
#brushTorrentMinSizeLimit = '0' # 刷流:种子最小体积限制。体积小于此值的种子不会被选择
#brushTorrentMaxSizeLimit = '1PiB' # 刷流:种子最大体积限制。体积大于此值的种子不会被选择
Expand Down
32 changes: 19 additions & 13 deletions site/discuz/discuz.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@ import (
)

type Site struct {
Name string
Location *time.Location
SiteConfig *config.SiteConfigStruct
Config *config.ConfigStruct
HttpClient *azuretls.Session
Name string
Location *time.Location
SiteConfig *config.SiteConfigStruct
Config *config.ConfigStruct
HttpClient *azuretls.Session
HttpHeaders [][]string
}

func (dzsite *Site) GetDefaultHttpHeaders() [][]string {
return dzsite.HttpHeaders
}

func (dzsite *Site) PurgeCache() {
Expand All @@ -42,7 +47,7 @@ func (dzsite *Site) GetSiteConfig() *config.SiteConfigStruct {

func (dzsite *Site) GetStatus() (*site.Status, error) {
doc, _, err := util.GetUrlDocWithAzuretls(dzsite.SiteConfig.Url+"forum.php?mod=torrents", dzsite.HttpClient,
dzsite.GetSiteConfig().Cookie, site.GetUa(dzsite), site.GetHttpHeaders(dzsite))
dzsite.GetSiteConfig().Cookie, site.GetUa(dzsite), dzsite.GetDefaultHttpHeaders())
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -79,7 +84,7 @@ func (dzsite *Site) DownloadTorrent(torrentUrl string) ([]byte, string, error) {
threadUrl := regexp.MustCompile(`mod=viewthread&tid=(?P<id>\d+)\b`)
if threadUrl.MatchString(torrentUrl) {
doc, _, err := util.GetUrlDocWithAzuretls(torrentUrl, dzsite.HttpClient,
dzsite.GetSiteConfig().Cookie, site.GetUa(dzsite), site.GetHttpHeaders(dzsite))
dzsite.GetSiteConfig().Cookie, site.GetUa(dzsite), dzsite.GetDefaultHttpHeaders())
if err != nil {
return nil, "", fmt.Errorf("failed to get thread doc: %v", err)
}
Expand Down Expand Up @@ -112,16 +117,17 @@ func NewSite(name string, siteConfig *config.SiteConfigStruct, config *config.Co
if err != nil {
return nil, fmt.Errorf("invalid site timezone %s: %v", siteConfig.GetTimezone(), err)
}
httpClient, err := site.CreateSiteHttpClient(siteConfig, config)
httpClient, httpHeaders, err := site.CreateSiteHttpClient(siteConfig, config)
if err != nil {
return nil, fmt.Errorf("failed to create site http client: %v", err)
}
site := &Site{
Name: name,
Location: location,
SiteConfig: siteConfig,
Config: config,
HttpClient: httpClient,
Name: name,
Location: location,
SiteConfig: siteConfig,
Config: config,
HttpClient: httpClient,
HttpHeaders: httpHeaders,
}
return site, nil
}
Expand Down
30 changes: 18 additions & 12 deletions site/gazelle/gazelle.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ import (
)

type Site struct {
Name string
Location *time.Location
SiteConfig *config.SiteConfigStruct
Config *config.ConfigStruct
HttpClient *azuretls.Session
Name string
Location *time.Location
SiteConfig *config.SiteConfigStruct
Config *config.ConfigStruct
HttpClient *azuretls.Session
HttpHeaders [][]string
}

const (
Expand All @@ -33,6 +34,10 @@ const (
SELECTOR_USER_DOWNLOADED = "#stats_leeching"
)

func (gzsite *Site) GetDefaultHttpHeaders() [][]string {
return gzsite.HttpHeaders
}

func (gzsite *Site) PurgeCache() {
}

Expand All @@ -46,7 +51,7 @@ func (gzsite *Site) GetSiteConfig() *config.SiteConfigStruct {

func (gzsite *Site) GetStatus() (*site.Status, error) {
doc, _, err := util.GetUrlDocWithAzuretls(gzsite.SiteConfig.Url+"torrents.php", gzsite.HttpClient,
gzsite.GetSiteConfig().Cookie, site.GetUa(gzsite), site.GetHttpHeaders(gzsite))
gzsite.GetSiteConfig().Cookie, site.GetUa(gzsite), gzsite.GetDefaultHttpHeaders())
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -113,16 +118,17 @@ func NewSite(name string, siteConfig *config.SiteConfigStruct, config *config.Co
if err != nil {
return nil, fmt.Errorf("invalid site timezone %s: %v", siteConfig.GetTimezone(), err)
}
httpClient, err := site.CreateSiteHttpClient(siteConfig, config)
httpClient, httpHeaders, err := site.CreateSiteHttpClient(siteConfig, config)
if err != nil {
return nil, fmt.Errorf("failed to create site http client: %v", err)
}
site := &Site{
Name: name,
Location: location,
SiteConfig: siteConfig,
Config: config,
HttpClient: httpClient,
Name: name,
Location: location,
SiteConfig: siteConfig,
Config: config,
HttpClient: httpClient,
HttpHeaders: httpHeaders,
}
return site, nil
}
Expand Down
30 changes: 18 additions & 12 deletions site/gazellepw/gazellepw.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,16 @@ import (
)

type Site struct {
Name string
Location *time.Location
SiteConfig *config.SiteConfigStruct
Config *config.ConfigStruct
HttpClient *azuretls.Session
Name string
Location *time.Location
SiteConfig *config.SiteConfigStruct
Config *config.ConfigStruct
HttpClient *azuretls.Session
HttpHeaders [][]string
}

func (gpwsite *Site) GetDefaultHttpHeaders() [][]string {
return gpwsite.HttpHeaders
}

func (gpwsite *Site) PurgeCache() {
Expand All @@ -40,7 +45,7 @@ func (gpwsite *Site) GetSiteConfig() *config.SiteConfigStruct {

func (gpwsite *Site) GetStatus() (*site.Status, error) {
doc, _, err := util.GetUrlDocWithAzuretls(gpwsite.SiteConfig.Url+"torrents.php", gpwsite.HttpClient,
gpwsite.GetSiteConfig().Cookie, site.GetUa(gpwsite), site.GetHttpHeaders(gpwsite))
gpwsite.GetSiteConfig().Cookie, site.GetUa(gpwsite), gpwsite.GetDefaultHttpHeaders())
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -94,16 +99,17 @@ func NewSite(name string, siteConfig *config.SiteConfigStruct, config *config.Co
if err != nil {
return nil, fmt.Errorf("invalid site timezone %s: %v", siteConfig.GetTimezone(), err)
}
httpClient, err := site.CreateSiteHttpClient(siteConfig, config)
httpClient, httpHeaders, err := site.CreateSiteHttpClient(siteConfig, config)
if err != nil {
return nil, fmt.Errorf("failed to create site http client: %v", err)
}
site := &Site{
Name: name,
Location: location,
SiteConfig: siteConfig,
Config: config,
HttpClient: httpClient,
Name: name,
Location: location,
SiteConfig: siteConfig,
Config: config,
HttpClient: httpClient,
HttpHeaders: httpHeaders,
}
return site, nil
}
Expand Down

0 comments on commit 3e16163

Please sign in to comment.