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)
]*\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 tryExtractLinks(text string) []string {
aiResponce, err := openrouter.AskOpenRouter(fmt.Sprintf("Ты - умный парсер для веб страниц. Данная страница представляет из себя тестовое задание и тебе нужно проанализировать страницу, найти блок в котором находится задание, и если внутри этого блока есть изображения - достать их и вернуть в виде JSON массива со строками на эти изображения. ВОЗВРАЩАЙ ТОЛЬКО И ТОЛЬКО JSON обьект, БЕЗ КАКИХ ЛИБО ДОПОЛНИТЕЛЬНЫХ СЛОВ, ФРАЗ, СИМВОЛОВ etc. В ФОРМАТЕ {\"images\":[\"test", "test\"]}", string(text)))
if err != nil {
log.Printf("openrouter failed %s", err)
return []string{}
}
log.Println(aiResponce)
return []string{}
}
func DefaultQuestionTestHook(_ *http.Request, html []byte) ([]byte, error) {
switch cheating.DetermineQuestionType(string(html)) {
case cheating.FullTextQuestion:
{
//log.Println(tryExtractLinks(string(html)))
aiResponce, err := openrouter.AskOpenRouter(fmt.Sprintf("прочитай задание и выпиши достаточно подробный список формул/гайд по решению которые могут помочь при решении задач ИЛИ ЕСЛИ МОЖЕШЬ СРАЗУ ДАТЬ ОТВЕТ - ответы списком: %s. пиши без latex обычным читаемым текстом и максимально кратко. учти что это работа за 10 класс российской школы", string(html)))
if err != nil {
log.Printf("openrouter failed %s", err)
return html, nil
}
return []byte(strings.ReplaceAll(string(html), "generated", fmt.Sprintf("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)
}
}