upd
This commit is contained in:
124
internal/rewrite/html.go
Normal file
124
internal/rewrite/html.go
Normal file
@@ -0,0 +1,124 @@
|
||||
package rewrite
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/flate"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"git.gulenok.ru/greenhaze/gaslight/internal/cheating"
|
||||
"git.gulenok.ru/greenhaze/gaslight/internal/latex"
|
||||
"git.gulenok.ru/greenhaze/gaslight/internal/openrouter"
|
||||
)
|
||||
|
||||
var questionTestDivRe = regexp.MustCompile(`(?is)<div[^>]*\bid\s*=\s*["'][^"']*\bQuestionTest\b[^"']*["'][^>]*>`)
|
||||
|
||||
type HTMLHook func(req *http.Request, html []byte) ([]byte, error)
|
||||
|
||||
type Processor struct {
|
||||
hook HTMLHook
|
||||
}
|
||||
|
||||
func NewProcessor(hook HTMLHook) *Processor {
|
||||
return &Processor{hook: hook}
|
||||
}
|
||||
|
||||
func DefaultQuestionTestHook(_ *http.Request, html []byte) ([]byte, error) {
|
||||
switch cheating.DetermineQuestionType(string(html)) {
|
||||
case cheating.FullTextQuestion:
|
||||
{
|
||||
|
||||
aiResponce, err := openrouter.AskOpenRouter(fmt.Sprintf("РЕШИ ЗАДАНИЕ И ДАЙ МАКСИМАЛЬНО КРАТКИЙ ОТВЕТ: %s", string(html)))
|
||||
if err != nil {
|
||||
log.Printf("openrouter failed %s", err)
|
||||
return html, nil
|
||||
}
|
||||
return []byte(strings.ReplaceAll(string(html), "generated", latex.ConvertLaTeXToASCII(aiResponce))), nil
|
||||
}
|
||||
case cheating.QuestionWithPicture:
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return []byte(strings.ReplaceAll(string(html), "generated", "pwned")), nil
|
||||
}
|
||||
|
||||
func IsHTMLResponse(contentType string) bool {
|
||||
contentType = strings.ToLower(contentType)
|
||||
return strings.Contains(contentType, "text/html") || strings.Contains(contentType, "application/xhtml+xml")
|
||||
}
|
||||
|
||||
func (p *Processor) RewriteIfNeeded(req *http.Request, contentEncoding string, body []byte) ([]byte, error) {
|
||||
decoded, err := decodeBody(contentEncoding, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !questionTestDivRe.Match(decoded) {
|
||||
return body, nil
|
||||
}
|
||||
|
||||
modifiedDecoded, err := p.hook(req, decoded)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodeBody(contentEncoding, modifiedDecoded)
|
||||
}
|
||||
|
||||
func decodeBody(encoding string, body []byte) ([]byte, error) {
|
||||
switch strings.ToLower(strings.TrimSpace(encoding)) {
|
||||
case "", "identity":
|
||||
return body, nil
|
||||
case "gzip":
|
||||
r, err := gzip.NewReader(bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer r.Close()
|
||||
return io.ReadAll(r)
|
||||
case "deflate":
|
||||
r := flate.NewReader(bytes.NewReader(body))
|
||||
defer r.Close()
|
||||
return io.ReadAll(r)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported content-encoding: %s", encoding)
|
||||
}
|
||||
}
|
||||
|
||||
func encodeBody(encoding string, decoded []byte) ([]byte, error) {
|
||||
switch strings.ToLower(strings.TrimSpace(encoding)) {
|
||||
case "", "identity":
|
||||
return decoded, nil
|
||||
case "gzip":
|
||||
var buf bytes.Buffer
|
||||
w := gzip.NewWriter(&buf)
|
||||
if _, err := w.Write(decoded); err != nil {
|
||||
_ = w.Close()
|
||||
return nil, err
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
case "deflate":
|
||||
var buf bytes.Buffer
|
||||
w, err := flate.NewWriter(&buf, flate.DefaultCompression)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := w.Write(decoded); err != nil {
|
||||
_ = w.Close()
|
||||
return nil, err
|
||||
}
|
||||
if err := w.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported content-encoding: %s", encoding)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user