moth

Monarch Of The Hill game server
git clone https://git.woozle.org/neale/moth.git

moth / theme / workspace
Neale Pickett  ·  2024-04-09

python.mjs

 1import * as pyodide from "https://cdn.jsdelivr.net/npm/pyodide@0.25.1/pyodide.mjs" // v0.16.1 known good
 2
 3const HOME = "/home/web_user"
 4
 5async function createInstance() {
 6    let instance = await pyodide.loadPyodide()
 7    instance.runPython("import sys")
 8    self.postMessage({type: "loaded"})
 9    return instance
10}
11const initialized = createInstance()
12
13class Buffer {
14    constructor() {
15        this.buf = []
16    }
17
18    write(s) {
19        this.buf.push(s)
20    }
21
22    value() {
23        return this.buf.join("")
24    }
25}
26
27async function handleMessage(event) {
28    let data = event.data
29    
30    let instance = await initialized
31    let fs = instance._module.FS
32
33    let ret = {
34        result: null,
35        answer: null,
36        stdout: null,
37        stderr: null,
38        traceback: null,
39    }
40
41    switch (data.type) {
42        case "nop":
43            // You might want to do nothing in order to display to the user that a run can now be handled
44            break
45        case "run":
46            let sys = instance.globals.get("sys")
47            sys.stdout = new Buffer()
48            sys.stderr = new Buffer()
49            instance.globals.set("setanswer", (s) => {ret.answer = s})
50
51            try {
52                ret.result = await instance.runPythonAsync(data.code)
53            } catch (err) {
54                ret.traceback = err
55            }
56            ret.stdout = sys.stdout.value()
57            ret.stderr = sys.stderr.value()
58            break
59        case "wget":
60            let url = data.url
61            let dir = data.directory || fs.cwd()
62            let filename = url.split("/").pop()
63            let path = dir + "/" + filename
64
65            if (fs.analyzePath(path).exists) {
66                fs.unlink(path)
67            }
68            fs.createLazyFile(dir, filename, url, true, false)
69            break
70        default:
71            ret.result = "Unknown message type: " + data.type
72            break
73    }
74    if (data.channel) {
75        data.channel.postMessage(ret)
76    }
77}
78self.addEventListener("message", e => handleMessage(e))