forked from lug/matterbridge
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:
145
vendor/github.com/d5/tengo/compiler/symbol_table.go
generated
vendored
Normal file
145
vendor/github.com/d5/tengo/compiler/symbol_table.go
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
package compiler
|
||||
|
||||
// SymbolTable represents a symbol table.
|
||||
type SymbolTable struct {
|
||||
parent *SymbolTable
|
||||
block bool
|
||||
store map[string]*Symbol
|
||||
numDefinition int
|
||||
maxDefinition int
|
||||
freeSymbols []*Symbol
|
||||
}
|
||||
|
||||
// NewSymbolTable creates a SymbolTable.
|
||||
func NewSymbolTable() *SymbolTable {
|
||||
return &SymbolTable{
|
||||
store: make(map[string]*Symbol),
|
||||
}
|
||||
}
|
||||
|
||||
// Define adds a new symbol in the current scope.
|
||||
func (t *SymbolTable) Define(name string) *Symbol {
|
||||
symbol := &Symbol{Name: name, Index: t.nextIndex()}
|
||||
t.numDefinition++
|
||||
|
||||
if t.Parent(true) == nil {
|
||||
symbol.Scope = ScopeGlobal
|
||||
} else {
|
||||
symbol.Scope = ScopeLocal
|
||||
}
|
||||
|
||||
t.store[name] = symbol
|
||||
|
||||
t.updateMaxDefs(symbol.Index + 1)
|
||||
|
||||
return symbol
|
||||
}
|
||||
|
||||
// DefineBuiltin adds a symbol for builtin function.
|
||||
func (t *SymbolTable) DefineBuiltin(index int, name string) *Symbol {
|
||||
symbol := &Symbol{
|
||||
Name: name,
|
||||
Index: index,
|
||||
Scope: ScopeBuiltin,
|
||||
}
|
||||
|
||||
t.store[name] = symbol
|
||||
|
||||
return symbol
|
||||
}
|
||||
|
||||
// Resolve resolves a symbol with a given name.
|
||||
func (t *SymbolTable) Resolve(name string) (symbol *Symbol, depth int, ok bool) {
|
||||
symbol, ok = t.store[name]
|
||||
if !ok && t.parent != nil {
|
||||
symbol, depth, ok = t.parent.Resolve(name)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if !t.block {
|
||||
depth++
|
||||
}
|
||||
|
||||
// if symbol is defined in parent table and if it's not global/builtin
|
||||
// then it's free variable.
|
||||
if !t.block && depth > 0 && symbol.Scope != ScopeGlobal && symbol.Scope != ScopeBuiltin {
|
||||
return t.defineFree(symbol), depth, true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Fork creates a new symbol table for a new scope.
|
||||
func (t *SymbolTable) Fork(block bool) *SymbolTable {
|
||||
return &SymbolTable{
|
||||
store: make(map[string]*Symbol),
|
||||
parent: t,
|
||||
block: block,
|
||||
}
|
||||
}
|
||||
|
||||
// Parent returns the outer scope of the current symbol table.
|
||||
func (t *SymbolTable) Parent(skipBlock bool) *SymbolTable {
|
||||
if skipBlock && t.block {
|
||||
return t.parent.Parent(skipBlock)
|
||||
}
|
||||
|
||||
return t.parent
|
||||
}
|
||||
|
||||
// MaxSymbols returns the total number of symbols defined in the scope.
|
||||
func (t *SymbolTable) MaxSymbols() int {
|
||||
return t.maxDefinition
|
||||
}
|
||||
|
||||
// FreeSymbols returns free symbols for the scope.
|
||||
func (t *SymbolTable) FreeSymbols() []*Symbol {
|
||||
return t.freeSymbols
|
||||
}
|
||||
|
||||
// Names returns the name of all the symbols.
|
||||
func (t *SymbolTable) Names() []string {
|
||||
var names []string
|
||||
for name := range t.store {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
func (t *SymbolTable) nextIndex() int {
|
||||
if t.block {
|
||||
return t.parent.nextIndex() + t.numDefinition
|
||||
}
|
||||
|
||||
return t.numDefinition
|
||||
}
|
||||
|
||||
func (t *SymbolTable) updateMaxDefs(numDefs int) {
|
||||
if numDefs > t.maxDefinition {
|
||||
t.maxDefinition = numDefs
|
||||
}
|
||||
|
||||
if t.block {
|
||||
t.parent.updateMaxDefs(numDefs)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *SymbolTable) defineFree(original *Symbol) *Symbol {
|
||||
// TODO: should we check duplicates?
|
||||
|
||||
t.freeSymbols = append(t.freeSymbols, original)
|
||||
|
||||
symbol := &Symbol{
|
||||
Name: original.Name,
|
||||
Index: len(t.freeSymbols) - 1,
|
||||
Scope: ScopeFree,
|
||||
}
|
||||
|
||||
t.store[original.Name] = symbol
|
||||
|
||||
return symbol
|
||||
}
|
||||
Reference in New Issue
Block a user