This commit is contained in:
Lain Iwakura 2025-07-12 21:46:10 +03:00
parent 2037c78dd3
commit 98a6500ab8
No known key found for this signature in database
GPG Key ID: C7C18257F2ADC6F8
2 changed files with 84 additions and 14 deletions

2
go.mod
View File

@ -2,4 +2,4 @@ module github.com/cryptexctl/gbio
go 1.24.4 go 1.24.4
require github.com/gorilla/websocket v1.5.3 // indirect require github.com/gorilla/websocket v1.5.3

96
main.go
View File

@ -25,6 +25,53 @@ type KeyPress struct {
Key string `json:"key"` Key string `json:"key"`
} }
type RateLimiter struct {
connections map[string]int
messages map[string]time.Time
mutex sync.RWMutex
}
var limiter = &RateLimiter{
connections: make(map[string]int),
messages: make(map[string]time.Time),
}
var trollingGifBase64 string
var trollingHTML string
var trollingHTMLOnce sync.Once
func (rl *RateLimiter) canConnect(ip string) bool {
rl.mutex.Lock()
defer rl.mutex.Unlock()
if rl.connections[ip] >= 3 {
return false
}
rl.connections[ip]++
return true
}
func (rl *RateLimiter) canSendMessage(ip string) bool {
rl.mutex.Lock()
defer rl.mutex.Unlock()
lastMessage, exists := rl.messages[ip]
if exists && time.Since(lastMessage) < 30*time.Millisecond {
return false
}
rl.messages[ip] = time.Now()
return true
}
func (rl *RateLimiter) disconnect(ip string) {
rl.mutex.Lock()
defer rl.mutex.Unlock()
if rl.connections[ip] > 0 {
rl.connections[ip]--
}
}
type gzipResponseWriter struct { type gzipResponseWriter struct {
io.Writer io.Writer
http.ResponseWriter http.ResponseWriter
@ -50,6 +97,21 @@ func gzipHandler(next http.HandlerFunc) http.HandlerFunc {
} }
func wsHandler(w http.ResponseWriter, r *http.Request) { func wsHandler(w http.ResponseWriter, r *http.Request) {
ip := strings.Split(r.RemoteAddr, ":")[0]
if !limiter.canConnect(ip) {
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Printf("WebSocket upgrade error: %v", err)
return
}
conn.WriteJSON(map[string]string{"action": "show_message", "message": "You make too many requests, yk..."})
conn.Close()
return
}
defer limiter.disconnect(ip)
conn, err := upgrader.Upgrade(w, r, nil) conn, err := upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
log.Printf("WebSocket upgrade error: %v", err) log.Printf("WebSocket upgrade error: %v", err)
@ -67,6 +129,11 @@ func wsHandler(w http.ResponseWriter, r *http.Request) {
break break
} }
if !limiter.canSendMessage(ip) {
conn.WriteJSON(map[string]string{"action": "show_message", "message": "You make too many requests, yk..."})
continue
}
now := time.Now() now := time.Now()
if now.Sub(lastPress) > 5*time.Second { if now.Sub(lastPress) > 5*time.Second {
buffer = "" buffer = ""
@ -140,19 +207,15 @@ func wsHandler(w http.ResponseWriter, r *http.Request) {
} }
} }
func trollingHandler(w http.ResponseWriter, r *http.Request) { func initTrollingHTML() {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("Server", "0BSD_FOR_EVERYONE")
fileContent, err := os.ReadFile("files/trolling.gif") fileContent, err := os.ReadFile("files/trolling.gif")
if err != nil { if err != nil {
log.Printf("Ошибка чтения файла: %v", err) log.Printf("Error reading file: %v", err)
fileContent = []byte("Файл не найден") fileContent = []byte("File not found")
} }
base64Content := base64.StdEncoding.EncodeToString(fileContent) trollingGifBase64 = base64.StdEncoding.EncodeToString(fileContent)
trollingHTML = fmt.Sprintf(`
html := fmt.Sprintf(`
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
@ -177,9 +240,16 @@ func trollingHandler(w http.ResponseWriter, r *http.Request) {
<body> <body>
<img src="data:image/gif;base64,%s" alt="мы делаем небольшой троллинг"> <img src="data:image/gif;base64,%s" alt="мы делаем небольшой троллинг">
</body> </body>
</html>`, base64Content) </html>`, trollingGifBase64)
}
fmt.Fprint(w, html) func trollingHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("Server", "0BSD_FOR_EVERYONE")
w.Header().Set("Cache-Control", "public, max-age=3600")
trollingHTMLOnce.Do(initTrollingHTML)
fmt.Fprint(w, trollingHTML)
} }
func statusHandler(w http.ResponseWriter, r *http.Request) { func statusHandler(w http.ResponseWriter, r *http.Request) {
@ -297,9 +367,9 @@ func main() {
IdleTimeout: 60 * time.Second, IdleTimeout: 60 * time.Second,
} }
log.Printf("Сервер запущен на порту %s", p) log.Printf("Server started on port %s", p)
if err := server.ListenAndServe(); err != nil { if err := server.ListenAndServe(); err != nil {
log.Printf("Ошибка на порту %s: %v", p, err) log.Printf("Error on port %s: %v", p, err)
} }
}(port) }(port)
} }