Skip to content

Commit

Permalink
Merge pull request #1166 from SteffoSpieler/feat/add-pishock-service
Browse files Browse the repository at this point in the history
Add PiShock Service
  • Loading branch information
hlxid authored Sep 11, 2024
2 parents 9946634 + fb872b8 commit 7966552
Show file tree
Hide file tree
Showing 12 changed files with 264 additions and 10 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ nodecg-io is the successor of [ChatOverflow](https://github.com/codeoverflow-org
- OBS
- [OpenTTS](https://github.com/synesthesiam/opentts)
- Philips Hue
- [PiShock](https://pishock.com)
- RCON
- Reddit
- sACN Receiver
Expand Down
56 changes: 49 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions samples/pishock/extension/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import NodeCG from "@nodecg/types";
import { PiShockClient } from "nodecg-io-pishock";
import { requireService } from "nodecg-io-core";

module.exports = function (nodecg: NodeCG.ServerAPI) {
nodecg.log.info("Sample bundle for the PiShock service started.");

const pishock = requireService<PiShockClient>(nodecg, "pishock");

pishock?.onAvailable((client) => {
nodecg.log.info("PiShock client has been updated, printing all device's infos");
client.connectedDevices.forEach(async (device) => {
const info = await device.getInfo();
nodecg.log.info(
`Client ID: ${info.clientId}, ID: ${info.id}, Name: ${info.name}, Paused: ${info.paused}, ` +
`MaxIntensity: ${info.maxIntensity}, MaxDuration: ${info.maxDuration}, Online: ${info.online}`,
);
});
});

pishock?.onUnavailable(() => {
nodecg.log.info("PiShock service unavailable.");
});
};
20 changes: 20 additions & 0 deletions samples/pishock/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "pishock",
"version": "0.3.0",
"private": true,
"nodecg": {
"compatibleRange": ">=1.1.1 <3.0.0",
"bundleDependencies": {
"nodecg-io-pishock": "^0.3.0"
}
},
"license": "MIT",
"dependencies": {
"@types/node": "^20.12.2",
"@nodecg/types": "^2.1.12",
"nodecg-io-core": "^0.3.0",
"nodecg-io-pishock": "^0.3.0",
"typescript": "^5.4.3",
"nodecg-io-tsconfig": "^1.0.0"
}
}
11 changes: 11 additions & 0 deletions samples/pishock/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "nodecg-io-tsconfig",
"references": [
{
"path": "../../nodecg-io-core"
},
{
"path": "../../services/nodecg-io-template"
}
]
}
2 changes: 1 addition & 1 deletion services/nodecg-io-gametts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"contributors": [
{
"name": "SteffoSpieler",
"url": "https://about.steffospieler.de"
"url": "https://steffo.dev"
}
],
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion services/nodecg-io-google-cast/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"contributors": [
{
"name": "SteffoSpieler",
"url": "https://about.steffospieler.de"
"url": "https://steffo.dev"
}
],
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion services/nodecg-io-opentts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"contributors": [
{
"name": "SteffoSpieler",
"url": "https://about.steffospieler.de"
"url": "https://steffo.dev"
}
],
"repository": {
Expand Down
65 changes: 65 additions & 0 deletions services/nodecg-io-pishock/extension/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import NodeCG from "@nodecg/types";
import { Result, emptySuccess, success, ServiceBundle, Logger, error } from "nodecg-io-core";
import { PiShockDevice, PiShockAuthentication } from "pishock-ts";

export interface PiShockConfig {
authentications: Array<PiShockAuthentication>;
}

export interface PiShockClient {
connectedDevices: Array<PiShockDevice>;
}

module.exports = (nodecg: NodeCG.ServerAPI) => {
new PiShockService(nodecg, "pishock", __dirname, "../schema.json").register();
};

class PiShockService extends ServiceBundle<PiShockConfig, PiShockClient> {
async validateConfig(config: PiShockConfig): Promise<Result<void>> {
for (const deviceConfig of config.authentications) {
if (!/[0-9a-f-]+/.test(deviceConfig.apiKey)) {
return error(`Invalid PiShock apiKey format: ${deviceConfig.apiKey}`);
}

if (!/[0-9A-Z]+/.test(deviceConfig.code)) {
return error(`Invalid PiShock code format: ${deviceConfig.code}`);
}
}

return emptySuccess();
}

async createClient(config: PiShockConfig, logger: Logger): Promise<Result<PiShockClient>> {
const devices = config.authentications.map((c) => {
// Set name if missing.
c.name ??= "nodecg-io PiShock Service";
return new PiShockDevice(c);
});

// Test connection and return error if any provided auth details fail to do the request.
const connectionStates = await Promise.all(
devices.map(async (dev) => {
try {
await dev.getInfo();
return true;
} catch (err) {
return err;
}
}),
);

for (const state of connectionStates) {
if (state instanceof Error) {
return error(`Failed to connect to PiShock api: ${state.message}`);
}
}

const client = { connectedDevices: devices };
logger.info("Successfully created PiShock client.");
return success(client);
}

stopClient(_: PiShockClient, _logger: Logger): void {
// Stateless REST API, cannot be stopped
}
}
50 changes: 50 additions & 0 deletions services/nodecg-io-pishock/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"name": "nodecg-io-pishock",
"version": "0.3.0",
"description": "Allows using the PiShock api.",
"homepage": "https://nodecg.io/RELEASE/samples/pishock",
"author": {
"name": "CodeOverflow team",
"url": "https://github.com/codeoverflow-org"
},
"contributors": [
{
"name": "SteffoSpieler",
"url": "https://steffo.dev"
}
],
"repository": {
"type": "git",
"url": "https://github.com/codeoverflow-org/nodecg-io.git",
"directory": "services/nodecg-io-pishock"
},
"files": [
"**/*.js",
"**/*.js.map",
"**/*.d.ts",
"*.json"
],
"main": "extension/index",
"keywords": [
"nodecg-io",
"nodecg-bundle",
"pishock"
],
"nodecg": {
"compatibleRange": ">=1.1.1 <3.0.0",
"bundleDependencies": {
"nodecg-io-core": "^0.3.0"
}
},
"license": "MIT",
"devDependencies": {
"@types/node": "^20.12.2",
"@nodecg/types": "^2.1.12",
"typescript": "^5.4.3",
"nodecg-io-tsconfig": "^1.0.0"
},
"dependencies": {
"nodecg-io-core": "^0.3.0",
"pishock-ts": "^1.0.1"
}
}
33 changes: 33 additions & 0 deletions services/nodecg-io-pishock/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"additionalProperties": false,
"properties": {
"authentications": {
"type": "array",
"items": {
"type": "object",
"required": ["username", "apiKey", "code"],
"properties": {
"username": {
"type": "string",
"description": "Username you use to log into PiShock.com. Can be found in the Account section of the website."
},
"apiKey": {
"type": "string",
"description": "API Key generated on PiShock.com. Can be found in the Account section of the website."
},
"code": {
"type": "string",
"description": "Sharecode generated on PiShock.com. Limitations can be set when generating the code."
},
"name": {
"type": "string",
"description": "Name of what sent the commands. This will show up in the PiShock logs on the website."
}
}
}
}
},
"required": ["authentications"]
}
8 changes: 8 additions & 0 deletions services/nodecg-io-pishock/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "nodecg-io-tsconfig",
"references": [
{
"path": "../../nodecg-io-core"
}
]
}

0 comments on commit 7966552

Please sign in to comment.