diff options
author | Wim <wim@42.be> | 2019-02-23 16:39:44 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-23 16:39:44 +0100 |
commit | 1bb39eba8717f62336cc98c5bb7cfbef194f3626 (patch) | |
tree | 0437ae89473b8e25ad1c9597e1049a23a7933f6a /vendor/github.com/d5/tengo/compiler/bytecode.go | |
parent | 3190703dc8618896c932a23d8ca155fbbf6fab13 (diff) | |
download | matterbridge-msglm-1bb39eba8717f62336cc98c5bb7cfbef194f3626.tar.gz matterbridge-msglm-1bb39eba8717f62336cc98c5bb7cfbef194f3626.tar.bz2 matterbridge-msglm-1bb39eba8717f62336cc98c5bb7cfbef194f3626.zip |
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
Diffstat (limited to 'vendor/github.com/d5/tengo/compiler/bytecode.go')
-rw-r--r-- | vendor/github.com/d5/tengo/compiler/bytecode.go | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/vendor/github.com/d5/tengo/compiler/bytecode.go b/vendor/github.com/d5/tengo/compiler/bytecode.go new file mode 100644 index 00000000..42527731 --- /dev/null +++ b/vendor/github.com/d5/tengo/compiler/bytecode.go @@ -0,0 +1,134 @@ +package compiler + +import ( + "encoding/gob" + "fmt" + "io" + "reflect" + + "github.com/d5/tengo/compiler/source" + "github.com/d5/tengo/objects" +) + +// Bytecode is a compiled instructions and constants. +type Bytecode struct { + FileSet *source.FileSet + MainFunction *objects.CompiledFunction + Constants []objects.Object +} + +// Decode reads Bytecode data from the reader. +func (b *Bytecode) Decode(r io.Reader) error { + dec := gob.NewDecoder(r) + + if err := dec.Decode(&b.FileSet); err != nil { + return err + } + // TODO: files in b.FileSet.File does not have their 'set' field properly set to b.FileSet + // as it's private field and not serialized by gob encoder/decoder. + + if err := dec.Decode(&b.MainFunction); err != nil { + return err + } + + if err := dec.Decode(&b.Constants); err != nil { + return err + } + + // replace Bool and Undefined with known value + for i, v := range b.Constants { + b.Constants[i] = cleanupObjects(v) + } + + return nil +} + +// Encode writes Bytecode data to the writer. +func (b *Bytecode) Encode(w io.Writer) error { + enc := gob.NewEncoder(w) + + if err := enc.Encode(b.FileSet); err != nil { + return err + } + + if err := enc.Encode(b.MainFunction); err != nil { + return err + } + + // constants + return enc.Encode(b.Constants) +} + +// FormatInstructions returns human readable string representations of +// compiled instructions. +func (b *Bytecode) FormatInstructions() []string { + return FormatInstructions(b.MainFunction.Instructions, 0) +} + +// FormatConstants returns human readable string representations of +// compiled constants. +func (b *Bytecode) FormatConstants() (output []string) { + for cidx, cn := range b.Constants { + switch cn := cn.(type) { + case *objects.CompiledFunction: + output = append(output, fmt.Sprintf("[% 3d] (Compiled Function|%p)", cidx, &cn)) + for _, l := range FormatInstructions(cn.Instructions, 0) { + output = append(output, fmt.Sprintf(" %s", l)) + } + default: + output = append(output, fmt.Sprintf("[% 3d] %s (%s|%p)", cidx, cn, reflect.TypeOf(cn).Elem().Name(), &cn)) + } + } + + return +} + +func cleanupObjects(o objects.Object) objects.Object { + switch o := o.(type) { + case *objects.Bool: + if o.IsFalsy() { + return objects.FalseValue + } + return objects.TrueValue + case *objects.Undefined: + return objects.UndefinedValue + case *objects.Array: + for i, v := range o.Value { + o.Value[i] = cleanupObjects(v) + } + case *objects.Map: + for k, v := range o.Value { + o.Value[k] = cleanupObjects(v) + } + } + + return o +} + +func init() { + gob.Register(&source.FileSet{}) + gob.Register(&source.File{}) + gob.Register(&objects.Array{}) + gob.Register(&objects.ArrayIterator{}) + gob.Register(&objects.Bool{}) + gob.Register(&objects.Break{}) + gob.Register(&objects.BuiltinFunction{}) + gob.Register(&objects.Bytes{}) + gob.Register(&objects.Char{}) + gob.Register(&objects.Closure{}) + gob.Register(&objects.CompiledFunction{}) + gob.Register(&objects.Continue{}) + gob.Register(&objects.Error{}) + gob.Register(&objects.Float{}) + gob.Register(&objects.ImmutableArray{}) + gob.Register(&objects.ImmutableMap{}) + gob.Register(&objects.Int{}) + gob.Register(&objects.Map{}) + gob.Register(&objects.MapIterator{}) + gob.Register(&objects.ReturnValue{}) + gob.Register(&objects.String{}) + gob.Register(&objects.StringIterator{}) + gob.Register(&objects.Time{}) + gob.Register(&objects.Undefined{}) + gob.Register(&objects.UserFunction{}) +} |