Add initial Azure Functions support, clean up gitignore
This commit is contained in:
parent
dd7bd6b4cc
commit
6bf0537c29
29 changed files with 267 additions and 65 deletions
11
.env.example
11
.env.example
|
@ -43,5 +43,12 @@ TMP_DOMAIN=
|
|||
# Port for serving metrics. Metrics served are compatible with Prometheus.
|
||||
METRICS=
|
||||
|
||||
# Set this to true if you want to use the external image API script, located in api/index.js
|
||||
API=false
|
||||
# The image API type to be used
|
||||
# Set this to `none` to process all images locally
|
||||
# Set this to `ws` if you want to use the external image API script, located in api/index.js
|
||||
# Set this to `azure` to use the Azure Functions API
|
||||
API_TYPE=none
|
||||
# If API_TYPE is `azure`, set this to your Azure webhook URL
|
||||
AZURE_URL=
|
||||
# If API_TYPE is `azure`, set an optional password for webhook responses
|
||||
AZURE_PASS=
|
136
.gitignore
vendored
136
.gitignore
vendored
|
@ -1,42 +1,130 @@
|
|||
cache/
|
||||
build/
|
||||
data/
|
||||
appold.js
|
||||
migrate.js
|
||||
config.json
|
||||
.env
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
lib-cov
|
||||
coverage
|
||||
.nyc_output
|
||||
.grunt
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
build/Release
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
.next
|
||||
.ftpconfig
|
||||
coverage.lcov
|
||||
bannedusers.json
|
||||
*.code-workspace
|
||||
todo.txt
|
||||
.vscode/
|
||||
migratedb.js
|
||||
processed.txt
|
||||
data.sqlite
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Debugging
|
||||
*.heap
|
||||
*.out.*
|
||||
|
||||
# vscode stuff
|
||||
.vscode
|
||||
*.code-workspace
|
||||
|
||||
# Databases
|
||||
data/
|
||||
*.sqlite
|
||||
|
||||
# Azure Functions artifacts
|
||||
bin
|
||||
obj
|
||||
appsettings.json
|
||||
local.settings.json
|
||||
|
||||
# Azurite artifacts
|
||||
__blobstorage__
|
||||
__queuestorage__
|
||||
__azurite_db*__.json
|
|
@ -25,7 +25,7 @@ class InfoCommand extends Command {
|
|||
},
|
||||
{
|
||||
name: "📝 Credits:",
|
||||
value: "Bot by **[Essem](https://essem.space)** and **[various contributors](https://github.com/esmBot/esmBot/graphs/contributors)**\nIcon by **[MintBurrow](https://twitter.com/MintBurrow)**"
|
||||
value: "Bot by **[Essem](https://essem.space)** and **[various contributors](https://github.com/esmBot/esmBot/graphs/contributors)**\nLogo by **[MintBurrow](https://twitter.com/MintBurrow)**"
|
||||
},
|
||||
{
|
||||
name: "💬 Total Servers:",
|
||||
|
|
|
@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
|
||||
class NineGagCommand extends ImageCommand {
|
||||
params = {
|
||||
water: "./assets/images/9gag.png",
|
||||
water: "assets/images/9gag.png",
|
||||
gravity: 6
|
||||
};
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
|
||||
class AVSCommand extends ImageCommand {
|
||||
params = {
|
||||
water: "./assets/images/avs4you.png",
|
||||
water: "assets/images/avs4you.png",
|
||||
gravity: 5,
|
||||
resize: true
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
|
||||
class BandicamCommand extends ImageCommand {
|
||||
params = {
|
||||
water: "./assets/images/bandicam.png",
|
||||
water: "assets/images/bandicam.png",
|
||||
gravity: 2,
|
||||
resize: true
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
|
||||
class DeviantArtCommand extends ImageCommand {
|
||||
params = {
|
||||
water: "./assets/images/deviantart.png",
|
||||
water: "assets/images/deviantart.png",
|
||||
gravity: 5,
|
||||
resize: true
|
||||
};
|
||||
|
|
|
@ -10,14 +10,14 @@ class FlagCommand extends ImageCommand {
|
|||
const text = this.type === "classic" ? this.args[0] : this.options.text;
|
||||
if (!text.match(emojiRegex)) return false;
|
||||
const flag = emoji.unemojify(text).replaceAll(":", "").replace("flag-", "");
|
||||
let path = `./assets/images/region-flags/png/${flag.toUpperCase()}.png`;
|
||||
if (flag === "pirate_flag") path = "./assets/images/pirateflag.png";
|
||||
if (flag === "rainbow-flag") path = "./assets/images/rainbowflag.png";
|
||||
if (flag === "checkered_flag") path = "./assets/images/checkeredflag.png";
|
||||
if (flag === "transgender_flag") path = "./assets/images/transflag.png";
|
||||
if (text === "🏴") path = "./assets/images/region-flags/png/GB-SCT.png";
|
||||
if (text === "🏴") path = "./assets/images/region-flags/png/GB-WLS.png";
|
||||
if (text === "🏴") path = "./assets/images/region-flags/png/GB-ENG.png";
|
||||
let path = `assets/images/region-flags/png/${flag.toUpperCase()}.png`;
|
||||
if (flag === "pirate_flag") path = "assets/images/pirateflag.png";
|
||||
if (flag === "rainbow-flag") path = "assets/images/rainbowflag.png";
|
||||
if (flag === "checkered_flag") path = "assets/images/checkeredflag.png";
|
||||
if (flag === "transgender_flag") path = "assets/images/transflag.png";
|
||||
if (text === "🏴") path = "assets/images/region-flags/png/GB-SCT.png";
|
||||
if (text === "🏴") path = "assets/images/region-flags/png/GB-WLS.png";
|
||||
if (text === "🏴") path = "assets/images/region-flags/png/GB-ENG.png";
|
||||
try {
|
||||
await fs.promises.access(path);
|
||||
this.flagPath = path;
|
||||
|
|
|
@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
|
||||
class FunkyCommand extends ImageCommand {
|
||||
params = {
|
||||
water: "./assets/images/funky.png",
|
||||
water: "assets/images/funky.png",
|
||||
gravity: 3,
|
||||
resize: true
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
|
||||
class HypercamCommand extends ImageCommand {
|
||||
params = {
|
||||
water: "./assets/images/hypercam.png",
|
||||
water: "assets/images/hypercam.png",
|
||||
gravity: 1,
|
||||
resize: true
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
|
||||
class iFunnyCommand extends ImageCommand {
|
||||
params = {
|
||||
water: "./assets/images/ifunny.png",
|
||||
water: "assets/images/ifunny.png",
|
||||
gravity: 8,
|
||||
resize: true,
|
||||
append: true
|
||||
|
|
|
@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
|
||||
class KineMasterCommand extends ImageCommand {
|
||||
params = {
|
||||
water: "./assets/images/kinemaster.png",
|
||||
water: "assets/images/kinemaster.png",
|
||||
gravity: 3,
|
||||
resize: true
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
|
||||
class MemeCenterCommand extends ImageCommand {
|
||||
params = {
|
||||
water: "./assets/images/memecenter.png",
|
||||
water: "assets/images/memecenter.png",
|
||||
gravity: 9,
|
||||
mc: true
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
|
||||
class ShutterstockCommand extends ImageCommand {
|
||||
params = {
|
||||
water: "./assets/images/shutterstock.png",
|
||||
water: "assets/images/shutterstock.png",
|
||||
gravity: 5,
|
||||
resize: true
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
|
||||
class SpeechBubbleCommand extends ImageCommand {
|
||||
params = {
|
||||
water: "./assets/images/speechbubble.png",
|
||||
water: "assets/images/speechbubble.png",
|
||||
gravity: "north",
|
||||
resize: true,
|
||||
yscale: 0.2,
|
||||
|
|
|
@ -15,6 +15,7 @@ Napi::Value Flag(const Napi::CallbackInfo &info) {
|
|||
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
|
||||
string overlay = obj.Get("overlay").As<Napi::String>().Utf8Value();
|
||||
string type = obj.Get("type").As<Napi::String>().Utf8Value();
|
||||
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
|
||||
int delay =
|
||||
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
|
||||
|
||||
|
@ -31,7 +32,8 @@ Napi::Value Flag(const Napi::CallbackInfo &info) {
|
|||
} catch (Magick::Warning &warning) {
|
||||
cerr << "Warning: " << warning.what() << endl;
|
||||
}
|
||||
watermark.read(overlay);
|
||||
string assetPath = basePath + overlay;
|
||||
watermark.read(assetPath);
|
||||
watermark.alphaChannel(Magick::SetAlphaChannel);
|
||||
watermark.evaluate(Magick::AlphaChannel, Magick::MultiplyEvaluateOperator,
|
||||
0.5);
|
||||
|
|
|
@ -14,6 +14,7 @@ Napi::Value Gamexplain(const Napi::CallbackInfo &info) {
|
|||
Napi::Object obj = info[0].As<Napi::Object>();
|
||||
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
|
||||
string type = obj.Get("type").As<Napi::String>().Utf8Value();
|
||||
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
|
||||
int delay =
|
||||
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
|
||||
|
||||
|
@ -30,7 +31,8 @@ Napi::Value Gamexplain(const Napi::CallbackInfo &info) {
|
|||
} catch (Magick::Warning &warning) {
|
||||
cerr << "Warning: " << warning.what() << endl;
|
||||
}
|
||||
watermark.read("./assets/images/gamexplain.png");
|
||||
string assetPath = basePath + "assets/images/gamexplain.png";
|
||||
watermark.read(assetPath);
|
||||
coalesceImages(&coalesced, frames.begin(), frames.end());
|
||||
|
||||
for (Image &image : coalesced) {
|
||||
|
|
|
@ -14,6 +14,7 @@ Napi::Value Globe(const Napi::CallbackInfo &info) {
|
|||
Napi::Object obj = info[0].As<Napi::Object>();
|
||||
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
|
||||
string type = obj.Get("type").As<Napi::String>().Utf8Value();
|
||||
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
|
||||
int delay =
|
||||
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
|
||||
|
||||
|
@ -31,8 +32,8 @@ Napi::Value Globe(const Napi::CallbackInfo &info) {
|
|||
} catch (Magick::Warning &warning) {
|
||||
cerr << "Warning: " << warning.what() << endl;
|
||||
}
|
||||
distort.read("./assets/images/spheremap.png");
|
||||
overlay.read("./assets/images/sphere_overlay.png");
|
||||
distort.read(basePath + "assets/images/spheremap.png");
|
||||
overlay.read(basePath + "assets/images/sphere_overlay.png");
|
||||
coalesceImages(&coalesced, frames.begin(), frames.end());
|
||||
|
||||
if (type != "gif") {
|
||||
|
|
|
@ -12,11 +12,13 @@ Napi::Value Homebrew(const Napi::CallbackInfo &info) {
|
|||
try {
|
||||
Napi::Object obj = info[0].As<Napi::Object>();
|
||||
string caption = obj.Get("caption").As<Napi::String>().Utf8Value();
|
||||
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
|
||||
|
||||
Blob blob;
|
||||
|
||||
Image image;
|
||||
image.read("./assets/images/hbc.png");
|
||||
string assetPath = basePath + "assets/images/hbc.png";
|
||||
image.read(assetPath);
|
||||
image.textGravity(Magick::CenterGravity);
|
||||
image.font("./assets/hbc.ttf");
|
||||
image.textKerning(-5);
|
||||
|
|
|
@ -14,6 +14,7 @@ Napi::Value Reddit(const Napi::CallbackInfo &info) {
|
|||
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
|
||||
string text = obj.Get("caption").As<Napi::String>().Utf8Value();
|
||||
string type = obj.Get("type").As<Napi::String>().Utf8Value();
|
||||
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
|
||||
int delay =
|
||||
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
|
||||
|
||||
|
@ -32,7 +33,7 @@ Napi::Value Reddit(const Napi::CallbackInfo &info) {
|
|||
cerr << "Warning: " << warning.what() << endl;
|
||||
}
|
||||
|
||||
watermark.read("./assets/images/reddit.png");
|
||||
watermark.read(basePath + "assets/images/reddit.png");
|
||||
text_image.textGravity(Magick::WestGravity);
|
||||
text_image.font("Roboto");
|
||||
text_image.fontPointsize(47);
|
||||
|
|
|
@ -14,6 +14,7 @@ Napi::Value Retro(const Napi::CallbackInfo &info) {
|
|||
string line1 = obj.Get("line1").As<Napi::String>().Utf8Value();
|
||||
string line2 = obj.Get("line2").As<Napi::String>().Utf8Value();
|
||||
string line3 = obj.Get("line3").As<Napi::String>().Utf8Value();
|
||||
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
|
||||
|
||||
Blob blob;
|
||||
|
||||
|
@ -22,7 +23,7 @@ Napi::Value Retro(const Napi::CallbackInfo &info) {
|
|||
Image line2_text;
|
||||
Image line3_text;
|
||||
|
||||
image.read("./assets/images/retro.png");
|
||||
image.read(basePath + "assets/images/retro.png");
|
||||
|
||||
line2_text.backgroundColor("none");
|
||||
line2_text.fontPointsize(128);
|
||||
|
|
|
@ -14,6 +14,7 @@ Napi::Value Scott(const Napi::CallbackInfo &info) {
|
|||
Napi::Object obj = info[0].As<Napi::Object>();
|
||||
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
|
||||
string type = obj.Get("type").As<Napi::String>().Utf8Value();
|
||||
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
|
||||
int delay =
|
||||
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
|
||||
|
||||
|
@ -30,7 +31,7 @@ Napi::Value Scott(const Napi::CallbackInfo &info) {
|
|||
} catch (Magick::Warning &warning) {
|
||||
cerr << "Warning: " << warning.what() << endl;
|
||||
}
|
||||
watermark.read("./assets/images/scott.png");
|
||||
watermark.read(basePath + "assets/images/scott.png");
|
||||
coalesceImages(&coalesced, frames.begin(), frames.end());
|
||||
|
||||
for (Image &image : coalesced) {
|
||||
|
|
|
@ -12,6 +12,7 @@ Napi::Value Sonic(const Napi::CallbackInfo &info) {
|
|||
try {
|
||||
Napi::Object obj = info[0].As<Napi::Object>();
|
||||
string text = obj.Get("text").As<Napi::String>().Utf8Value();
|
||||
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
|
||||
|
||||
Blob blob;
|
||||
|
||||
|
@ -24,7 +25,7 @@ Napi::Value Sonic(const Napi::CallbackInfo &info) {
|
|||
text_image.read("pango:<span foreground='white'>" + text + "</span>");
|
||||
text_image.resize(Geometry(474, 332));
|
||||
text_image.extent(Geometry("1024x538-435-145"), Magick::CenterGravity);
|
||||
image.read("./assets/images/sonic.jpg");
|
||||
image.read(basePath + "assets/images/sonic.jpg");
|
||||
image.composite(text_image, Geometry("+160+10"), Magick::OverCompositeOp);
|
||||
image.magick("PNG");
|
||||
image.write(&blob);
|
||||
|
|
|
@ -26,6 +26,7 @@ Napi::Value Watermark(const Napi::CallbackInfo &info) {
|
|||
? obj.Get("append").As<Napi::Boolean>().Value()
|
||||
: false;
|
||||
bool mc = obj.Has("mc") ? obj.Get("mc").As<Napi::Boolean>().Value() : false;
|
||||
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
|
||||
string type = obj.Get("type").As<Napi::String>().Utf8Value();
|
||||
int delay =
|
||||
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
|
||||
|
@ -43,7 +44,8 @@ Napi::Value Watermark(const Napi::CallbackInfo &info) {
|
|||
} catch (Magick::Warning &warning) {
|
||||
cerr << "Warning: " << warning.what() << endl;
|
||||
}
|
||||
watermark.read(water);
|
||||
string merged = basePath + water;
|
||||
watermark.read(merged);
|
||||
if (resize && append) {
|
||||
string query(to_string(frames.front().baseColumns()) + "x");
|
||||
watermark.scale(Geometry(query));
|
||||
|
|
|
@ -14,6 +14,7 @@ Napi::Value Wdt(const Napi::CallbackInfo &info) {
|
|||
Napi::Object obj = info[0].As<Napi::Object>();
|
||||
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
|
||||
string type = obj.Get("type").As<Napi::String>().Utf8Value();
|
||||
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
|
||||
int delay =
|
||||
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
|
||||
|
||||
|
@ -30,7 +31,7 @@ Napi::Value Wdt(const Napi::CallbackInfo &info) {
|
|||
} catch (Magick::Warning &warning) {
|
||||
cerr << "Warning: " << warning.what() << endl;
|
||||
}
|
||||
watermark.read("./assets/images/whodidthis.png");
|
||||
watermark.read(basePath + "assets/images/whodidthis.png");
|
||||
coalesceImages(&coalesced, frames.begin(), frames.end());
|
||||
|
||||
for (Image &image : coalesced) {
|
||||
|
|
|
@ -13,6 +13,7 @@ Napi::Value Zamn(const Napi::CallbackInfo &info) {
|
|||
Napi::Object obj = info[0].As<Napi::Object>();
|
||||
Napi::Buffer<char> data = obj.Get("data").As<Napi::Buffer<char>>();
|
||||
string type = obj.Get("type").As<Napi::String>().Utf8Value();
|
||||
string basePath = obj.Get("basePath").As<Napi::String>().Utf8Value();
|
||||
int delay =
|
||||
obj.Has("delay") ? obj.Get("delay").As<Napi::Number>().Int32Value() : 0;
|
||||
|
||||
|
@ -23,7 +24,7 @@ Napi::Value Zamn(const Napi::CallbackInfo &info) {
|
|||
list<Image> mid;
|
||||
Image watermark;
|
||||
readImages(&frames, Blob(data.Data(), data.Length()));
|
||||
watermark.read("./assets/images/zamn.png");
|
||||
watermark.read(basePath + "assets/images/zamn.png");
|
||||
coalesceImages(&coalesced, frames.begin(), frames.end());
|
||||
|
||||
for (Image &image : coalesced) {
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import { createRequire } from "module";
|
||||
import { isMainThread, parentPort, workerData } from "worker_threads";
|
||||
import fetch from "node-fetch";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const nodeRequire = createRequire(import.meta.url);
|
||||
|
||||
const magick = nodeRequire(`../build/${process.env.DEBUG && process.env.DEBUG === "true" ? "Debug" : "Release"}/image.node`);
|
||||
const relPath = `../build/${process.env.DEBUG && process.env.DEBUG === "true" ? "Debug" : "Release"}/image.node`;
|
||||
const magick = nodeRequire(relPath);
|
||||
|
||||
const enumMap = {
|
||||
"forget": 0,
|
||||
|
@ -42,6 +45,7 @@ export default function run(object) {
|
|||
objectWithFixedType.gravity = enumMap[objectWithFixedType.gravity];
|
||||
}
|
||||
}
|
||||
objectWithFixedType.basePath = path.join(path.dirname(fileURLToPath(import.meta.url)), "../");
|
||||
try {
|
||||
const result = magick[object.cmd](objectWithFixedType);
|
||||
const returnObject = {
|
||||
|
|
|
@ -5,6 +5,9 @@ import path from "path";
|
|||
import { fileURLToPath } from "url";
|
||||
import { Worker } from "worker_threads";
|
||||
import { createRequire } from "module";
|
||||
import { createServer } from "http";
|
||||
import fetch from "node-fetch";
|
||||
import EventEmitter from "events";
|
||||
|
||||
// only requiring this to work around an issue regarding worker threads
|
||||
const nodeRequire = createRequire(import.meta.url);
|
||||
|
@ -18,11 +21,14 @@ class ImageWorker extends BaseServiceWorker {
|
|||
|
||||
console.info = (str) => this.ipc.sendToAdmiral("info", str);
|
||||
|
||||
if (process.env.API === "true") {
|
||||
this.jobs = {};
|
||||
if (process.env.API_TYPE === "ws") {
|
||||
this.connections = new Map();
|
||||
this.servers = JSON.parse(fs.readFileSync(new URL("../../servers.json", import.meta.url), { encoding: "utf8" })).image;
|
||||
this.nextID = 0;
|
||||
} else if (process.env.API_TYPE === "azure") {
|
||||
this.jobs = new Map();
|
||||
this.webhook = createServer();
|
||||
this.port = parseInt(process.env.WEBHOOK_PORT) || 3763;
|
||||
}
|
||||
|
||||
this.begin().then(() => this.serviceReady());
|
||||
|
@ -30,7 +36,7 @@ class ImageWorker extends BaseServiceWorker {
|
|||
|
||||
async begin() {
|
||||
// connect to image api if enabled
|
||||
if (process.env.API === "true") {
|
||||
if (process.env.API_TYPE === "ws") {
|
||||
for (const server of this.servers) {
|
||||
try {
|
||||
await this.connect(server.server, server.auth);
|
||||
|
@ -38,6 +44,73 @@ class ImageWorker extends BaseServiceWorker {
|
|||
logger.error(e);
|
||||
}
|
||||
}
|
||||
} else if (process.env.API_TYPE === "azure") {
|
||||
this.webhook.on("request", async (req, res) => {
|
||||
if (req.method !== "POST") {
|
||||
res.statusCode = 405;
|
||||
return res.end("405 Method Not Allowed");
|
||||
}
|
||||
if (process.env.AZURE_PASS && req.headers.authorization !== process.env.AZURE_PASS) {
|
||||
res.statusCode = 401;
|
||||
return res.end("401 Unauthorized");
|
||||
}
|
||||
const reqUrl = new URL(req.url, `http://${req.headers.host}`);
|
||||
if (reqUrl.pathname === "/callback") {
|
||||
try {
|
||||
const chunks = [];
|
||||
req.on("data", (data) => {
|
||||
chunks.push(data);
|
||||
});
|
||||
req.once("end", () => {
|
||||
if (this.jobs.has(req.headers["x-azure-id"])) {
|
||||
try {
|
||||
const error = JSON.parse(Buffer.concat(chunks).toString());
|
||||
if (error.error) this.jobs.get(req.headers["x-azure-id"]).emit("error", new Error(error.message));
|
||||
} catch {
|
||||
// no-op
|
||||
}
|
||||
const contentType = req.headers["content-type"];
|
||||
let type;
|
||||
switch (contentType) {
|
||||
case "image/gif":
|
||||
type = "gif";
|
||||
break;
|
||||
case "image/png":
|
||||
type = "png";
|
||||
break;
|
||||
case "image/jpeg":
|
||||
type = "jpg";
|
||||
break;
|
||||
case "image/webp":
|
||||
type = "webp";
|
||||
break;
|
||||
default:
|
||||
type = contentType;
|
||||
break;
|
||||
}
|
||||
this.jobs.get(req.headers["x-azure-id"]).emit("image", { buffer: Buffer.concat(chunks), type });
|
||||
return res.end("OK");
|
||||
} else {
|
||||
res.statusCode = 409;
|
||||
return res.end("409 Conflict");
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
logger.error("An error occurred while processing a webhook request: ", e);
|
||||
res.statusCode = 500;
|
||||
return res.end("500 Internal Server Error");
|
||||
}
|
||||
} else {
|
||||
res.statusCode = 404;
|
||||
return res.end("404 Not Found");
|
||||
}
|
||||
});
|
||||
this.webhook.on("error", (e) => {
|
||||
logger.error("An error occurred on the Azure webhook: ", e);
|
||||
});
|
||||
this.webhook.listen(this.port, () => {
|
||||
logger.log(`Azure HTTP webhook listening on port ${this.port}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +122,7 @@ class ImageWorker extends BaseServiceWorker {
|
|||
|
||||
async getRunning() {
|
||||
const statuses = [];
|
||||
if (process.env.API === "true") {
|
||||
if (process.env.API_TYPE === "ws") {
|
||||
for (const [address, connection] of this.connections) {
|
||||
if (connection.conn.readyState !== 0 && connection.conn.readyState !== 1) {
|
||||
continue;
|
||||
|
@ -115,8 +188,17 @@ class ImageWorker extends BaseServiceWorker {
|
|||
});
|
||||
}
|
||||
|
||||
waitForAzure(event) {
|
||||
return new Promise((resolve, reject) => {
|
||||
event.once("image", (data) => {
|
||||
resolve(data);
|
||||
});
|
||||
event.once("error", reject);
|
||||
});
|
||||
}
|
||||
|
||||
async run(object) {
|
||||
if (process.env.API === "true") {
|
||||
if (process.env.API_TYPE === "ws") {
|
||||
let num = this.nextID++;
|
||||
if (num > 4294967295) num = this.nextID = 0;
|
||||
for (let i = 0; i < 3; i++) {
|
||||
|
@ -135,6 +217,12 @@ class ImageWorker extends BaseServiceWorker {
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if (process.env.API_TYPE === "azure") {
|
||||
object.callback = `${process.env.AZURE_CALLBACK_URL}:${this.port}/callback`;
|
||||
const response = await fetch(`${process.env.AZURE_URL}/api/orchestrators/ImageOrchestrator`, { method: "POST", body: JSON.stringify(object) }).then(r => r.json());
|
||||
const event = new EventEmitter();
|
||||
this.jobs.set(response.id, event);
|
||||
return await this.waitForAzure(event);
|
||||
} else {
|
||||
// Called from command (not using image API)
|
||||
const worker = new Worker(path.join(path.dirname(fileURLToPath(import.meta.url)), "../image-runner.js"), {
|
||||
|
|
|
@ -22,7 +22,7 @@ class PrometheusWorker extends BaseServiceWorker {
|
|||
# HELP esmbot_shard_count Number of shards the bot has
|
||||
# TYPE esmbot_shard_count gauge
|
||||
`);
|
||||
if (process.env.API === "true") {
|
||||
if (process.env.API_TYPE === "ws") {
|
||||
const servers = await this.ipc.serviceCommand("image", { type: "stats" }, true);
|
||||
res.write(`# HELP esmbot_connected_workers Number of workers connected
|
||||
# TYPE esmbot_connected_workers gauge
|
||||
|
|
Loading…
Reference in a new issue