mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-07-02 00:06:19 +00:00
Add scripting (tengo) support for every incoming message (#731)
TengoModifyMessage allows you to specify the location of a tengo (https://github.com/d5/tengo/) script. This script will receive every incoming message and can be used to modify the Username and the Text of that message. The script will have the following global variables: to modify: msgUsername and msgText to read: msgChannel and msgAccount The script is reloaded on every message, so you can modify the script on the fly. Example script can be found in https://github.com/42wim/matterbridge/tree/master/gateway/bench.tengo and https://github.com/42wim/matterbridge/tree/master/contrib/example.tengo The example below will check if the text contains blah and if so, it'll replace the text and the username of that message. text := import("text") if text.re_match("blah",msgText) { msgText="replaced by this" msgUsername="fakeuser" } More information about tengo on: https://github.com/d5/tengo/blob/master/docs/tutorial.md and https://github.com/d5/tengo/blob/master/docs/stdlib.md
This commit is contained in:
123
vendor/github.com/d5/tengo/compiler/compiler_module.go
generated
vendored
Normal file
123
vendor/github.com/d5/tengo/compiler/compiler_module.go
generated
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
package compiler
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/d5/tengo/compiler/ast"
|
||||
"github.com/d5/tengo/compiler/parser"
|
||||
"github.com/d5/tengo/objects"
|
||||
)
|
||||
|
||||
func (c *Compiler) compileModule(expr *ast.ImportExpr) (*objects.CompiledFunction, error) {
|
||||
compiledModule, exists := c.loadCompiledModule(expr.ModuleName)
|
||||
if exists {
|
||||
return compiledModule, nil
|
||||
}
|
||||
|
||||
moduleName := expr.ModuleName
|
||||
|
||||
// read module source from loader
|
||||
var moduleSrc []byte
|
||||
if c.moduleLoader == nil {
|
||||
// default loader: read from local file
|
||||
if !strings.HasSuffix(moduleName, ".tengo") {
|
||||
moduleName += ".tengo"
|
||||
}
|
||||
|
||||
if err := c.checkCyclicImports(expr, moduleName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var err error
|
||||
moduleSrc, err = ioutil.ReadFile(moduleName)
|
||||
if err != nil {
|
||||
return nil, c.errorf(expr, "module file read error: %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
if err := c.checkCyclicImports(expr, moduleName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var err error
|
||||
moduleSrc, err = c.moduleLoader(moduleName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
compiledModule, err := c.doCompileModule(moduleName, moduleSrc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.storeCompiledModule(moduleName, compiledModule)
|
||||
|
||||
return compiledModule, nil
|
||||
}
|
||||
|
||||
func (c *Compiler) checkCyclicImports(node ast.Node, moduleName string) error {
|
||||
if c.moduleName == moduleName {
|
||||
return c.errorf(node, "cyclic module import: %s", moduleName)
|
||||
} else if c.parent != nil {
|
||||
return c.parent.checkCyclicImports(node, moduleName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Compiler) doCompileModule(moduleName string, src []byte) (*objects.CompiledFunction, error) {
|
||||
modFile := c.file.Set().AddFile(moduleName, -1, len(src))
|
||||
p := parser.NewParser(modFile, src, nil)
|
||||
file, err := p.ParseFile()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
symbolTable := NewSymbolTable()
|
||||
|
||||
// inherit builtin functions
|
||||
for idx, fn := range objects.Builtins {
|
||||
s, _, ok := c.symbolTable.Resolve(fn.Name)
|
||||
if ok && s.Scope == ScopeBuiltin {
|
||||
symbolTable.DefineBuiltin(idx, fn.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// no global scope for the module
|
||||
symbolTable = symbolTable.Fork(false)
|
||||
|
||||
// compile module
|
||||
moduleCompiler := c.fork(modFile, moduleName, symbolTable)
|
||||
if err := moduleCompiler.Compile(file); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// add OpReturn (== export undefined) if export is missing
|
||||
if !moduleCompiler.lastInstructionIs(OpReturnValue) {
|
||||
moduleCompiler.emit(nil, OpReturn)
|
||||
}
|
||||
|
||||
compiledFunc := moduleCompiler.Bytecode().MainFunction
|
||||
compiledFunc.NumLocals = symbolTable.MaxSymbols()
|
||||
|
||||
return compiledFunc, nil
|
||||
}
|
||||
|
||||
func (c *Compiler) loadCompiledModule(moduleName string) (mod *objects.CompiledFunction, ok bool) {
|
||||
if c.parent != nil {
|
||||
return c.parent.loadCompiledModule(moduleName)
|
||||
}
|
||||
|
||||
mod, ok = c.compiledModules[moduleName]
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Compiler) storeCompiledModule(moduleName string, module *objects.CompiledFunction) {
|
||||
if c.parent != nil {
|
||||
c.parent.storeCompiledModule(moduleName, module)
|
||||
}
|
||||
|
||||
c.compiledModules[moduleName] = module
|
||||
}
|
Reference in New Issue
Block a user