feat: add support for new conversion plan and tool listing in error messages

This commit is contained in:
Daniel Lavrushin 2026-08-08 22:06:21 +02:00 committed by Daniel Lavrushin
parent 4d85344cb8
commit 1f0bfaf8d9
4 changed files with 165 additions and 1 deletions

View file

@ -4786,6 +4786,12 @@
"$ref": "#/definitions/convert.Note"
}
},
"plan": {
"type": "array",
"items": {
"$ref": "#/definitions/convert.SetPlan"
}
},
"sets": {
"type": "array",
"items": {
@ -4821,6 +4827,47 @@
}
}
},
"convert.SetPlan": {
"type": "object",
"properties": {
"accepts_targets": {
"type": "boolean"
},
"domains": {
"type": "array",
"items": {
"type": "string"
}
},
"enabled": {
"type": "boolean"
},
"faking": {
"type": "boolean"
},
"fallback_for": {
"type": "integer"
},
"ips": {
"type": "array",
"items": {
"type": "string"
}
},
"name": {
"type": "string"
},
"profile": {
"type": "integer"
},
"role": {
"type": "string"
},
"strategy": {
"type": "string"
}
}
},
"convert.Status": {
"type": "string",
"enum": [
@ -6080,6 +6127,15 @@
"name_prefix": {
"type": "string"
},
"profile_domains": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
},
"text": {
"type": "string"
},

View file

@ -4786,6 +4786,12 @@
"$ref": "#/definitions/convert.Note"
}
},
"plan": {
"type": "array",
"items": {
"$ref": "#/definitions/convert.SetPlan"
}
},
"sets": {
"type": "array",
"items": {
@ -4821,6 +4827,47 @@
}
}
},
"convert.SetPlan": {
"type": "object",
"properties": {
"accepts_targets": {
"type": "boolean"
},
"domains": {
"type": "array",
"items": {
"type": "string"
}
},
"enabled": {
"type": "boolean"
},
"faking": {
"type": "boolean"
},
"fallback_for": {
"type": "integer"
},
"ips": {
"type": "array",
"items": {
"type": "string"
}
},
"name": {
"type": "string"
},
"profile": {
"type": "integer"
},
"role": {
"type": "string"
},
"strategy": {
"type": "string"
}
}
},
"convert.Status": {
"type": "string",
"enum": [
@ -6080,6 +6127,15 @@
"name_prefix": {
"type": "string"
},
"profile_domains": {
"type": "object",
"additionalProperties": {
"type": "array",
"items": {
"type": "string"
}
}
},
"text": {
"type": "string"
},

View file

@ -5,6 +5,7 @@ import (
"errors"
"net/http"
"strconv"
"strings"
"github.com/daniellavrushin/b4/config"
"github.com/daniellavrushin/b4/convert"
@ -171,13 +172,29 @@ func (api *API) runConvert(req convertRequest) (*convert.Result, error) {
case errors.Is(err, convert.ErrNothingToParse):
return nil, ErrBadRequest("No recognizable options were found in the supplied text")
case errors.Is(err, convert.ErrUnsupportedTool):
return nil, ErrBadRequest("These options belong to a tool b4 cannot convert yet. Only byedpi command lines are supported so far")
return nil, ErrBadRequest("These options belong to a tool b4 cannot convert yet. Supported: " +
supportedToolList())
}
return nil, ErrBadRequest(err.Error())
}
return res, nil
}
func supportedToolList() string {
tools, err := convert.Tools()
if err != nil {
return "none"
}
names := make([]string, 0, len(tools))
for _, t := range tools {
names = append(names, t.Label)
}
if len(names) == 0 {
return "none"
}
return strings.Join(names, ", ")
}
func assignSetIDs(sets []config.SetConfig) []*config.SetConfig {
ids := make(map[string]string, len(sets))
out := make([]*config.SetConfig, 0, len(sets))

View file

@ -143,6 +143,41 @@ func TestAssignSetIDs_DropsDanglingEscalation(t *testing.T) {
}
}
func TestSupportedToolList_NamesEveryRegisteredTool(t *testing.T) {
tools, err := convert.Tools()
if err != nil {
t.Fatal(err)
}
if len(tools) == 0 {
t.Fatal("no tools registered")
}
list := supportedToolList()
for _, x := range tools {
if !strings.Contains(list, x.Label) {
t.Errorf("%q is a supported tool but the message does not name it: %q", x.Label, list)
}
}
}
func TestHandleConvertAnalyze_UnsupportedToolNamesWhatIsSupported(t *testing.T) {
mux := convertAPI(t)
rec := postConvert(t, mux, "/api/convert/analyze",
`{"text":"--dpi-desync=fake --tlsrec=1 --mod-http=h"}`)
if rec.Code != http.StatusBadRequest {
t.Fatalf("got %d (%s), want 400", rec.Code, rec.Body.String())
}
tools, err := convert.Tools()
if err != nil {
t.Fatal(err)
}
for _, x := range tools {
if !strings.Contains(rec.Body.String(), x.Label) {
t.Errorf("error body does not name %q: %s", x.Label, rec.Body.String())
}
}
}
func TestNormalizeDomains(t *testing.T) {
got := normalizeDomains([]string{" YouTube.com ", "https://youtube.com/watch", "", "vk.com:443"})
want := []string{"youtube.com", "vk.com"}