mirror of
https://github.com/projectdiscovery/nuclei.git
synced 2025-12-18 20:35:24 +00:00
158 lines
3.9 KiB
Go
158 lines
3.9 KiB
Go
|
|
package main
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bytes"
|
||
|
|
"context"
|
||
|
|
"flag"
|
||
|
|
"fmt"
|
||
|
|
"go/ast"
|
||
|
|
"go/parser"
|
||
|
|
"go/token"
|
||
|
|
"log"
|
||
|
|
"os"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
filutil "github.com/projectdiscovery/utils/file"
|
||
|
|
"github.com/sashabaranov/go-openai"
|
||
|
|
)
|
||
|
|
|
||
|
|
var sysprompt = `
|
||
|
|
data present after ---raw data--- contains raw data extracted by a parser and contains information about function
|
||
|
|
--- example ---
|
||
|
|
Name: log
|
||
|
|
Signatures: "log(msg string)"
|
||
|
|
Signatures: "log(msg map[string]interface{})"
|
||
|
|
Description: log prints given input to stdout with [JS] prefix for debugging purposes
|
||
|
|
--- end example ---
|
||
|
|
Here Name is name of function , signature[s] is actual function declaration and description is description of function
|
||
|
|
using this data for every such function generate a abstract implementation of function in javascript along with jsdoc annotations
|
||
|
|
--- example expected output---
|
||
|
|
/**
|
||
|
|
* log prints given input to stdout with [JS] prefix for debugging purposes
|
||
|
|
* log(msg string)
|
||
|
|
* log(msg map[string]interface{})
|
||
|
|
* @function
|
||
|
|
* @param {string} msg - The message to print.
|
||
|
|
*/
|
||
|
|
function log(msg) {
|
||
|
|
// implemented in go
|
||
|
|
};
|
||
|
|
--- instructions ---
|
||
|
|
ACT as helpful coding assistant and do the same for all functions present in data
|
||
|
|
`
|
||
|
|
|
||
|
|
const userPrompt = `
|
||
|
|
---raw data---
|
||
|
|
{{source}}
|
||
|
|
---new javascript---
|
||
|
|
`
|
||
|
|
|
||
|
|
var (
|
||
|
|
dir string
|
||
|
|
key string
|
||
|
|
keyfile string
|
||
|
|
out string
|
||
|
|
)
|
||
|
|
|
||
|
|
func main() {
|
||
|
|
flag.StringVar(&dir, "dir", "pkg/js/global", "directory to process")
|
||
|
|
flag.StringVar(&key, "key", "", "openai api key")
|
||
|
|
flag.StringVar(&keyfile, "keyfile", "", "openai api key file")
|
||
|
|
flag.StringVar(&out, "out", "", "output js file with declarations of all global functions")
|
||
|
|
flag.Parse()
|
||
|
|
|
||
|
|
finalKey := ""
|
||
|
|
if key != "" {
|
||
|
|
key = finalKey
|
||
|
|
}
|
||
|
|
if keyfile != "" && filutil.FileExists(keyfile) {
|
||
|
|
data, err := os.ReadFile(keyfile)
|
||
|
|
if err != nil {
|
||
|
|
log.Fatal(err)
|
||
|
|
}
|
||
|
|
finalKey = string(data)
|
||
|
|
}
|
||
|
|
if key := os.Getenv("OPENAI_API_KEY"); key != "" {
|
||
|
|
finalKey = key
|
||
|
|
}
|
||
|
|
|
||
|
|
if finalKey == "" {
|
||
|
|
log.Fatal("openai api key is not set")
|
||
|
|
}
|
||
|
|
llm := openai.NewClient(finalKey)
|
||
|
|
var buff bytes.Buffer
|
||
|
|
|
||
|
|
fset := token.NewFileSet()
|
||
|
|
pkgs, err := parser.ParseDir(fset, dir, nil, 0)
|
||
|
|
if err != nil {
|
||
|
|
fmt.Println(err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, pkg := range pkgs {
|
||
|
|
for _, file := range pkg.Files {
|
||
|
|
ast.Inspect(file, func(n ast.Node) bool {
|
||
|
|
switch x := n.(type) {
|
||
|
|
case *ast.CallExpr:
|
||
|
|
if sel, ok := x.Fun.(*ast.SelectorExpr); ok {
|
||
|
|
if sel.Sel.Name == "RegisterFuncWithSignature" {
|
||
|
|
for _, arg := range x.Args {
|
||
|
|
if kv, ok := arg.(*ast.CompositeLit); ok {
|
||
|
|
for _, elt := range kv.Elts {
|
||
|
|
if kv, ok := elt.(*ast.KeyValueExpr); ok {
|
||
|
|
key := kv.Key.(*ast.Ident).Name
|
||
|
|
switch key {
|
||
|
|
case "Name", "Description":
|
||
|
|
buff.WriteString(fmt.Sprintf("%s: %s\n", key, strings.Trim(kv.Value.(*ast.BasicLit).Value, `"`)))
|
||
|
|
case "Signatures":
|
||
|
|
if comp, ok := kv.Value.(*ast.CompositeLit); ok {
|
||
|
|
for _, signature := range comp.Elts {
|
||
|
|
buff.WriteString(fmt.Sprintf("%s: %s\n", key, signature.(*ast.BasicLit).Value))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
buff.WriteString("\n")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return true
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fmt.Printf("[+] Scraped %d functions\n\n", strings.Count(buff.String(), "Name:"))
|
||
|
|
fmt.Println(buff.String())
|
||
|
|
|
||
|
|
fmt.Printf("[+] Generating jsdoc for all functions\n\n")
|
||
|
|
resp, err := llm.CreateChatCompletion(context.TODO(), openai.ChatCompletionRequest{
|
||
|
|
Model: "gpt-4",
|
||
|
|
Messages: []openai.ChatCompletionMessage{
|
||
|
|
{Role: "system", Content: sysprompt},
|
||
|
|
{Role: "user", Content: strings.ReplaceAll(userPrompt, "{{source}}", buff.String())},
|
||
|
|
},
|
||
|
|
Temperature: 0.1,
|
||
|
|
})
|
||
|
|
if err != nil {
|
||
|
|
fmt.Println(err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
if len(resp.Choices) == 0 {
|
||
|
|
fmt.Println("no choices returned")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
data := resp.Choices[0].Message.Content
|
||
|
|
|
||
|
|
fmt.Println(data)
|
||
|
|
|
||
|
|
if out != "" {
|
||
|
|
if err := os.WriteFile(out, []byte(data), 0600); err != nil {
|
||
|
|
fmt.Println(err)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|