v2.0.1: Auto-update & Telegram auto-config

This commit is contained in:
y0sy4 2026-03-22 20:11:45 +03:00
parent 677d5fb3ba
commit ab25511f6e
5 changed files with 237 additions and 27 deletions

48
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,48 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone.
## Our Standards
Examples of behavior that contributes to a positive environment:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes
Examples of unacceptable behavior:
* The use of sexualized language or imagery
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information without explicit permission
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
https://github.com/y0sy4/tg-ws-proxy-go/issues
All complaints will be reviewed and investigated promptly and fairly.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org),
version 2.1, available at
https://www.contributor-covenant.org/version/2/1/code_of_conduct.html

68
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,68 @@
# Contributing to TG WS Proxy Go
First off, thank you for considering contributing to TG WS Proxy Go!
## How Can I Contribute?
### Reporting Bugs
Before creating bug reports, please check the existing issues as you might find out that you don't need to create one. When you are creating a bug report, please include as many details as possible:
* **Use a clear and descriptive title**
* **Describe the exact steps to reproduce the problem**
* **Provide specific examples to demonstrate the steps**
* **Describe the behavior you observed and what behavior you expected**
* **Include logs if possible** (from %APPDATA%/TgWsProxy/proxy.log)
### Suggesting Enhancements
Enhancement suggestions are tracked as GitHub issues. When creating an enhancement suggestion, please include:
* **Use a clear and descriptive title**
* **Provide a detailed description of the suggested enhancement**
* **Explain why this enhancement would be useful**
* **List some examples of how this enhancement would be used**
### Pull Requests
* Fill in the required template
* Follow the Go style guide
* Include comments in your code where necessary
* Update documentation if needed
## Development Setup
### Prerequisites
* Go 1.21 or later
* Git
### Building
```bash
# Clone the repository
git clone https://github.com/y0sy4/tg-ws-proxy-go.git
cd tg-ws-proxy-go
# Build for your platform
go build -o TgWsProxy.exe ./cmd/proxy # Windows
go build -o TgWsProxy_linux ./cmd/proxy # Linux
go build -o TgWsProxy_macos ./cmd/proxy # macOS
```
### Running Tests
```bash
go test -v ./internal/...
```
## Code Style
* Follow [Effective Go](https://golang.org/doc/effective_go)
* Use `gofmt` or `goimports` to format code
* Keep functions small and focused
* Add comments for exported functions
## Questions?
Feel free to open an issue for any questions!

View File

@ -32,13 +32,10 @@ go build -o TgWsProxy.exe ./cmd/proxy
### Запуск ### Запуск
```bash ```bash
# Windows # Windows (автоматически откроет настройку прокси в Telegram)
start run.bat start run.bat
# Windows с авто-настройкой Telegram # Linux/macOS (автоматически откроет настройку прокси в Telegram)
TgWsProxy.exe --auto-config
# Linux/macOS
./TgWsProxy ./TgWsProxy
# С опциями # С опциями

View File

@ -31,7 +31,6 @@ func main() {
bufKB := flag.Int("buf-kb", 256, "Socket buffer size in KB") bufKB := flag.Int("buf-kb", 256, "Socket buffer size in KB")
poolSize := flag.Int("pool-size", 4, "WS pool size per DC") poolSize := flag.Int("pool-size", 4, "WS pool size per DC")
auth := flag.String("auth", "", "SOCKS5 authentication (username:password)") auth := flag.String("auth", "", "SOCKS5 authentication (username:password)")
autoConfig := flag.Bool("auto-config", false, "Auto-configure Telegram Desktop on startup")
showVersion := flag.Bool("version", false, "Show version") showVersion := flag.Bool("version", false, "Show version")
flag.Parse() flag.Parse()
@ -89,25 +88,24 @@ func main() {
log.Fatalf("Failed to create server: %v", err) log.Fatalf("Failed to create server: %v", err)
} }
// Auto-configure Telegram Desktop // Auto-configure Telegram Desktop (always attempt on first run)
if *autoConfig { log.Println("Attempting to configure Telegram Desktop...")
log.Println("Attempting to auto-configure Telegram Desktop...") username, password := "", ""
username, password := "", "" if cfg.Auth != "" {
if cfg.Auth != "" { parts := strings.SplitN(cfg.Auth, ":", 2)
parts := strings.SplitN(cfg.Auth, ":", 2) if len(parts) == 2 {
if len(parts) == 2 { username, password = parts[0], parts[1]
username, password = parts[0], parts[1]
}
}
if telegram.ConfigureProxy(cfg.Host, cfg.Port, username, password) {
log.Println("✓ Telegram Desktop proxy configuration opened")
} else {
log.Println("✗ Failed to open Telegram Desktop. Please configure manually.")
log.Println(" Open in browser: tg://socks?server=127.0.0.1&port=1080")
} }
} }
if telegram.ConfigureProxy(cfg.Host, cfg.Port, username, password) {
log.Println("✓ Telegram Desktop proxy configuration opened")
} else {
log.Println("✗ Failed to auto-configure Telegram.")
log.Println(" Manual setup: Settings → Advanced → Connection Type → Proxy")
log.Println(" Or open: tg://socks?server=127.0.0.1&port=1080")
}
// Check for updates (non-blocking) // Check for updates and auto-download (non-blocking)
go func() { go func() {
hasUpdate, latest, url, err := version.CheckUpdate() hasUpdate, latest, url, err := version.CheckUpdate()
if err != nil { if err != nil {
@ -115,7 +113,18 @@ func main() {
} }
if hasUpdate { if hasUpdate {
log.Printf("⚡ NEW VERSION AVAILABLE: v%s (current: v%s)", latest, version.CurrentVersion) log.Printf("⚡ NEW VERSION AVAILABLE: v%s (current: v%s)", latest, version.CurrentVersion)
log.Printf(" Download: %s", url) log.Printf(" Downloading update...")
// Try to download update
downloadedPath, err := version.DownloadUpdate(latest)
if err != nil {
log.Printf(" Download failed: %v", err)
log.Printf(" Manual download: %s", url)
return
}
log.Printf(" ✓ Downloaded to: %s", downloadedPath)
log.Printf(" Restart the proxy to apply update")
} }
}() }()

View File

@ -6,6 +6,9 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"os"
"path/filepath"
"runtime"
"strings" "strings"
"time" "time"
) )
@ -16,10 +19,16 @@ const (
) )
type Release struct { type Release struct {
TagName string `json:"tag_name"` TagName string `json:"tag_name"`
Name string `json:"name"` Name string `json:"name"`
Body string `json:"body"` Body string `json:"body"`
HTMLURL string `json:"html_url"` HTMLURL string `json:"html_url"`
Assets []Asset `json:"assets"`
}
type Asset struct {
Name string `json:"name"`
BrowserDownloadURL string `json:"browser_download_url"`
} }
// CheckUpdate checks for new version on GitHub. // CheckUpdate checks for new version on GitHub.
@ -53,6 +62,85 @@ func CheckUpdate() (bool, string, string, error) {
return false, current, "", nil return false, current, "", nil
} }
// DownloadUpdate downloads the latest version for current platform.
// Returns path to downloaded file or error.
func DownloadUpdate(latestVersion string) (string, error) {
client := &http.Client{Timeout: 30 * time.Second}
resp, err := client.Get(RepoURL)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
var release Release
if err := json.Unmarshal(body, &release); err != nil {
return "", err
}
// Find asset for current platform
assetName := getAssetName()
for _, asset := range release.Assets {
if asset.Name == assetName {
return downloadAsset(client, asset.BrowserDownloadURL, assetName)
}
}
return "", fmt.Errorf("no asset found for %s", runtime.GOOS)
}
func getAssetName() string {
switch runtime.GOOS {
case "windows":
return "TgWsProxy_windows_amd64.exe"
case "linux":
return "TgWsProxy_linux_amd64"
case "darwin":
if runtime.GOARCH == "arm64" {
return "TgWsProxy_darwin_arm64"
}
return "TgWsProxy_darwin_amd64"
default:
return ""
}
}
func downloadAsset(client *http.Client, url, filename string) (string, error) {
resp, err := client.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
// Get executable directory
exe, err := os.Executable()
if err != nil {
return "", err
}
exeDir := filepath.Dir(exe)
// Download to temp file first
tempPath := filepath.Join(exeDir, filename+".new")
out, err := os.Create(tempPath)
if err != nil {
return "", err
}
defer out.Close()
_, err = io.Copy(out, resp.Body)
if err != nil {
os.Remove(tempPath)
return "", err
}
return tempPath, nil
}
// compareVersions compares two semantic versions. // compareVersions compares two semantic versions.
// Returns: 1 if v1 > v2, -1 if v1 < v2, 0 if equal. // Returns: 1 if v1 > v2, -1 if v1 < v2, 0 if equal.
func compareVersions(v1, v2 string) int { func compareVersions(v1, v2 string) int {