Clean up processor
This commit is contained in:
@@ -1,35 +1,16 @@
|
|||||||
package processor
|
package processor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/md5"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/antchfx/xmlquery"
|
|
||||||
lua "github.com/yuin/gopher-lua"
|
lua "github.com/yuin/gopher-lua"
|
||||||
|
|
||||||
"modify/logger"
|
"modify/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Processor defines the interface for all file processors
|
// Maybe we make this an interface again for the shits and giggles
|
||||||
type Processor interface {
|
// We will see, it could easily be...
|
||||||
// Process handles processing a file with the given pattern and Lua expression
|
|
||||||
// Now implemented as a base function in processor.go
|
|
||||||
// Process(filename string, pattern string, luaExpr string) (int, int, error)
|
|
||||||
|
|
||||||
// ProcessContent handles processing a string content directly with the given pattern and Lua expression
|
|
||||||
// Returns the modified content, modification count, match count, and any error
|
|
||||||
ProcessContent(content string, pattern string, luaExpr string) (string, int, int, error)
|
|
||||||
|
|
||||||
// ToLua converts processor-specific data to Lua variables
|
|
||||||
ToLua(L *lua.LState, data interface{}) error
|
|
||||||
|
|
||||||
// FromLua retrieves modified data from Lua
|
|
||||||
FromLua(L *lua.LState) (interface{}, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewLuaState() (*lua.LState, error) {
|
func NewLuaState() (*lua.LState, error) {
|
||||||
L := lua.NewState()
|
L := lua.NewState()
|
||||||
@@ -54,166 +35,73 @@ func NewLuaState() (*lua.LState, error) {
|
|||||||
return L, nil
|
return L, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Process(p Processor, filename string, pattern string, luaExpr string) (int, int, error) {
|
// func Process(filename string, pattern string, luaExpr string) (int, int, error) {
|
||||||
logger.Debug("Processing file %q with pattern %q", filename, pattern)
|
// logger.Debug("Processing file %q with pattern %q", filename, pattern)
|
||||||
|
//
|
||||||
// Read file content
|
// // Read file content
|
||||||
cwd, err := os.Getwd()
|
// cwd, err := os.Getwd()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
logger.Error("Failed to get current working directory: %v", err)
|
// logger.Error("Failed to get current working directory: %v", err)
|
||||||
return 0, 0, fmt.Errorf("error getting current working directory: %v", err)
|
// return 0, 0, fmt.Errorf("error getting current working directory: %v", err)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
fullPath := filepath.Join(cwd, filename)
|
// fullPath := filepath.Join(cwd, filename)
|
||||||
logger.Trace("Reading file from: %s", fullPath)
|
// logger.Trace("Reading file from: %s", fullPath)
|
||||||
|
//
|
||||||
stat, err := os.Stat(fullPath)
|
// stat, err := os.Stat(fullPath)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
logger.Error("Failed to stat file %s: %v", fullPath, err)
|
// logger.Error("Failed to stat file %s: %v", fullPath, err)
|
||||||
return 0, 0, fmt.Errorf("error getting file info: %v", err)
|
// return 0, 0, fmt.Errorf("error getting file info: %v", err)
|
||||||
}
|
// }
|
||||||
logger.Debug("File size: %d bytes, modified: %s", stat.Size(), stat.ModTime().Format(time.RFC3339))
|
// logger.Debug("File size: %d bytes, modified: %s", stat.Size(), stat.ModTime().Format(time.RFC3339))
|
||||||
|
//
|
||||||
content, err := os.ReadFile(fullPath)
|
// content, err := os.ReadFile(fullPath)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
logger.Error("Failed to read file %s: %v", fullPath, err)
|
// logger.Error("Failed to read file %s: %v", fullPath, err)
|
||||||
return 0, 0, fmt.Errorf("error reading file: %v", err)
|
// return 0, 0, fmt.Errorf("error reading file: %v", err)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
fileContent := string(content)
|
// fileContent := string(content)
|
||||||
logger.Trace("File read successfully: %d bytes, hash: %x", len(content), md5sum(content))
|
// logger.Trace("File read successfully: %d bytes, hash: %x", len(content), md5sum(content))
|
||||||
|
//
|
||||||
// Detect and log file type
|
// // Detect and log file type
|
||||||
fileType := detectFileType(filename, fileContent)
|
// fileType := detectFileType(filename, fileContent)
|
||||||
if fileType != "" {
|
// if fileType != "" {
|
||||||
logger.Debug("Detected file type: %s", fileType)
|
// logger.Debug("Detected file type: %s", fileType)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
// Process the content
|
// // Process the content
|
||||||
logger.Debug("Starting content processing")
|
// logger.Debug("Starting content processing")
|
||||||
modifiedContent, modCount, matchCount, err := p.ProcessContent(fileContent, pattern, luaExpr)
|
// modifiedContent, modCount, matchCount, err := ProcessContent(fileContent, pattern, luaExpr)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
logger.Error("Processing error: %v", err)
|
// logger.Error("Processing error: %v", err)
|
||||||
return 0, 0, err
|
// return 0, 0, err
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
logger.Debug("Processing results: %d matches, %d modifications", matchCount, modCount)
|
// logger.Debug("Processing results: %d matches, %d modifications", matchCount, modCount)
|
||||||
|
//
|
||||||
// If we made modifications, save the file
|
// // If we made modifications, save the file
|
||||||
if modCount > 0 {
|
// if modCount > 0 {
|
||||||
// Calculate changes summary
|
// // Calculate changes summary
|
||||||
changePercent := float64(len(modifiedContent)) / float64(len(fileContent)) * 100
|
// changePercent := float64(len(modifiedContent)) / float64(len(fileContent)) * 100
|
||||||
logger.Info("File size change: %d → %d bytes (%.1f%%)",
|
// logger.Info("File size change: %d → %d bytes (%.1f%%)",
|
||||||
len(fileContent), len(modifiedContent), changePercent)
|
// len(fileContent), len(modifiedContent), changePercent)
|
||||||
|
//
|
||||||
logger.Debug("Writing modified content to %s", fullPath)
|
// logger.Debug("Writing modified content to %s", fullPath)
|
||||||
err = os.WriteFile(fullPath, []byte(modifiedContent), 0644)
|
// err = os.WriteFile(fullPath, []byte(modifiedContent), 0644)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
logger.Error("Failed to write to file %s: %v", fullPath, err)
|
// logger.Error("Failed to write to file %s: %v", fullPath, err)
|
||||||
return 0, 0, fmt.Errorf("error writing file: %v", err)
|
// return 0, 0, fmt.Errorf("error writing file: %v", err)
|
||||||
}
|
// }
|
||||||
logger.Debug("File written successfully, new hash: %x", md5sum([]byte(modifiedContent)))
|
// logger.Debug("File written successfully, new hash: %x", md5sum([]byte(modifiedContent)))
|
||||||
} else if matchCount > 0 {
|
// } else if matchCount > 0 {
|
||||||
logger.Debug("No content modifications needed for %d matches", matchCount)
|
// logger.Debug("No content modifications needed for %d matches", matchCount)
|
||||||
} else {
|
// } else {
|
||||||
logger.Debug("No matches found in file")
|
// logger.Debug("No matches found in file")
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return modCount, matchCount, nil
|
// return modCount, matchCount, nil
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Helper function to get a short MD5 hash of content for logging
|
|
||||||
func md5sum(data []byte) []byte {
|
|
||||||
h := md5.New()
|
|
||||||
h.Write(data)
|
|
||||||
return h.Sum(nil)[:4] // Just use first 4 bytes for brevity
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function to detect basic file type from extension and content
|
|
||||||
func detectFileType(filename string, content string) string {
|
|
||||||
ext := strings.ToLower(filepath.Ext(filename))
|
|
||||||
|
|
||||||
switch ext {
|
|
||||||
case ".xml":
|
|
||||||
return "XML"
|
|
||||||
case ".json":
|
|
||||||
return "JSON"
|
|
||||||
case ".html", ".htm":
|
|
||||||
return "HTML"
|
|
||||||
case ".txt":
|
|
||||||
return "Text"
|
|
||||||
case ".go":
|
|
||||||
return "Go"
|
|
||||||
case ".js":
|
|
||||||
return "JavaScript"
|
|
||||||
case ".py":
|
|
||||||
return "Python"
|
|
||||||
case ".java":
|
|
||||||
return "Java"
|
|
||||||
case ".c", ".cpp", ".h":
|
|
||||||
return "C/C++"
|
|
||||||
default:
|
|
||||||
// Try content-based detection for common formats
|
|
||||||
if strings.HasPrefix(strings.TrimSpace(content), "<?xml") {
|
|
||||||
return "XML"
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(strings.TrimSpace(content), "{") ||
|
|
||||||
strings.HasPrefix(strings.TrimSpace(content), "[") {
|
|
||||||
return "JSON"
|
|
||||||
}
|
|
||||||
if strings.HasPrefix(strings.TrimSpace(content), "<!DOCTYPE html") ||
|
|
||||||
strings.HasPrefix(strings.TrimSpace(content), "<html") {
|
|
||||||
return "HTML"
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToLua converts a struct or map to a Lua table recursively
|
|
||||||
func ToLua(L *lua.LState, data interface{}) (lua.LValue, error) {
|
|
||||||
switch v := data.(type) {
|
|
||||||
case *xmlquery.Node:
|
|
||||||
luaTable := L.NewTable()
|
|
||||||
luaTable.RawSetString("text", lua.LString(v.Data))
|
|
||||||
// Should be a map, simple key value pairs
|
|
||||||
attr, err := ToLua(L, v.Attr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
luaTable.RawSetString("attr", attr)
|
|
||||||
return luaTable, nil
|
|
||||||
case map[string]interface{}:
|
|
||||||
luaTable := L.NewTable()
|
|
||||||
for key, value := range v {
|
|
||||||
luaValue, err := ToLua(L, value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
luaTable.RawSetString(key, luaValue)
|
|
||||||
}
|
|
||||||
return luaTable, nil
|
|
||||||
case []interface{}:
|
|
||||||
luaTable := L.NewTable()
|
|
||||||
for i, value := range v {
|
|
||||||
luaValue, err := ToLua(L, value)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
luaTable.RawSetInt(i+1, luaValue) // Lua arrays are 1-indexed
|
|
||||||
}
|
|
||||||
return luaTable, nil
|
|
||||||
case string:
|
|
||||||
return lua.LString(v), nil
|
|
||||||
case bool:
|
|
||||||
return lua.LBool(v), nil
|
|
||||||
case float64:
|
|
||||||
return lua.LNumber(v), nil
|
|
||||||
case nil:
|
|
||||||
return lua.LNil, nil
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unsupported data type: %T", data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromLua converts a Lua table to a struct or map recursively
|
// FromLua converts a Lua table to a struct or map recursively
|
||||||
func FromLua(L *lua.LState, luaValue lua.LValue) (interface{}, error) {
|
func FromLua(L *lua.LState, luaValue lua.LValue) (interface{}, error) {
|
||||||
@@ -364,8 +252,6 @@ modified = false
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper utility functions
|
|
||||||
|
|
||||||
// LimitString truncates a string to maxLen and adds "..." if truncated
|
// LimitString truncates a string to maxLen and adds "..." if truncated
|
||||||
func LimitString(s string, maxLen int) string {
|
func LimitString(s string, maxLen int) string {
|
||||||
s = strings.ReplaceAll(s, "\n", "\\n")
|
s = strings.ReplaceAll(s, "\n", "\\n")
|
||||||
@@ -438,19 +324,3 @@ func printToGo(L *lua.LState) int {
|
|||||||
logger.Lua("%s", message)
|
logger.Lua("%s", message)
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Max returns the maximum of two integers
|
|
||||||
func Max(a, b int) int {
|
|
||||||
if a > b {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// Min returns the minimum of two integers
|
|
||||||
func Min(a, b int) int {
|
|
||||||
if a < b {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
@@ -48,11 +48,6 @@ func (p *RegexProcessor) ToLua(L *lua.LState, data interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *RegexProcessor) FromLua(L *lua.LState) (interface{}, error) {
|
|
||||||
// Stub to satisfy interface
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromLua implements the Processor interface for RegexProcessor
|
// FromLua implements the Processor interface for RegexProcessor
|
||||||
func (p *RegexProcessor) FromLuaCustom(L *lua.LState, captureGroups []*CaptureGroup) ([]*CaptureGroup, error) {
|
func (p *RegexProcessor) FromLuaCustom(L *lua.LState, captureGroups []*CaptureGroup) ([]*CaptureGroup, error) {
|
||||||
captureIndex := 0
|
captureIndex := 0
|
||||||
|
Reference in New Issue
Block a user