Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embedded javascript plugins #1393

Merged
merged 9 commits into from
May 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ require (
github.com/mattn/go-sqlite3 v1.14.6
github.com/natefinch/pie v0.0.0-20170715172608-9a0d72014007
github.com/remeh/sizedwaitgroup v1.0.0
github.com/robertkrimen/otto v0.0.0-20200922221731-ef014fd054ac
github.com/rs/cors v1.6.0
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f
github.com/sirupsen/logrus v1.4.2
Expand All @@ -38,6 +39,7 @@ require (
golang.org/x/net v0.0.0-20200822124328-c89045814202
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd
golang.org/x/tools v0.0.0-20200915031644-64986481280e // indirect
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/yaml.v2 v2.3.0
)

Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,8 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E=
github.com/remeh/sizedwaitgroup v1.0.0/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo=
github.com/robertkrimen/otto v0.0.0-20200922221731-ef014fd054ac h1:kYPjbEN6YPYWWHI6ky1J813KzIq/8+Wg4TO4xU7A/KU=
github.com/robertkrimen/otto v0.0.0-20200922221731-ef014fd054ac/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.0.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.1.0 h1:g0fH8RicVgNl+zVZDCDfbdWxAWoAEJyI7I3TZYXFiig=
Expand Down Expand Up @@ -1084,6 +1086,8 @@ gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/mail.v2 v2.0.0-20180731213649-a0242b2233b4/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
Expand Down
3 changes: 3 additions & 0 deletions pkg/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ func Start() {

gqlHandler := handler.GraphQL(models.NewExecutableSchema(models.Config{Resolvers: resolver}), recoverFunc, websocketUpgrader, websocketKeepAliveDuration, maxUploadSize)

// register GQL handler with plugin cache
manager.GetInstance().PluginCache.RegisterGQLHandler(gqlHandler)

r.Handle("/graphql", gqlHandler)
r.Handle("/playground", handler.Playground("GraphQL playground", "/graphql"))

Expand Down
8 changes: 7 additions & 1 deletion pkg/plugin/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,12 @@ const (
// common.PluginOutput. If this decoding fails, then the raw output will be
// treated as the output.
InterfaceEnumRaw interfaceEnum = "raw"

InterfaceEnumJS interfaceEnum = "js"
)

func (i interfaceEnum) Valid() bool {
return i == InterfaceEnumRPC || i == InterfaceEnumRaw
return i == InterfaceEnumRPC || i == InterfaceEnumRaw || i == InterfaceEnumJS
}

func (i *interfaceEnum) getTaskBuilder() taskBuilder {
Expand All @@ -162,6 +164,10 @@ func (i *interfaceEnum) getTaskBuilder() taskBuilder {
return &rpcTaskBuilder{}
}

if *i == InterfaceEnumJS {
return &jsTaskBuilder{}
}

// shouldn't happen
return nil
}
Expand Down
210 changes: 210 additions & 0 deletions pkg/plugin/examples/js/js.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
var tagName = "Hawwwwt"

function main() {
var modeArg = input.Args.mode;
try {
if (modeArg == "" || modeArg == "add") {
addTag();
} else if (modeArg == "remove") {
removeTag();
} else if (modeArg == "long") {
doLongTask();
} else if (modeArg == "indef") {
doIndefiniteTask();
}
} catch (err) {
return {
Error: err
};
}

return {
Output: "ok"
};
}

function getResult(result) {
if (result[1]) {
throw result[1];
}

return result[0];
}

function getTagID(create) {
log.Info("Checking if tag exists already (via GQL)")

// see if tag exists already
var query = "\
query {\
allTags {\
id\
name\
}\
}"

var result = gql.Do(query);
var allTags = result["allTags"];

var tag;
for (var i = 0; i < allTags.length; ++i) {
if (allTags[i].name === tagName) {
tag = allTags[i];
break;
}
}

if (tag) {
log.Info("found existing tag");
return tag.id;
}

if (!create) {
log.Info("Not found and not creating");
return null;
}

log.Info("Creating new tag");

var mutation = "\
mutation tagCreate($input: TagCreateInput!) {\
tagCreate(input: $input) {\
id\
}\
}";

var variables = {
input: {
'name': tagName
}
};

result = gql.Do(mutation, variables);
log.Info("tag id = " + result.tagCreate.id);
return result.tagCreate.id;
}

function addTag() {
var tagID = getTagID(true)

var scene = findRandomScene();

if (scene === null) {
throw "no scenes to add tag to";
}

var tagIds = []
var found = false;
for (var i = 0; i < scene.tags.length; ++i) {
var sceneTagID = scene.tags[i].id;
if (tagID === sceneTagID) {
found = true;
}
tagIds.push(sceneTagID);
}

if (found) {
log.Info("already has tag");
return;
}

tagIds.push(tagID)

var mutation = "\
mutation sceneUpdate($input: SceneUpdateInput!) {\
sceneUpdate(input: $input) {\
id\
}\
}";

var variables = {
input: {
id: scene.id,
tag_ids: tagIds,
}
};

log.Info("Adding tag to scene " + scene.id);

gql.Do(mutation, variables);
}

function removeTag() {
var tagID = getTagID(false);

if (tagID == null) {
log.Info("Tag does not exist. Nothing to remove");
return
}

log.Info("Destroying tag");

var mutation = "\
mutation tagDestroy($input: TagDestroyInput!) {\
tagDestroy(input: $input)\
}";

var variables = {
input: {
id: tagID
}
};

gql.Do(mutation, variables);
}

function findRandomScene() {
// get a random scene
log.Info("Finding a random scene")

var query = "\
query findScenes($filter: FindFilterType!) {\
findScenes(filter: $filter) {\
count\
scenes {\
id\
tags {\
id\
}\
}\
}\
}"

var variables = {
filter: {
per_page: 1,
sort: 'random'
}
};

var result = gql.Do(query, variables);
var findScenes = result["findScenes"];

if (findScenes.Count === 0) {
return null;
}

return findScenes.scenes[0];
}

function doLongTask() {
var total = 100;
var upTo = 0;

log.Info("Doing long task");
while (upTo < total) {
util.Sleep(1000);

log.Progress(upTo / total);
upTo = upTo + 1;
}
}

function doIndefiniteTask() {
log.Info("Sleeping indefinitely");
while (true) {
util.Sleep(1000);
}
}

main();
27 changes: 27 additions & 0 deletions pkg/plugin/examples/js/js.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# example plugin config
name: Hawwwwt Tagger (Javascript edition)
description: Javascript Hawwwwt tagging utility (using raw interface).
version: 1.0
url: http://www.github.com/stashapp/stash
exec:
- js.js
interface: js
tasks:
- name: Add hawwwwt tag to random scene
description: Creates a "Hawwwwt" tag if not present and adds to a random scene.
defaultArgs:
mode: add
- name: Remove hawwwwt tag from system
description: Removes the "Hawwwwt" tag from all scenes and deletes the tag.
defaultArgs:
mode: remove
- name: Indefinite task
description: Sleeps indefinitely - interruptable
# we'll try command-line argument for this one
defaultArgs:
mode: indef
- name: Long task
description: Sleeps for 100 seconds - interruptable
defaultArgs:
mode: long

Loading