├── reflink ├── .gitignore ├── go.mod ├── go.sum ├── Makefile ├── errors.go ├── reflink.go ├── writer.go ├── LICENSE └── README.md ├── go-socket.io ├── _examples │ ├── dockerize-default-http │ │ ├── README.md │ │ ├── go.mod │ │ ├── .dockerignore │ │ ├── Makefile │ │ ├── Dockerfile │ │ ├── main.go │ │ ├── asset │ │ │ └── index.html │ │ └── go.sum │ ├── pprof │ │ └── go.mod │ ├── redis-adapter-unix-socket │ │ ├── go.mod │ │ ├── Makefile │ │ ├── redis.conf │ │ ├── Dockerfile │ │ ├── docker-compose.yml │ │ ├── asset │ │ │ └── index.html │ │ └── main.go │ ├── default-http │ │ └── go.mod │ ├── graceful-shutdown │ │ └── go.mod │ ├── gf │ │ ├── go.mod │ │ └── main.go │ ├── gin-cors │ │ └── go.mod │ ├── gin-gonic │ │ ├── go.mod │ │ └── main.go │ ├── redis-adapter │ │ ├── go.mod │ │ ├── docker-compose.yml │ │ └── main.go │ ├── go-echo │ │ ├── go.mod │ │ └── main.go │ ├── client │ │ └── main.go │ ├── iris │ │ ├── go.mod │ │ └── main.go │ └── asset │ │ └── index.html ├── .github │ ├── ISSUE_TEMPLATE │ │ ├── question.md │ │ ├── feature_request.md │ │ └── bug_report.md │ ├── dependabot.yml │ └── workflows │ │ └── ci.yaml ├── helpers.go ├── .gitignore ├── engineio │ ├── transport │ │ ├── errors.go │ │ ├── utils │ │ │ ├── clock_test.go │ │ │ └── clock.go │ │ ├── polling │ │ │ ├── util.go │ │ │ └── util_test.go │ │ ├── transport.go │ │ ├── manager_test.go │ │ ├── manager.go │ │ ├── parameters_test.go │ │ ├── websocket │ │ │ └── connect_test.go │ │ └── parameters.go │ ├── packet │ │ ├── types.go │ │ ├── fake_writer.go │ │ ├── fake_discarder.go │ │ ├── decoder.go │ │ ├── fake_frame.go │ │ ├── encoder.go │ │ ├── encoder_test.go │ │ ├── fake_reader.go │ │ └── packet_test.go │ ├── types.go │ ├── session │ │ ├── base.go │ │ ├── session_id_generator.go │ │ └── session_manager.go │ ├── frame │ │ ├── frame.go │ │ └── frame_test.go │ ├── connect.go │ ├── payload │ │ ├── errors_test.go │ │ ├── errors.go │ │ └── util.go │ ├── _examples │ │ └── main.go │ └── README.md ├── .deepsource.toml ├── go.mod ├── logger │ ├── logger.go │ └── README.md ├── types.go ├── .golangci.yml ├── parser │ ├── errors.go │ ├── packet.go │ └── buffer.go ├── Makefile ├── upgrade workflow.md ├── CONTRIBUTING.md ├── namespace_handlers.go ├── errors.go ├── namespaces.go ├── LICENSE ├── adapter_options.go └── handler.go ├── flags └── flags.go ├── cmd ├── sites │ ├── all │ │ └── all.go │ └── show │ │ └── show.go ├── hardlink │ ├── all │ │ └── all.go │ ├── hardlink.go │ ├── cp │ │ └── suggest.go │ └── torrent │ │ └── suggest.go ├── reseed │ ├── all │ │ └── all.go │ ├── reseed.go │ ├── match │ │ └── suggest.go │ └── status │ │ └── status.go ├── configcmd │ ├── all │ │ └── all.go │ ├── create │ │ └── create.go │ └── example │ │ └── example.go ├── cookiecloud │ ├── all │ │ └── all.go │ └── cookiecloud.go ├── iyuu │ ├── all │ │ └── all.go │ ├── xseed │ │ └── suggest.go │ ├── status │ │ └── status.go │ └── xseedtest │ │ └── xseedtest.go ├── statscmd │ └── suggest.go ├── status │ └── suggest.go ├── xseedadd │ └── suggest.go ├── maketorrent │ └── suggest.go ├── edittorrent │ └── suggest.go ├── parsetorrent │ └── suggest.go ├── verifytorrent │ └── suggest.go ├── tidyup │ └── suggest.go ├── checktag │ ├── suggest.go │ └── checktag.go ├── gettags │ ├── suggest.go │ └── gettags.go ├── search │ └── suggest.go ├── findalone │ └── suggest.go ├── renametag │ └── suggest.go ├── createtags │ ├── suggest.go │ └── createtags.go ├── deletetags │ ├── suggest.go │ └── deletetags.go ├── getcategories │ ├── suggest.go │ └── getcategories.go ├── createcategory │ ├── suggest.go │ └── createcategory.go ├── deletecategories │ ├── suggest.go │ └── deletecategories.go ├── brush │ └── suggest.go ├── delete │ └── suggest.go ├── dltorrent │ └── suggest.go ├── pause │ └── suggest.go ├── export │ └── suggest.go ├── resume │ └── suggest.go ├── recheck │ └── suggest.go ├── reannounce │ └── suggest.go ├── addtrackers │ └── suggest.go ├── edittracker │ └── suggest.go ├── modifytorrent │ └── suggest.go ├── skipchecking │ └── suggest.go ├── removetrackers │ └── suggest.go ├── transfertorrent │ └── suggest.go ├── markinvalidtracker │ └── suggest.go ├── addtags │ └── suggest.go ├── dynamicseeding │ └── suggest.go ├── removetags │ └── suggest.go ├── partialdownload │ └── suggest.go ├── setcategory │ └── suggest.go ├── setsavepath │ └── suggest.go ├── movesavepath │ └── suggest.go ├── add │ └── suggest.go ├── xseedcheck │ └── suggest.go ├── clientctl │ └── suggest.go ├── show │ └── suggest.go ├── batchdl │ └── suggest.go └── run │ └── run.go ├── client ├── all │ └── all.go └── qbittorrent │ └── fastresume.go ├── transmissionrpc ├── go.mod ├── go.sum ├── session_shutdown.go ├── port_checking.go ├── blocklist.go ├── torrent_remove.go ├── LICENSE └── free_space.go ├── cobra-prompt ├── _example │ ├── cmd │ │ ├── root.go │ │ ├── error.go │ │ └── get.go │ └── main.go ├── .gitignore ├── .github │ └── workflows │ │ └── go.yml ├── README.md ├── go.mod ├── LICENSE └── CHANGELOG.md ├── go-prompt ├── _tools │ ├── README.md │ ├── complete_file │ │ └── main.go │ ├── vt100_debug │ │ └── main.go │ └── sigwinch │ │ └── main.go ├── .github │ └── ISSUE_TEMPLATE │ │ ├── feature_request.md │ │ └── bug_report.md ├── go.mod ├── .gitignore ├── internal │ ├── bisect │ │ ├── bisect.go │ │ └── bisect_test.go │ ├── term │ │ ├── term.go │ │ └── raw.go │ ├── debug │ │ ├── assert.go │ │ └── log.go │ └── strings │ │ └── strings_test.go ├── _example │ ├── http-prompt │ │ └── api.py │ ├── build.sh │ ├── exec-command │ │ └── main.go │ ├── simple-echo │ │ ├── cjk-cyrillic │ │ │ └── main.go │ │ └── main.go │ ├── README.md │ └── live-prefix │ │ └── main.go ├── input_test.go ├── emacs_test.go ├── signal_windows.go ├── signal_posix.go ├── LICENSE ├── output_windows.go ├── shortcut.go ├── Makefile ├── key_bind.go ├── key_string.go ├── key_bind_func.go ├── history_test.go ├── output_vt100_test.go ├── history.go └── output_posix.go ├── site ├── tnode │ └── api.go ├── all │ └── all.go └── mtorrent │ └── json.go ├── ptool.go ├── util └── osutil │ ├── others.go │ └── windows.go ├── version └── version.go ├── .github └── workflows │ ├── release.yml │ └── go.yml ├── .gitignore ├── config └── ptool.example.yaml ├── .goreleaser.yaml └── jinja └── jinja.go /reflink/.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | -------------------------------------------------------------------------------- /go-socket.io/_examples/dockerize-default-http/README.md: -------------------------------------------------------------------------------- 1 | 2 | # Run 3 | 4 | ```bash 5 | make -i 6 | ``` 7 | -------------------------------------------------------------------------------- /go-socket.io/.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Questions and troubleshooting 4 | 5 | --- 6 | -------------------------------------------------------------------------------- /reflink/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/KarpelesLab/reflink 2 | 3 | go 1.19 4 | 5 | require golang.org/x/sys v0.9.0 // indirect 6 | -------------------------------------------------------------------------------- /flags/flags.go: -------------------------------------------------------------------------------- 1 | // Runtime command line flags. 2 | package flags 3 | 4 | var ( 5 | DumpHeaders = false 6 | DumpBodies = false 7 | ) 8 | -------------------------------------------------------------------------------- /cmd/sites/all/all.go: -------------------------------------------------------------------------------- 1 | package all 2 | 3 | import ( 4 | _ "github.com/sagan/ptool/cmd/sites" 5 | _ "github.com/sagan/ptool/cmd/sites/show" 6 | ) 7 | -------------------------------------------------------------------------------- /client/all/all.go: -------------------------------------------------------------------------------- 1 | package all 2 | 3 | import ( 4 | _ "github.com/sagan/ptool/client/qbittorrent" 5 | _ "github.com/sagan/ptool/client/transmission" 6 | ) 7 | -------------------------------------------------------------------------------- /go-socket.io/helpers.go: -------------------------------------------------------------------------------- 1 | package socketio 2 | 3 | import "github.com/gofrs/uuid" 4 | 5 | func newV4UUID() string { 6 | return uuid.Must(uuid.NewV4()).String() 7 | } 8 | -------------------------------------------------------------------------------- /reflink/go.sum: -------------------------------------------------------------------------------- 1 | golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= 2 | golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 3 | -------------------------------------------------------------------------------- /go-socket.io/.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /vendor 3 | /vendor.pb 4 | .DS_STORE 5 | /.idea 6 | /.vscode 7 | *.o 8 | *.out 9 | profile.cov 10 | *.prof 11 | *.svg 12 | */node_modules -------------------------------------------------------------------------------- /transmissionrpc/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/hekmon/transmissionrpc/v2 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/hashicorp/go-cleanhttp v0.5.2 7 | github.com/hekmon/cunits/v2 v2.1.0 8 | ) 9 | -------------------------------------------------------------------------------- /go-socket.io/_examples/dockerize-default-http/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/googollee/go-socket.io/_examples/docker-with-deault-http 2 | 3 | go 1.16 4 | 5 | require github.com/googollee/go-socket.io v1.6.0 6 | -------------------------------------------------------------------------------- /cmd/hardlink/all/all.go: -------------------------------------------------------------------------------- 1 | package all 2 | 3 | import ( 4 | _ "github.com/sagan/ptool/cmd/hardlink" 5 | _ "github.com/sagan/ptool/cmd/hardlink/cp" 6 | _ "github.com/sagan/ptool/cmd/hardlink/torrent" 7 | ) 8 | -------------------------------------------------------------------------------- /go-socket.io/engineio/transport/errors.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import "errors" 4 | 5 | // ErrInvalidFrame is returned when writing invalid frame type. 6 | var ErrInvalidFrame = errors.New("invalid frame type") 7 | -------------------------------------------------------------------------------- /cmd/reseed/all/all.go: -------------------------------------------------------------------------------- 1 | package all 2 | 3 | import ( 4 | _ "github.com/sagan/ptool/cmd/reseed" 5 | _ "github.com/sagan/ptool/cmd/reseed/match" 6 | _ "github.com/sagan/ptool/cmd/reseed/sites" 7 | _ "github.com/sagan/ptool/cmd/reseed/status" 8 | ) 9 | -------------------------------------------------------------------------------- /go-socket.io/_examples/pprof/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/googollee/go-socket.io/_examples/pprof 2 | 3 | go 1.16 4 | 5 | require github.com/googollee/go-socket.io v0.0.0-00010101000000-000000000000 6 | 7 | replace github.com/googollee/go-socket.io => ../../ 8 | -------------------------------------------------------------------------------- /go-socket.io/_examples/redis-adapter-unix-socket/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/googollee/go-socket.io/_example/redis-adapter-unix-socket 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.7.7 7 | github.com/googollee/go-socket.io v1.6.0 8 | ) 9 | -------------------------------------------------------------------------------- /cmd/configcmd/all/all.go: -------------------------------------------------------------------------------- 1 | package all 2 | 3 | import ( 4 | _ "github.com/sagan/ptool/cmd/configcmd" 5 | _ "github.com/sagan/ptool/cmd/configcmd/create" 6 | _ "github.com/sagan/ptool/cmd/configcmd/example" 7 | _ "github.com/sagan/ptool/cmd/configcmd/show" 8 | ) 9 | -------------------------------------------------------------------------------- /go-socket.io/_examples/default-http/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/googollee/go-socket.io/_examples/deault-http 2 | 3 | go 1.16 4 | 5 | require github.com/googollee/go-socket.io v0.0.0-00010101000000-000000000000 6 | 7 | replace github.com/googollee/go-socket.io => ../../ 8 | -------------------------------------------------------------------------------- /go-socket.io/.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gomod 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | - package-ecosystem: github-actions 8 | directory: "/" 9 | schedule: 10 | interval: daily -------------------------------------------------------------------------------- /go-socket.io/_examples/graceful-shutdown/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/googollee/go-socket.io/_examples/graceful-shutdown 2 | 3 | go 1.16 4 | 5 | require github.com/googollee/go-socket.io v0.0.0-00010101000000-000000000000 6 | 7 | replace github.com/googollee/go-socket.io => ../../ 8 | -------------------------------------------------------------------------------- /cobra-prompt/_example/cmd/root.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | ) 6 | 7 | var RootCmd = &cobra.Command{ 8 | Use: "cobra-prompt", 9 | SilenceUsage: true, // Only print usage when defined in command. 10 | SilenceErrors: true, 11 | } 12 | -------------------------------------------------------------------------------- /go-socket.io/.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | test_patterns = ["**/*_test.go"] 4 | 5 | exclude_patterns = ["/_example/**"] 6 | 7 | [[analyzers]] 8 | name = "go" 9 | enabled = true 10 | 11 | [analyzers.meta] 12 | import_paths = ["github.com/googollee/go-socket.io"] 13 | -------------------------------------------------------------------------------- /go-socket.io/_examples/dockerize-default-http/.dockerignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /vendor 3 | /vendor.pb 4 | .DS_STORE 5 | /.idea 6 | /.vscode 7 | *.o 8 | *.out 9 | profile.cov 10 | *.prof 11 | *.svg 12 | */node_modules 13 | _examples/ 14 | .github/ 15 | *.md 16 | !asset/ 17 | *.toml 18 | Makefile 19 | -------------------------------------------------------------------------------- /go-prompt/_tools/README.md: -------------------------------------------------------------------------------- 1 | ## Tools of go-prompt 2 | 3 | ### vt100_debug 4 | 5 | ![vt100_debug](https://github.com/c-bata/assets/raw/master/go-prompt/tools/vt100_debug.gif) 6 | 7 | ### sigwinch 8 | 9 | ![sigwinch](https://github.com/c-bata/assets/raw/master/go-prompt/tools/sigwinch.gif) 10 | 11 | -------------------------------------------------------------------------------- /go-socket.io/_examples/gf/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/googollee/go-socket.io/_examples/gf 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/gogf/gf v1.15.6 7 | github.com/googollee/go-socket.io v0.0.0-00010101000000-000000000000 8 | ) 9 | 10 | replace github.com/googollee/go-socket.io => ../../ 11 | -------------------------------------------------------------------------------- /go-prompt/.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Feature request" 3 | about: Suggest an idea for new features in go-prompt. 4 | title: "[Feature Request]" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | # Feature Request 11 | 12 | *Please write your suggestion here.* 13 | 14 | -------------------------------------------------------------------------------- /go-socket.io/engineio/packet/types.go: -------------------------------------------------------------------------------- 1 | package packet 2 | 3 | import ( 4 | "github.com/googollee/go-socket.io/engineio/frame" 5 | ) 6 | 7 | type Frame struct { 8 | FType frame.Type 9 | Data []byte 10 | } 11 | 12 | type Packet struct { 13 | FType frame.Type 14 | PType Type 15 | Data []byte 16 | } 17 | -------------------------------------------------------------------------------- /go-prompt/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/c-bata/go-prompt 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/mattn/go-colorable v0.1.7 7 | github.com/mattn/go-runewidth v0.0.9 8 | github.com/mattn/go-tty v0.0.3 9 | github.com/pkg/term v1.2.0-beta.2 10 | golang.org/x/sys v0.0.0-20200918174421-af09f7315aff 11 | ) 12 | -------------------------------------------------------------------------------- /go-socket.io/_examples/gin-cors/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/googollee/go-socket.io/_examples/gin-cors 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.7.7 7 | github.com/googollee/go-socket.io v0.0.0-00010101000000-000000000000 8 | ) 9 | 10 | replace github.com/googollee/go-socket.io => ../../ 11 | -------------------------------------------------------------------------------- /go-socket.io/_examples/gin-gonic/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/googollee/go-socket.io/_examples/gin-gonic 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.7.7 7 | github.com/googollee/go-socket.io v0.0.0-00010101000000-000000000000 8 | ) 9 | 10 | replace github.com/googollee/go-socket.io => ../../ 11 | -------------------------------------------------------------------------------- /go-socket.io/_examples/redis-adapter/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/googollee/go-socket.io/_examples/redis-adapter 2 | 3 | go 1.16 4 | 5 | replace github.com/googollee/go-socket.io => ../../ 6 | 7 | require ( 8 | github.com/gin-gonic/gin v1.7.7 9 | github.com/googollee/go-socket.io v0.0.0-00010101000000-000000000000 10 | ) 11 | -------------------------------------------------------------------------------- /site/tnode/api.go: -------------------------------------------------------------------------------- 1 | package tnode 2 | 3 | // https://zhuque.in/api/user/getMainInfo 4 | type apiMainInfoResponse struct { 5 | Status int64 `json:"status"` 6 | Data struct { 7 | Username string `json:"username"` 8 | Download int64 `json:"download"` 9 | Upload int64 `json:"upload"` 10 | } `json:"data"` 11 | } 12 | -------------------------------------------------------------------------------- /go-socket.io/engineio/types.go: -------------------------------------------------------------------------------- 1 | package engineio 2 | 3 | import ( 4 | "net/http" 5 | ) 6 | 7 | // CheckerFunc is function to check request. 8 | type CheckerFunc func(*http.Request) (http.Header, error) 9 | 10 | // ConnInitorFunc is function to do after create connection. 11 | type ConnInitorFunc func(*http.Request, Conn) 12 | -------------------------------------------------------------------------------- /go-socket.io/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/googollee/go-socket.io 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/gofrs/uuid v4.4.0+incompatible 7 | github.com/gomodule/redigo v1.8.9 8 | github.com/gorilla/websocket v1.5.0 9 | github.com/stretchr/testify v1.8.4 10 | golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 11 | ) 12 | -------------------------------------------------------------------------------- /go-socket.io/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "golang.org/x/exp/slog" 5 | ) 6 | 7 | var Log *slog.Logger = slog.Default() 8 | 9 | func Error(msg string, err error) { 10 | Log.Error(msg, "err", err.Error()) 11 | } 12 | 13 | func Info(msg string, args ...interface{}) { 14 | Log.Info(msg, args...) 15 | } 16 | -------------------------------------------------------------------------------- /cmd/cookiecloud/all/all.go: -------------------------------------------------------------------------------- 1 | package all 2 | 3 | import ( 4 | _ "github.com/sagan/ptool/cmd/cookiecloud" 5 | _ "github.com/sagan/ptool/cmd/cookiecloud/get" 6 | _ "github.com/sagan/ptool/cmd/cookiecloud/importsites" 7 | _ "github.com/sagan/ptool/cmd/cookiecloud/status" 8 | _ "github.com/sagan/ptool/cmd/cookiecloud/sync" 9 | ) 10 | -------------------------------------------------------------------------------- /cmd/iyuu/all/all.go: -------------------------------------------------------------------------------- 1 | package all 2 | 3 | import ( 4 | _ "github.com/sagan/ptool/cmd/iyuu" 5 | _ "github.com/sagan/ptool/cmd/iyuu/bind" 6 | _ "github.com/sagan/ptool/cmd/iyuu/sites" 7 | _ "github.com/sagan/ptool/cmd/iyuu/status" 8 | _ "github.com/sagan/ptool/cmd/iyuu/xseed" 9 | _ "github.com/sagan/ptool/cmd/iyuu/xseedtest" 10 | ) 11 | -------------------------------------------------------------------------------- /ptool.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | _ "time/tzdata" 5 | 6 | _ "github.com/sagan/ptool/client/all" 7 | "github.com/sagan/ptool/cmd" 8 | _ "github.com/sagan/ptool/cmd/all" 9 | _ "github.com/sagan/ptool/site/all" 10 | "github.com/sagan/ptool/util/osutil" 11 | ) 12 | 13 | func main() { 14 | osutil.Init() 15 | cmd.Execute() 16 | } 17 | -------------------------------------------------------------------------------- /go-socket.io/types.go: -------------------------------------------------------------------------------- 1 | package socketio 2 | 3 | import ( 4 | "reflect" 5 | ) 6 | 7 | // namespace 8 | const ( 9 | aliasRootNamespace = "/" 10 | rootNamespace = "" 11 | ) 12 | 13 | // message 14 | const ( 15 | clientDisconnectMsg = "client namespace disconnect" 16 | ) 17 | 18 | var ( 19 | defaultHeaderType = []reflect.Type{reflect.TypeOf("")} 20 | ) 21 | -------------------------------------------------------------------------------- /reflink/Makefile: -------------------------------------------------------------------------------- 1 | #!/bin/make 2 | GOROOT:=$(shell PATH="/pkg/main/dev-lang.go/bin:$$PATH" go env GOROOT) 3 | GO=$(GOROOT)/bin/go 4 | GOPATH:=$(shell $(GO) env GOPATH) 5 | 6 | .PHONY: test deps 7 | 8 | all: 9 | $(GOPATH)/bin/goimports -w -l . 10 | $(GO) build -v ./... 11 | 12 | deps: 13 | $(GO) get -v -t ./... 14 | 15 | test: 16 | $(GO) test -v ./... -test.count 1 17 | -------------------------------------------------------------------------------- /transmissionrpc/go.sum: -------------------------------------------------------------------------------- 1 | github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 2 | github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 3 | github.com/hekmon/cunits/v2 v2.1.0 h1:k6wIjc4PlacNOHwKEMBgWV2/c8jyD4eRMs5mR1BBhI0= 4 | github.com/hekmon/cunits/v2 v2.1.0/go.mod h1:9r1TycXYXaTmEWlAIfFV8JT+Xo59U96yUJAYHxzii2M= 5 | -------------------------------------------------------------------------------- /go-socket.io/engineio/session/base.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | import ( 4 | "github.com/googollee/go-socket.io/engineio/frame" 5 | ) 6 | 7 | // FrameType is type of message frame. 8 | type FrameType frame.Type 9 | 10 | const ( 11 | // TEXT is text type message. 12 | TEXT = FrameType(frame.String) 13 | // BINARY is binary type message. 14 | BINARY = FrameType(frame.Binary) 15 | ) 16 | -------------------------------------------------------------------------------- /go-socket.io/.golangci.yml: -------------------------------------------------------------------------------- 1 | # More info on config here: https://github.com/golangci/golangci-lint#config-file 2 | run: 3 | timeout: 3m 4 | deadline: 5m 5 | 6 | output: 7 | format: colored-line-number 8 | print-issued-lines: true 9 | print-linter-name: true 10 | 11 | issues: 12 | exclude-use-default: false 13 | exclude: 14 | # support go 1.13 with deprecated APIs 15 | - SA1019 16 | -------------------------------------------------------------------------------- /go-socket.io/parser/errors.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrInvalidPacketType = errors.New("invalid packet type") 7 | 8 | errInvalidBinaryBufferType = errors.New("buffer packet should be binary") 9 | 10 | errInvalidFirstPacketType = errors.New("first packet should be text frame") 11 | 12 | errFailedBufferAddress = errors.New("can't get Buffer address") 13 | ) 14 | -------------------------------------------------------------------------------- /go-prompt/.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | bin/ 6 | 7 | # Folders 8 | pkg/ 9 | _obj 10 | _test 11 | 12 | # Architecture specific extensions/prefixes 13 | *.cgo1.go 14 | *.cgo2.c 15 | _cgo_defun.c 16 | _cgo_gotypes.go 17 | _cgo_export.* 18 | 19 | _testmain.go 20 | 21 | *.exe 22 | *.test 23 | *.prof 24 | 25 | # Glide 26 | vendor/ 27 | -------------------------------------------------------------------------------- /cmd/hardlink/hardlink.go: -------------------------------------------------------------------------------- 1 | package hardlink 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | ) 8 | 9 | var Command = &cobra.Command{ 10 | Use: "hardlink", 11 | Short: "Hardlink utilities", 12 | Long: `Hardlink utilities`, 13 | Args: cobra.MatchAll(cobra.ExactArgs(0), cobra.OnlyValidArgs), 14 | } 15 | 16 | func init() { 17 | cmd.RootCmd.AddCommand(Command) 18 | } 19 | -------------------------------------------------------------------------------- /reflink/errors.go: -------------------------------------------------------------------------------- 1 | package reflink 2 | 3 | import "errors" 4 | 5 | // ErrReflinkUnsupported is returned by Always() if the operation is not 6 | // supported on the current operating system. Auto() will never return this 7 | // error. 8 | var ( 9 | ErrReflinkUnsupported = errors.New("reflink is not supported on this OS") 10 | ErrReflinkFailed = errors.New("reflink is not supported on this OS or file") 11 | ) 12 | -------------------------------------------------------------------------------- /go-prompt/internal/bisect/bisect.go: -------------------------------------------------------------------------------- 1 | package bisect 2 | 3 | import "sort" 4 | 5 | // Right to locate the insertion point for v in a to maintain sorted order. 6 | func Right(a []int, v int) int { 7 | return bisectRightRange(a, v, 0, len(a)) 8 | } 9 | 10 | func bisectRightRange(a []int, v int, lo, hi int) int { 11 | s := a[lo:hi] 12 | return sort.Search(len(s), func(i int) bool { 13 | return s[i] > v 14 | }) 15 | } 16 | -------------------------------------------------------------------------------- /go-socket.io/_examples/go-echo/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/googollee/go-socket.io/_examples/go-echo 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/googollee/go-socket.io v0.0.0-00010101000000-000000000000 7 | github.com/labstack/echo v3.3.10+incompatible 8 | github.com/labstack/gommon v0.3.0 // indirect 9 | golang.org/x/crypto v0.1.0 // indirect 10 | ) 11 | 12 | replace github.com/googollee/go-socket.io => ../../ 13 | -------------------------------------------------------------------------------- /go-socket.io/_examples/redis-adapter-unix-socket/Makefile: -------------------------------------------------------------------------------- 1 | 2 | IMAGE_NAME=gin-redis-adapter 3 | CONTAINER_NAME=gin-redis-adapter 4 | 5 | all: run 6 | 7 | run: build 8 | docker-compose up -d 9 | 10 | build: clean_up 11 | docker build . -t $(IMAGE_NAME) 12 | 13 | clean_up: stop 14 | docker-compose down 15 | docker rm $(CONTAINER_NAME) 16 | docker rmi $(IMAGE_NAME) 17 | 18 | stop: 19 | docker stop $(CONTAINER_NAME) -------------------------------------------------------------------------------- /go-socket.io/_examples/dockerize-default-http/Makefile: -------------------------------------------------------------------------------- 1 | 2 | IMAGE_NAME=default-http 3 | CONTAINER_NAME=default-http 4 | 5 | all: run 6 | 7 | run: build 8 | docker run -d -p 8000:8000 --name $(CONTAINER_NAME) $(IMAGE_NAME):latest 9 | 10 | build: clean_up 11 | docker build . -t $(IMAGE_NAME) 12 | 13 | clean_up: stop 14 | docker rm $(CONTAINER_NAME) 15 | docker rmi $(IMAGE_NAME) 16 | 17 | stop: 18 | docker stop $(CONTAINER_NAME) -------------------------------------------------------------------------------- /go-prompt/_example/http-prompt/api.py: -------------------------------------------------------------------------------- 1 | from bottle import route, run, request 2 | 3 | @route('/') 4 | def hello(): 5 | return "Hello World!" 6 | 7 | @route('/ping') 8 | def hello(): 9 | return "pong!" 10 | 11 | @route('/register', method='POST') 12 | def register(): 13 | name = request.json.get("name") 14 | return "Hello %s!" % name 15 | 16 | if __name__ == "__main__": 17 | run(host='localhost', port=8000, debug=True) 18 | -------------------------------------------------------------------------------- /go-socket.io/engineio/packet/fake_writer.go: -------------------------------------------------------------------------------- 1 | package packet 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/googollee/go-socket.io/engineio/frame" 7 | ) 8 | 9 | type fakeConnWriter struct { 10 | Frames []Frame 11 | } 12 | 13 | func NewFakeConnWriter() *fakeConnWriter { 14 | return &fakeConnWriter{} 15 | } 16 | 17 | func (w *fakeConnWriter) NextWriter(fType frame.Type) (io.WriteCloser, error) { 18 | return newFakeFrame(w, fType), nil 19 | } 20 | -------------------------------------------------------------------------------- /cobra-prompt/.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | 16 | # Intellij 17 | .idea/ 18 | 19 | vendor/ 20 | 21 | _example/cobra-prompt 22 | _example/_example -------------------------------------------------------------------------------- /reflink/reflink.go: -------------------------------------------------------------------------------- 1 | //go:build !linux 2 | 3 | package reflink 4 | 5 | import "os" 6 | 7 | func reflinkInternal(d, s *os.File) error { 8 | return ErrReflinkUnsupported 9 | } 10 | 11 | func reflinkRangeInternal(dst, src *os.File, dstOffset, srcOffset, n int64) error { 12 | return ErrReflinkUnsupported 13 | } 14 | 15 | func copyFileRange(dst, src *os.File, dstOffset, srcOffset, n int64) (int64, error) { 16 | return 0, ErrReflinkUnsupported // @fix 17 | } 18 | -------------------------------------------------------------------------------- /site/all/all.go: -------------------------------------------------------------------------------- 1 | package all 2 | 3 | import ( 4 | _ "github.com/sagan/ptool/site/discuz" 5 | _ "github.com/sagan/ptool/site/gazelle" 6 | _ "github.com/sagan/ptool/site/gazellepw" 7 | _ "github.com/sagan/ptool/site/mtorrent" 8 | _ "github.com/sagan/ptool/site/nexusphp" 9 | _ "github.com/sagan/ptool/site/tnode" 10 | _ "github.com/sagan/ptool/site/torrenttrader" 11 | _ "github.com/sagan/ptool/site/tpl" 12 | _ "github.com/sagan/ptool/site/unit3d" 13 | ) 14 | -------------------------------------------------------------------------------- /cobra-prompt/_example/cmd/error.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/spf13/cobra" 7 | ) 8 | 9 | var errorCmd = &cobra.Command{ 10 | Use: "error", 11 | Short: "Returns error", 12 | RunE: func(cmd *cobra.Command, args []string) error { 13 | return errors.New("when an error accure you can decide if you want to continue or not by handling error with OnErrorFunc") 14 | }, 15 | } 16 | 17 | func init() { 18 | RootCmd.AddCommand(errorCmd) 19 | } 20 | -------------------------------------------------------------------------------- /cmd/hardlink/cp/suggest.go: -------------------------------------------------------------------------------- 1 | package hardlinkcp 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("hardlinkcp", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIsFlag { 14 | return nil 15 | } 16 | return suggest.FileArg(info.MatchingPrefix, "", false) 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /go-socket.io/engineio/frame/frame.go: -------------------------------------------------------------------------------- 1 | package frame 2 | 3 | // Type is the type of frames. 4 | type Type byte 5 | 6 | const ( 7 | // String identifies a string frame. 8 | String Type = iota 9 | // Binary identifies a binary frame. 10 | Binary 11 | ) 12 | 13 | // ByteToFrameType converts a byte to FrameType. 14 | func ByteToFrameType(b byte) Type { 15 | return Type(b) 16 | } 17 | 18 | // Byte returns type in byte. 19 | func (t Type) Byte() byte { 20 | return byte(t) 21 | } 22 | -------------------------------------------------------------------------------- /cobra-prompt/.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Set up Go 17 | uses: actions/setup-go@v2 18 | with: 19 | go-version: 1.17 20 | 21 | - name: Build 22 | run: go build -v 23 | 24 | - name: Test 25 | run: go test -v 26 | -------------------------------------------------------------------------------- /go-socket.io/logger/README.md: -------------------------------------------------------------------------------- 1 | # Socket.io Logging 2 | 3 | Override internal logger with: 4 | 5 | ```go 6 | import ( 7 | ... 8 | "github.com/googollee/go-socket.io/logger" 9 | ) 10 | 11 | func main() { 12 | json_logger := slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ 13 | Level: slog.LevelInfo, // Set Level for each handler 14 | }) 15 | 16 | log := slog.New(json_logger).With("server", "socket.io") // attach attribute to all log lines 17 | logger.Log = log 18 | } 19 | ``` -------------------------------------------------------------------------------- /go-socket.io/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | all: 3 | go install ./... 4 | 5 | .PHONY: get_dev 6 | get_dev: 7 | go get -t ./... 8 | 9 | .PHONY: test 10 | test: 11 | go clean -testcache && go test -v -race -count=1 ./... 12 | 13 | .PHONY: bench 14 | bench: 15 | go clean -testcache && go test -bench . -benchmem ./... 16 | 17 | .PHONY: lint 18 | lint: 19 | golangci-lint run 20 | 21 | .PHONY: cover 22 | cover: 23 | go clean -testcache && go test ./... -cover -coverprofile=c.out && go tool cover -html=c.out 24 | -------------------------------------------------------------------------------- /go-socket.io/upgrade workflow.md: -------------------------------------------------------------------------------- 1 | ```mermaid 2 | sequenceDiagram 3 | client->>server: dial 4 | server->>client: reply open 5 | client->>server: dial upgrade 6 | client->>server: upgrade ping probe 7 | server->>client: upgrade pong probe 8 | client->>client: pause old conn 9 | client->>client: switch old conn to upgraded conn 10 | client->>server: upgrade 11 | server->>server: pause old conn(return noop if waiting) 12 | server->>server: switch old conn to upgraded conn 13 | server->>server: close old conn 14 | ``` 15 | -------------------------------------------------------------------------------- /util/osutil/others.go: -------------------------------------------------------------------------------- 1 | //go:build !linux && !windows 2 | // +build !linux,!windows 3 | 4 | package osutil 5 | 6 | import ( 7 | "runtime" 8 | 9 | log "github.com/sirupsen/logrus" 10 | ) 11 | 12 | // Non Linux/Window platforms setup / initialization. 13 | func Init() { 14 | } 15 | 16 | // Dummy (placeholder). 17 | // The real implentation (on Linux) will fork the child process and exit. 18 | func Fork(removeArg string) { 19 | log.Fatalf("Fork mode is NOT supported on current platform %s", runtime.GOOS) 20 | } 21 | -------------------------------------------------------------------------------- /go-socket.io/engineio/frame/frame_test.go: -------------------------------------------------------------------------------- 1 | package frame 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestFrameType(t *testing.T) { 10 | at := assert.New(t) 11 | tests := []struct { 12 | b byte 13 | typ Type 14 | outb byte 15 | }{ 16 | {0, String, 0}, 17 | {1, Binary, 1}, 18 | } 19 | 20 | for _, test := range tests { 21 | typ := ByteToFrameType(test.b) 22 | at.Equal(test.typ, typ) 23 | b := typ.Byte() 24 | at.Equal(test.outb, b) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /cmd/statscmd/suggest.go: -------------------------------------------------------------------------------- 1 | package statscmd 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("statscmd", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | return suggest.ClientArg(info.MatchingPrefix) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /cmd/status/suggest.go: -------------------------------------------------------------------------------- 1 | package status 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("status", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | return suggest.ClientOrSiteOrGroupArg(info.MatchingPrefix) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /go-prompt/_example/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export GO111MODULE=on 4 | DIR=$(cd $(dirname $0); pwd) 5 | BIN_DIR=$(cd $(dirname $(dirname $0)); pwd)/bin 6 | 7 | mkdir -p ${BIN_DIR} 8 | go build -o ${BIN_DIR}/exec-command ${DIR}/exec-command/main.go 9 | go build -o ${BIN_DIR}/http-prompt ${DIR}/http-prompt/main.go 10 | go build -o ${BIN_DIR}/live-prefix ${DIR}/live-prefix/main.go 11 | go build -o ${BIN_DIR}/simple-echo ${DIR}/simple-echo/main.go 12 | go build -o ${BIN_DIR}/simple-echo-cjk-cyrillic ${DIR}/simple-echo/cjk-cyrillic/main.go 13 | -------------------------------------------------------------------------------- /go-socket.io/_examples/redis-adapter-unix-socket/redis.conf: -------------------------------------------------------------------------------- 1 | # create a unix domain socket to listen on 2 | unixsocket /tmp/docker/redis.sock 3 | 4 | # set permissions for the socket 5 | unixsocketperm 770 6 | 7 | #requirepass passwordtouse 8 | 9 | # listen on localhost only 10 | bind 127.0.0.1 11 | 12 | #daemonize yes 13 | #stop-writes-on-bgsave-error no 14 | #rdbcompression yes 15 | # maximum memory allowed for redis 16 | #maxmemory 50M 17 | # how redis will evice old objects - least recently used 18 | #maxmemory-policy allkeys-lru 19 | -------------------------------------------------------------------------------- /cmd/xseedadd/suggest.go: -------------------------------------------------------------------------------- 1 | package xseedadd 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("xseedadd", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | return suggest.FileArg(info.MatchingPrefix, ".torrent", false) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /cmd/maketorrent/suggest.go: -------------------------------------------------------------------------------- 1 | package maketorrent 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("maketorrent", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex != 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | return suggest.FileArg(info.MatchingPrefix, "", false) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /go-socket.io/_examples/redis-adapter/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | redis: 5 | container_name: redis 6 | hostname: redis 7 | image: redis:alpine 8 | ports: 9 | - "6379:6379" 10 | 11 | redis-commander: 12 | container_name: redis-commander 13 | hostname: redis-commander 14 | image: rediscommander/redis-commander:latest 15 | restart: always 16 | depends_on: 17 | - redis 18 | environment: 19 | - REDIS_HOSTS=local:redis:6379 20 | ports: 21 | - "8081:8081" 22 | -------------------------------------------------------------------------------- /cmd/edittorrent/suggest.go: -------------------------------------------------------------------------------- 1 | package edittorrent 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("edittorrent", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | return suggest.FileArg(info.MatchingPrefix, ".torrent", false) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /cmd/parsetorrent/suggest.go: -------------------------------------------------------------------------------- 1 | package parsetorrent 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("parsetorrent", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | return suggest.FileArg(info.MatchingPrefix, ".torrent", false) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /cmd/verifytorrent/suggest.go: -------------------------------------------------------------------------------- 1 | package verifytorrent 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("verifytorrent", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | return suggest.FileArg(info.MatchingPrefix, ".torrent", false) 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /cmd/hardlink/torrent/suggest.go: -------------------------------------------------------------------------------- 1 | package hardlinktorrent 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("hardlinktorrent", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIsFlag { 14 | return nil 15 | } 16 | if info.LastArgIndex == 1 { 17 | return suggest.FileArg(info.MatchingPrefix, ".torrent", false) 18 | } 19 | return nil 20 | }) 21 | } 22 | -------------------------------------------------------------------------------- /go-socket.io/engineio/packet/fake_discarder.go: -------------------------------------------------------------------------------- 1 | package packet 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/googollee/go-socket.io/engineio/frame" 7 | ) 8 | 9 | type fakeOneFrameDiscarder struct{} 10 | 11 | func (d fakeOneFrameDiscarder) Write(p []byte) (int, error) { 12 | return len(p), nil 13 | } 14 | 15 | func (d fakeOneFrameDiscarder) Close() error { 16 | return nil 17 | } 18 | 19 | type FakeDiscardWriter struct{} 20 | 21 | func (w *FakeDiscardWriter) NextWriter(fType frame.Type) (io.WriteCloser, error) { 22 | return fakeOneFrameDiscarder{}, nil 23 | } 24 | -------------------------------------------------------------------------------- /go-socket.io/_examples/dockerize-default-http/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.16-alpine as build 2 | 3 | ENV GO11MODULE=on \ 4 | CGO_ENABLED=0 \ 5 | GOOS=linux \ 6 | GOARCH=amd64 \ 7 | BASE_PATH=/go/src/app 8 | 9 | WORKDIR $BASE_PATH 10 | 11 | COPY . . 12 | 13 | RUN go mod download 14 | RUN go build -o main . 15 | 16 | 17 | # Run section 18 | FROM scratch as run 19 | 20 | ENV BASE_PATH=/go/src/app 21 | 22 | COPY --from=build $BASE_PATH/main /app/main 23 | COPY --from=build $BASE_PATH/asset /asset 24 | 25 | EXPOSE 8000 26 | 27 | ENTRYPOINT ["/app/main"] 28 | -------------------------------------------------------------------------------- /go-socket.io/_examples/redis-adapter-unix-socket/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.16-alpine as build 2 | 3 | ENV GO11MODULE=on \ 4 | CGO_ENABLED=0 \ 5 | GOOS=linux \ 6 | GOARCH=amd64 \ 7 | BASE_PATH=/go/src/app 8 | 9 | WORKDIR $BASE_PATH 10 | 11 | COPY . . 12 | 13 | RUN go mod download 14 | RUN go build -o main . 15 | 16 | 17 | # Run section 18 | FROM scratch as run 19 | 20 | ENV BASE_PATH=/go/src/app 21 | 22 | COPY --from=build $BASE_PATH/main /app/main 23 | COPY --from=build $BASE_PATH/asset /asset 24 | 25 | EXPOSE 8000 26 | 27 | ENTRYPOINT ["/app/main"] 28 | -------------------------------------------------------------------------------- /cmd/tidyup/suggest.go: -------------------------------------------------------------------------------- 1 | package tidyup 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("tidyup", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex != 1 { 20 | return nil 21 | } 22 | return suggest.ClientArg(info.MatchingPrefix) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/checktag/suggest.go: -------------------------------------------------------------------------------- 1 | package checktag 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("checktag", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex != 1 { 20 | return nil 21 | } 22 | return suggest.ClientArg(info.MatchingPrefix) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/gettags/suggest.go: -------------------------------------------------------------------------------- 1 | package gettags 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("gettags", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex != 1 { 20 | return nil 21 | } 22 | return suggest.ClientArg(info.MatchingPrefix) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/search/suggest.go: -------------------------------------------------------------------------------- 1 | package search 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("search", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex != 1 { 20 | return nil 21 | } 22 | return suggest.SiteOrGroupArg(info.MatchingPrefix) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /version/version.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/sagan/ptool/constants" 7 | ) 8 | 9 | var ( 10 | VersionSuffix = "DEV" // e.g. DEV 11 | VersionTag = "v0.1.11" 12 | Version = "" 13 | Commit = constants.NONE 14 | Date = "unknown" 15 | ) 16 | 17 | func init() { 18 | if Version == "" { 19 | if VersionSuffix == "" { 20 | Version = VersionTag 21 | } else { 22 | Version = VersionTag + "-" + VersionSuffix 23 | } 24 | } else if !strings.HasPrefix(Version, "v") { 25 | Version = "v" + Version 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /cmd/findalone/suggest.go: -------------------------------------------------------------------------------- 1 | package findalone 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("findalone", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex != 1 { 20 | return nil 21 | } 22 | return suggest.ClientArg(info.MatchingPrefix) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/iyuu/xseed/suggest.go: -------------------------------------------------------------------------------- 1 | package xseed 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("iyuu.xseed", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 2 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex != 2 { 20 | return nil 21 | } 22 | return suggest.ClientArg(info.MatchingPrefix) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/renametag/suggest.go: -------------------------------------------------------------------------------- 1 | package renametag 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("renametag", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return nil 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/createtags/suggest.go: -------------------------------------------------------------------------------- 1 | package createtags 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("createtags", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex != 1 { 20 | return nil 21 | } 22 | return suggest.ClientArg(info.MatchingPrefix) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/deletetags/suggest.go: -------------------------------------------------------------------------------- 1 | package deletetags 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("deletetags", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex != 1 { 20 | return nil 21 | } 22 | return suggest.ClientArg(info.MatchingPrefix) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/getcategories/suggest.go: -------------------------------------------------------------------------------- 1 | package getcategories 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("getcategories", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex != 1 { 20 | return nil 21 | } 22 | return suggest.ClientArg(info.MatchingPrefix) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /go-socket.io/engineio/connect.go: -------------------------------------------------------------------------------- 1 | package engineio 2 | 3 | import ( 4 | "io" 5 | "net" 6 | "net/http" 7 | "net/url" 8 | 9 | "github.com/googollee/go-socket.io/engineio/session" 10 | ) 11 | 12 | // Conn is connection by client session 13 | type Conn interface { 14 | ID() string 15 | NextReader() (session.FrameType, io.ReadCloser, error) 16 | NextWriter(fType session.FrameType) (io.WriteCloser, error) 17 | Close() error 18 | URL() url.URL 19 | LocalAddr() net.Addr 20 | RemoteAddr() net.Addr 21 | RemoteHeader() http.Header 22 | SetContext(v interface{}) 23 | Context() interface{} 24 | } 25 | -------------------------------------------------------------------------------- /cmd/createcategory/suggest.go: -------------------------------------------------------------------------------- 1 | package createcategory 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("createcategory", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex != 1 { 20 | return nil 21 | } 22 | return suggest.ClientArg(info.MatchingPrefix) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/deletecategories/suggest.go: -------------------------------------------------------------------------------- 1 | package deletecategories 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("deletecategories", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex != 1 { 20 | return nil 21 | } 22 | return suggest.ClientArg(info.MatchingPrefix) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /go-prompt/_example/exec-command/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "os/exec" 6 | 7 | prompt "github.com/c-bata/go-prompt" 8 | ) 9 | 10 | func executor(t string) { 11 | if t == "bash" { 12 | cmd := exec.Command("bash") 13 | cmd.Stdin = os.Stdin 14 | cmd.Stdout = os.Stdout 15 | cmd.Stderr = os.Stderr 16 | cmd.Run() 17 | } 18 | return 19 | } 20 | 21 | func completer(t prompt.Document) []prompt.Suggest { 22 | return []prompt.Suggest{ 23 | {Text: "bash"}, 24 | } 25 | } 26 | 27 | func main() { 28 | p := prompt.New( 29 | executor, 30 | completer, 31 | ) 32 | p.Run() 33 | } 34 | -------------------------------------------------------------------------------- /cmd/brush/suggest.go: -------------------------------------------------------------------------------- 1 | package brush 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("brush", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.SiteOrGroupArg(info.MatchingPrefix) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/delete/suggest.go: -------------------------------------------------------------------------------- 1 | package delete 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("delete", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.InfoHashArg(info.MatchingPrefix, info.Args[1]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/dltorrent/suggest.go: -------------------------------------------------------------------------------- 1 | package dltorrent 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("dltorrent", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | switch info.LastArgFlag { 18 | case "site": 19 | return suggest.SiteArg(info.MatchingPrefix) 20 | default: 21 | return nil 22 | } 23 | } 24 | return nil 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /cmd/reseed/reseed.go: -------------------------------------------------------------------------------- 1 | package reseed 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | ) 8 | 9 | // 使用 Reseed (https://github.com/tongyifan/Reseed-backend) 后端的自动辅种工具。 10 | // 将找到的所有辅种 .torrent 文件下载到本地。 11 | // 使用 ptool xseedadd 将辅种种子添加到客户端。 12 | 13 | var Command = &cobra.Command{ 14 | Use: "reseed", 15 | Short: "Cross seed automation tool using Reseed (https://github.com/tongyifan/Reseed-backend) API.", 16 | Long: `Cross seed automation tool using Reseed (https://github.com/tongyifan/Reseed-backend) API.`, 17 | } 18 | 19 | func init() { 20 | cmd.RootCmd.AddCommand(Command) 21 | } 22 | -------------------------------------------------------------------------------- /go-socket.io/engineio/transport/utils/clock_test.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | 7 | "github.com/stretchr/testify/assert" 8 | "github.com/stretchr/testify/require" 9 | ) 10 | 11 | type testClock struct { 12 | now time.Time 13 | } 14 | 15 | func (c testClock) Now() time.Time { 16 | return c.now 17 | } 18 | 19 | func TestTimestampFromClock(t *testing.T) { 20 | ts1 := TimestampFromClock(testClock{time.Unix(0, 1000)}) 21 | ts2 := TimestampFromClock(testClock{time.Unix(0, 2000)}) 22 | 23 | require.NotEmpty(t, ts1) 24 | require.NotEmpty(t, ts2) 25 | 26 | assert.NotEqual(t, ts1, ts2) 27 | } 28 | -------------------------------------------------------------------------------- /cmd/pause/suggest.go: -------------------------------------------------------------------------------- 1 | package pause 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("pause", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cobra-prompt/README.md: -------------------------------------------------------------------------------- 1 | # Cobra-Prompt 2 | 3 | Cobra-prompt makes every Cobra command and flag available for go-prompt. 4 | - https://github.com/spf13/cobra 5 | - https://github.com/c-bata/go-prompt 6 | 7 | 8 | ## Features 9 | 10 | - Traverse cobra command tree. Every command and flag will be available. 11 | - Persist flag values. 12 | - Add custom functions for dynamic suggestions. 13 | 14 | ## Getting started 15 | 16 | Get the module: 17 | 18 | ``` 19 | go get github.com/stromland/cobra-prompt 20 | ``` 21 | 22 | ## Explore the example 23 | 24 | ``` 25 | cd _example 26 | go build -o cobra-prompt 27 | ./cobra-prompt 28 | ``` 29 | -------------------------------------------------------------------------------- /go-socket.io/.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*" 7 | 8 | jobs: 9 | release: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write 13 | steps: 14 | - uses: actions/checkout@v4 15 | with: 16 | fetch-depth: 0 17 | 18 | - uses: actions/setup-go@v5 19 | with: 20 | go-version-file: go.mod 21 | cache: true 22 | 23 | - uses: goreleaser/goreleaser-action@v6 24 | with: 25 | args: release --clean 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # 自動で生成されるシークレット 28 | -------------------------------------------------------------------------------- /cmd/export/suggest.go: -------------------------------------------------------------------------------- 1 | package export 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("export", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/resume/suggest.go: -------------------------------------------------------------------------------- 1 | package resume 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("resume", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/recheck/suggest.go: -------------------------------------------------------------------------------- 1 | package recheck 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("recheck", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/reannounce/suggest.go: -------------------------------------------------------------------------------- 1 | package reannounce 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("reannounce", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /transmissionrpc/session_shutdown.go: -------------------------------------------------------------------------------- 1 | package transmissionrpc 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | ) 7 | 8 | /* 9 | Session shutdown 10 | https://github.com/transmission/transmission/blob/3.00/extras/rpc-spec.txt#L615 11 | */ 12 | 13 | // SessionClose tells the transmission session to shut down. 14 | // https://github.com/transmission/transmission/blob/3.00/extras/rpc-spec.txt#L619 15 | func (c *Client) SessionClose(ctx context.Context) (err error) { 16 | // Send request 17 | if err = c.rpcCall(ctx, "session-close", nil, nil); err != nil { 18 | err = fmt.Errorf("'session-close' rpc method failed: %w", err) 19 | } 20 | return 21 | } 22 | -------------------------------------------------------------------------------- /cmd/addtrackers/suggest.go: -------------------------------------------------------------------------------- 1 | package addtrackers 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("addtrackers", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/edittracker/suggest.go: -------------------------------------------------------------------------------- 1 | package edittracker 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("edittracker", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/modifytorrent/suggest.go: -------------------------------------------------------------------------------- 1 | package modifytorrent 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("modifytorrent", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/skipchecking/suggest.go: -------------------------------------------------------------------------------- 1 | package skipchecking 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("skipchecking", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/removetrackers/suggest.go: -------------------------------------------------------------------------------- 1 | package removetrackers 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("removetrackers", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/transfertorrent/suggest.go: -------------------------------------------------------------------------------- 1 | package transfertorrent 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("transfertorrent", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/reseed/match/suggest.go: -------------------------------------------------------------------------------- 1 | package match 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("reseed.match", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | switch info.LastArgFlag { 18 | case "download-dir": 19 | return suggest.DirArg(info.MatchingPrefix) 20 | default: 21 | return nil 22 | } 23 | } 24 | return suggest.DirArg(info.MatchingPrefix) 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /go-socket.io/parser/packet.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | // Type of packet. 4 | type Type byte 5 | 6 | const ( 7 | // Connect type 8 | Connect Type = iota 9 | // Disconnect type 10 | Disconnect 11 | // Event type 12 | Event 13 | // Ack type 14 | Ack 15 | // Error type 16 | Error 17 | 18 | // BinaryEvent type 19 | binaryEvent 20 | // BinaryAck type 21 | binaryAck 22 | ) 23 | 24 | // Header of packet. 25 | type Header struct { 26 | Type Type 27 | ID uint64 28 | NeedAck bool 29 | Namespace string 30 | Query string 31 | } 32 | 33 | // Payload of packet. 34 | type Payload struct { 35 | Header Header 36 | 37 | Data []interface{} 38 | } 39 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a golang project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go 3 | 4 | name: Go 5 | 6 | on: 7 | push: 8 | branches: [ "master" ] 9 | pull_request: 10 | branches: [ "master" ] 11 | 12 | jobs: 13 | 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v3 18 | 19 | - name: Set up Go 20 | uses: actions/setup-go@v3 21 | with: 22 | go-version-file: go.mod 23 | 24 | - name: Build 25 | run: go build -v ./... 26 | 27 | - name: Test 28 | run: go test -v ./... 29 | -------------------------------------------------------------------------------- /cmd/markinvalidtracker/suggest.go: -------------------------------------------------------------------------------- 1 | package markinvalidtracker 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("markinvalidtracker", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 23 | }) 24 | } 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | *.db 8 | 9 | # Test binary, built with `go test -c` 10 | *.test 11 | 12 | # Output of the go coverage tool, specifically when used with LiteIDE 13 | *.out 14 | 15 | # Dependency directories (remove the comment below to include it) 16 | # vendor/ 17 | 18 | # config files 19 | ptool.toml 20 | ptool.yaml 21 | ptool.lock 22 | ptool-global.lock 23 | ptool_history 24 | ptool_stats.txt 25 | iyuu.db 26 | 27 | # local 28 | /.local/ 29 | devtest/ 30 | 31 | # Linux ELF 32 | /ptool 33 | 34 | # test torrent files 35 | *.torrent 36 | *.fastresume 37 | *.bak 38 | *.log 39 | 40 | dist/ 41 | -------------------------------------------------------------------------------- /go-socket.io/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via issue, 4 | email, or any other method with the owners of this repository before making a change. 5 | 6 | Please note we have a code of conduct, please follow it in all your interactions with the project. 7 | 8 | ## Pull Request Process 9 | 10 | 1. Fork it 11 | 2. Create your feature branch (`git checkout -b my-new-feature`) 12 | 3. Commit your changes (`git commit -am 'Add some feature'`) 13 | 4. Push to the branch (`git push origin my-new-feature`) 14 | 5. Create new Pull Request 15 | 16 | Please make an issue first if the change is likely to increase. -------------------------------------------------------------------------------- /go-prompt/input_test.go: -------------------------------------------------------------------------------- 1 | package prompt 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestPosixParserGetKey(t *testing.T) { 8 | scenarioTable := []struct { 9 | name string 10 | input []byte 11 | expected Key 12 | }{ 13 | { 14 | name: "escape", 15 | input: []byte{0x1b}, 16 | expected: Escape, 17 | }, 18 | { 19 | name: "undefined", 20 | input: []byte{'a'}, 21 | expected: NotDefined, 22 | }, 23 | } 24 | 25 | for _, s := range scenarioTable { 26 | t.Run(s.name, func(t *testing.T) { 27 | key := GetKey(s.input) 28 | if key != s.expected { 29 | t.Errorf("Should be %s, but got %s", key, s.expected) 30 | } 31 | }) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /cmd/addtags/suggest.go: -------------------------------------------------------------------------------- 1 | package addtags 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("addtags", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | if info.LastArgIndex >= 3 { 23 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 24 | } 25 | return nil 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /cmd/dynamicseeding/suggest.go: -------------------------------------------------------------------------------- 1 | package dynamicseeding 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("dynamicseeding", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | switch info.LastArgIndex { 20 | case 1: 21 | return suggest.ClientArg(info.MatchingPrefix) 22 | case 2: 23 | return suggest.SiteArg(info.MatchingPrefix) 24 | default: 25 | return nil 26 | } 27 | }) 28 | } 29 | -------------------------------------------------------------------------------- /go-socket.io/engineio/session/session_id_generator.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | import ( 4 | "strconv" 5 | "sync/atomic" 6 | ) 7 | 8 | // IDGenerator generates new session id. Default behavior is simple 9 | // increasing number. 10 | // If you need custom session id, for example using local ip as prefix, you can 11 | // implement SessionIDGenerator and save in Configure. Engine.io will use custom 12 | // one to generate new session id. 13 | type IDGenerator interface { 14 | NewID() string 15 | } 16 | 17 | type DefaultIDGenerator struct { 18 | ID uint64 19 | } 20 | 21 | func (g *DefaultIDGenerator) NewID() string { 22 | id := atomic.AddUint64(&g.ID, 1) 23 | return strconv.FormatUint(id, 36) 24 | } 25 | -------------------------------------------------------------------------------- /cmd/removetags/suggest.go: -------------------------------------------------------------------------------- 1 | package removetags 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("removetags", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | if info.LastArgIndex >= 3 { 23 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 24 | } 25 | return nil 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /go-socket.io/.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug to help us improve 4 | title: "" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Brief code to reproduce the behavior. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Environment (please complete the following information):** 20 | - Go version: [e.g. v1.11] 21 | - Server version [e.g. go-socket.io v1.4] 22 | - Client version [e.g. socket.io v1.4] 23 | 24 | **Additional context** 25 | Add any other context about the problem here. 26 | -------------------------------------------------------------------------------- /client/qbittorrent/fastresume.go: -------------------------------------------------------------------------------- 1 | package qbittorrent 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/anacrolix/torrent/bencode" 8 | ) 9 | 10 | type FastresumeFile struct { 11 | Trackers [][]string `bencode:"trackers,omitempty"` 12 | } 13 | 14 | func parseQbFastresumeFile(path string) (*FastresumeFile, error) { 15 | fd, err := os.Open(path) 16 | if err != nil { 17 | return nil, err 18 | } 19 | defer fd.Close() 20 | var ff FastresumeFile 21 | d := bencode.NewDecoder(fd) 22 | err = d.Decode(&ff) 23 | if err != nil { 24 | return nil, err 25 | } 26 | err = d.ReadEOF() 27 | if err != nil { 28 | return nil, fmt.Errorf("error after decoding bencode: %w", err) 29 | } 30 | return &ff, nil 31 | } 32 | -------------------------------------------------------------------------------- /cmd/partialdownload/suggest.go: -------------------------------------------------------------------------------- 1 | package partialdownload 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("partialdownload", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } else if info.LastArgIndex == 2 { 22 | return suggest.InfoHashArg(info.MatchingPrefix, info.Args[1]) 23 | } 24 | return nil 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /cmd/setcategory/suggest.go: -------------------------------------------------------------------------------- 1 | package setcategory 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("setcategory", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | if info.LastArgIndex >= 3 { 23 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 24 | } 25 | return nil 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /cmd/setsavepath/suggest.go: -------------------------------------------------------------------------------- 1 | package setsavepath 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("setsavepath", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | if info.LastArgIndex == 1 { 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | } 22 | if info.LastArgIndex >= 3 { 23 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 24 | } 25 | return nil 26 | }) 27 | } 28 | -------------------------------------------------------------------------------- /go-socket.io/engineio/payload/errors_test.go: -------------------------------------------------------------------------------- 1 | package payload 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestOpError(t *testing.T) { 10 | assert := assert.New(t) 11 | 12 | tests := []struct { 13 | op string 14 | err error 15 | temporary bool 16 | errString string 17 | }{ 18 | {"read", errPaused, true, "read: paused"}, 19 | {"read", errTimeout, false, "read: timeout"}, 20 | } 21 | 22 | for _, test := range tests { 23 | var err = newOpError(test.op, test.err) 24 | 25 | assert.EqualError(err, test.errString) 26 | 27 | re, ok := err.(Error) 28 | assert.True(ok) 29 | 30 | assert.Equal(test.temporary, re.Temporary()) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /go-socket.io/namespace_handlers.go: -------------------------------------------------------------------------------- 1 | package socketio 2 | 3 | import "sync" 4 | 5 | type namespaceHandlers struct { 6 | handlers map[string]*namespaceHandler 7 | mu sync.RWMutex 8 | } 9 | 10 | func newNamespaceHandlers() *namespaceHandlers { 11 | return &namespaceHandlers{ 12 | handlers: make(map[string]*namespaceHandler), 13 | } 14 | } 15 | 16 | func (h *namespaceHandlers) Set(namespace string, handler *namespaceHandler) { 17 | h.mu.Lock() 18 | defer h.mu.Unlock() 19 | 20 | h.handlers[namespace] = handler 21 | } 22 | 23 | func (h *namespaceHandlers) Get(nsp string) (*namespaceHandler, bool) { 24 | h.mu.RLock() 25 | defer h.mu.RUnlock() 26 | 27 | handler, ok := h.handlers[nsp] 28 | return handler, ok 29 | } 30 | -------------------------------------------------------------------------------- /cmd/movesavepath/suggest.go: -------------------------------------------------------------------------------- 1 | package movesavepath 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("movesavepath", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | switch info.LastArgFlag { 18 | case "client": 19 | return suggest.ClientArg(info.MatchingPrefix) 20 | default: 21 | return nil 22 | } 23 | } 24 | if info.LastArgIndex == 1 || info.LastArgIndex == 2 { 25 | return suggest.FileArg("", "", true) 26 | } 27 | return nil 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /cmd/add/suggest.go: -------------------------------------------------------------------------------- 1 | package add 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("add", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | switch info.LastArgFlag { 18 | case "site": 19 | return suggest.SiteArg(info.MatchingPrefix) 20 | default: 21 | return nil 22 | } 23 | } 24 | if info.LastArgIndex > 1 { 25 | return suggest.FileArg(info.MatchingPrefix, ".torrent", false) 26 | } 27 | return suggest.ClientArg(info.MatchingPrefix) 28 | }) 29 | } 30 | -------------------------------------------------------------------------------- /go-socket.io/engineio/transport/utils/clock.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import "time" 4 | 5 | var chars = []byte("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_") 6 | 7 | type clock interface { 8 | Now() time.Time 9 | } 10 | 11 | type timeClock struct{} 12 | 13 | func (timeClock) Now() time.Time { 14 | return time.Now() 15 | } 16 | 17 | // Timestamp returns a string based on different nano time. 18 | func Timestamp() string { 19 | return TimestampFromClock(timeClock{}) 20 | } 21 | 22 | func TimestampFromClock(c clock) string { 23 | now := c.Now().UnixNano() 24 | ret := make([]byte, 0, 16) 25 | for now > 0 { 26 | ret = append(ret, chars[int(now%int64(len(chars)))]) 27 | now = now / int64(len(chars)) 28 | } 29 | return string(ret) 30 | } 31 | -------------------------------------------------------------------------------- /go-socket.io/_examples/client/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "time" 6 | 7 | socketio "github.com/googollee/go-socket.io" 8 | ) 9 | 10 | func main() { 11 | // Simple client to talk to default-http example 12 | uri := "http://127.0.0.1:8000" 13 | 14 | client, err := socketio.NewClient(uri, nil) 15 | if err != nil { 16 | panic(err) 17 | } 18 | 19 | // Handle an incoming event 20 | client.OnEvent("reply", func(s socketio.Conn, msg string) { 21 | log.Println("Receive Message /reply: ", "reply", msg) 22 | }) 23 | 24 | err = client.Connect() 25 | if err != nil { 26 | panic(err) 27 | } 28 | 29 | client.Emit("notice", "hello") 30 | 31 | time.Sleep(1 * time.Second) 32 | err = client.Close() 33 | if err != nil { 34 | panic(err) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /cmd/xseedcheck/suggest.go: -------------------------------------------------------------------------------- 1 | package xseedcheck 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/shell/suggest" 8 | ) 9 | 10 | func init() { 11 | cmd.AddShellCompletion("xseedcheck", func(document *prompt.Document) []prompt.Suggest { 12 | info := suggest.Parse(document) 13 | if info.LastArgIndex < 1 { 14 | return nil 15 | } 16 | if info.LastArgIsFlag { 17 | return nil 18 | } 19 | switch info.LastArgIndex { 20 | case 1: 21 | return suggest.ClientArg(info.MatchingPrefix) 22 | case 2: 23 | return suggest.InfoHashArg(info.MatchingPrefix, info.Args[1]) 24 | case 3: 25 | return suggest.FileArg(info.MatchingPrefix, ".torrent", false) 26 | default: 27 | return nil 28 | } 29 | }) 30 | } 31 | -------------------------------------------------------------------------------- /go-prompt/internal/term/term.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | package term 5 | 6 | import ( 7 | "sync" 8 | 9 | "github.com/pkg/term/termios" 10 | "golang.org/x/sys/unix" 11 | ) 12 | 13 | var ( 14 | saveTermios *unix.Termios 15 | saveTermiosFD int 16 | saveTermiosOnce sync.Once 17 | ) 18 | 19 | func getOriginalTermios(fd int) (unix.Termios, error) { 20 | var err error 21 | saveTermiosOnce.Do(func() { 22 | saveTermiosFD = fd 23 | saveTermios, err = termios.Tcgetattr(uintptr(fd)) 24 | }) 25 | return *saveTermios, err 26 | } 27 | 28 | // Restore terminal's mode. 29 | func Restore() error { 30 | o, err := getOriginalTermios(saveTermiosFD) 31 | if err != nil { 32 | return err 33 | } 34 | return termios.Tcsetattr(uintptr(saveTermiosFD), termios.TCSANOW, &o) 35 | } 36 | -------------------------------------------------------------------------------- /go-socket.io/engineio/packet/decoder.go: -------------------------------------------------------------------------------- 1 | package packet 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/googollee/go-socket.io/engineio/frame" 7 | ) 8 | 9 | // FrameReader is the reader which supports framing. 10 | type FrameReader interface { 11 | NextReader() (frame.Type, io.ReadCloser, error) 12 | } 13 | 14 | type Decoder struct { 15 | r FrameReader 16 | } 17 | 18 | func NewDecoder(r FrameReader) *Decoder { 19 | return &Decoder{ 20 | r: r, 21 | } 22 | } 23 | 24 | func (e *Decoder) NextReader() (frame.Type, Type, io.ReadCloser, error) { 25 | ft, r, err := e.r.NextReader() 26 | if err != nil { 27 | return 0, 0, nil, err 28 | } 29 | var b [1]byte 30 | if _, err := io.ReadFull(r, b[:]); err != nil { 31 | _ = r.Close() 32 | return 0, 0, nil, err 33 | } 34 | return ft, ByteToPacketType(b[0], ft), r, nil 35 | } 36 | -------------------------------------------------------------------------------- /go-socket.io/engineio/transport/polling/util.go: -------------------------------------------------------------------------------- 1 | package polling 2 | 3 | import ( 4 | "errors" 5 | "mime" 6 | "strings" 7 | ) 8 | 9 | type Addr struct { 10 | Host string 11 | } 12 | 13 | func (a Addr) Network() string { 14 | return "tcp" 15 | } 16 | 17 | func (a Addr) String() string { 18 | return a.Host 19 | } 20 | 21 | func mimeIsSupportBinary(m string) (bool, error) { 22 | typ, params, err := mime.ParseMediaType(m) 23 | if err != nil { 24 | return false, err 25 | } 26 | 27 | switch typ { 28 | case "application/octet-stream": 29 | return true, nil 30 | 31 | case "text/plain": 32 | charset := strings.ToLower(params["charset"]) 33 | if charset != "utf-8" { 34 | return false, errors.New("invalid charset") 35 | } 36 | return false, nil 37 | } 38 | 39 | return false, errors.New("invalid content-type") 40 | } 41 | -------------------------------------------------------------------------------- /transmissionrpc/port_checking.go: -------------------------------------------------------------------------------- 1 | package transmissionrpc 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | ) 7 | 8 | /* 9 | Port Checking 10 | https://github.com/transmission/transmission/blob/3.00/extras/rpc-spec.txt#L606 11 | */ 12 | 13 | // PortTest allows tests to see if your incoming peer port is accessible from the outside world. 14 | // https://github.com/transmission/transmission/blob/3.00/extras/rpc-spec.txt#L611 15 | func (c *Client) PortTest(ctx context.Context) (open bool, err error) { 16 | var result portTestAnswer 17 | // Send request 18 | if err = c.rpcCall(ctx, "port-test", nil, &result); err == nil { 19 | open = result.PortOpen 20 | } else { 21 | err = fmt.Errorf("'port-test' rpc method failed: %w", err) 22 | } 23 | return 24 | } 25 | 26 | type portTestAnswer struct { 27 | PortOpen bool `json:"port-is-open"` 28 | } 29 | -------------------------------------------------------------------------------- /go-prompt/.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Bug report" 3 | about: Create a bug report to improve go-prompt 4 | title: "[Bug]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | # Bug reports 11 | 12 | *Please file a bug report here.* 13 | 14 | ## Expected Behavior 15 | 16 | *Please describe the behavior you are expecting* 17 | 18 | ## Current Behavior and Steps to Reproduce 19 | 20 | *What is the current behavior? Please provide detailed steps for reproducing the issue.* 21 | *A picture or gif animation tells a thousand words* 22 | 23 | ## Context 24 | 25 | Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions. 26 | 27 | * Operating System: 28 | * Terminal Emulator: (i.e. iTerm2) 29 | * tag of go-prompt or commit revision: 30 | 31 | -------------------------------------------------------------------------------- /go-socket.io/engineio/packet/fake_frame.go: -------------------------------------------------------------------------------- 1 | package packet 2 | 3 | import ( 4 | "bytes" 5 | 6 | "github.com/googollee/go-socket.io/engineio/frame" 7 | ) 8 | 9 | type fakeFrame struct { 10 | w *fakeConnWriter 11 | typ frame.Type 12 | data *bytes.Buffer 13 | } 14 | 15 | func newFakeFrame(w *fakeConnWriter, fType frame.Type) *fakeFrame { 16 | return &fakeFrame{ 17 | w: w, 18 | typ: fType, 19 | data: bytes.NewBuffer(nil), 20 | } 21 | } 22 | 23 | func (w *fakeFrame) Write(p []byte) (int, error) { 24 | return w.data.Write(p) 25 | } 26 | 27 | func (w *fakeFrame) Read(p []byte) (int, error) { 28 | return w.data.Read(p) 29 | } 30 | 31 | func (w *fakeFrame) Close() error { 32 | if w.w == nil { 33 | return nil 34 | } 35 | w.w.Frames = append(w.w.Frames, Frame{ 36 | FType: w.typ, 37 | Data: w.data.Bytes(), 38 | }) 39 | return nil 40 | } 41 | -------------------------------------------------------------------------------- /cobra-prompt/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/stromland/cobra-prompt 2 | 3 | go 1.17 4 | 5 | require ( 6 | github.com/c-bata/go-prompt v0.2.6 7 | github.com/mattn/go-colorable v0.1.11 // indirect 8 | github.com/mattn/go-runewidth v0.0.13 // indirect 9 | github.com/mattn/go-tty v0.0.3 // indirect 10 | github.com/pkg/term v1.2.0-beta.2 // indirect 11 | github.com/spf13/cobra v1.2.1 12 | github.com/spf13/pflag v1.0.5 13 | github.com/stretchr/testify v1.7.0 14 | ) 15 | 16 | require ( 17 | github.com/davecgh/go-spew v1.1.1 // indirect 18 | github.com/inconshreveable/mousetrap v1.0.0 // indirect 19 | github.com/mattn/go-isatty v0.0.14 // indirect 20 | github.com/pmezard/go-difflib v1.0.0 // indirect 21 | github.com/rivo/uniseg v0.2.0 // indirect 22 | golang.org/x/sys v0.0.0-20211001092434-39dca1131b70 // indirect 23 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 24 | ) 25 | -------------------------------------------------------------------------------- /go-prompt/emacs_test.go: -------------------------------------------------------------------------------- 1 | package prompt 2 | 3 | import "testing" 4 | 5 | func TestEmacsKeyBindings(t *testing.T) { 6 | buf := NewBuffer() 7 | buf.InsertText("abcde", false, true) 8 | if buf.cursorPosition != len("abcde") { 9 | t.Errorf("Want %d, but got %d", len("abcde"), buf.cursorPosition) 10 | } 11 | 12 | // Go to the beginning of the line 13 | applyEmacsKeyBind(buf, ControlA) 14 | if buf.cursorPosition != 0 { 15 | t.Errorf("Want %d, but got %d", 0, buf.cursorPosition) 16 | } 17 | 18 | // Go to the end of the line 19 | applyEmacsKeyBind(buf, ControlE) 20 | if buf.cursorPosition != len("abcde") { 21 | t.Errorf("Want %d, but got %d", len("abcde"), buf.cursorPosition) 22 | } 23 | } 24 | 25 | func applyEmacsKeyBind(buf *Buffer, key Key) { 26 | for i := range emacsKeyBindings { 27 | kb := emacsKeyBindings[i] 28 | if kb.Key == key { 29 | kb.Fn(buf) 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /go-socket.io/engineio/transport/polling/util_test.go: -------------------------------------------------------------------------------- 1 | package polling 2 | 3 | import ( 4 | "github.com/stretchr/testify/assert" 5 | "testing" 6 | ) 7 | 8 | func TestNormalizeMime(t *testing.T) { 9 | at := assert.New(t) 10 | 11 | tests := []struct { 12 | mime string 13 | supportBinary bool 14 | ok bool 15 | }{ 16 | {"application/octet-stream", true, true}, 17 | {"text/plain; charset=utf-8", false, true}, 18 | {"text/plain;charset=UTF-8", false, true}, 19 | 20 | {"text/plain;charset=gbk", false, false}, 21 | {"text/plain charset=U;TF-8", false, false}, 22 | {"text/html", false, false}, 23 | } 24 | 25 | for _, test := range tests { 26 | isSupportBinary, err := mimeIsSupportBinary(test.mime) 27 | at.Equal(test.ok, err == nil) 28 | 29 | if err != nil { 30 | continue 31 | } 32 | 33 | at.Equal(test.supportBinary, isSupportBinary) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /transmissionrpc/blocklist.go: -------------------------------------------------------------------------------- 1 | package transmissionrpc 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | ) 7 | 8 | /* 9 | Blocklist 10 | https://github.com/transmission/transmission/blob/3.00/extras/rpc-spec.txt#L600 11 | */ 12 | 13 | // BlocklistUpdate triggers a blocklist update. It returns the number of entries of the updated blocklist. 14 | // https://github.com/transmission/transmission/blob/3.00/extras/rpc-spec.txt#L602 15 | func (c *Client) BlocklistUpdate(ctx context.Context) (nbEntries int64, err error) { 16 | var answer blocklistUpdateAnswer 17 | // Send request 18 | if err = c.rpcCall(ctx, "blocklist-update", nil, &answer); err == nil { 19 | nbEntries = answer.NbEntries 20 | } else { 21 | err = fmt.Errorf("'blocklist-update' rpc method failed: %w", err) 22 | } 23 | return 24 | } 25 | 26 | type blocklistUpdateAnswer struct { 27 | NbEntries int64 `json:"blocklist-size"` 28 | } 29 | -------------------------------------------------------------------------------- /cmd/clientctl/suggest.go: -------------------------------------------------------------------------------- 1 | package clientctl 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/c-bata/go-prompt" 7 | 8 | "github.com/sagan/ptool/cmd" 9 | "github.com/sagan/ptool/cmd/shell/suggest" 10 | ) 11 | 12 | func init() { 13 | cmd.AddShellCompletion("clientctl", func(document *prompt.Document) []prompt.Suggest { 14 | info := suggest.Parse(document) 15 | if info.LastArgIndex < 1 { 16 | return nil 17 | } 18 | if info.LastArgIsFlag { 19 | return nil 20 | } 21 | if info.LastArgIndex == 1 { 22 | return suggest.ClientArg(info.MatchingPrefix) 23 | } 24 | if strings.HasPrefix(info.MatchingPrefix, "=") { 25 | return nil 26 | } 27 | commpletions := [][2]string{} 28 | for _, option := range allOptions { 29 | commpletions = append(commpletions, [2]string{option.Name, option.Description}) 30 | } 31 | return suggest.EnumArg(info.MatchingPrefix, commpletions) 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /go-prompt/_example/simple-echo/cjk-cyrillic/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | prompt "github.com/c-bata/go-prompt" 7 | ) 8 | 9 | func executor(in string) { 10 | fmt.Println("Your input: " + in) 11 | } 12 | 13 | func completer(in prompt.Document) []prompt.Suggest { 14 | s := []prompt.Suggest{ 15 | {Text: "こんにちは", Description: "'こんにちは' means 'Hello' in Japanese"}, 16 | {Text: "감사합니다", Description: "'안녕하세요' means 'Hello' in Korean."}, 17 | {Text: "您好", Description: "'您好' means 'Hello' in Chinese."}, 18 | {Text: "Добрый день", Description: "'Добрый день' means 'Hello' in Russian."}, 19 | } 20 | return prompt.FilterHasPrefix(s, in.GetWordBeforeCursor(), true) 21 | } 22 | 23 | func main() { 24 | p := prompt.New( 25 | executor, 26 | completer, 27 | prompt.OptionPrefix(">>> "), 28 | prompt.OptionTitle("sql-prompt for multi width characters"), 29 | ) 30 | p.Run() 31 | } 32 | -------------------------------------------------------------------------------- /go-socket.io/errors.go: -------------------------------------------------------------------------------- 1 | package socketio 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | // connect errors. 9 | var ( 10 | errUnavailableRootHandler = errors.New("root ('/') doesn't have a namespace handler") 11 | 12 | errFailedConnectNamespace = errors.New("failed connect to namespace without handler") 13 | ) 14 | 15 | // common connection dispatch errors. 16 | var ( 17 | errHandleDispatch = errors.New("handler dispatch error") 18 | 19 | errDecodeArgs = errors.New("decode args error") 20 | ) 21 | 22 | type errorMessage struct { 23 | namespace string 24 | 25 | err error 26 | } 27 | 28 | func (e errorMessage) Error() string { 29 | return fmt.Sprintf("error in namespace: (%s) with error: (%s)", e.namespace, e.err.Error()) 30 | } 31 | 32 | func newErrorMessage(namespace string, err error) *errorMessage { 33 | return &errorMessage{ 34 | namespace: namespace, 35 | err: err, 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /cmd/configcmd/create/create.go: -------------------------------------------------------------------------------- 1 | package create 2 | 3 | import ( 4 | "fmt" 5 | "path/filepath" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/sagan/ptool/cmd/configcmd" 10 | "github.com/sagan/ptool/config" 11 | ) 12 | 13 | var command = &cobra.Command{ 14 | Use: "create", 15 | Short: "Create initial pool config file.", 16 | Long: `Create initial pool config file.`, 17 | Args: cobra.MatchAll(cobra.ExactArgs(0), cobra.OnlyValidArgs), 18 | RunE: create, 19 | } 20 | 21 | func init() { 22 | configcmd.Command.AddCommand(command) 23 | } 24 | 25 | func create(cmd *cobra.Command, args []string) error { 26 | fmt.Printf("Creating config file %s%c%s\n", config.ConfigDir, filepath.Separator, config.ConfigFile) 27 | err := config.CreateDefaultConfig() 28 | if err == nil { 29 | fmt.Printf("Successfully created config file. Now edit it to add your sites / clients / others.\n") 30 | } 31 | return err 32 | } 33 | -------------------------------------------------------------------------------- /go-prompt/internal/term/raw.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | // +build !windows 3 | 4 | package term 5 | 6 | import ( 7 | "syscall" 8 | 9 | "github.com/pkg/term/termios" 10 | "golang.org/x/sys/unix" 11 | ) 12 | 13 | // SetRaw put terminal into a raw mode 14 | func SetRaw(fd int) error { 15 | n, err := getOriginalTermios(fd) 16 | if err != nil { 17 | return err 18 | } 19 | 20 | n.Iflag &^= syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | 21 | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | 22 | syscall.ICRNL | syscall.IXON 23 | n.Lflag &^= syscall.ECHO | syscall.ICANON | syscall.IEXTEN | syscall.ISIG | syscall.ECHONL 24 | n.Cflag &^= syscall.CSIZE | syscall.PARENB 25 | n.Cflag |= syscall.CS8 // Set to 8-bit wide. Typical value for displaying characters. 26 | n.Cc[syscall.VMIN] = 1 27 | n.Cc[syscall.VTIME] = 0 28 | 29 | return termios.Tcsetattr(uintptr(fd), termios.TCSANOW, (*unix.Termios)(&n)) 30 | } 31 | -------------------------------------------------------------------------------- /cmd/show/suggest.go: -------------------------------------------------------------------------------- 1 | package show 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/common" 8 | "github.com/sagan/ptool/cmd/shell/suggest" 9 | ) 10 | 11 | func init() { 12 | cmd.AddShellCompletion("show", func(document *prompt.Document) []prompt.Suggest { 13 | info := suggest.Parse(document) 14 | if info.LastArgIndex < 1 { 15 | return nil 16 | } 17 | if info.LastArgIsFlag { 18 | switch info.LastArgFlag { 19 | case "order": 20 | return suggest.EnumFlagArg(info.MatchingPrefix, common.OrderFlag) 21 | case "sort": 22 | return suggest.EnumFlagArg(info.MatchingPrefix, common.ClientTorrentSortFlag) 23 | default: 24 | return nil 25 | } 26 | } 27 | if info.LastArgIndex == 1 { 28 | return suggest.ClientArg(info.MatchingPrefix) 29 | } 30 | return suggest.InfoHashOrFilterArg(info.MatchingPrefix, info.Args[1]) 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /config/ptool.example.yaml: -------------------------------------------------------------------------------- 1 | # 本 ptool.example.yaml 文件包含的配置项不完整。建议参考 ptool.example.toml 版本的示例配置文件。 2 | iyuuToken: abcdefg 3 | #brushEnableStats: false # 启用刷流统计功能 4 | clients: 5 | - 6 | name: "local" 7 | type: "qbittorrent" 8 | url: "http://localhost:8085/" # qb web UI 地址 9 | username: "admin" 10 | password: "adminadmin" 11 | #brushMinDiskSpace: "5GB" # 刷流:保留最小空闲磁盘空间。 12 | #brushSlowUploadSpeedTier: "100KB" # 刷流:上传速度持续低于此值的种子将可能被删除 13 | #brushMaxDownloadingTorrents: 6 # 刷流:位于下载状态的种子数上限 14 | #brushMaxTorrents: 50 # 刷流:种子数(所有状态)上限 15 | #brushMinRatio: 0.2 # 刷流:最小上传/下载量比例 16 | #brushDefaultUploadSpeedLimit: "10MB" # 默认最大上传速度限制(/s) 17 | sites: 18 | - 19 | name: "mt" 20 | type: "nexusphp" 21 | url: "https://kp.m-team.cc/" 22 | cookie: "cookie_here" 23 | #torrentsUrl: "https://kp.m-team.cc/adult.php" # 单独设置种子列表页 url。如不指定,np 使用 torrents.php 24 | #timezone: "Asia/Shanghai" # 网站页面显示时间的时区 25 | -------------------------------------------------------------------------------- /cmd/batchdl/suggest.go: -------------------------------------------------------------------------------- 1 | package batchdl 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/cmd/common" 8 | "github.com/sagan/ptool/cmd/shell/suggest" 9 | ) 10 | 11 | func init() { 12 | cmd.AddShellCompletion("batchdl", func(document *prompt.Document) []prompt.Suggest { 13 | info := suggest.Parse(document) 14 | if info.LastArgIndex < 1 { 15 | return nil 16 | } 17 | if info.LastArgIsFlag { 18 | switch info.LastArgFlag { 19 | case "add-client": 20 | return suggest.ClientArg(info.MatchingPrefix) 21 | case "order": 22 | return suggest.EnumFlagArg(info.MatchingPrefix, common.OrderFlag) 23 | case "sort": 24 | return suggest.EnumFlagArg(info.MatchingPrefix, common.SiteTorrentSortFlag) 25 | default: 26 | return nil 27 | } 28 | } 29 | if info.LastArgIndex != 1 { 30 | return nil 31 | } 32 | return suggest.SiteArg(info.MatchingPrefix) 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /go-socket.io/engineio/transport/transport.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "io" 5 | "net" 6 | "net/http" 7 | "net/url" 8 | "time" 9 | 10 | "github.com/googollee/go-socket.io/engineio/frame" 11 | "github.com/googollee/go-socket.io/engineio/packet" 12 | ) 13 | 14 | // FrameReader reads a frame. It needs be closed before next reading. 15 | type FrameReader interface { 16 | NextReader() (frame.Type, packet.Type, io.ReadCloser, error) 17 | } 18 | 19 | // FrameWriter writes a frame. It needs be closed before next writing. 20 | type FrameWriter interface { 21 | NextWriter(ft frame.Type, pt packet.Type) (io.WriteCloser, error) 22 | } 23 | 24 | // Conn is a transport connection. 25 | type Conn interface { 26 | FrameReader 27 | FrameWriter 28 | io.Closer 29 | URL() url.URL 30 | LocalAddr() net.Addr 31 | RemoteAddr() net.Addr 32 | RemoteHeader() http.Header 33 | SetReadDeadline(t time.Time) error 34 | SetWriteDeadline(t time.Time) error 35 | } 36 | -------------------------------------------------------------------------------- /go-prompt/signal_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package prompt 4 | 5 | import ( 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | 10 | "github.com/c-bata/go-prompt/internal/debug" 11 | ) 12 | 13 | func (p *Prompt) handleSignals(exitCh chan int, winSizeCh chan *WinSize, stop chan struct{}) { 14 | sigCh := make(chan os.Signal, 1) 15 | signal.Notify( 16 | sigCh, 17 | syscall.SIGINT, 18 | syscall.SIGTERM, 19 | syscall.SIGQUIT, 20 | ) 21 | 22 | for { 23 | select { 24 | case <-stop: 25 | debug.Log("stop handleSignals") 26 | return 27 | case s := <-sigCh: 28 | switch s { 29 | 30 | case syscall.SIGINT: // kill -SIGINT XXXX or Ctrl+c 31 | debug.Log("Catch SIGINT") 32 | exitCh <- 0 33 | 34 | case syscall.SIGTERM: // kill -SIGTERM XXXX 35 | debug.Log("Catch SIGTERM") 36 | exitCh <- 1 37 | 38 | case syscall.SIGQUIT: // kill -SIGQUIT XXXX 39 | debug.Log("Catch SIGQUIT") 40 | exitCh <- 0 41 | } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /go-socket.io/_examples/iris/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/googollee/go-socket.io/_examples/iris 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/ajg/form v1.5.1 // indirect 7 | github.com/google/go-querystring v1.1.0 // indirect 8 | github.com/googollee/go-socket.io v0.0.0-00010101000000-000000000000 9 | github.com/imkira/go-interpol v1.1.0 // indirect 10 | github.com/kataras/iris/v12 v12.1.8 11 | github.com/moul/http2curl v1.0.0 // indirect 12 | github.com/sergi/go-diff v1.3.1 // indirect 13 | github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect 14 | github.com/smartystreets/goconvey v1.7.2 // indirect 15 | github.com/valyala/fasthttp v1.44.0 // indirect 16 | github.com/xeipuuv/gojsonschema v1.2.0 // indirect 17 | github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0 // indirect 18 | github.com/yudai/gojsondiff v1.0.0 // indirect 19 | github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect 20 | ) 21 | 22 | replace github.com/googollee/go-socket.io => ../../ 23 | -------------------------------------------------------------------------------- /go-socket.io/namespaces.go: -------------------------------------------------------------------------------- 1 | package socketio 2 | 3 | import "sync" 4 | 5 | type namespaces struct { 6 | namespaces map[string]*namespaceConn 7 | mu sync.RWMutex 8 | } 9 | 10 | func newNamespaces() *namespaces { 11 | return &namespaces{ 12 | namespaces: make(map[string]*namespaceConn), 13 | } 14 | } 15 | 16 | func (n *namespaces) Get(ns string) (*namespaceConn, bool) { 17 | n.mu.RLock() 18 | defer n.mu.RUnlock() 19 | 20 | namespace, ok := n.namespaces[ns] 21 | return namespace, ok 22 | } 23 | 24 | func (n *namespaces) Set(ns string, conn *namespaceConn) { 25 | n.mu.Lock() 26 | defer n.mu.Unlock() 27 | 28 | n.namespaces[ns] = conn 29 | } 30 | 31 | func (n *namespaces) Delete(ns string) { 32 | n.mu.Lock() 33 | defer n.mu.Unlock() 34 | 35 | delete(n.namespaces, ns) 36 | } 37 | 38 | func (n *namespaces) Range(fn func(ns string, nc *namespaceConn)) { 39 | n.mu.RLock() 40 | defer n.mu.RUnlock() 41 | 42 | for ns, nc := range n.namespaces { 43 | fn(ns, nc) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /go-prompt/_tools/complete_file/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "strings" 7 | 8 | prompt "github.com/c-bata/go-prompt" 9 | "github.com/c-bata/go-prompt/completer" 10 | ) 11 | 12 | var filePathCompleter = completer.FilePathCompleter{ 13 | IgnoreCase: true, 14 | Filter: func(fi os.FileInfo) bool { 15 | return fi.IsDir() || strings.HasSuffix(fi.Name(), ".go") 16 | }, 17 | } 18 | 19 | func executor(in string) { 20 | fmt.Println("Your input: " + in) 21 | } 22 | 23 | func completerFunc(d prompt.Document) []prompt.Suggest { 24 | t := d.GetWordBeforeCursor() 25 | if strings.HasPrefix(t, "--") { 26 | return []prompt.Suggest{ 27 | {"--foo", ""}, 28 | {"--bar", ""}, 29 | {"--baz", ""}, 30 | } 31 | } 32 | return filePathCompleter.Complete(d) 33 | } 34 | 35 | func main() { 36 | p := prompt.New( 37 | executor, 38 | completerFunc, 39 | prompt.OptionPrefix(">>> "), 40 | prompt.OptionCompletionWordSeparator(completer.FilePathCompletionSeparator), 41 | ) 42 | p.Run() 43 | } 44 | -------------------------------------------------------------------------------- /transmissionrpc/torrent_remove.go: -------------------------------------------------------------------------------- 1 | package transmissionrpc 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | ) 7 | 8 | /* 9 | Removing a Torrent 10 | https://github.com/transmission/transmission/blob/3.00/extras/rpc-spec.txt#L428 11 | */ 12 | 13 | // TorrentRemove allows to delete one or more torrents only or with their data. 14 | // https://github.com/transmission/transmission/blob/3.00/extras/rpc-spec.txt#L430 15 | func (c *Client) TorrentRemove(ctx context.Context, payload TorrentRemovePayload) (err error) { 16 | // Send payload 17 | if err = c.rpcCall(ctx, "torrent-remove", payload, nil); err != nil { 18 | return fmt.Errorf("'torrent-remove' rpc method failed: %w", err) 19 | } 20 | return 21 | } 22 | 23 | // TorrentRemovePayload holds the torrent id(s) to delete with a data deletion flag. 24 | // https://github.com/transmission/transmission/blob/3.00/extras/rpc-spec.txt#L432 25 | type TorrentRemovePayload struct { 26 | IDs []int64 `json:"ids"` 27 | DeleteLocalData bool `json:"delete-local-data"` 28 | } 29 | -------------------------------------------------------------------------------- /go-prompt/_tools/vt100_debug/main.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package main 4 | 5 | import ( 6 | "fmt" 7 | "syscall" 8 | 9 | prompt "github.com/c-bata/go-prompt" 10 | "github.com/c-bata/go-prompt/internal/term" 11 | ) 12 | 13 | func main() { 14 | if err := term.SetRaw(syscall.Stdin); err != nil { 15 | fmt.Println(err) 16 | return 17 | } 18 | defer term.Restore() 19 | 20 | bufCh := make(chan []byte, 128) 21 | go readBuffer(bufCh) 22 | fmt.Print("> ") 23 | 24 | for { 25 | b := <-bufCh 26 | if key := prompt.GetKey(b); key == prompt.NotDefined { 27 | fmt.Printf("Key '%s' data:'%#v'\n", string(b), b) 28 | } else { 29 | if key == prompt.ControlC { 30 | fmt.Println("exit.") 31 | return 32 | } 33 | fmt.Printf("Key '%s' data:'%#v'\n", key, b) 34 | } 35 | fmt.Print("> ") 36 | } 37 | } 38 | 39 | func readBuffer(bufCh chan []byte) { 40 | buf := make([]byte, 1024) 41 | 42 | for { 43 | if n, err := syscall.Read(syscall.Stdin, buf); err == nil { 44 | bufCh <- buf[:n] 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /reflink/writer.go: -------------------------------------------------------------------------------- 1 | package reflink 2 | 3 | import ( 4 | "errors" 5 | "io" 6 | ) 7 | 8 | // sectionWriter is a helper used when we need to fallback into copying data manually 9 | type sectionWriter struct { 10 | w io.WriterAt // target file 11 | base int64 // base position in file 12 | off int64 // current relative offset 13 | } 14 | 15 | // Write writes & updates offset 16 | func (s *sectionWriter) Write(p []byte) (int, error) { 17 | n, err := s.w.WriteAt(p, s.base+s.off) 18 | s.off += int64(n) 19 | return n, err 20 | } 21 | 22 | func (s *sectionWriter) Seek(offset int64, whence int) (int64, error) { 23 | switch whence { 24 | case io.SeekStart: 25 | // nothing needed 26 | case io.SeekCurrent: 27 | offset += s.off 28 | case io.SeekEnd: 29 | // we don't support io.SeekEnd 30 | fallthrough 31 | default: 32 | return s.off, errors.New("Seek: invalid whence") 33 | } 34 | if offset < 0 { 35 | return s.off, errors.New("Seek: invalid offset") 36 | } 37 | s.off = offset 38 | return offset, nil 39 | } 40 | -------------------------------------------------------------------------------- /cmd/gettags/gettags.go: -------------------------------------------------------------------------------- 1 | package gettags 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/sagan/ptool/client" 10 | "github.com/sagan/ptool/cmd" 11 | ) 12 | 13 | var command = &cobra.Command{ 14 | Use: "gettags {client}", 15 | Annotations: map[string]string{"cobra-prompt-dynamic-suggestions": "gettags"}, 16 | Short: "Get all tags of client.", 17 | Long: `Get all tags of client.`, 18 | Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), 19 | RunE: gettags, 20 | } 21 | 22 | func init() { 23 | cmd.RootCmd.AddCommand(command) 24 | } 25 | 26 | func gettags(cmd *cobra.Command, args []string) error { 27 | clientInstance, err := client.CreateClient(args[0]) 28 | if err != nil { 29 | return fmt.Errorf("failed to create client: %w", err) 30 | } 31 | 32 | tags, err := clientInstance.GetTags() 33 | if err != nil { 34 | return fmt.Errorf("failed to get tags: %w", err) 35 | } 36 | fmt.Printf("%s\n", strings.Join(tags, ", ")) 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /go-prompt/_example/simple-echo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | prompt "github.com/c-bata/go-prompt" 7 | ) 8 | 9 | func completer(in prompt.Document) []prompt.Suggest { 10 | s := []prompt.Suggest{ 11 | {Text: "users", Description: "Store the username and age"}, 12 | {Text: "articles", Description: "Store the article text posted by user"}, 13 | {Text: "comments", Description: "Store the text commented to articles"}, 14 | {Text: "groups", Description: "Combine users with specific rules"}, 15 | } 16 | return prompt.FilterHasPrefix(s, in.GetWordBeforeCursor(), true) 17 | } 18 | 19 | func main() { 20 | in := prompt.Input(">>> ", completer, 21 | prompt.OptionTitle("sql-prompt"), 22 | prompt.OptionHistory([]string{"SELECT * FROM users;"}), 23 | prompt.OptionPrefixTextColor(prompt.Yellow), 24 | prompt.OptionPreviewSuggestionTextColor(prompt.Blue), 25 | prompt.OptionSelectedSuggestionBGColor(prompt.LightGray), 26 | prompt.OptionSuggestionBGColor(prompt.DarkGray)) 27 | fmt.Println("Your input: " + in) 28 | } 29 | -------------------------------------------------------------------------------- /go-socket.io/engineio/packet/encoder.go: -------------------------------------------------------------------------------- 1 | package packet 2 | 3 | import ( 4 | "io" 5 | 6 | "github.com/googollee/go-socket.io/engineio/frame" 7 | "github.com/googollee/go-socket.io/logger" 8 | ) 9 | 10 | // FrameWriter is the writer which supports framing. 11 | type FrameWriter interface { 12 | NextWriter(typ frame.Type) (io.WriteCloser, error) 13 | } 14 | 15 | type Encoder struct { 16 | w FrameWriter 17 | } 18 | 19 | func NewEncoder(w FrameWriter) *Encoder { 20 | return &Encoder{ 21 | w: w, 22 | } 23 | } 24 | 25 | func (e *Encoder) NextWriter(ft frame.Type, pt Type) (io.WriteCloser, error) { 26 | w, err := e.w.NextWriter(ft) 27 | if err != nil { 28 | return nil, err 29 | } 30 | 31 | var b [1]byte 32 | if ft == frame.String { 33 | b[0] = pt.StringByte() 34 | } else { 35 | b[0] = pt.BinaryByte() 36 | } 37 | 38 | if _, err := w.Write(b[:]); err != nil { 39 | if closeErr := w.Close(); closeErr != nil { 40 | logger.Error("close writer after write:", closeErr) 41 | } 42 | 43 | return nil, err 44 | } 45 | 46 | return w, nil 47 | } 48 | -------------------------------------------------------------------------------- /go-socket.io/_examples/redis-adapter-unix-socket/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | tmp: 5 | image: busybox 6 | command: chmod -R 777 /tmp/docker 7 | volumes: 8 | - /tmp/docker 9 | 10 | app: 11 | build: . 12 | container_name: app 13 | ports: 14 | - "8080:8080" 15 | volumes_from: 16 | - tmp 17 | depends_on: 18 | - redis 19 | - tmp 20 | 21 | redis: 22 | container_name: redis 23 | hostname: redis 24 | image: redis 25 | command: redis-server /etc/redis/redis.conf 26 | volumes: 27 | - ./redis.conf:/etc/redis/redis.conf 28 | volumes_from: 29 | - tmp 30 | ports: 31 | - "6379:6379" 32 | depends_on: 33 | - tmp 34 | 35 | redis-commander: 36 | container_name: redis-commander 37 | hostname: redis-commander 38 | image: rediscommander/redis-commander:latest 39 | restart: always 40 | depends_on: 41 | - redis 42 | environment: 43 | - REDIS_SOCKET=/tmp/docker/redis.sock 44 | ports: 45 | - "8081:8081" 46 | -------------------------------------------------------------------------------- /go-prompt/internal/debug/assert.go: -------------------------------------------------------------------------------- 1 | package debug 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | ) 7 | 8 | const ( 9 | envAssertPanic = "GO_PROMPT_ENABLE_ASSERT" 10 | ) 11 | 12 | var ( 13 | enableAssert bool 14 | ) 15 | 16 | func init() { 17 | if e := os.Getenv(envAssertPanic); e == "true" || e == "1" { 18 | enableAssert = true 19 | } 20 | } 21 | 22 | // Assert ensures expected condition. 23 | func Assert(cond bool, msg interface{}) { 24 | if cond { 25 | return 26 | } 27 | if enableAssert { 28 | panic(msg) 29 | } 30 | writeWithSync(2, "[ASSERT] "+toString(msg)) 31 | } 32 | 33 | func toString(v interface{}) string { 34 | switch a := v.(type) { 35 | case func() string: 36 | return a() 37 | case string: 38 | return a 39 | case fmt.Stringer: 40 | return a.String() 41 | default: 42 | return fmt.Sprintf("unexpected type, %t", v) 43 | } 44 | } 45 | 46 | // AssertNoError ensures err is nil. 47 | func AssertNoError(err error) { 48 | if err == nil { 49 | return 50 | } 51 | if enableAssert { 52 | panic(err) 53 | } 54 | writeWithSync(2, "[ASSERT] "+err.Error()) 55 | } 56 | -------------------------------------------------------------------------------- /cobra-prompt/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2018 Espen Strømland 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /go-socket.io/engineio/session/session_manager.go: -------------------------------------------------------------------------------- 1 | package session 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | type Manager struct { 8 | IDGenerator 9 | 10 | sessions map[string]*Session 11 | locker sync.RWMutex 12 | } 13 | 14 | func NewManager(gen IDGenerator) *Manager { 15 | if gen == nil { 16 | gen = &DefaultIDGenerator{} 17 | } 18 | return &Manager{ 19 | IDGenerator: gen, 20 | sessions: make(map[string]*Session), 21 | } 22 | } 23 | 24 | func (m *Manager) Add(s *Session) { 25 | m.locker.Lock() 26 | defer m.locker.Unlock() 27 | 28 | m.sessions[s.ID()] = s 29 | } 30 | 31 | func (m *Manager) Get(sid string) (*Session, bool) { 32 | m.locker.RLock() 33 | defer m.locker.RUnlock() 34 | 35 | s, ok := m.sessions[sid] 36 | return s, ok 37 | } 38 | 39 | func (m *Manager) Remove(sid string) { 40 | m.locker.Lock() 41 | defer m.locker.Unlock() 42 | 43 | if _, ok := m.sessions[sid]; !ok { 44 | return 45 | } 46 | delete(m.sessions, sid) 47 | } 48 | 49 | func (m *Manager) Count() int { 50 | m.locker.Lock() 51 | defer m.locker.Unlock() 52 | 53 | return len(m.sessions) 54 | } 55 | -------------------------------------------------------------------------------- /cmd/run/run.go: -------------------------------------------------------------------------------- 1 | package run 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/google/shlex" 8 | "github.com/spf13/cobra" 9 | 10 | "github.com/sagan/ptool/cmd" 11 | ) 12 | 13 | var command = &cobra.Command{ 14 | Use: "run {cmdline}", 15 | Short: `Run cmdline. Accept the whole cmdline as single arg, e.g. 'ptool run "status local -t"'.`, 16 | Long: `Run cmdline. Accept the whole cmdline as single arg, e.g. 'ptool run "status local -t"'.`, 17 | DisableFlagParsing: true, 18 | Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), 19 | RunE: run, 20 | } 21 | 22 | func init() { 23 | cmd.RootCmd.AddCommand(command) 24 | } 25 | 26 | func run(_ *cobra.Command, args []string) error { 27 | cmdline := args[0] 28 | cmdlineArgs, err := shlex.Split(cmdline) 29 | if err != nil { 30 | return fmt.Errorf("failed to parse cmdline '%s': %w", cmdline, err) 31 | } 32 | os.Args = append([]string{os.Args[0]}, cmdlineArgs...) 33 | fmt.Fprintf(os.Stderr, "Run cmdline: %v\n", os.Args[1:]) 34 | return cmd.RootCmd.Execute() 35 | } 36 | -------------------------------------------------------------------------------- /cmd/createtags/createtags.go: -------------------------------------------------------------------------------- 1 | package createtags 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/sagan/ptool/client" 9 | "github.com/sagan/ptool/cmd" 10 | ) 11 | 12 | var command = &cobra.Command{ 13 | Use: "createtags {client} {tags}...", 14 | Aliases: []string{"createtag"}, 15 | Annotations: map[string]string{"cobra-prompt-dynamic-suggestions": "createtags"}, 16 | Short: "Create tags in client.", 17 | Long: `Create tags in client.`, 18 | Args: cobra.MatchAll(cobra.MinimumNArgs(2), cobra.OnlyValidArgs), 19 | RunE: createtags, 20 | } 21 | 22 | func init() { 23 | cmd.RootCmd.AddCommand(command) 24 | } 25 | 26 | func createtags(cmd *cobra.Command, args []string) error { 27 | clientName := args[0] 28 | tags := args[1:] 29 | clientInstance, err := client.CreateClient(clientName) 30 | if err != nil { 31 | return fmt.Errorf("failed to create client: %w", err) 32 | } 33 | 34 | err = clientInstance.CreateTags(tags...) 35 | if err != nil { 36 | return fmt.Errorf("Failed to create tags: %w", err) 37 | } 38 | return nil 39 | } 40 | -------------------------------------------------------------------------------- /cmd/deletetags/deletetags.go: -------------------------------------------------------------------------------- 1 | package deletetags 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/sagan/ptool/client" 9 | "github.com/sagan/ptool/cmd" 10 | ) 11 | 12 | var command = &cobra.Command{ 13 | Use: "deletetags {client} {tags}...", 14 | Aliases: []string{"deletetag", "deltags", "deltag"}, 15 | Annotations: map[string]string{"cobra-prompt-dynamic-suggestions": "deletetags"}, 16 | Short: "Delete tags from client.", 17 | Long: `Delete tags from client.`, 18 | Args: cobra.MatchAll(cobra.MinimumNArgs(2), cobra.OnlyValidArgs), 19 | RunE: deletetags, 20 | } 21 | 22 | func init() { 23 | cmd.RootCmd.AddCommand(command) 24 | } 25 | 26 | func deletetags(cmd *cobra.Command, args []string) error { 27 | clientInstance, err := client.CreateClient(args[0]) 28 | if err != nil { 29 | return fmt.Errorf("failed to create client: %w", err) 30 | } 31 | 32 | tags := args[1:] 33 | 34 | err = clientInstance.DeleteTags(tags...) 35 | if err != nil { 36 | return fmt.Errorf("failed to delete tags: %w", err) 37 | } 38 | return nil 39 | } 40 | -------------------------------------------------------------------------------- /go-prompt/signal_posix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package prompt 4 | 5 | import ( 6 | "os" 7 | "os/signal" 8 | "syscall" 9 | 10 | "github.com/c-bata/go-prompt/internal/debug" 11 | ) 12 | 13 | func (p *Prompt) handleSignals(exitCh chan int, winSizeCh chan *WinSize, stop chan struct{}) { 14 | in := p.in 15 | sigCh := make(chan os.Signal, 1) 16 | signal.Notify( 17 | sigCh, 18 | syscall.SIGINT, 19 | syscall.SIGTERM, 20 | syscall.SIGQUIT, 21 | syscall.SIGWINCH, 22 | ) 23 | 24 | for { 25 | select { 26 | case <-stop: 27 | debug.Log("stop handleSignals") 28 | return 29 | case s := <-sigCh: 30 | switch s { 31 | case syscall.SIGINT: // kill -SIGINT XXXX or Ctrl+c 32 | debug.Log("Catch SIGINT") 33 | exitCh <- 0 34 | 35 | case syscall.SIGTERM: // kill -SIGTERM XXXX 36 | debug.Log("Catch SIGTERM") 37 | exitCh <- 1 38 | 39 | case syscall.SIGQUIT: // kill -SIGQUIT XXXX 40 | debug.Log("Catch SIGQUIT") 41 | exitCh <- 0 42 | 43 | case syscall.SIGWINCH: 44 | debug.Log("Catch SIGWINCH") 45 | winSizeCh <- in.GetWinSize() 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /cobra-prompt/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [0.5.0] - 2023-01-28 9 | 10 | ### Added 11 | 12 | - `RunContext` - option to pass context into nested command execututions. ([#9](https://github.com/stromland/cobra-prompt/pull/9) by [@klowdo](https://github.com/klowdo)) 13 | 14 | ## [0.4.0] - 2022-10-04 15 | 16 | ### Added 17 | 18 | - `SuggestionFilter` to `CobraPrompt`. Function to decide which suggestions that should be presentet to the user. Overrides the current filter from go-prompt. ([#8](https://github.com/stromland/cobra-prompt/pull/8) by [@klowdo](https://github.com/klowdo)) 19 | 20 | ## [0.3.0] - 2022-04-25 21 | 22 | ### Added 23 | 24 | - `InArgsParser` to `CobraPrompt`. This makes it possible to decide how arguments should be structured before passing them to Cobra. ([#7](https://github.com/stromland/cobra-prompt/pull/7) by [@klowdo](https://github.com/klowdo)) 25 | -------------------------------------------------------------------------------- /go-prompt/internal/debug/log.go: -------------------------------------------------------------------------------- 1 | package debug 2 | 3 | import ( 4 | "io/ioutil" 5 | "log" 6 | "os" 7 | ) 8 | 9 | const ( 10 | envEnableLog = "GO_PROMPT_ENABLE_LOG" 11 | logFileName = "go-prompt.log" 12 | ) 13 | 14 | var ( 15 | logfile *os.File 16 | logger *log.Logger 17 | ) 18 | 19 | func init() { 20 | if e := os.Getenv(envEnableLog); e == "true" || e == "1" { 21 | var err error 22 | logfile, err = os.OpenFile(logFileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666) 23 | if err == nil { 24 | logger = log.New(logfile, "", log.Llongfile) 25 | return 26 | } 27 | } 28 | logger = log.New(ioutil.Discard, "", log.Llongfile) 29 | } 30 | 31 | // Teardown to close logfile 32 | func Teardown() { 33 | if logfile == nil { 34 | return 35 | } 36 | _ = logfile.Close() 37 | } 38 | 39 | func writeWithSync(calldepth int, msg string) { 40 | calldepth++ 41 | if logfile == nil { 42 | return 43 | } 44 | _ = logger.Output(calldepth, msg) 45 | _ = logfile.Sync() // immediately write msg 46 | } 47 | 48 | // Log to output message 49 | func Log(msg string) { 50 | calldepth := 2 51 | writeWithSync(calldepth, msg) 52 | } 53 | -------------------------------------------------------------------------------- /cmd/deletecategories/deletecategories.go: -------------------------------------------------------------------------------- 1 | package deletecategories 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/sagan/ptool/client" 9 | "github.com/sagan/ptool/cmd" 10 | ) 11 | 12 | var command = &cobra.Command{ 13 | Use: "deletecategories {client} {category}...", 14 | Aliases: []string{"delcats"}, 15 | Annotations: map[string]string{"cobra-prompt-dynamic-suggestions": "deletecategories"}, 16 | Short: "Delete categories from client.", 17 | Long: `Delete categories from client.`, 18 | Args: cobra.MatchAll(cobra.MinimumNArgs(2), cobra.OnlyValidArgs), 19 | RunE: deletecategories, 20 | } 21 | 22 | func init() { 23 | cmd.RootCmd.AddCommand(command) 24 | } 25 | 26 | func deletecategories(cmd *cobra.Command, args []string) error { 27 | clientName := args[0] 28 | categories := args[1:] 29 | clientInstance, err := client.CreateClient(clientName) 30 | if err != nil { 31 | return fmt.Errorf("failed to create client: %w", err) 32 | } 33 | 34 | err = clientInstance.DeleteCategories(categories) 35 | if err != nil { 36 | return err 37 | } 38 | return nil 39 | } 40 | -------------------------------------------------------------------------------- /transmissionrpc/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Edouard Hur 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /go-prompt/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Masashi SHIBATA 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /reflink/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Karpelès Lab Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /go-socket.io/engineio/payload/errors.go: -------------------------------------------------------------------------------- 1 | package payload 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | ) 7 | 8 | // Error is payload error. 9 | type Error interface { 10 | Error() string 11 | Temporary() bool 12 | } 13 | 14 | // OpError is operation error. 15 | type OpError struct { 16 | Op string 17 | Err error 18 | } 19 | 20 | func newOpError(op string, err error) error { 21 | return &OpError{ 22 | Op: op, 23 | Err: err, 24 | } 25 | } 26 | 27 | func (e *OpError) Error() string { 28 | return fmt.Sprintf("%s: %s", e.Op, e.Err.Error()) 29 | } 30 | 31 | // Temporary returns true if error can retry. 32 | func (e *OpError) Temporary() bool { 33 | if oe, ok := e.Err.(Error); ok { 34 | return oe.Temporary() 35 | } 36 | return false 37 | } 38 | 39 | type retryError struct { 40 | err string 41 | } 42 | 43 | func (e retryError) Error() string { 44 | return e.err 45 | } 46 | 47 | func (e retryError) Temporary() bool { 48 | return true 49 | } 50 | 51 | var errPaused = retryError{"paused"} 52 | 53 | var errTimeout = errors.New("timeout") 54 | 55 | var errInvalidPayload = errors.New("invalid payload") 56 | 57 | var errOverlap = errors.New("overlap") 58 | -------------------------------------------------------------------------------- /go-socket.io/engineio/packet/encoder_test.go: -------------------------------------------------------------------------------- 1 | package packet 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | 8 | "github.com/googollee/go-socket.io/engineio/frame" 9 | ) 10 | 11 | func TestEncoder(t *testing.T) { 12 | at := assert.New(t) 13 | 14 | for _, test := range tests { 15 | w := NewFakeConnWriter() 16 | encoder := NewEncoder(w) 17 | for _, p := range test.packets { 18 | fw, err := encoder.NextWriter(p.FType, p.PType) 19 | at.Nil(err) 20 | _, err = fw.Write(p.Data) 21 | at.Nil(err) 22 | err = fw.Close() 23 | at.Nil(err) 24 | } 25 | at.Equal(test.frames, w.Frames) 26 | } 27 | } 28 | 29 | func BenchmarkEncoder(b *testing.B) { 30 | encoder := NewEncoder(&FakeDiscardWriter{}) 31 | 32 | b.ResetTimer() 33 | 34 | for i := 0; i < b.N; i++ { 35 | w, err := encoder.NextWriter(frame.String, MESSAGE) 36 | if err != nil { 37 | b.Error(err) 38 | } 39 | 40 | err = w.Close() 41 | if err != nil { 42 | b.Error(err) 43 | } 44 | 45 | w, err = encoder.NextWriter(frame.Binary, MESSAGE) 46 | if err != nil { 47 | b.Error(err) 48 | } 49 | 50 | err = w.Close() 51 | if err != nil { 52 | b.Error(err) 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /go-prompt/internal/strings/strings_test.go: -------------------------------------------------------------------------------- 1 | package strings_test 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/c-bata/go-prompt/internal/strings" 7 | ) 8 | 9 | func ExampleIndexNotByte() { 10 | fmt.Println(strings.IndexNotByte("golang", 'g')) 11 | fmt.Println(strings.IndexNotByte("golang", 'x')) 12 | fmt.Println(strings.IndexNotByte("gggggg", 'g')) 13 | // Output: 14 | // 1 15 | // 0 16 | // -1 17 | } 18 | 19 | func ExampleLastIndexNotByte() { 20 | fmt.Println(strings.LastIndexNotByte("golang", 'g')) 21 | fmt.Println(strings.LastIndexNotByte("golang", 'x')) 22 | fmt.Println(strings.LastIndexNotByte("gggggg", 'g')) 23 | // Output: 24 | // 4 25 | // 5 26 | // -1 27 | } 28 | 29 | func ExampleIndexNotAny() { 30 | fmt.Println(strings.IndexNotAny("golang", "glo")) 31 | fmt.Println(strings.IndexNotAny("golang", "gl")) 32 | fmt.Println(strings.IndexNotAny("golang", "golang")) 33 | // Output: 34 | // 3 35 | // 1 36 | // -1 37 | } 38 | 39 | func ExampleLastIndexNotAny() { 40 | fmt.Println(strings.LastIndexNotAny("golang", "agn")) 41 | fmt.Println(strings.LastIndexNotAny("golang", "an")) 42 | fmt.Println(strings.LastIndexNotAny("golang", "golang")) 43 | // Output: 44 | // 2 45 | // 5 46 | // -1 47 | } 48 | -------------------------------------------------------------------------------- /go-socket.io/engineio/transport/manager_test.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "net/http" 5 | "net/url" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | type fakeTransport struct { 12 | name string 13 | } 14 | 15 | func (f fakeTransport) Name() string { 16 | return f.name 17 | } 18 | 19 | func (f fakeTransport) Dial(url *url.URL, header http.Header) (Conn, error) { 20 | return nil, nil 21 | } 22 | 23 | func (f fakeTransport) Accept(http.ResponseWriter, *http.Request) (Conn, error) { 24 | return nil, nil 25 | } 26 | 27 | func TestManager(t *testing.T) { 28 | at := assert.New(t) 29 | 30 | t1 := fakeTransport{"t1"} 31 | t2 := fakeTransport{"t2"} 32 | t3 := fakeTransport{"t3"} 33 | t4 := fakeTransport{"t4"} 34 | 35 | m := NewManager([]Transport{ 36 | t1, 37 | t2, 38 | t3, 39 | t4, 40 | }) 41 | 42 | tg, ok := m.Get("t1") 43 | at.True(ok) 44 | at.Equal(t1, tg) 45 | 46 | tg, ok = m.Get("not_exist") 47 | at.False(ok) 48 | at.Nil(tg) 49 | 50 | names := m.UpgradeFrom("t2") 51 | at.Equal([]string{"t3", "t4"}, names) 52 | 53 | names = m.UpgradeFrom("t4") 54 | at.Equal([]string{}, names) 55 | 56 | names = m.UpgradeFrom("not_ exist") 57 | at.Nil(names) 58 | } 59 | -------------------------------------------------------------------------------- /cmd/iyuu/status/status.go: -------------------------------------------------------------------------------- 1 | package status 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | log "github.com/sirupsen/logrus" 8 | "github.com/spf13/cobra" 9 | 10 | "github.com/sagan/ptool/cmd/iyuu" 11 | "github.com/sagan/ptool/config" 12 | "github.com/sagan/ptool/util" 13 | ) 14 | 15 | var command = &cobra.Command{ 16 | Use: "status", 17 | Annotations: map[string]string{"cobra-prompt-dynamic-suggestions": "iyuu.status"}, 18 | Short: "Show iyuu user status.", 19 | Long: `Show iyuu user status. 20 | 21 | The output is returned by iyuu server and printed as opaque json object, ptool does not interpret it. 22 | The command always exits with 0 as long as iyuu returns a http 200 response.`, 23 | RunE: status, 24 | } 25 | 26 | func init() { 27 | iyuu.Command.AddCommand(command) 28 | } 29 | 30 | func status(cmd *cobra.Command, args []string) error { 31 | log.Tracef("iyuu token: %s", config.Get().IyuuToken) 32 | if config.Get().IyuuToken == "" { 33 | return fmt.Errorf("you must config iyuuToken in ptool.toml to use iyuu functions") 34 | } 35 | 36 | data, err := iyuu.IyuuApiUsersProfile(config.Get().IyuuToken) 37 | log.Warnf("Iyuu status: error=%v", err) 38 | util.PrintJson(os.Stdout, data) 39 | return err 40 | } 41 | -------------------------------------------------------------------------------- /go-prompt/_example/README.md: -------------------------------------------------------------------------------- 1 | # Examples of go-prompt 2 | 3 | This directory includes some examples using go-prompt. 4 | These examples are useful to know the usage of go-prompt and check behavior for development. 5 | 6 | ## simple-echo 7 | 8 | ![simple-input](https://github.com/c-bata/assets/raw/master/go-prompt/examples/input.gif) 9 | 10 | A simple echo example using `prompt.Input`. 11 | 12 | ## http-prompt 13 | 14 | ![http-prompt](https://github.com/c-bata/assets/raw/master/go-prompt/examples/http-prompt.gif) 15 | 16 | A simple [http-prompt](https://github.com/eliangcs/http-prompt) implementation using go-prompt in less than 200 lines of Go. 17 | 18 | ## live-prefix 19 | 20 | ![live-prefix](https://github.com/c-bata/assets/raw/master/go-prompt/examples/live-prefix.gif) 21 | 22 | A example application which changes a prefix string dynamically. 23 | This feature is used like [ktr0731/evans](https://github.com/ktr0731/evans) which is interactive gRPC client using go-prompt. 24 | 25 | ## exec-command 26 | 27 | Run another CLI tool via `os/exec` package. 28 | More practical example is [a source code of kube-prompt](https://github.com/c-bata/kube-prompt). 29 | I recommend you to look this if you want to create tools like kube-prompt. 30 | 31 | -------------------------------------------------------------------------------- /cmd/iyuu/xseedtest/xseedtest.go: -------------------------------------------------------------------------------- 1 | package xseedtest 2 | 3 | import ( 4 | "fmt" 5 | 6 | log "github.com/sirupsen/logrus" 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/sagan/ptool/cmd/iyuu" 10 | "github.com/sagan/ptool/config" 11 | ) 12 | 13 | var command = &cobra.Command{ 14 | Use: "xseedtest", 15 | Annotations: map[string]string{"cobra-prompt-dynamic-suggestions": "iyuu.xseedtest"}, 16 | Short: "Cross seed test.", 17 | Long: `Cross seed test.`, 18 | RunE: xseed, 19 | } 20 | 21 | var ( 22 | infoHash = "" 23 | ) 24 | 25 | func init() { 26 | command.Flags().StringVarP(&infoHash, "info-hash", "", "", "Torrent info hash") 27 | iyuu.Command.AddCommand(command) 28 | } 29 | 30 | func xseed(cmd *cobra.Command, args []string) error { 31 | log.Tracef("iyuu token: %s", config.Get().IyuuToken) 32 | if config.Get().IyuuToken == "" { 33 | return fmt.Errorf("you must config iyuuToken in ptool.toml to use iyuu functions") 34 | } 35 | 36 | if infoHash != "" { 37 | iyuuSites, _ := iyuu.IyuuApiSites(config.Get().IyuuToken) 38 | sid_sha1, _ := iyuu.IyuuApiReportExisting(config.Get().IyuuToken, iyuuSites) 39 | iyuu.IyuuApiHash(config.Get().IyuuToken, []string{infoHash}, sid_sha1) 40 | } 41 | return nil 42 | } 43 | -------------------------------------------------------------------------------- /cmd/configcmd/example/example.go: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | 8 | "github.com/spf13/cobra" 9 | 10 | "github.com/sagan/ptool/cmd/configcmd" 11 | "github.com/sagan/ptool/config" 12 | ) 13 | 14 | var command = &cobra.Command{ 15 | Use: "example", 16 | Short: "Display example config file contents.", 17 | Long: `Display example config file contents.`, 18 | Args: cobra.MatchAll(cobra.ExactArgs(0), cobra.OnlyValidArgs), 19 | RunE: example, 20 | } 21 | 22 | var ( 23 | format = "" 24 | ) 25 | 26 | func init() { 27 | command.Flags().StringVarP(&format, "format", "", "", `Select the format of example config file to display, `+ 28 | `e.g. "toml", "yaml". By default it uses the format of current config file`) 29 | configcmd.Command.AddCommand(command) 30 | } 31 | 32 | func example(cmd *cobra.Command, args []string) error { 33 | if format == "" { 34 | format = config.ConfigType 35 | } 36 | if file, err := config.DefaultConfigFs.Open(config.EXAMPLE_CONFIG_FILE + "." + format); err != nil { 37 | return fmt.Errorf("unsupported config file type %q: %w", format, err) 38 | } else { 39 | fmt.Printf("# %s.%s\n\n", config.EXAMPLE_CONFIG_FILE, format) 40 | io.Copy(os.Stdout, file) 41 | return nil 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /cmd/reseed/status/status.go: -------------------------------------------------------------------------------- 1 | package status 2 | 3 | import ( 4 | "fmt" 5 | 6 | log "github.com/sirupsen/logrus" 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/sagan/ptool/cmd/reseed" 10 | "github.com/sagan/ptool/config" 11 | ) 12 | 13 | var command = &cobra.Command{ 14 | Use: "status", 15 | Annotations: map[string]string{"cobra-prompt-dynamic-suggestions": "reseed.status"}, 16 | Short: "Show Reseed user status.", 17 | Long: `Show Reseed user status.`, 18 | RunE: status, 19 | } 20 | 21 | func init() { 22 | reseed.Command.AddCommand(command) 23 | } 24 | 25 | func status(cmd *cobra.Command, args []string) error { 26 | if config.Get().ReseedUsername == "" || config.Get().ReseedPassword == "" { 27 | return fmt.Errorf("you must config reseedUsername & reseedPassword in ptool.toml to use reseed functions") 28 | } 29 | log.Debugf("Login to Reseed using username=%s password=%s", config.Get().ReseedUsername, config.Get().ReseedPassword) 30 | token, err := reseed.Login(config.Get().ReseedUsername, config.Get().ReseedPassword) 31 | if err != nil { 32 | return err 33 | } 34 | fmt.Printf("✓ success logined to Reseed with username %s, acquired token: %s\n", 35 | config.Get().ReseedUsername, token) 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /go-prompt/output_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package prompt 4 | 5 | import ( 6 | "io" 7 | 8 | colorable "github.com/mattn/go-colorable" 9 | ) 10 | 11 | // WindowsWriter is a ConsoleWriter implementation for Win32 console. 12 | // Output is converted from VT100 escape sequences by mattn/go-colorable. 13 | type WindowsWriter struct { 14 | VT100Writer 15 | out io.Writer 16 | } 17 | 18 | // Flush to flush buffer 19 | func (w *WindowsWriter) Flush() error { 20 | _, err := w.out.Write(w.buffer) 21 | if err != nil { 22 | return err 23 | } 24 | w.buffer = []byte{} 25 | return nil 26 | } 27 | 28 | var _ ConsoleWriter = &WindowsWriter{} 29 | 30 | var ( 31 | // NewStandardOutputWriter is Deprecated: Please use NewStdoutWriter 32 | NewStandardOutputWriter = NewStdoutWriter 33 | ) 34 | 35 | // NewStdoutWriter returns ConsoleWriter object to write to stdout. 36 | // This generates win32 control sequences. 37 | func NewStdoutWriter() ConsoleWriter { 38 | return &WindowsWriter{ 39 | out: colorable.NewColorableStdout(), 40 | } 41 | } 42 | 43 | // NewStderrWriter returns ConsoleWriter object to write to stderr. 44 | // This generates win32 control sequences. 45 | func NewStderrWriter() ConsoleWriter { 46 | return &WindowsWriter{ 47 | out: colorable.NewColorableStderr(), 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /go-prompt/shortcut.go: -------------------------------------------------------------------------------- 1 | package prompt 2 | 3 | func dummyExecutor(in string) {} 4 | 5 | // Input get the input data from the user and return it. 6 | func Input(prefix string, completer Completer, opts ...Option) string { 7 | pt := New(dummyExecutor, completer) 8 | pt.renderer.prefixTextColor = DefaultColor 9 | pt.renderer.prefix = prefix 10 | 11 | for _, opt := range opts { 12 | if err := opt(pt); err != nil { 13 | panic(err) 14 | } 15 | } 16 | return pt.Input() 17 | } 18 | 19 | // Choose to the shortcut of input function to select from string array. 20 | // Deprecated: Maybe anyone want to use this. 21 | func Choose(prefix string, choices []string, opts ...Option) string { 22 | completer := newChoiceCompleter(choices, FilterHasPrefix) 23 | pt := New(dummyExecutor, completer) 24 | pt.renderer.prefixTextColor = DefaultColor 25 | pt.renderer.prefix = prefix 26 | 27 | for _, opt := range opts { 28 | if err := opt(pt); err != nil { 29 | panic(err) 30 | } 31 | } 32 | return pt.Input() 33 | } 34 | 35 | func newChoiceCompleter(choices []string, filter Filter) Completer { 36 | s := make([]Suggest, len(choices)) 37 | for i := range choices { 38 | s[i] = Suggest{Text: choices[i]} 39 | } 40 | return func(x Document) []Suggest { 41 | return filter(s, x.GetWordBeforeCursor(), true) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /go-prompt/internal/bisect/bisect_test.go: -------------------------------------------------------------------------------- 1 | package bisect_test 2 | 3 | import ( 4 | "fmt" 5 | "math/rand" 6 | "testing" 7 | 8 | "github.com/c-bata/go-prompt/internal/bisect" 9 | ) 10 | 11 | func Example() { 12 | in := []int{1, 2, 3, 3, 3, 6, 7} 13 | fmt.Println("Insertion position for 0 in the slice is", bisect.Right(in, 0)) 14 | fmt.Println("Insertion position for 4 in the slice is", bisect.Right(in, 4)) 15 | 16 | // Output: 17 | // Insertion position for 0 in the slice is 0 18 | // Insertion position for 4 in the slice is 5 19 | } 20 | 21 | func TestBisectRight(t *testing.T) { 22 | // Thanks!! https://play.golang.org/p/y9NRj_XVIW 23 | in := []int{1, 2, 3, 3, 3, 6, 7} 24 | 25 | r := bisect.Right(in, 0) 26 | if r != 0 { 27 | t.Errorf("number 0 should inserted at 0 position, but got %d", r) 28 | } 29 | 30 | r = bisect.Right(in, 4) 31 | if r != 5 { 32 | t.Errorf("number 4 should inserted at 5 position, but got %d", r) 33 | } 34 | } 35 | 36 | func BenchmarkRight(b *testing.B) { 37 | rand.Seed(0) 38 | 39 | for _, l := range []int{10, 1e2, 1e3, 1e4} { 40 | x := rand.Perm(l) 41 | insertion := rand.Int() 42 | 43 | b.Run(fmt.Sprintf("arrayLength=%d", l), func(b *testing.B) { 44 | b.ResetTimer() 45 | for n := 0; n < b.N; n++ { 46 | bisect.Right(x, insertion) 47 | } 48 | }) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /cmd/sites/show/show.go: -------------------------------------------------------------------------------- 1 | package show 2 | 3 | import ( 4 | "fmt" 5 | 6 | toml "github.com/pelletier/go-toml/v2" 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/sagan/ptool/cmd/sites" 10 | "github.com/sagan/ptool/site/tpl" 11 | "github.com/sagan/ptool/util" 12 | ) 13 | 14 | var command = &cobra.Command{ 15 | Use: "show {site}...", 16 | Short: "Show detailed configuration of internal supported PT site.", 17 | Long: `Show detailed configuration of internal supported PT site. 18 | It prints output in toml format. All configurations of any site can be overrided in ptool.toml.`, 19 | Args: cobra.MatchAll(cobra.MinimumNArgs(1), cobra.OnlyValidArgs), 20 | RunE: show, 21 | } 22 | 23 | func init() { 24 | sites.Command.AddCommand(command) 25 | } 26 | 27 | func show(cmd *cobra.Command, args []string) error { 28 | sitenames := args 29 | 30 | for _, sitename := range sitenames { 31 | tplconfig := tpl.SITES[sitename] 32 | if tplconfig == nil { 33 | fmt.Printf("# %s : is NOT a internal supported site\n", sitename) 34 | continue 35 | } 36 | str, err := toml.Marshal(util.StructToMap(*tplconfig, true, true)) 37 | if err != nil { 38 | fmt.Printf("# %s : failed to get detailed configuration: %v\n", sitename, err) 39 | continue 40 | } 41 | fmt.Printf("# %s\n[[sites]]\n%s\n", sitename, str) 42 | } 43 | return nil 44 | } 45 | -------------------------------------------------------------------------------- /go-prompt/_example/live-prefix/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | 6 | prompt "github.com/c-bata/go-prompt" 7 | ) 8 | 9 | var LivePrefixState struct { 10 | LivePrefix string 11 | IsEnable bool 12 | } 13 | 14 | func executor(in string) { 15 | fmt.Println("Your input: " + in) 16 | if in == "" { 17 | LivePrefixState.IsEnable = false 18 | LivePrefixState.LivePrefix = in 19 | return 20 | } 21 | LivePrefixState.LivePrefix = in + "> " 22 | LivePrefixState.IsEnable = true 23 | } 24 | 25 | func completer(in prompt.Document) []prompt.Suggest { 26 | s := []prompt.Suggest{ 27 | {Text: "users", Description: "Store the username and age"}, 28 | {Text: "articles", Description: "Store the article text posted by user"}, 29 | {Text: "comments", Description: "Store the text commented to articles"}, 30 | {Text: "groups", Description: "Combine users with specific rules"}, 31 | } 32 | return prompt.FilterHasPrefix(s, in.GetWordBeforeCursor(), true) 33 | } 34 | 35 | func changeLivePrefix() (string, bool) { 36 | return LivePrefixState.LivePrefix, LivePrefixState.IsEnable 37 | } 38 | 39 | func main() { 40 | p := prompt.New( 41 | executor, 42 | completer, 43 | prompt.OptionPrefix(">>> "), 44 | prompt.OptionLivePrefix(changeLivePrefix), 45 | prompt.OptionTitle("live-prefix-example"), 46 | ) 47 | p.Run() 48 | } 49 | -------------------------------------------------------------------------------- /go-socket.io/engineio/transport/manager.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "net/http" 5 | "net/url" 6 | ) 7 | 8 | // Transport is a transport which can creates base.Conn 9 | type Transport interface { 10 | Name() string 11 | Accept(w http.ResponseWriter, r *http.Request) (Conn, error) 12 | Dial(u *url.URL, requestHeader http.Header) (Conn, error) 13 | } 14 | 15 | // Manager is a manager of transports. 16 | type Manager struct { 17 | order []string 18 | transports map[string]Transport 19 | } 20 | 21 | // NewManager creates a new manager. 22 | func NewManager(transports []Transport) *Manager { 23 | tranMap := make(map[string]Transport) 24 | names := make([]string, len(transports)) 25 | for i, t := range transports { 26 | names[i] = t.Name() 27 | tranMap[t.Name()] = t 28 | } 29 | 30 | return &Manager{ 31 | order: names, 32 | transports: tranMap, 33 | } 34 | } 35 | 36 | // UpgradeFrom returns a name list of transports which can upgrade from given 37 | // name. 38 | func (m *Manager) UpgradeFrom(name string) []string { 39 | for i, n := range m.order { 40 | if n == name { 41 | return m.order[i+1:] 42 | } 43 | } 44 | return nil 45 | } 46 | 47 | // Get returns the transport with given name. 48 | func (m *Manager) Get(name string) (Transport, bool) { 49 | t, ok := m.transports[name] 50 | return t, ok 51 | } 52 | -------------------------------------------------------------------------------- /go-socket.io/engineio/_examples/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "log" 7 | "net/http/httptest" 8 | 9 | "github.com/googollee/go-socket.io/engineio" 10 | ) 11 | 12 | func main() { 13 | eio := engineio.NewServer(nil) 14 | httpSvr := httptest.NewServer(eio) 15 | defer httpSvr.Close() 16 | 17 | for { 18 | conn, err := eio.Accept() 19 | if err != nil { 20 | log.Fatalln("accept error:", err) 21 | } 22 | 23 | go func(conn engineio.Conn) { 24 | defer conn.Close() 25 | 26 | fmt.Println(conn.ID(), conn.RemoteAddr(), "->", conn.LocalAddr(), "with", conn.RemoteHeader()) 27 | 28 | for { 29 | typ, r, err := conn.NextReader() 30 | if err != nil { 31 | log.Fatalln("read error:", err) 32 | return 33 | } 34 | w, err := conn.NextWriter(typ) 35 | if err != nil { 36 | r.Close() 37 | log.Fatalln("write error:", err) 38 | return 39 | } 40 | _, err = io.Copy(w, r) 41 | if err != nil { 42 | r.Close() 43 | w.Close() 44 | log.Fatalln("copy error:", err) 45 | return 46 | } 47 | if err = w.Close(); err != nil { 48 | log.Fatalln("close writer error:", err) 49 | return 50 | } 51 | if err = r.Close(); err != nil { 52 | log.Fatalln("close reader error:", err) 53 | return 54 | } 55 | } 56 | }(conn) 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /go-prompt/Makefile: -------------------------------------------------------------------------------- 1 | .DEFAULT_GOAL := help 2 | 3 | SOURCES := $(shell find . -prune -o -name "*.go" -not -name '*_test.go' -print) 4 | 5 | GOIMPORTS ?= goimports 6 | GOCILINT ?= golangci-lint 7 | 8 | .PHONY: setup 9 | setup: ## Setup for required tools. 10 | go get -u golang.org/x/tools/cmd/goimports 11 | go get -u github.com/golangci/golangci-lint/cmd/golangci-lint 12 | go get -u golang.org/x/tools/cmd/stringer 13 | 14 | .PHONY: fmt 15 | fmt: $(SOURCES) ## Formatting source codes. 16 | @$(GOIMPORTS) -w $^ 17 | 18 | .PHONY: lint 19 | lint: ## Run golangci-lint. 20 | @$(GOCILINT) run --no-config --disable-all --enable=goimports --enable=misspell ./... 21 | 22 | .PHONY: test 23 | test: ## Run tests with race condition checking. 24 | @go test -race ./... 25 | 26 | .PHONY: bench 27 | bench: ## Run benchmarks. 28 | @go test -bench=. -run=- -benchmem ./... 29 | 30 | .PHONY: coverage 31 | cover: ## Run the tests. 32 | @go test -coverprofile=coverage.o 33 | @go tool cover -func=coverage.o 34 | 35 | .PHONY: generate 36 | generate: ## Run go generate 37 | @go generate ./... 38 | 39 | .PHONY: build 40 | build: ## Build example command lines. 41 | ./_example/build.sh 42 | 43 | .PHONY: help 44 | help: ## Show help text 45 | @echo "Commands:" 46 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-10s\033[0m %s\n", $$1, $$2}' 47 | -------------------------------------------------------------------------------- /go-prompt/key_bind.go: -------------------------------------------------------------------------------- 1 | package prompt 2 | 3 | // KeyBindFunc receives buffer and processed it. 4 | type KeyBindFunc func(*Buffer) 5 | 6 | // KeyBind represents which key should do what operation. 7 | type KeyBind struct { 8 | Key Key 9 | Fn KeyBindFunc 10 | } 11 | 12 | // ASCIICodeBind represents which []byte should do what operation 13 | type ASCIICodeBind struct { 14 | ASCIICode []byte 15 | Fn KeyBindFunc 16 | } 17 | 18 | // KeyBindMode to switch a key binding flexibly. 19 | type KeyBindMode string 20 | 21 | const ( 22 | // CommonKeyBind is a mode without any keyboard shortcut 23 | CommonKeyBind KeyBindMode = "common" 24 | // EmacsKeyBind is a mode to use emacs-like keyboard shortcut 25 | EmacsKeyBind KeyBindMode = "emacs" 26 | ) 27 | 28 | var commonKeyBindings = []KeyBind{ 29 | // Go to the End of the line 30 | { 31 | Key: End, 32 | Fn: GoLineEnd, 33 | }, 34 | // Go to the beginning of the line 35 | { 36 | Key: Home, 37 | Fn: GoLineBeginning, 38 | }, 39 | // Delete character under the cursor 40 | { 41 | Key: Delete, 42 | Fn: DeleteChar, 43 | }, 44 | // Backspace 45 | { 46 | Key: Backspace, 47 | Fn: DeleteBeforeChar, 48 | }, 49 | // Right allow: Forward one character 50 | { 51 | Key: Right, 52 | Fn: GoRightChar, 53 | }, 54 | // Left allow: Backward one character 55 | { 56 | Key: Left, 57 | Fn: GoLeftChar, 58 | }, 59 | } 60 | -------------------------------------------------------------------------------- /go-prompt/key_string.go: -------------------------------------------------------------------------------- 1 | // Code generated by "stringer -type=Key"; DO NOT EDIT. 2 | 3 | package prompt 4 | 5 | import "strconv" 6 | 7 | const _Key_name = "EscapeControlAControlBControlCControlDControlEControlFControlGControlHControlIControlJControlKControlLControlMControlNControlOControlPControlQControlRControlSControlTControlUControlVControlWControlXControlYControlZControlSpaceControlBackslashControlSquareCloseControlCircumflexControlUnderscoreControlLeftControlRightControlUpControlDownUpDownRightLeftShiftLeftShiftUpShiftDownShiftRightHomeEndDeleteShiftDeleteControlDeletePageUpPageDownBackTabInsertBackspaceTabEnterF1F2F3F4F5F6F7F8F9F10F11F12F13F14F15F16F17F18F19F20F21F22F23F24AnyCPRResponseVt100MouseEventWindowsMouseEventBracketedPasteIgnoreNotDefined" 8 | 9 | var _Key_index = [...]uint16{0, 6, 14, 22, 30, 38, 46, 54, 62, 70, 78, 86, 94, 102, 110, 118, 126, 134, 142, 150, 158, 166, 174, 182, 190, 198, 206, 214, 226, 242, 260, 277, 294, 305, 317, 326, 337, 339, 343, 348, 352, 361, 368, 377, 387, 391, 394, 400, 411, 424, 430, 438, 445, 451, 460, 463, 468, 470, 472, 474, 476, 478, 480, 482, 484, 486, 489, 492, 495, 498, 501, 504, 507, 510, 513, 516, 519, 522, 525, 528, 531, 534, 545, 560, 577, 591, 597, 607} 10 | 11 | func (i Key) String() string { 12 | if i < 0 || i >= Key(len(_Key_index)-1) { 13 | return "Key(" + strconv.FormatInt(int64(i), 10) + ")" 14 | } 15 | return _Key_name[_Key_index[i]:_Key_index[i+1]] 16 | } 17 | -------------------------------------------------------------------------------- /cobra-prompt/_example/cmd/get.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "github.com/c-bata/go-prompt" 5 | "github.com/spf13/cobra" 6 | cobraprompt "github.com/stromland/cobra-prompt" 7 | ) 8 | 9 | var getFoodDynamicAnnotationValue = "GetFood" 10 | 11 | var GetFoodDynamic = func(annotationValue string) []prompt.Suggest { 12 | if annotationValue != getFoodDynamicAnnotationValue { 13 | return nil 14 | } 15 | 16 | return []prompt.Suggest{ 17 | {Text: "apple", Description: "Green apple"}, 18 | {Text: "tomato", Description: "Red tomato"}, 19 | } 20 | } 21 | 22 | var getCmd = &cobra.Command{ 23 | Use: "get", 24 | Short: "Get something", 25 | Aliases: []string{"eat"}, 26 | Run: func(cmd *cobra.Command, args []string) { 27 | cmd.Usage() 28 | }, 29 | } 30 | 31 | var getFoodCmd = &cobra.Command{ 32 | Use: "food", 33 | Short: "Get some food", 34 | Annotations: map[string]string{ 35 | cobraprompt.DynamicSuggestionsAnnotation: getFoodDynamicAnnotationValue, 36 | }, 37 | Run: func(cmd *cobra.Command, args []string) { 38 | verbose, _ := cmd.Flags().GetBool("verbose") 39 | for _, v := range args { 40 | if verbose { 41 | cmd.Println("Here you go, take this:", v) 42 | } else { 43 | cmd.Println(v) 44 | } 45 | } 46 | }, 47 | } 48 | 49 | func init() { 50 | RootCmd.AddCommand(getCmd) 51 | getCmd.AddCommand(getFoodCmd) 52 | getCmd.PersistentFlags().BoolP("verbose", "v", false, "Verbose log") 53 | } 54 | -------------------------------------------------------------------------------- /transmissionrpc/free_space.go: -------------------------------------------------------------------------------- 1 | package transmissionrpc 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | 7 | "github.com/hekmon/cunits/v2" 8 | ) 9 | 10 | /* 11 | Free Space 12 | https://github.com/transmission/transmission/blob/3.00/extras/rpc-spec.txt#L640 13 | */ 14 | 15 | // FreeSpace allow to see how much free space is available in a client-specified folder. 16 | // https://github.com/transmission/transmission/blob/3.00/extras/rpc-spec.txt#L645 17 | func (c *Client) FreeSpace(ctx context.Context, path string) (freeSpace cunits.Bits, err error) { 18 | payload := &transmissionFreeSpacePayload{Path: path} 19 | var space TransmissionFreeSpace 20 | if err = c.rpcCall(ctx, "free-space", payload, &space); err == nil { 21 | if space.Path == path { 22 | freeSpace = cunits.ImportInByte(float64(space.Size)) 23 | } else { 24 | err = fmt.Errorf("returned path '%s' does not match with requested path '%s'", space.Path, path) 25 | } 26 | } else { 27 | err = fmt.Errorf("'free-space' rpc method failed: %w", err) 28 | } 29 | return 30 | } 31 | 32 | type transmissionFreeSpacePayload struct { 33 | Path string `json:"path"` 34 | } 35 | 36 | // TransmissionFreeSpace represents the freespace available in bytes for a specific path. 37 | // https://github.com/transmission/transmission/blob/3.00/extras/rpc-spec.txt#L653 38 | type TransmissionFreeSpace struct { 39 | Path string `json:"path"` 40 | Size int64 `json:"size-bytes"` 41 | } 42 | -------------------------------------------------------------------------------- /cobra-prompt/_example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "strings" 6 | 7 | "github.com/c-bata/go-prompt" 8 | cobraprompt "github.com/stromland/cobra-prompt" 9 | "github.com/stromland/cobra-prompt/_example/cmd" 10 | ) 11 | 12 | var advancedPrompt = &cobraprompt.CobraPrompt{ 13 | RootCmd: cmd.RootCmd, 14 | PersistFlagValues: true, 15 | ShowHelpCommandAndFlags: true, 16 | DisableCompletionCommand: true, 17 | AddDefaultExitCommand: true, 18 | GoPromptOptions: []prompt.Option{ 19 | prompt.OptionTitle("cobra-prompt"), 20 | prompt.OptionPrefix(">(^!^)> "), 21 | prompt.OptionMaxSuggestion(10), 22 | }, 23 | DynamicSuggestionsFunc: func(annotationValue string, document *prompt.Document) []prompt.Suggest { 24 | if suggestions := cmd.GetFoodDynamic(annotationValue); suggestions != nil { 25 | return suggestions 26 | } 27 | 28 | return []prompt.Suggest{} 29 | }, 30 | OnErrorFunc: func(err error) { 31 | if strings.Contains(err.Error(), "unknown command") { 32 | cmd.RootCmd.PrintErrln(err) 33 | return 34 | } 35 | 36 | cmd.RootCmd.PrintErr(err) 37 | os.Exit(1) 38 | }, 39 | } 40 | 41 | var simplePrompt = &cobraprompt.CobraPrompt{ 42 | RootCmd: cmd.RootCmd, 43 | AddDefaultExitCommand: true, 44 | DisableCompletionCommand: true, 45 | } 46 | 47 | func main() { 48 | // Change to simplePrompt to see the difference 49 | advancedPrompt.Run() 50 | } 51 | -------------------------------------------------------------------------------- /go-prompt/key_bind_func.go: -------------------------------------------------------------------------------- 1 | package prompt 2 | 3 | // GoLineEnd Go to the End of the line 4 | func GoLineEnd(buf *Buffer) { 5 | x := []rune(buf.Document().TextAfterCursor()) 6 | buf.CursorRight(len(x)) 7 | } 8 | 9 | // GoLineBeginning Go to the beginning of the line 10 | func GoLineBeginning(buf *Buffer) { 11 | x := []rune(buf.Document().TextBeforeCursor()) 12 | buf.CursorLeft(len(x)) 13 | } 14 | 15 | // DeleteChar Delete character under the cursor 16 | func DeleteChar(buf *Buffer) { 17 | buf.Delete(1) 18 | } 19 | 20 | // DeleteWord Delete word before the cursor 21 | func DeleteWord(buf *Buffer) { 22 | buf.DeleteBeforeCursor(len([]rune(buf.Document().TextBeforeCursor())) - buf.Document().FindStartOfPreviousWordWithSpace()) 23 | } 24 | 25 | // DeleteBeforeChar Go to Backspace 26 | func DeleteBeforeChar(buf *Buffer) { 27 | buf.DeleteBeforeCursor(1) 28 | } 29 | 30 | // GoRightChar Forward one character 31 | func GoRightChar(buf *Buffer) { 32 | buf.CursorRight(1) 33 | } 34 | 35 | // GoLeftChar Backward one character 36 | func GoLeftChar(buf *Buffer) { 37 | buf.CursorLeft(1) 38 | } 39 | 40 | // GoRightWord Forward one word 41 | func GoRightWord(buf *Buffer) { 42 | buf.CursorRight(buf.Document().FindEndOfCurrentWordWithSpace()) 43 | } 44 | 45 | // GoLeftWord Backward one word 46 | func GoLeftWord(buf *Buffer) { 47 | buf.CursorLeft(len([]rune(buf.Document().TextBeforeCursor())) - buf.Document().FindStartOfPreviousWordWithSpace()) 48 | } 49 | -------------------------------------------------------------------------------- /util/osutil/windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | // +build windows 3 | 4 | package osutil 5 | 6 | import ( 7 | "os" 8 | "runtime" 9 | 10 | log "github.com/sirupsen/logrus" 11 | "golang.org/x/sys/windows" 12 | ) 13 | 14 | // Windows platform setup / initialization. 15 | func Init() { 16 | // https://github.com/golang/go/issues/43947 17 | os.Setenv("NoDefaultCurrentDirectoryInExePath", "1") 18 | SetupConsole() 19 | } 20 | 21 | // Setup windows console: disable quick edit mode. 22 | // From https://stackoverflow.com/questions/71690354/disable-quick-edit-in-golang . 23 | // See https://stackoverflow.com/questions/33883530/why-is-my-command-prompt-freezing-on-windows-10 . 24 | // Known problem: Windows PowerShell 5.1 creates UTF-16 file when piping process's stdout / stderr; 25 | // See: https://github.com/golang/go/issues/65157 . 26 | func SetupConsole() { 27 | winConsole := windows.Handle(os.Stdin.Fd()) 28 | var mode uint32 29 | err := windows.GetConsoleMode(winConsole, &mode) 30 | if err != nil { 31 | return 32 | } 33 | // Disable this mode 34 | mode &^= windows.ENABLE_QUICK_EDIT_MODE 35 | // Enable this mode 36 | mode |= windows.ENABLE_EXTENDED_FLAGS 37 | windows.SetConsoleMode(winConsole, mode) 38 | } 39 | 40 | // Dummy (placeholder). 41 | // The real implentation (on Linux) will fork the child process and exit. 42 | func Fork(removeArg string) { 43 | log.Fatalf("Fork mode is NOT supported on current platform %s", runtime.GOOS) 44 | } 45 | -------------------------------------------------------------------------------- /go-socket.io/engineio/transport/parameters_test.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "bytes" 5 | "io/ioutil" 6 | "testing" 7 | "time" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | ) 12 | 13 | func TestConnParameters(t *testing.T) { 14 | must := require.New(t) 15 | at := assert.New(t) 16 | 17 | tests := []struct { 18 | para ConnParameters 19 | out string 20 | }{ 21 | { 22 | ConnParameters{ 23 | time.Second * 10, 24 | time.Second * 5, 25 | "vCcJKmYQcIf801WDAAAB", 26 | []string{"websocket", "polling"}, 27 | }, 28 | "{\"sid\":\"vCcJKmYQcIf801WDAAAB\",\"upgrades\":[\"websocket\",\"polling\"],\"pingInterval\":10000,\"pingTimeout\":5000}\n", 29 | }, 30 | } 31 | for _, test := range tests { 32 | buf := bytes.NewBuffer(nil) 33 | n, err := test.para.WriteTo(buf) 34 | must.Nil(err) 35 | 36 | at.Equal(int64(len(test.out)), n) 37 | at.Equal(test.out, buf.String()) 38 | 39 | conn, err := ReadConnParameters(buf) 40 | must.Nil(err) 41 | at.Equal(test.para, conn) 42 | } 43 | } 44 | 45 | func BenchmarkConnParameters(b *testing.B) { 46 | must := require.New(b) 47 | 48 | param := ConnParameters{ 49 | time.Second * 10, 50 | time.Second * 5, 51 | "vCcJKmYQcIf801WDAAAB", 52 | []string{"websocket", "polling"}, 53 | } 54 | 55 | b.ResetTimer() 56 | 57 | for i := 0; i < b.N; i++ { 58 | _, err := param.WriteTo(ioutil.Discard) 59 | must.Nil(err) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /go-socket.io/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014-2014 Googol Lee 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 3. The name of the author may not be used to endorse or promote products 12 | derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /go-socket.io/_examples/dockerize-default-http/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | socketio "github.com/googollee/go-socket.io" 8 | ) 9 | 10 | func main() { 11 | server := socketio.NewServer(nil) 12 | 13 | server.OnConnect("/", func(s socketio.Conn) error { 14 | s.SetContext("") 15 | log.Println("connected:", s.ID()) 16 | return nil 17 | }) 18 | 19 | server.OnEvent("/", "notice", func(s socketio.Conn, msg string) { 20 | log.Println("notice:", msg) 21 | s.Emit("reply", "have "+msg) 22 | }) 23 | 24 | server.OnEvent("/chat", "msg", func(s socketio.Conn, msg string) string { 25 | s.SetContext(msg) 26 | return "recv " + msg 27 | }) 28 | 29 | server.OnEvent("/", "bye", func(s socketio.Conn) string { 30 | last := s.Context().(string) 31 | s.Emit("bye", last) 32 | s.Close() 33 | return last 34 | }) 35 | 36 | server.OnError("/", func(s socketio.Conn, e error) { 37 | log.Println("meet error:", e) 38 | }) 39 | 40 | server.OnDisconnect("/", func(s socketio.Conn, reason string) { 41 | log.Println("closed", reason) 42 | }) 43 | 44 | go func() { 45 | if err := server.Serve(); err != nil { 46 | log.Fatalf("socketio listen error: %s\n", err) 47 | } 48 | }() 49 | defer server.Close() 50 | 51 | http.Handle("/socket.io/", server) 52 | http.Handle("/", http.FileServer(http.Dir("../asset"))) 53 | 54 | log.Println("Serving at localhost:8000...") 55 | log.Fatal(http.ListenAndServe(":8000", nil)) 56 | } 57 | -------------------------------------------------------------------------------- /go-socket.io/engineio/packet/fake_reader.go: -------------------------------------------------------------------------------- 1 | package packet 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "io/ioutil" 7 | 8 | "github.com/googollee/go-socket.io/engineio/frame" 9 | ) 10 | 11 | type fakeConnReader struct { 12 | frames []Frame 13 | } 14 | 15 | func NewFakeConnReader(frames []Frame) *fakeConnReader { 16 | return &fakeConnReader{ 17 | frames: frames, 18 | } 19 | } 20 | 21 | func (r *fakeConnReader) NextReader() (frame.Type, io.ReadCloser, error) { 22 | if len(r.frames) == 0 { 23 | return frame.String, nil, io.EOF 24 | } 25 | f := r.frames[0] 26 | r.frames = r.frames[1:] 27 | return f.FType, ioutil.NopCloser(bytes.NewReader(f.Data)), nil 28 | } 29 | 30 | type fakeOneFrameConst struct { 31 | b byte 32 | } 33 | 34 | func (c *fakeOneFrameConst) Read(p []byte) (int, error) { 35 | p[0] = c.b 36 | return 1, nil 37 | } 38 | 39 | type fakeConstReader struct { 40 | ft frame.Type 41 | r *fakeOneFrameConst 42 | } 43 | 44 | func NewFakeConstReader() *fakeConstReader { 45 | return &fakeConstReader{ 46 | ft: frame.String, 47 | r: &fakeOneFrameConst{ 48 | b: MESSAGE.StringByte(), 49 | }, 50 | } 51 | } 52 | 53 | func (r *fakeConstReader) NextReader() (frame.Type, io.ReadCloser, error) { 54 | ft := r.ft 55 | switch ft { 56 | case frame.Binary: 57 | r.ft = frame.String 58 | r.r.b = MESSAGE.StringByte() 59 | case frame.String: 60 | r.ft = frame.Binary 61 | r.r.b = MESSAGE.BinaryByte() 62 | } 63 | return ft, ioutil.NopCloser(r.r), nil 64 | } 65 | -------------------------------------------------------------------------------- /go-socket.io/adapter_options.go: -------------------------------------------------------------------------------- 1 | package socketio 2 | 3 | import "fmt" 4 | 5 | // RedisAdapterOptions is configuration to create new adapter 6 | type RedisAdapterOptions struct { 7 | // deprecated. Usage Addr options 8 | Host string 9 | // deprecated. Usage Addr options 10 | Port string 11 | Addr string 12 | Prefix string 13 | Network string 14 | Password string 15 | // DB : specifies the database to select when dialing a connection. 16 | DB int 17 | } 18 | 19 | func (ro *RedisAdapterOptions) getAddr() string { 20 | if ro.Addr == "" { 21 | ro.Addr = fmt.Sprintf("%s:%s", ro.Host, ro.Port) 22 | } 23 | return ro.Addr 24 | } 25 | 26 | func defaultOptions() *RedisAdapterOptions { 27 | return &RedisAdapterOptions{ 28 | Addr: "127.0.0.1:6379", 29 | Prefix: "socket.io", 30 | Network: "tcp", 31 | } 32 | } 33 | 34 | func getOptions(opts *RedisAdapterOptions) *RedisAdapterOptions { 35 | options := defaultOptions() 36 | 37 | if opts != nil { 38 | if opts.Host != "" { 39 | options.Host = opts.Host 40 | } 41 | 42 | if opts.Port != "" { 43 | options.Port = opts.Port 44 | } 45 | 46 | if opts.Addr != "" { 47 | options.Addr = opts.Addr 48 | } 49 | 50 | if opts.Prefix != "" { 51 | options.Prefix = opts.Prefix 52 | } 53 | 54 | if opts.Network != "" { 55 | options.Network = opts.Network 56 | } 57 | 58 | if len(opts.Password) > 0 { 59 | options.Password = opts.Password 60 | } 61 | } 62 | 63 | return options 64 | } 65 | -------------------------------------------------------------------------------- /cmd/createcategory/createcategory.go: -------------------------------------------------------------------------------- 1 | package createcategory 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/spf13/cobra" 7 | 8 | "github.com/sagan/ptool/client" 9 | "github.com/sagan/ptool/cmd" 10 | "github.com/sagan/ptool/constants" 11 | ) 12 | 13 | var command = &cobra.Command{ 14 | Use: "createcategory {client} {category} [--save-path path]", 15 | Annotations: map[string]string{"cobra-prompt-dynamic-suggestions": "createcategory"}, 16 | Short: "Create or edit category in client.", 17 | Long: `Create category in client. If category already exists, edit it. 18 | Use --save-path to set (or modify) the save path of the category.`, 19 | Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs), 20 | RunE: createcategory, 21 | } 22 | 23 | var ( 24 | savePath = "" 25 | ) 26 | 27 | func init() { 28 | command.Flags().StringVarP(&savePath, "save-path", "", "", 29 | `Set the save path of the category. Can use "`+constants.NONE+`" to set it back to default empty value`) 30 | cmd.RootCmd.AddCommand(command) 31 | } 32 | 33 | func createcategory(cmd *cobra.Command, args []string) error { 34 | clientName := args[0] 35 | category := args[1] 36 | clientInstance, err := client.CreateClient(clientName) 37 | if err != nil { 38 | return fmt.Errorf("failed to create client: %w", err) 39 | } 40 | 41 | err = clientInstance.MakeCategory(category, savePath) 42 | if err != nil { 43 | return fmt.Errorf("failed to create category: %w", err) 44 | } 45 | return nil 46 | } 47 | -------------------------------------------------------------------------------- /go-socket.io/engineio/transport/websocket/connect_test.go: -------------------------------------------------------------------------------- 1 | package websocket 2 | 3 | import ( 4 | "net" 5 | "net/http" 6 | "net/http/httptest" 7 | "net/url" 8 | "testing" 9 | "time" 10 | 11 | "github.com/stretchr/testify/assert" 12 | "github.com/stretchr/testify/require" 13 | 14 | "github.com/googollee/go-socket.io/engineio/transport" 15 | ) 16 | 17 | func TestWebsocketSetReadDeadline(t *testing.T) { 18 | at := assert.New(t) 19 | must := assert.New(t) 20 | 21 | tran := &Transport{} 22 | conn := make(chan transport.Conn, 1) 23 | handler := func(w http.ResponseWriter, r *http.Request) { 24 | c, err := tran.Accept(w, r) 25 | require.NoError(t, err) 26 | 27 | conn <- c 28 | } 29 | httpSvr := httptest.NewServer(http.HandlerFunc(handler)) 30 | defer httpSvr.Close() 31 | 32 | u, err := url.Parse(httpSvr.URL) 33 | require.NoError(t, err) 34 | 35 | u.Scheme = "ws" 36 | 37 | header := make(http.Header) 38 | cc, err := tran.Dial(u, header) 39 | require.NoError(t, err) 40 | 41 | defer func() { 42 | must.NoError(cc.Close()) 43 | }() 44 | 45 | sc := <-conn 46 | defer func() { 47 | must.NoError(sc.Close()) 48 | }() 49 | 50 | err = cc.SetReadDeadline(time.Now().Add(time.Second / 10)) 51 | require.NoError(t, err) 52 | 53 | _, _, _, err = cc.NextReader() 54 | require.Error(t, err) 55 | 56 | timeout, ok := err.(net.Error) 57 | at.True(ok) 58 | at.True(timeout.Timeout()) 59 | 60 | op, ok := err.(net.Error) 61 | at.True(ok) 62 | at.True(op.Timeout()) 63 | } 64 | -------------------------------------------------------------------------------- /reflink/README.md: -------------------------------------------------------------------------------- 1 | [![GoDoc](https://godoc.org/github.com/KarpelesLab/reflink?status.svg)](https://godoc.org/github.com/KarpelesLab/reflink) 2 | 3 | # reflink 4 | 5 | Perform reflink operation on compatible filesystems (btrfs or xfs). 6 | 7 | ## What is a reflink? 8 | 9 | There are a number of type of links existing on Linux: 10 | 11 | * symlinks 12 | * hardlinks 13 | * reflinks 14 | 15 | Reflinks are a new kind of links found in btrfs and xfs which act similar to hard links, except modifying one of the two files will not change the other, and typically only the changed data will take space on the disk (copy-on-write). 16 | 17 | ## Can I use reflinks? 18 | 19 | A machine needs to have a compatible OS and filesystem to perform reflinks. Known to work are: 20 | 21 | * btrfs on Linux 22 | * xfs on Linux 23 | 24 | Other OSes have similar features, to be implemented in the future. 25 | 26 | * Windows has `DUPLICATE_EXTENTS_TO_FILE` 27 | * Solaris has `reflink` 28 | * MacOS has `clonefile` 29 | 30 | ## Usage 31 | 32 | ```golang 33 | err := reflink.Always("original_file.bin", "snapshot-001.bin") 34 | 35 | // or 36 | 37 | err := reflink.Auto("source_img.png", "modified_img.png") 38 | ``` 39 | 40 | `reflink.Always` will fail if reflink is not supported or didn't work for any reason, while `reflink.Auto` will fallback to a regular file copy. 41 | 42 | # Notes 43 | 44 | * The arguments have been put in the same order as `os.Link` or `os.Rename` rather than `io.Copy` as we are dealing with filenames. 45 | -------------------------------------------------------------------------------- /go-socket.io/.github/workflows/ci.yaml: -------------------------------------------------------------------------------- 1 | name: CI 2 | permissions: 3 | contents: read 4 | 5 | on: 6 | push: 7 | branches: [master] 8 | pull_request: 9 | branches: [master] 10 | schedule: 11 | - cron: '0 8 * * 1' # run "At 08:00 on Monday" 12 | 13 | jobs: 14 | build: 15 | name: ${{ matrix.os }} Go (${{ matrix.go }}) 16 | timeout-minutes: 5 17 | strategy: 18 | matrix: 19 | go: ['stable','oldstable'] 20 | os: [ubuntu-latest, macos-latest, windows-latest] 21 | runs-on: ${{ matrix.os }} 22 | steps: 23 | - name: Install Go 1.x 24 | uses: actions/setup-go@v4 25 | with: 26 | go-version: ${{ matrix.go }} 27 | check-latest: true 28 | 29 | - name: Check out code into the Go module directory 30 | uses: actions/checkout@v3 31 | 32 | - name: Check go version 33 | run: go version 34 | 35 | - name: Go Format 36 | run: gofmt -s -w . && git diff --exit-code 37 | 38 | - name: Go Tidy 39 | run: go mod tidy && git diff --exit-code 40 | 41 | - name: Go Mod Verify 42 | run: go mod verify 43 | 44 | - name: Run linter 45 | uses: golangci/golangci-lint-action@v3 46 | with: 47 | version: latest 48 | skip-cache: true 49 | skip-pkg-cache: true 50 | skip-build-cache: true 51 | 52 | - name: Run tests 53 | run: | 54 | make test 55 | 56 | - name: Run benchmarks 57 | run: | 58 | make bench 59 | -------------------------------------------------------------------------------- /go-socket.io/_examples/go-echo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/labstack/echo" 7 | 8 | socketio "github.com/googollee/go-socket.io" 9 | ) 10 | 11 | func main() { 12 | server := socketio.NewServer(nil) 13 | 14 | server.OnConnect("/", func(s socketio.Conn) error { 15 | s.SetContext("") 16 | log.Println("connected:", s.ID()) 17 | return nil 18 | }) 19 | 20 | server.OnEvent("/", "notice", func(s socketio.Conn, msg string) { 21 | log.Println("notice:", msg) 22 | s.Emit("reply", "have "+msg) 23 | }) 24 | 25 | server.OnEvent("/chat", "msg", func(s socketio.Conn, msg string) string { 26 | s.SetContext(msg) 27 | return "recv " + msg 28 | }) 29 | 30 | server.OnEvent("/", "echo", func(s socketio.Conn, msg interface{}) { 31 | s.Emit("echo", msg) 32 | }) 33 | 34 | server.OnEvent("/", "bye", func(s socketio.Conn) string { 35 | last := s.Context().(string) 36 | s.Emit("bye", last) 37 | s.Close() 38 | return last 39 | }) 40 | 41 | server.OnError("/", func(s socketio.Conn, e error) { 42 | log.Println("meet error:", e) 43 | }) 44 | 45 | server.OnDisconnect("/", func(s socketio.Conn, reason string) { 46 | log.Println("closed", reason) 47 | }) 48 | 49 | go server.Serve() 50 | defer server.Close() 51 | 52 | e := echo.New() 53 | e.HideBanner = true 54 | 55 | e.Static("/", "../asset") 56 | e.Any("/socket.io/", func(context echo.Context) error { 57 | server.ServeHTTP(context.Response(), context.Request()) 58 | return nil 59 | }) 60 | e.Logger.Fatal(e.Start(":8000")) 61 | } 62 | -------------------------------------------------------------------------------- /.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | # This is an example .goreleaser.yml file with some sensible defaults. 2 | # Make sure to check the documentation at https://goreleaser.com 3 | # Docs: 4 | # https://goreleaser.com/customization/builds/ 5 | before: 6 | hooks: 7 | # You may remove this if you don't use go modules. 8 | - go mod tidy 9 | # you may remove this if you don't need go generate 10 | - go generate ./... 11 | builds: 12 | - env: 13 | - CGO_ENABLED=0 14 | goos: 15 | - linux 16 | - windows 17 | - darwin 18 | ignore: 19 | - goos: windows 20 | goarch: 386 21 | - goos: linux 22 | goarch: 386 23 | ldflags: 24 | - -s -w -X github.com/sagan/ptool/version.Version={{.Version}} -X github.com/sagan/ptool/version.Commit={{.Commit}} -X github.com/sagan/ptool/version.Date={{.Date}} -X main.builtBy=goreleaser 25 | archives: 26 | - format: zip 27 | # this name template makes the OS and Arch compatible with the results of uname. 28 | name_template: >- 29 | {{ .ProjectName }}-v{{ .Version }}-{{ .Os }}-{{ .Arch }} 30 | checksum: 31 | name_template: "checksums.txt" 32 | snapshot: 33 | name_template: "{{ incpatch .Version }}-snapshot" 34 | changelog: 35 | sort: asc 36 | filters: 37 | exclude: 38 | - "^docs:" 39 | - "^test:" 40 | # The lines beneath this are called `modelines`. See `:help modeline` 41 | # Feel free to remove those if you don't want/use them. 42 | # yaml-language-server: $schema=https://goreleaser.com/static/schema.json 43 | # vim: set ts=2 sw=2 tw=0 fo=cnqoj 44 | -------------------------------------------------------------------------------- /cmd/cookiecloud/cookiecloud.go: -------------------------------------------------------------------------------- 1 | package cookiecloud 2 | 3 | import ( 4 | "github.com/spf13/cobra" 5 | 6 | "github.com/sagan/ptool/cmd" 7 | "github.com/sagan/ptool/config" 8 | "github.com/sagan/ptool/util" 9 | ) 10 | 11 | var Command = &cobra.Command{ 12 | Use: "cookiecloud", 13 | Aliases: []string{"cc"}, 14 | Short: "Use cookiecloud to sync site cookies or import sites.", 15 | Long: `Use cookiecloud to sync site cookies or import sites. 16 | To use this feature, add the cookiecloud servers to config file, e.g. : 17 | 18 | ptool.toml 19 | ---------- 20 | [[cookieclouds]] 21 | server = 'https://cookiecloud.example.com' 22 | uuid = 'uuid' 23 | password = 'password' 24 | ---------- 25 | 26 | See also: 27 | * CookieCloud: https://github.com/easychen/CookieCloud`, 28 | Args: cobra.MatchAll(cobra.ExactArgs(0), cobra.OnlyValidArgs), 29 | } 30 | 31 | func init() { 32 | cmd.RootCmd.AddCommand(Command) 33 | } 34 | 35 | func ParseProfile(profile string) []*config.CookiecloudConfigStruct { 36 | cookiecloudProfiles := []*config.CookiecloudConfigStruct{} 37 | if profile == "" { 38 | for _, profile := range config.Get().Cookieclouds { 39 | if profile.Disabled { 40 | continue 41 | } 42 | cookiecloudProfiles = append(cookiecloudProfiles, profile) 43 | } 44 | } else { 45 | names := util.SplitCsv(profile) 46 | for _, name := range names { 47 | profile := config.GetCookiecloudConfig(name) 48 | if profile != nil { 49 | cookiecloudProfiles = append(cookiecloudProfiles, profile) 50 | } 51 | } 52 | } 53 | return cookiecloudProfiles 54 | } 55 | -------------------------------------------------------------------------------- /go-socket.io/_examples/asset/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Socket.IO chat 5 | 15 | 16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /go-socket.io/_examples/gin-gonic/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/gin-gonic/gin" 8 | 9 | socketio "github.com/googollee/go-socket.io" 10 | ) 11 | 12 | func main() { 13 | router := gin.New() 14 | 15 | server := socketio.NewServer(nil) 16 | 17 | server.OnConnect("/", func(s socketio.Conn) error { 18 | s.SetContext("") 19 | log.Println("connected:", s.ID()) 20 | return nil 21 | }) 22 | 23 | server.OnEvent("/", "notice", func(s socketio.Conn, msg string) { 24 | log.Println("notice:", msg) 25 | s.Emit("reply", "have "+msg) 26 | }) 27 | 28 | server.OnEvent("/chat", "msg", func(s socketio.Conn, msg string) string { 29 | s.SetContext(msg) 30 | return "recv " + msg 31 | }) 32 | 33 | server.OnEvent("/", "bye", func(s socketio.Conn) string { 34 | last := s.Context().(string) 35 | s.Emit("bye", last) 36 | s.Close() 37 | return last 38 | }) 39 | 40 | server.OnError("/", func(s socketio.Conn, e error) { 41 | log.Println("meet error:", e) 42 | }) 43 | 44 | server.OnDisconnect("/", func(s socketio.Conn, reason string) { 45 | log.Println("closed", reason) 46 | }) 47 | 48 | go func() { 49 | if err := server.Serve(); err != nil { 50 | log.Fatalf("socketio listen error: %s\n", err) 51 | } 52 | }() 53 | defer server.Close() 54 | 55 | router.GET("/socket.io/*any", gin.WrapH(server)) 56 | router.POST("/socket.io/*any", gin.WrapH(server)) 57 | router.StaticFS("/public", http.Dir("../asset")) 58 | 59 | if err := router.Run(":8000"); err != nil { 60 | log.Fatal("failed run app: ", err) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /go-prompt/history_test.go: -------------------------------------------------------------------------------- 1 | package prompt 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func TestHistoryClear(t *testing.T) { 9 | h := NewHistory() 10 | h.Add("foo") 11 | h.Clear() 12 | expected := &History{ 13 | histories: []string{"foo"}, 14 | tmp: []string{"foo", ""}, 15 | selected: 1, 16 | } 17 | if !reflect.DeepEqual(expected, h) { 18 | t.Errorf("Should be %#v, but got %#v", expected, h) 19 | } 20 | } 21 | 22 | func TestHistoryAdd(t *testing.T) { 23 | h := NewHistory() 24 | h.Add("echo 1") 25 | expected := &History{ 26 | histories: []string{"echo 1"}, 27 | tmp: []string{"echo 1", ""}, 28 | selected: 1, 29 | } 30 | if !reflect.DeepEqual(h, expected) { 31 | t.Errorf("Should be %v, but got %v", expected, h) 32 | } 33 | } 34 | 35 | func TestHistoryOlder(t *testing.T) { 36 | h := NewHistory() 37 | h.Add("echo 1") 38 | 39 | // Prepare buffer 40 | buf := NewBuffer() 41 | buf.InsertText("echo 2", false, true) 42 | 43 | // [1 time] Call Older function 44 | buf1, changed := h.Older(buf) 45 | if !changed { 46 | t.Error("Should be changed history but not changed.") 47 | } 48 | if buf1.Text() != "echo 1" { 49 | t.Errorf("Should be %#v, but got %#v", "echo 1", buf1.Text()) 50 | } 51 | 52 | // [2 times] Call Older function 53 | buf = NewBuffer() 54 | buf.InsertText("echo 1", false, true) 55 | buf2, changed := h.Older(buf) 56 | if changed { 57 | t.Error("Should be not changed history but changed.") 58 | } 59 | if !reflect.DeepEqual("echo 1", buf2.Text()) { 60 | t.Errorf("Should be %#v, but got %#v", "echo 1", buf2.Text()) 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /cmd/getcategories/getcategories.go: -------------------------------------------------------------------------------- 1 | package getcategories 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/sagan/ptool/client" 10 | "github.com/sagan/ptool/cmd" 11 | "github.com/sagan/ptool/util" 12 | ) 13 | 14 | var command = &cobra.Command{ 15 | Use: "getcategories {client}", 16 | Annotations: map[string]string{"cobra-prompt-dynamic-suggestions": "getcategories"}, 17 | Short: "Get all categories of client.", 18 | Long: `Get all categories of client.`, 19 | Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs), 20 | RunE: getcategories, 21 | } 22 | 23 | var ( 24 | showNamesOnly = false 25 | ) 26 | 27 | func init() { 28 | command.Flags().BoolVarP(&showNamesOnly, "show-names-only", "", false, "Show category names only") 29 | cmd.RootCmd.AddCommand(command) 30 | } 31 | 32 | func getcategories(cmd *cobra.Command, args []string) error { 33 | clientName := args[0] 34 | clientInstance, err := client.CreateClient(clientName) 35 | if err != nil { 36 | return fmt.Errorf("failed to create client: %w", err) 37 | } 38 | 39 | cats, err := clientInstance.GetCategories() 40 | if err != nil { 41 | return fmt.Errorf("failed to get categories: %w", err) 42 | } 43 | if showNamesOnly { 44 | fmt.Printf("%s\n", strings.Join(util.Map(cats, func(cat *client.TorrentCategory) string { 45 | return cat.Name 46 | }), ", ")) 47 | } else { 48 | fmt.Printf("%-20s %s\n", "Name", "SavePath") 49 | for _, cat := range cats { 50 | fmt.Printf("%-20s %s\n", cat.Name, cat.SavePath) 51 | } 52 | } 53 | return nil 54 | } 55 | -------------------------------------------------------------------------------- /go-socket.io/_examples/dockerize-default-http/asset/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Socket.IO chat 5 | 15 | 16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /go-socket.io/_examples/redis-adapter-unix-socket/asset/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Socket.IO chat 5 | 15 | 16 | 17 | 18 |
19 | 20 |
21 | 22 | 23 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /go-socket.io/_examples/gf/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | 6 | "github.com/gogf/gf/frame/g" 7 | "github.com/gogf/gf/net/ghttp" 8 | 9 | socketio "github.com/googollee/go-socket.io" 10 | ) 11 | 12 | func cors(r *ghttp.Request) { 13 | r.Response.CORSDefault() 14 | r.Middleware.Next() 15 | } 16 | 17 | func main() { 18 | s := g.Server() 19 | 20 | server := socketio.NewServer(nil) 21 | 22 | s.BindMiddlewareDefault(cors) 23 | s.BindHandler("/socket.io/", func(r *ghttp.Request) { 24 | server.ServeHTTP(r.Response.Writer, r.Request) 25 | }) 26 | 27 | server.OnConnect("/", func(s socketio.Conn) error { 28 | s.SetContext("") 29 | log.Println("connected:", s.ID()) 30 | return nil 31 | }) 32 | 33 | server.OnEvent("/", "notice", func(s socketio.Conn, msg string) { 34 | log.Println("notice:", msg) 35 | s.Emit("reply", "have "+msg) 36 | }) 37 | 38 | server.OnEvent("/chat", "msg", func(s socketio.Conn, msg string) string { 39 | s.SetContext(msg) 40 | return "recv " + msg 41 | }) 42 | 43 | server.OnEvent("/", "bye", func(s socketio.Conn) string { 44 | last := s.Context().(string) 45 | s.Emit("bye", last) 46 | s.Close() 47 | return last 48 | }) 49 | 50 | server.OnError("/", func(s socketio.Conn, e error) { 51 | log.Println("meet error:", e) 52 | }) 53 | 54 | server.OnDisconnect("/", func(s socketio.Conn, reason string) { 55 | log.Println("closed", reason) 56 | }) 57 | 58 | go func() { 59 | if err := server.Serve(); err != nil { 60 | log.Fatalf("socketio listen error: %s\n", err) 61 | } 62 | }() 63 | defer server.Close() 64 | 65 | s.SetPort(8000) 66 | s.Run() 67 | } 68 | -------------------------------------------------------------------------------- /jinja/jinja.go: -------------------------------------------------------------------------------- 1 | // @todo: replace gonja with Go standard library text template. 2 | // ptool uses gonja (https://github.com/noirbizarre/gonja) as template language. 3 | // gonja is a Go port of Jinja which supported features & syntaxes is a subset of the latter. 4 | // This package implements some Jinja filters that are currently missing in gonja. 5 | package jinja 6 | 7 | import ( 8 | "fmt" 9 | "regexp" 10 | "strings" 11 | 12 | "github.com/noirbizarre/gonja" 13 | "github.com/noirbizarre/gonja/exec" 14 | "github.com/pkg/errors" 15 | ) 16 | 17 | func init() { 18 | // regex_search is a ansible filter that is commonly used in Jinja. 19 | // See https://docs.ansible.com/ansible/latest/collections/ansible/builtin/regex_search_filter.html . 20 | // Only basic (1-arg) usage is implemented for now. 21 | gonja.DefaultEnv.Filters.Register("regex_search", func(e *exec.Evaluator, in *exec.Value, 22 | params *exec.VarArgs) *exec.Value { 23 | if p := params.ExpectArgs(1); p.IsError() { 24 | return exec.AsValue(errors.Wrap(p, "Wrong signature for 'regex_search'")) 25 | } 26 | regxp, err := regexp.Compile(params.Args[0].String()) 27 | if err != nil { 28 | return exec.AsValue("") 29 | } 30 | return exec.AsValue(regxp.FindString(in.String())) 31 | }) 32 | } 33 | 34 | func Render(template string, context map[string]any) (string, error) { 35 | tpl, err := gonja.FromString(template) 36 | if err != nil { 37 | return "", fmt.Errorf("failed to parse jinja template: %w", err) 38 | } 39 | out, err := tpl.Execute(context) 40 | if err != nil { 41 | return "", fmt.Errorf("failed to render payload: %w", err) 42 | } 43 | return strings.TrimSpace(out), nil 44 | } 45 | -------------------------------------------------------------------------------- /go-socket.io/engineio/packet/packet_test.go: -------------------------------------------------------------------------------- 1 | package packet 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | "github.com/stretchr/testify/require" 9 | 10 | "github.com/googollee/go-socket.io/engineio/frame" 11 | ) 12 | 13 | func TestPacketType(t *testing.T) { 14 | var tests = []struct { 15 | b byte 16 | fType frame.Type 17 | pType Type 18 | strByte byte 19 | binByte byte 20 | str string 21 | }{ 22 | {0, frame.Binary, OPEN, '0', 0, "open"}, 23 | {1, frame.Binary, CLOSE, '1', 1, "close"}, 24 | {2, frame.Binary, PING, '2', 2, "ping"}, 25 | {3, frame.Binary, PONG, '3', 3, "pong"}, 26 | {4, frame.Binary, MESSAGE, '4', 4, "message"}, 27 | {5, frame.Binary, UPGRADE, '5', 5, "upgrade"}, 28 | {6, frame.Binary, NOOP, '6', 6, "noop"}, 29 | 30 | {'0', frame.String, OPEN, '0', 0, "open"}, 31 | {'1', frame.String, CLOSE, '1', 1, "close"}, 32 | {'2', frame.String, PING, '2', 2, "ping"}, 33 | {'3', frame.String, PONG, '3', 3, "pong"}, 34 | {'4', frame.String, MESSAGE, '4', 4, "message"}, 35 | {'5', frame.String, UPGRADE, '5', 5, "upgrade"}, 36 | {'6', frame.String, NOOP, '6', 6, "noop"}, 37 | } 38 | 39 | for i, test := range tests { 40 | typ := ByteToPacketType(test.b, test.fType) 41 | 42 | require.Equal(t, test.pType, typ, fmt.Sprintf(`types not equal by case: %d`, i)) 43 | 44 | assert.Equal(t, test.strByte, typ.StringByte(), fmt.Sprintf(`string byte not equal by case: %d`, i)) 45 | assert.Equal(t, test.binByte, typ.BinaryByte(), fmt.Sprintf(`bytes not equal by case: %d`, i)) 46 | assert.Equal(t, test.str, typ.String(), fmt.Sprintf(`strings not equal by case: %d`, i)) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /cmd/checktag/checktag.go: -------------------------------------------------------------------------------- 1 | package checktag 2 | 3 | import ( 4 | "fmt" 5 | "slices" 6 | 7 | "github.com/spf13/cobra" 8 | 9 | "github.com/sagan/ptool/client" 10 | "github.com/sagan/ptool/cmd" 11 | "github.com/sagan/ptool/util" 12 | ) 13 | 14 | var command = &cobra.Command{ 15 | Use: "checktag {client} {tag}", 16 | Annotations: map[string]string{"cobra-prompt-dynamic-suggestions": "gettags"}, 17 | Short: "Check whether tag(s) exists in client.", 18 | Long: `Check whether tag(s) exists in client. 19 | {tag}: comma-separated tag list. 20 | 21 | If any one of {tag} list exists in client, exit with 0; Otherwise exit with a non-zero code.`, 22 | Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs), 23 | RunE: checktag, 24 | } 25 | 26 | func init() { 27 | cmd.RootCmd.AddCommand(command) 28 | } 29 | 30 | func checktag(cmd *cobra.Command, args []string) error { 31 | clientName := args[0] 32 | tag := args[1] 33 | clientInstance, err := client.CreateClient(clientName) 34 | if err != nil { 35 | return fmt.Errorf("failed to create client: %w", err) 36 | } 37 | tags := util.SplitCsv(tag) 38 | 39 | clientTags, err := clientInstance.GetTags() 40 | if err != nil { 41 | return fmt.Errorf("failed to get client %s tags: %w", clientName, err) 42 | } 43 | ok := false 44 | for _, tag := range tags { 45 | if slices.Contains(clientTags, tag) { 46 | fmt.Printf("✓ tag %s exists in client %s\n", tag, clientName) 47 | ok = true 48 | } else { 49 | fmt.Printf("✕ tag %s does NOT exist in client %s\n", tag, clientName) 50 | } 51 | } 52 | if !ok { 53 | return fmt.Errorf("none of tags %v exists in client %s", tags, clientName) 54 | } 55 | return nil 56 | } 57 | -------------------------------------------------------------------------------- /go-socket.io/_examples/redis-adapter-unix-socket/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/gin-gonic/gin" 8 | 9 | socketio "github.com/googollee/go-socket.io" 10 | ) 11 | 12 | func main() { 13 | router := gin.New() 14 | 15 | server := socketio.NewServer(nil) 16 | 17 | _, err := server.Adapter(&socketio.RedisAdapterOptions{ 18 | Addr: "/tmp/docker/redis.sock", 19 | Network: "unix", 20 | }) 21 | if err != nil { 22 | log.Println("error:", err) 23 | return 24 | } 25 | 26 | server.OnConnect("/", func(s socketio.Conn) error { 27 | s.SetContext("") 28 | log.Println("connected:", s.ID()) 29 | return nil 30 | }) 31 | 32 | server.OnEvent("/", "notice", func(s socketio.Conn, msg string) { 33 | log.Println("notice:", msg) 34 | s.Emit("reply", "have "+msg) 35 | }) 36 | 37 | server.OnEvent("/chat", "msg", func(s socketio.Conn, msg string) string { 38 | s.SetContext(msg) 39 | return "recv " + msg 40 | }) 41 | 42 | server.OnEvent("/", "bye", func(s socketio.Conn) string { 43 | last := s.Context().(string) 44 | s.Emit("bye", last) 45 | s.Close() 46 | return last 47 | }) 48 | 49 | server.OnError("/", func(s socketio.Conn, e error) { 50 | log.Println("meet error:", e) 51 | }) 52 | 53 | server.OnDisconnect("/", func(s socketio.Conn, reason string) { 54 | log.Println("closed", reason) 55 | }) 56 | 57 | go server.Serve() 58 | defer server.Close() 59 | 60 | router.GET("/socket.io/*any", gin.WrapH(server)) 61 | router.POST("/socket.io/*any", gin.WrapH(server)) 62 | router.StaticFS("/public", http.Dir("../asset")) 63 | 64 | if err := router.Run(); err != nil { 65 | log.Fatal("failed run app: ", err) 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /go-socket.io/_examples/redis-adapter/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | 7 | "github.com/gin-gonic/gin" 8 | 9 | socketio "github.com/googollee/go-socket.io" 10 | ) 11 | 12 | func main() { 13 | router := gin.New() 14 | 15 | server := socketio.NewServer(nil) 16 | 17 | _, err := server.Adapter(nil) 18 | if err != nil { 19 | log.Println("error:", err) 20 | return 21 | } 22 | 23 | server.OnConnect("/", func(s socketio.Conn) error { 24 | s.SetContext("") 25 | log.Println("connected:", s.ID()) 26 | return nil 27 | }) 28 | 29 | server.OnEvent("/", "notice", func(s socketio.Conn, msg string) { 30 | log.Println("notice:", msg) 31 | s.Emit("reply", "have "+msg) 32 | }) 33 | 34 | server.OnEvent("/chat", "msg", func(s socketio.Conn, msg string) string { 35 | s.SetContext(msg) 36 | return "recv " + msg 37 | }) 38 | 39 | server.OnEvent("/", "bye", func(s socketio.Conn) string { 40 | last := s.Context().(string) 41 | s.Emit("bye", last) 42 | s.Close() 43 | return last 44 | }) 45 | 46 | server.OnError("/", func(s socketio.Conn, e error) { 47 | log.Println("meet error:", e) 48 | }) 49 | 50 | server.OnDisconnect("/", func(s socketio.Conn, reason string) { 51 | log.Println("closed", reason) 52 | }) 53 | 54 | go func() { 55 | if err := server.Serve(); err != nil { 56 | log.Fatalf("socketio listen error: %s\n", err) 57 | } 58 | }() 59 | defer server.Close() 60 | 61 | router.GET("/socket.io/*any", gin.WrapH(server)) 62 | router.POST("/socket.io/*any", gin.WrapH(server)) 63 | router.StaticFS("/public", http.Dir("../asset")) 64 | 65 | if err := router.Run(":8000"); err != nil { 66 | log.Fatal("failed run app: ", err) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /go-socket.io/_examples/iris/main.go: -------------------------------------------------------------------------------- 1 | // Package main runs a go-socket.io based websocket server with Iris web server. 2 | package main 3 | 4 | import ( 5 | "log" 6 | 7 | "github.com/kataras/iris/v12" 8 | 9 | socketio "github.com/googollee/go-socket.io" 10 | ) 11 | 12 | func main() { 13 | app := iris.New() 14 | 15 | server := socketio.NewServer(nil) 16 | 17 | server.OnConnect("/", func(s socketio.Conn) error { 18 | s.SetContext("") 19 | log.Println("connected:", s.ID()) 20 | return nil 21 | }) 22 | 23 | server.OnEvent("/", "notice", func(s socketio.Conn, msg string) { 24 | log.Println("notice:", msg) 25 | s.Emit("reply", "have "+msg) 26 | }) 27 | 28 | server.OnEvent("/chat", "msg", func(s socketio.Conn, msg string) string { 29 | s.SetContext(msg) 30 | return "recv " + msg 31 | }) 32 | 33 | server.OnEvent("/", "bye", func(s socketio.Conn) string { 34 | last := s.Context().(string) 35 | s.Emit("bye", last) 36 | s.Close() 37 | return last 38 | }) 39 | 40 | server.OnError("/", func(s socketio.Conn, e error) { 41 | log.Println("meet error:", e) 42 | }) 43 | 44 | server.OnDisconnect("/", func(s socketio.Conn, reason string) { 45 | log.Println("closed", reason) 46 | }) 47 | 48 | go func() { 49 | if err := server.Serve(); err != nil { 50 | log.Fatalf("socketio listen error: %s\n", err) 51 | } 52 | }() 53 | defer server.Close() 54 | 55 | app.HandleMany("GET POST", "/socket.io/{any:path}", iris.FromStd(server)) 56 | app.HandleDir("/", "../asset") 57 | 58 | if err := app.Run( 59 | iris.Addr(":8000"), 60 | iris.WithoutPathCorrection, 61 | iris.WithoutServerError(iris.ErrServerClosed), 62 | ); err != nil { 63 | log.Fatal("failed run app: ", err) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /go-prompt/output_vt100_test.go: -------------------------------------------------------------------------------- 1 | package prompt 2 | 3 | import ( 4 | "bytes" 5 | "testing" 6 | ) 7 | 8 | func TestVT100WriterWrite(t *testing.T) { 9 | scenarioTable := []struct { 10 | input []byte 11 | expected []byte 12 | }{ 13 | { 14 | input: []byte{0x1b}, 15 | expected: []byte{'?'}, 16 | }, 17 | { 18 | input: []byte{'a'}, 19 | expected: []byte{'a'}, 20 | }, 21 | } 22 | 23 | for _, s := range scenarioTable { 24 | pw := &VT100Writer{} 25 | pw.Write(s.input) 26 | 27 | if !bytes.Equal(pw.buffer, s.expected) { 28 | t.Errorf("Should be %+#v, but got %+#v", pw.buffer, s.expected) 29 | } 30 | } 31 | } 32 | 33 | func TestVT100WriterWriteStr(t *testing.T) { 34 | scenarioTable := []struct { 35 | input string 36 | expected []byte 37 | }{ 38 | { 39 | input: "\x1b", 40 | expected: []byte{'?'}, 41 | }, 42 | { 43 | input: "a", 44 | expected: []byte{'a'}, 45 | }, 46 | } 47 | 48 | for _, s := range scenarioTable { 49 | pw := &VT100Writer{} 50 | pw.WriteStr(s.input) 51 | 52 | if !bytes.Equal(pw.buffer, s.expected) { 53 | t.Errorf("Should be %+#v, but got %+#v", pw.buffer, s.expected) 54 | } 55 | } 56 | } 57 | 58 | func TestVT100WriterWriteRawStr(t *testing.T) { 59 | scenarioTable := []struct { 60 | input string 61 | expected []byte 62 | }{ 63 | { 64 | input: "\x1b", 65 | expected: []byte{0x1b}, 66 | }, 67 | { 68 | input: "a", 69 | expected: []byte{'a'}, 70 | }, 71 | } 72 | 73 | for _, s := range scenarioTable { 74 | pw := &VT100Writer{} 75 | pw.WriteRawStr(s.input) 76 | 77 | if !bytes.Equal(pw.buffer, s.expected) { 78 | t.Errorf("Should be %+#v, but got %+#v", pw.buffer, s.expected) 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /go-socket.io/handler.go: -------------------------------------------------------------------------------- 1 | package socketio 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | ) 7 | 8 | const ( 9 | goSocketIOConnInterface = "Conn" 10 | ) 11 | 12 | type funcHandler struct { 13 | argTypes []reflect.Type 14 | f reflect.Value 15 | } 16 | 17 | func (h *funcHandler) Call(args []reflect.Value) (ret []reflect.Value, err error) { 18 | defer func() { 19 | if r := recover(); r != nil { 20 | var ok bool 21 | err, ok = r.(error) 22 | if !ok { 23 | err = fmt.Errorf("event call error: %s", r) 24 | } 25 | } 26 | }() 27 | 28 | ret = h.f.Call(args) 29 | 30 | return 31 | } 32 | 33 | func newEventFunc(f interface{}) *funcHandler { 34 | fv := reflect.ValueOf(f) 35 | 36 | if fv.Kind() != reflect.Func { 37 | panic("event handler must be a func.") 38 | } 39 | ft := fv.Type() 40 | 41 | if ft.NumIn() < 1 || ft.In(0).Name() != goSocketIOConnInterface { 42 | panic("handler function should be like func(socketio.Conn, ...)") 43 | } 44 | 45 | argTypes := make([]reflect.Type, ft.NumIn()-1) 46 | for i := range argTypes { 47 | argTypes[i] = ft.In(i + 1) 48 | } 49 | 50 | if len(argTypes) == 0 { 51 | argTypes = nil 52 | } 53 | 54 | return &funcHandler{ 55 | argTypes: argTypes, 56 | f: fv, 57 | } 58 | } 59 | 60 | func newAckFunc(f interface{}) *funcHandler { 61 | fv := reflect.ValueOf(f) 62 | 63 | if fv.Kind() != reflect.Func { 64 | panic("ack callback must be a func.") 65 | } 66 | 67 | ft := fv.Type() 68 | argTypes := make([]reflect.Type, ft.NumIn()) 69 | 70 | for i := range argTypes { 71 | argTypes[i] = ft.In(i) 72 | } 73 | if len(argTypes) == 0 { 74 | argTypes = nil 75 | } 76 | 77 | return &funcHandler{ 78 | argTypes: argTypes, 79 | f: fv, 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /go-prompt/history.go: -------------------------------------------------------------------------------- 1 | package prompt 2 | 3 | // History stores the texts that are entered. 4 | type History struct { 5 | histories []string 6 | tmp []string 7 | selected int 8 | } 9 | 10 | // Add to add text in history. 11 | func (h *History) Add(input string) { 12 | h.histories = append(h.histories, input) 13 | h.Clear() 14 | } 15 | 16 | // Clear to clear the history. 17 | func (h *History) Clear() { 18 | h.tmp = make([]string, len(h.histories)) 19 | for i := range h.histories { 20 | h.tmp[i] = h.histories[i] 21 | } 22 | h.tmp = append(h.tmp, "") 23 | h.selected = len(h.tmp) - 1 24 | } 25 | 26 | // Older saves a buffer of current line and get a buffer of previous line by up-arrow. 27 | // The changes of line buffers are stored until new history is created. 28 | func (h *History) Older(buf *Buffer) (new *Buffer, changed bool) { 29 | if len(h.tmp) == 1 || h.selected == 0 { 30 | return buf, false 31 | } 32 | h.tmp[h.selected] = buf.Text() 33 | 34 | h.selected-- 35 | new = NewBuffer() 36 | new.InsertText(h.tmp[h.selected], false, true) 37 | return new, true 38 | } 39 | 40 | // Newer saves a buffer of current line and get a buffer of next line by up-arrow. 41 | // The changes of line buffers are stored until new history is created. 42 | func (h *History) Newer(buf *Buffer) (new *Buffer, changed bool) { 43 | if h.selected >= len(h.tmp)-1 { 44 | return buf, false 45 | } 46 | h.tmp[h.selected] = buf.Text() 47 | 48 | h.selected++ 49 | new = NewBuffer() 50 | new.InsertText(h.tmp[h.selected], false, true) 51 | return new, true 52 | } 53 | 54 | // NewHistory returns new history object. 55 | func NewHistory() *History { 56 | return &History{ 57 | histories: []string{}, 58 | tmp: []string{""}, 59 | selected: 0, 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /go-socket.io/engineio/transport/parameters.go: -------------------------------------------------------------------------------- 1 | package transport 2 | 3 | import ( 4 | "encoding/json" 5 | "io" 6 | "time" 7 | ) 8 | 9 | // ConnParameters is connection parameter of server. 10 | type ConnParameters struct { 11 | PingInterval time.Duration 12 | PingTimeout time.Duration 13 | SID string 14 | Upgrades []string 15 | } 16 | 17 | type jsonParameters struct { 18 | SID string `json:"sid"` 19 | Upgrades []string `json:"upgrades"` 20 | PingInterval int `json:"pingInterval"` 21 | PingTimeout int `json:"pingTimeout"` 22 | } 23 | 24 | // ReadConnParameters reads ConnParameters from r. 25 | func ReadConnParameters(r io.Reader) (ConnParameters, error) { 26 | var param jsonParameters 27 | if err := json.NewDecoder(r).Decode(¶m); err != nil { 28 | return ConnParameters{}, err 29 | } 30 | 31 | return ConnParameters{ 32 | SID: param.SID, 33 | Upgrades: param.Upgrades, 34 | PingInterval: time.Duration(param.PingInterval) * time.Millisecond, 35 | PingTimeout: time.Duration(param.PingTimeout) * time.Millisecond, 36 | }, nil 37 | } 38 | 39 | // WriteTo writes to w with json format. 40 | func (p ConnParameters) WriteTo(w io.Writer) (int64, error) { 41 | arg := jsonParameters{ 42 | SID: p.SID, 43 | Upgrades: p.Upgrades, 44 | PingInterval: int(p.PingInterval / time.Millisecond), 45 | PingTimeout: int(p.PingTimeout / time.Millisecond), 46 | } 47 | writer := writer{ 48 | w: w, 49 | } 50 | err := json.NewEncoder(&writer).Encode(arg) 51 | return writer.i, err 52 | } 53 | 54 | type writer struct { 55 | i int64 56 | w io.Writer 57 | } 58 | 59 | func (w *writer) Write(p []byte) (int, error) { 60 | n, err := w.w.Write(p) 61 | w.i += int64(n) 62 | return n, err 63 | } 64 | -------------------------------------------------------------------------------- /go-prompt/_tools/sigwinch/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "os/signal" 7 | "syscall" 8 | "unsafe" 9 | ) 10 | 11 | // Winsize is winsize struct got from the ioctl(2) system call. 12 | type Winsize struct { 13 | Row uint16 14 | Col uint16 15 | X uint16 // pixel value 16 | Y uint16 // pixel value 17 | } 18 | 19 | // GetWinSize returns winsize struct which is the response of ioctl(2). 20 | func GetWinSize(fd int) *Winsize { 21 | ws := &Winsize{} 22 | retCode, _, errno := syscall.Syscall( 23 | syscall.SYS_IOCTL, 24 | uintptr(fd), 25 | uintptr(syscall.TIOCGWINSZ), 26 | uintptr(unsafe.Pointer(ws))) 27 | 28 | if int(retCode) == -1 { 29 | panic(errno) 30 | } 31 | return ws 32 | } 33 | 34 | func main() { 35 | signalChan := make(chan os.Signal, 1) 36 | signal.Notify( 37 | signalChan, 38 | syscall.SIGHUP, 39 | syscall.SIGINT, 40 | syscall.SIGTERM, 41 | syscall.SIGQUIT, 42 | syscall.SIGWINCH, 43 | ) 44 | ws := GetWinSize(syscall.Stdin) 45 | fmt.Printf("Row %d : Col %d\n", ws.Row, ws.Col) 46 | 47 | exitChan := make(chan int) 48 | go func() { 49 | for { 50 | s := <-signalChan 51 | switch s { 52 | // kill -SIGHUP XXXX 53 | case syscall.SIGHUP: 54 | exitChan <- 0 55 | 56 | // kill -SIGINT XXXX or Ctrl+c 57 | case syscall.SIGINT: 58 | exitChan <- 0 59 | 60 | // kill -SIGTERM XXXX 61 | case syscall.SIGTERM: 62 | exitChan <- 0 63 | 64 | // kill -SIGQUIT XXXX 65 | case syscall.SIGQUIT: 66 | exitChan <- 0 67 | 68 | case syscall.SIGWINCH: 69 | ws := GetWinSize(syscall.Stdin) 70 | fmt.Printf("Row %d : Col %d\n", ws.Row, ws.Col) 71 | 72 | default: 73 | exitChan <- 1 74 | } 75 | } 76 | }() 77 | 78 | code := <-exitChan 79 | os.Exit(code) 80 | } 81 | -------------------------------------------------------------------------------- /go-socket.io/parser/buffer.go: -------------------------------------------------------------------------------- 1 | package parser 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "strconv" 7 | ) 8 | 9 | // Buffer is an binary buffer handler used in emit args. All buffers will be 10 | // sent as binary in the transport layer. 11 | type Buffer struct { 12 | num uint64 13 | isBinary bool 14 | 15 | Data []byte 16 | } 17 | 18 | type BufferData struct { 19 | Num uint64 20 | PlaceHolder bool `json:"_placeholder"` 21 | Data []byte 22 | } 23 | 24 | // MarshalJSON marshals to JSON. 25 | func (a Buffer) MarshalJSON() ([]byte, error) { 26 | var buf bytes.Buffer 27 | if err := a.marshalJSONBuf(&buf); err != nil { 28 | return nil, err 29 | } 30 | 31 | return buf.Bytes(), nil 32 | } 33 | 34 | func (a *Buffer) marshalJSONBuf(buf *bytes.Buffer) error { 35 | encode := a.encodeText 36 | if a.isBinary { 37 | encode = a.encodeBinary 38 | } 39 | 40 | return encode(buf) 41 | } 42 | 43 | func (a *Buffer) encodeText(buf *bytes.Buffer) error { 44 | buf.WriteString(`{"type":"Buffer","data":[`) 45 | for i, d := range a.Data { 46 | if i > 0 { 47 | buf.WriteString(",") 48 | } 49 | buf.WriteString(strconv.Itoa(int(d))) 50 | } 51 | buf.WriteString("]}") 52 | 53 | return nil 54 | } 55 | 56 | func (a *Buffer) encodeBinary(buf *bytes.Buffer) error { 57 | buf.WriteString(`{"_placeholder":true,"num":`) 58 | buf.WriteString(strconv.FormatUint(a.num, 10)) 59 | buf.WriteString("}") 60 | 61 | return nil 62 | } 63 | 64 | // UnmarshalJSON unmarshal data from JSON. 65 | func (a *Buffer) UnmarshalJSON(b []byte) error { 66 | var data BufferData 67 | if err := json.Unmarshal(b, &data); err != nil { 68 | return err 69 | } 70 | 71 | a.isBinary = data.PlaceHolder 72 | a.Data = data.Data 73 | a.num = data.Num 74 | 75 | return nil 76 | } 77 | -------------------------------------------------------------------------------- /site/mtorrent/json.go: -------------------------------------------------------------------------------- 1 | package mtorrent 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "strconv" 7 | "time" 8 | ) 9 | 10 | type Time struct { 11 | time.Time 12 | } 13 | 14 | func (ct *Time) MarshalJSON() ([]byte, error) { 15 | return []byte(fmt.Sprintf(`"%s"`, ct.Format(time.DateTime))), nil 16 | } 17 | 18 | func (ct *Time) UnmarshalJSON(data []byte) error { 19 | parsedTime, err := time.Parse(time.DateTime, string(data[1:len(data)-1])) 20 | if err != nil { 21 | return err 22 | } 23 | ct.Time = parsedTime 24 | return nil 25 | } 26 | 27 | func (ct *Time) UnixWithDefault(defaultValue int64) int64 { 28 | if ct == nil { 29 | return defaultValue 30 | } 31 | 32 | return ct.Unix() 33 | } 34 | 35 | type Int64 int64 36 | 37 | func (ci *Int64) UnmarshalJSON(data []byte) error { 38 | var raw json.RawMessage 39 | if err := json.Unmarshal(data, &raw); err != nil { 40 | return err 41 | } 42 | 43 | var num int64 44 | if err := json.Unmarshal(raw, &num); err == nil { 45 | *ci = Int64(num) 46 | return nil 47 | } 48 | 49 | var str string 50 | if err := json.Unmarshal(raw, &str); err != nil { 51 | return err 52 | } 53 | 54 | num, err := strconv.ParseInt(str, 10, 64) 55 | if err != nil { 56 | return err 57 | } 58 | 59 | *ci = Int64(num) 60 | return nil 61 | } 62 | 63 | func (ci *Int64) MarshalJSON() ([]byte, error) { 64 | return json.Marshal(strconv.FormatInt(int64(*ci), 10)) 65 | } 66 | 67 | func (ci *Int64) Value() int64 { 68 | return int64(*ci) 69 | } 70 | 71 | type Float64String string 72 | 73 | type Int64String string 74 | 75 | func (ci Float64String) Value() float64 { 76 | v, e := strconv.ParseFloat(string(ci), 64) 77 | if e != nil { 78 | return 0 79 | } 80 | return v 81 | } 82 | 83 | func (ci Int64String) Value() int64 { 84 | return int64(Float64String(ci).Value()) 85 | } 86 | -------------------------------------------------------------------------------- /go-prompt/output_posix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package prompt 4 | 5 | import ( 6 | "syscall" 7 | ) 8 | 9 | const flushMaxRetryCount = 3 10 | 11 | // PosixWriter is a ConsoleWriter implementation for POSIX environment. 12 | // To control terminal emulator, this outputs VT100 escape sequences. 13 | type PosixWriter struct { 14 | VT100Writer 15 | fd int 16 | } 17 | 18 | // Flush to flush buffer 19 | func (w *PosixWriter) Flush() error { 20 | l := len(w.buffer) 21 | offset := 0 22 | retry := 0 23 | for { 24 | n, err := syscall.Write(w.fd, w.buffer[offset:]) 25 | if err != nil { 26 | if retry < flushMaxRetryCount { 27 | retry++ 28 | continue 29 | } 30 | return err 31 | } 32 | offset += n 33 | if offset == l { 34 | break 35 | } 36 | } 37 | w.buffer = []byte{} 38 | return nil 39 | } 40 | 41 | var _ ConsoleWriter = &PosixWriter{} 42 | 43 | var ( 44 | // NewStandardOutputWriter returns ConsoleWriter object to write to stdout. 45 | // This generates VT100 escape sequences because almost terminal emulators 46 | // in POSIX OS built on top of a VT100 specification. 47 | // Deprecated: Please use NewStdoutWriter 48 | NewStandardOutputWriter = NewStdoutWriter 49 | ) 50 | 51 | // NewStdoutWriter returns ConsoleWriter object to write to stdout. 52 | // This generates VT100 escape sequences because almost terminal emulators 53 | // in POSIX OS built on top of a VT100 specification. 54 | func NewStdoutWriter() ConsoleWriter { 55 | return &PosixWriter{ 56 | fd: syscall.Stdout, 57 | } 58 | } 59 | 60 | // NewStderrWriter returns ConsoleWriter object to write to stderr. 61 | // This generates VT100 escape sequences because almost terminal emulators 62 | // in POSIX OS built on top of a VT100 specification. 63 | func NewStderrWriter() ConsoleWriter { 64 | return &PosixWriter{ 65 | fd: syscall.Stderr, 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /go-socket.io/_examples/dockerize-default-http/go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= 5 | github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= 6 | github.com/gomodule/redigo v1.8.4 h1:Z5JUg94HMTR1XpwBaSH4vq3+PNSIykBLxMdglbw10gg= 7 | github.com/gomodule/redigo v1.8.4/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= 8 | github.com/googollee/go-socket.io v1.6.0 h1:zbz0kEERgeYL/yEu9pBXSIyZEBluiNc2AJaMFmFjIOY= 9 | github.com/googollee/go-socket.io v1.6.0/go.mod h1:0vGP8/dXR9SZUMMD4+xxaGo/lohOw3YWMh2WRiWeKxg= 10 | github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= 11 | github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 12 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 13 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 14 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 15 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= 16 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 17 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 18 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 19 | gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= 20 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 21 | -------------------------------------------------------------------------------- /go-socket.io/engineio/README.md: -------------------------------------------------------------------------------- 1 | # go-engine.io 2 | 3 | [![GoDoc](http://godoc.org/github.com/googollee/go-socket.io/engineio?status.svg)](http://godoc.org/github.com/googollee/go-socket.io/engineio) 4 | 5 | go-engine.io is the implement of engine.io in golang, which is transport-based cross-browser/cross-device bi-directional communication layer for [go-socket.io](https://github.com/googollee/go-socket.io). 6 | 7 | It is compatible with node.js implement, and supported long-polling and websocket transport. 8 | 9 | ## Install 10 | 11 | Install the package with: 12 | 13 | ```bash 14 | go get github.com/googollee/go-socket.io/engineio@v1 15 | ``` 16 | 17 | Import it with: 18 | 19 | ```go 20 | import "github.com/googollee/go-socket.io/engineio" 21 | ``` 22 | 23 | and use `engineio` as the package name inside the code. 24 | 25 | ## Example 26 | 27 | Please check example folder for details. 28 | 29 | ```go 30 | package main 31 | 32 | import ( 33 | "io/ioutil" 34 | "log" 35 | "net/http" 36 | 37 | "github.com/googollee/go-socket.io/engineio" 38 | ) 39 | 40 | func main() { 41 | server := engineio.NewServer(nil) 42 | 43 | go func() { 44 | for { 45 | conn, err := server.Accept() 46 | if err != nil { 47 | log.Fatalln("accept error:", err) 48 | } 49 | 50 | go func() { 51 | defer conn.Close() 52 | 53 | for { 54 | t, r, _ := conn.NextReader() 55 | b, _ := ioutil.ReadAll(r) 56 | r.Close() 57 | 58 | w, _ := conn.NextWriter(t) 59 | w.Write(b) 60 | w.Close() 61 | } 62 | }() 63 | } 64 | }() 65 | 66 | http.Handle("/engine.io/", server) 67 | log.Println("Serving at localhost:5000...") 68 | 69 | log.Fatal(http.ListenAndServe(":5000", nil)) 70 | } 71 | ``` 72 | 73 | ## License 74 | 75 | The 3-clause BSD License - see [LICENSE](https://opensource.org/licenses/BSD-3-Clause) for more details 76 | -------------------------------------------------------------------------------- /go-socket.io/engineio/payload/util.go: -------------------------------------------------------------------------------- 1 | package payload 2 | 3 | import "bytes" 4 | 5 | func writeBinaryLen(l int64, w *bytes.Buffer) error { 6 | if l <= 0 { 7 | if err := w.WriteByte(0x00); err != nil { 8 | return err 9 | } 10 | if err := w.WriteByte(0xff); err != nil { 11 | return err 12 | } 13 | return nil 14 | } 15 | max := int64(1) 16 | for n := l / 10; n > 0; n /= 10 { 17 | max *= 10 18 | } 19 | for max > 0 { 20 | n := l / max 21 | if err := w.WriteByte(byte(n)); err != nil { 22 | return err 23 | } 24 | l -= n * max 25 | max /= 10 26 | } 27 | return w.WriteByte(0xff) 28 | } 29 | 30 | func writeTextLen(l int64, w *bytes.Buffer) error { 31 | if l <= 0 { 32 | if err := w.WriteByte('0'); err != nil { 33 | return err 34 | } 35 | if err := w.WriteByte(':'); err != nil { 36 | return err 37 | } 38 | return nil 39 | } 40 | max := int64(1) 41 | for n := l / 10; n > 0; n /= 10 { 42 | max *= 10 43 | } 44 | for max > 0 { 45 | n := l / max 46 | if err := w.WriteByte(byte(n) + '0'); err != nil { 47 | return err 48 | } 49 | l -= n * max 50 | max /= 10 51 | } 52 | return w.WriteByte(':') 53 | } 54 | 55 | func readBinaryLen(r byteReader) (int64, error) { 56 | ret := int64(0) 57 | for { 58 | b, err := r.ReadByte() 59 | if err != nil { 60 | return 0, err 61 | } 62 | if b == 0xff { 63 | break 64 | } 65 | if b > 9 { 66 | return 0, errInvalidPayload 67 | } 68 | ret = ret*10 + int64(b) 69 | } 70 | return ret, nil 71 | } 72 | 73 | func readTextLen(r byteReader) (int64, error) { 74 | ret := int64(0) 75 | for { 76 | b, err := r.ReadByte() 77 | if err != nil { 78 | return 0, err 79 | } 80 | if b == ':' { 81 | break 82 | } 83 | if b < '0' || b > '9' { 84 | return 0, errInvalidPayload 85 | } 86 | ret = ret*10 + int64(b-'0') 87 | } 88 | return ret, nil 89 | } 90 | --------------------------------------------------------------------------------