Advertisement
Guest User

Untitled

a guest
Jul 22nd, 2017
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 3.75 KB | None | 0 0
  1. package eval
  2.  
  3. import (
  4.     "bytes"
  5.     "encoding/json"
  6.     "errors"
  7.     "fmt"
  8.     "time"
  9.  
  10.     "github.com/Necroforger/Fantasia/system"
  11.     "github.com/Necroforger/dgwidgets"
  12.     "github.com/Necroforger/discordgo"
  13.     "github.com/Necroforger/dream"
  14.     "github.com/robertkrimen/otto"
  15. )
  16.  
  17. var errVMTimeout = errors.New("error: code execution halted for taking too long")
  18.  
  19. // EvalJS ...
  20. func (m *Module) EvalJS(ctx *system.Context) {
  21.     script := ctx.Args.After()
  22.     vm := otto.New()
  23.     b := ctx.Ses
  24.  
  25.     // Dangerous: Gives full access to Command router, discordgo session, tokens etc...
  26.     for _, v := range ctx.System.Config.Admins {
  27.         if v == ctx.Msg.Author.ID {
  28.             evalJSSetFunctions(ctx, vm)
  29.             break
  30.         }
  31.     }
  32.  
  33.     if len(script) != 0 {
  34.         sendResult(ctx, ctx.Msg.ChannelID, evalJSEmbed(vm, script, time.Second*1).MessageEmbed)
  35.         return
  36.     }
  37.  
  38.     b.SendEmbed(ctx.Msg, dream.NewEmbed().
  39.         SetTitle("Entered javascript interpreter").
  40.         SetDescription("Type `exit` to leave"))
  41.     for {
  42.  
  43.         msg := b.NextMessageCreate()
  44.         fmt.Println(msg.Content)
  45.  
  46.         if msg.Author.ID != ctx.Msg.Author.ID {
  47.             continue
  48.         }
  49.  
  50.         if msg.Content == "exit" {
  51.             ctx.ReplyStatus(system.StatusNotify, "Left javascript interpreter")
  52.             return
  53.         }
  54.         chunklen := 1024
  55.         embed := evalJSEmbed(vm, msg.Content, time.Second*1)
  56.         if len(embed.Description) < chunklen {
  57.             b.SendEmbed(msg.ChannelID, embed)
  58.         } else {
  59.             sendResult(ctx, msg.ChannelID, embed.MessageEmbed)
  60.         }
  61.     }
  62. }
  63.  
  64. func sendResult(ctx *system.Context, channelID string, embed *discordgo.MessageEmbed) {
  65.  
  66.     if len(embed.Description) <= 1024 {
  67.         ctx.ReplyEmbed(embed)
  68.     }
  69.  
  70.     p := dgwidgets.NewPaginator(ctx.Ses.DG, channelID)
  71.     p.Add(dgwidgets.EmbedsFromString(embed.Description, 1024)...)
  72.  
  73.     p.Widget.Handle("💾", func(w *dgwidgets.Widget, r *discordgo.MessageReaction) {
  74.         if r.UserID != ctx.Msg.Author.ID {
  75.             return
  76.         }
  77.         if userchan, err := w.Ses.UserChannelCreate(r.UserID); err == nil {
  78.             var content string
  79.             extension := "txt"
  80.             for _, v := range p.Pages {
  81.                 content += v.Description
  82.             }
  83.             var js interface{}
  84.             if err := json.Unmarshal([]byte(content), &js); err == nil {
  85.                 if t, err := json.MarshalIndent(js, "", "\t"); err == nil {
  86.                     content = string(t)
  87.                     extension = "json"
  88.                 }
  89.             }
  90.             w.Ses.ChannelFileSend(userchan.ID, "content."+extension, bytes.NewReader([]byte(content)))
  91.         }
  92.     })
  93.  
  94.     for _, v := range p.Pages {
  95.         v.Color = embed.Color
  96.     }
  97.  
  98.     p.SetPageFooters()
  99.     p.Widget.Timeout = time.Minute * 2
  100.     p.ColourWhenDone = system.StatusWarning
  101.  
  102.     go p.Spawn()
  103. }
  104. func evalJSEmbed(vm *otto.Otto, script string, timeout time.Duration) *dream.Embed {
  105.     embed := dream.NewEmbed()
  106.  
  107.     res, err := evalJS(vm, script, timeout)
  108.  
  109.     if err != nil {
  110.         embed.Description = err.Error()
  111.         embed.Color = system.StatusError
  112.     } else {
  113.         embed.Description = res
  114.         embed.Color = system.StatusSuccess
  115.     }
  116.  
  117.     return embed
  118. }
  119.  
  120. func evalJS(vm *otto.Otto, script string, timeout time.Duration) (result string, err error) {
  121.  
  122.     resChan := make(chan string)
  123.     errChan := make(chan error)
  124.     timeoutChan := make(chan error)
  125.     vm.Interrupt = make(chan func(), 1)
  126.  
  127.     result = "error: timed out"
  128.  
  129.     go func() {
  130.         defer func() {
  131.             if v := recover(); v != nil {
  132.                 if v == errVMTimeout {
  133.                     return
  134.                 }
  135.                 panic(v)
  136.             }
  137.         }()
  138.  
  139.         res, er := vm.Run(script)
  140.         if er != nil {
  141.             errChan <- er
  142.         } else {
  143.             resChan <- res.String()
  144.         }
  145.  
  146.     }()
  147.  
  148.     go func() {
  149.         time.Sleep(timeout)
  150.         timeoutChan <- errVMTimeout
  151.     }()
  152.  
  153.     select {
  154.     case result = <-resChan:
  155.     case err = <-timeoutChan:
  156.         vm.Interrupt <- func() {
  157.             panic(errVMTimeout)
  158.         }
  159.     case err = <-errChan:
  160.     }
  161.  
  162.     return
  163. }
  164.  
  165. func evalJSSetFunctions(ctx *system.Context, vm *otto.Otto) {
  166.     vm.Set("ctx", ctx)
  167.     vm.Run(`function view(data) { return JSON.stringify(data, "", "\t"); }`)
  168. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement