diff --git a/README.md b/README.md
index ee2f680..c71caf4 100644
--- a/README.md
+++ b/README.md
@@ -151,6 +151,10 @@ When Download type is Around the user, the offsets are the amount of entries aro
| Activate Steam overlay to store | Activates the Steam Overlay to the Steam store page for the provided app | App ID *(number)*
Flag *(combo)*
|
| Trigger screenshot (synchronous) | Captures the current screen and saves to Steam screenshot library (synchronous) | Tag *(string)*
|
| Trigger screenshot | Captures the current screen and saves to Steam screenshot library | |
+| Save screenshot from URL (synchronous) | Saves an image from a URL as a Steam screenshot. The image will be loaded, converted to base64, and its dimensions calculated automatically. (synchronous) | URL *(string)*
Tag *(string)*
|
+| Save screenshot from URL | Saves an image from a URL as a Steam screenshot. The image will be loaded, converted to base64, and its dimensions calculated automatically. | URL *(string)*
|
+| Add screenshot to library (synchronous) | Adds an existing screenshot file to the Steam screenshot library. Returns the handle of the screenshot. (synchronous) | Filename *(string)*
Thumbnail Filename *(string)*
Width *(number)*
Height *(number)*
Tag *(string)*
|
+| Add screenshot to library | Adds an existing screenshot file to the Steam screenshot library. Returns the handle of the screenshot. | Filename *(string)*
Thumbnail Filename *(string)*
Width *(number)*
Height *(number)*
|
| Check DLC is installed (synchronous) | Checks if the user owns and has installed a specific DLC (synchronous) | DLC App ID *(number)*
Tag *(string)*
|
| Check DLC is installed | Checks if the user owns and has installed a specific DLC | DLC App ID *(number)*
|
| Create workshop item (synchronous) | Creates a new workshop item for the specified Steam App ID and returns its ID (synchronous) | App ID *(number)*
Tag *(string)*
|
@@ -385,6 +389,14 @@ When Download type is Around the user, the offsets are the amount of entries aro
| On any "TriggerScreenshot" success | Trigger when any of the "TriggerScreenshot" are executed with success. | |
| On "TriggerScreenshot" error | Trigger when the "TriggerScreenshot" failed to execute. | Tag *(string)*
|
| On any "TriggerScreenshot" error | Trigger when any of the "TriggerScreenshot" failed to execute. | |
+| On "SaveScreenshotFromURL" success | Trigger when the "SaveScreenshotFromURL" is executed with success. | Tag *(string)*
|
+| On any "SaveScreenshotFromURL" success | Trigger when any of the "SaveScreenshotFromURL" are executed with success. | |
+| On "SaveScreenshotFromURL" error | Trigger when the "SaveScreenshotFromURL" failed to execute. | Tag *(string)*
|
+| On any "SaveScreenshotFromURL" error | Trigger when any of the "SaveScreenshotFromURL" failed to execute. | |
+| On "AddScreenshotToLibrary" success | Trigger when the "AddScreenshotToLibrary" is executed with success. | Tag *(string)*
|
+| On any "AddScreenshotToLibrary" success | Trigger when any of the "AddScreenshotToLibrary" are executed with success. | |
+| On "AddScreenshotToLibrary" error | Trigger when the "AddScreenshotToLibrary" failed to execute. | Tag *(string)*
|
+| On any "AddScreenshotToLibrary" error | Trigger when any of the "AddScreenshotToLibrary" failed to execute. | |
| On "CheckDLCIsInstalled" success | Trigger when the "CheckDLCIsInstalled" is executed with success. | Tag *(string)*
|
| On any "CheckDLCIsInstalled" success | Trigger when any of the "CheckDLCIsInstalled" are executed with success. | |
| On "CheckDLCIsInstalled" error | Trigger when the "CheckDLCIsInstalled" failed to execute. | Tag *(string)*
|
@@ -557,6 +569,10 @@ When Download type is Around the user, the offsets are the amount of entries aro
| ActivateToStoreResult | The result of the "ActivateToStore last call" | string | |
| TriggerScreenshotError | The error of the "TriggerScreenshot last call" | string | |
| TriggerScreenshotResult | The result of the "TriggerScreenshot last call" | string | |
+| SaveScreenshotFromURLError | The error of the "SaveScreenshotFromURL last call" | string | |
+| SaveScreenshotFromURLResult | The result of the "SaveScreenshotFromURL last call" | string | |
+| AddScreenshotToLibraryError | The error of the "AddScreenshotToLibrary last call" | string | |
+| AddScreenshotToLibraryResult | The result of the "AddScreenshotToLibrary last call" | string | |
| CheckDLCIsInstalledError | The error of the "CheckDLCIsInstalled last call" | string | |
| CheckDLCIsInstalledResult | The result of the "CheckDLCIsInstalled last call" | string | |
| CreateWorkshopItemError | The error of the "CreateWorkshopItem last call" | string | |
diff --git a/src/instance.js b/src/instance.js
index ca345d0..a8d09fb 100644
--- a/src/instance.js
+++ b/src/instance.js
@@ -2302,6 +2302,115 @@ function getInstanceJs(parentClass, addonTriggers, C3) {
_TriggerScreenshot = this._TriggerScreenshotBase
_TriggerScreenshotSync = this._TriggerScreenshotBase
+ // Save Screenshot from URL
+ _SaveScreenshotFromURLBase = this.wrap(super._SaveScreenshotFromURL, async (
+ /** @type {string} */ url,
+ /** @type {Tag} */ tag
+ ) => {
+ try {
+ // Load the image from URL and convert to base64
+ const img = new Image();
+ img.crossOrigin = 'anonymous';
+
+ const imageLoaded = new Promise((resolve, reject) => {
+ img.onload = () => resolve(img);
+ img.onerror = (e) => reject(new Error('Failed to load image from URL'));
+ });
+
+ img.src = url;
+ await imageLoaded;
+
+ // Get dimensions
+ const width = img.naturalWidth;
+ const height = img.naturalHeight;
+
+ // Convert to base64 data URL
+ const canvas = document.createElement('canvas');
+ canvas.width = width;
+ canvas.height = height;
+ const ctx = canvas.getContext('2d');
+ if (!ctx) {
+ throw new Error('Failed to get canvas context');
+ }
+ ctx.drawImage(img, 0, 0);
+ const dataUrl = canvas.toDataURL('image/png');
+
+ const order = {
+ url: '/steam/screenshots/save',
+ body: {
+ dataUrl,
+ width,
+ height,
+ },
+ };
+ const answer = await this.ws?.sendAndWaitForResponse(order);
+ if (answer?.body.success === false) {
+ throw new Error(answer?.body.error || 'Failed to save screenshot')
+ }
+ this._SaveScreenshotFromURLResultValue = answer?.body.data ?? ''
+ this._SaveScreenshotFromURLErrorValue = ''
+
+ await this.trigger(tag, [
+ C3.Plugins.pipelabv2.Cnds.OnSaveScreenshotFromURLSuccess,
+ C3.Plugins.pipelabv2.Cnds.OnAnySaveScreenshotFromURLSuccess
+ ])
+ } catch (e) {
+ if (e instanceof Error) {
+ this._SaveScreenshotFromURLErrorValue = e.message
+ this._SaveScreenshotFromURLResultValue = ''
+ await this.trigger(tag, [
+ C3.Plugins.pipelabv2.Cnds.OnSaveScreenshotFromURLError,
+ C3.Plugins.pipelabv2.Cnds.OnAnySaveScreenshotFromURLError
+ ])
+ }
+ }
+ }, this.unsupportedEngine)
+ _SaveScreenshotFromURL = this._SaveScreenshotFromURLBase
+ _SaveScreenshotFromURLSync = this._SaveScreenshotFromURLBase
+
+ // Add Screenshot to Library
+ _AddScreenshotToLibraryBase = this.wrap(super._AddScreenshotToLibrary, async (
+ /** @type {string} */ filename,
+ /** @type {string} */ thumbnailFilename,
+ /** @type {number} */ width,
+ /** @type {number} */ height,
+ /** @type {Tag} */ tag
+ ) => {
+ try {
+ /** @type {import('@pipelab/core').MakeInputOutput, 'input'>} */
+ const order = {
+ url: '/steam/raw',
+ body: {
+ namespace: 'screenshots',
+ method: 'addScreenshotToLibrary',
+ args: [filename, thumbnailFilename || null, width, height],
+ },
+ };
+ const answer = await this.ws?.sendAndWaitForResponse(order);
+ if (answer?.body.success === false) {
+ throw new Error(answer?.body.error || 'Failed to add screenshot to library')
+ }
+ this._AddScreenshotToLibraryResultValue = answer?.body.data ?? -1
+ this._AddScreenshotToLibraryErrorValue = ''
+
+ await this.trigger(tag, [
+ C3.Plugins.pipelabv2.Cnds.OnAddScreenshotToLibrarySuccess,
+ C3.Plugins.pipelabv2.Cnds.OnAnyAddScreenshotToLibrarySuccess
+ ])
+ } catch (e) {
+ if (e instanceof Error) {
+ this._AddScreenshotToLibraryErrorValue = e.message
+ this._AddScreenshotToLibraryResultValue = -1
+ await this.trigger(tag, [
+ C3.Plugins.pipelabv2.Cnds.OnAddScreenshotToLibraryError,
+ C3.Plugins.pipelabv2.Cnds.OnAnyAddScreenshotToLibraryError
+ ])
+ }
+ }
+ }, this.unsupportedEngine)
+ _AddScreenshotToLibrary = this._AddScreenshotToLibraryBase
+ _AddScreenshotToLibrarySync = this._AddScreenshotToLibraryBase
+
// Steam DLC
_CheckDLCIsInstalledBase = this.wrap(super._CheckDLCIsInstalled, async (
/** @type {number} */ appId,
@@ -3566,6 +3675,16 @@ function getInstanceJs(parentClass, addonTriggers, C3) {
_OnTriggerScreenshotError = this.wrap(super._OnTriggerScreenshotError, (/** @type {Tag} */ tag) => this._currentTag === tag)
_OnAnyTriggerScreenshotError = this.wrap(super._OnAnyTriggerScreenshotError, () => true)
+ _OnSaveScreenshotFromURLSuccess = this.wrap(super._OnSaveScreenshotFromURLSuccess, (/** @type {Tag} */ tag) => this._currentTag === tag)
+ _OnAnySaveScreenshotFromURLSuccess = this.wrap(super._OnAnySaveScreenshotFromURLSuccess, () => true)
+ _OnSaveScreenshotFromURLError = this.wrap(super._OnSaveScreenshotFromURLError, (/** @type {Tag} */ tag) => this._currentTag === tag)
+ _OnAnySaveScreenshotFromURLError = this.wrap(super._OnAnySaveScreenshotFromURLError, () => true)
+
+ _OnAddScreenshotToLibrarySuccess = this.wrap(super._OnAddScreenshotToLibrarySuccess, (/** @type {Tag} */ tag) => this._currentTag === tag)
+ _OnAnyAddScreenshotToLibrarySuccess = this.wrap(super._OnAnyAddScreenshotToLibrarySuccess, () => true)
+ _OnAddScreenshotToLibraryError = this.wrap(super._OnAddScreenshotToLibraryError, (/** @type {Tag} */ tag) => this._currentTag === tag)
+ _OnAnyAddScreenshotToLibraryError = this.wrap(super._OnAnyAddScreenshotToLibraryError, () => true)
+
_OnCheckDLCIsInstalledSuccess = this.wrap(super._OnCheckDLCIsInstalledSuccess, (/** @type {Tag} */ tag) => this._currentTag === tag)
_OnAnyCheckDLCIsInstalledSuccess = this.wrap(super._OnAnyCheckDLCIsInstalledSuccess, () => true)
_OnCheckDLCIsInstalledError = this.wrap(super._OnCheckDLCIsInstalledError, (/** @type {Tag} */ tag) => this._currentTag === tag)
@@ -4130,6 +4249,20 @@ function getInstanceJs(parentClass, addonTriggers, C3) {
return this._TriggerScreenshotResultValue
})
+ _SaveScreenshotFromURLError = this.exprs(super._SaveScreenshotFromURLError, () => {
+ return this._SaveScreenshotFromURLErrorValue
+ })
+ _SaveScreenshotFromURLResult = this.exprs(super._SaveScreenshotFromURLResult, () => {
+ return this._SaveScreenshotFromURLResultValue
+ })
+
+ _AddScreenshotToLibraryError = this.exprs(super._AddScreenshotToLibraryError, () => {
+ return this._AddScreenshotToLibraryErrorValue
+ })
+ _AddScreenshotToLibraryResult = this.exprs(super._AddScreenshotToLibraryResult, () => {
+ return this._AddScreenshotToLibraryResultValue
+ })
+
_CheckDLCIsInstalledError = this.exprs(super._CheckDLCIsInstalledError, () => {
return this._CheckDLCIsInstalledErrorValue
})
diff --git a/src/pluginConfig.js b/src/pluginConfig.js
index e33f9e0..0c4039b 100644
--- a/src/pluginConfig.js
+++ b/src/pluginConfig.js
@@ -1223,6 +1223,63 @@ const TriggerScreenshot = ACEGenerator("TriggerScreenshot", /** @type {const} */
description: "Captures the current screen and saves to Steam screenshot library",
}))
+const SaveScreenshotFromURL = ACEGenerator("SaveScreenshotFromURL", /** @type {const} */({
+ category: "steam",
+ highlight: false,
+ deprecated: false,
+ params: [
+ {
+ id: 'url',
+ desc: "The URL of the image to save as a screenshot (will be converted to base64)",
+ name: "URL",
+ type: 'string',
+ initialValue: "\"\"",
+ }
+ ],
+ listName: "Save screenshot from URL",
+ displayText: "Save screenshot from URL [b]{0}[/b]",
+ description: "Saves an image from a URL as a Steam screenshot. The image will be loaded, converted to base64, and its dimensions calculated automatically.",
+}))
+
+const AddScreenshotToLibrary = ACEGenerator("AddScreenshotToLibrary", /** @type {const} */({
+ category: "steam",
+ highlight: false,
+ deprecated: false,
+ params: [
+ {
+ id: 'filename',
+ desc: "The absolute path to the screenshot file on disk",
+ name: "Filename",
+ type: 'string',
+ initialValue: "\"\"",
+ },
+ {
+ id: 'thumbnailFilename',
+ desc: "Optional absolute path to a thumbnail file (leave empty for no thumbnail)",
+ name: "Thumbnail Filename",
+ type: 'string',
+ initialValue: "\"\"",
+ },
+ {
+ id: 'width',
+ desc: "The width of the screenshot in pixels",
+ name: "Width",
+ type: 'number',
+ initialValue: "0",
+ },
+ {
+ id: 'height',
+ desc: "The height of the screenshot in pixels",
+ name: "Height",
+ type: 'number',
+ initialValue: "0",
+ }
+ ],
+ listName: "Add screenshot to library",
+ displayText: "Add screenshot [b]{0}[/b] to library (thumbnail: {1}, size: {2}x{3})",
+ description: "Adds an existing screenshot file to the Steam screenshot library. Returns the handle of the screenshot.",
+}))
+
// Steam DLC
const CheckDLCIsInstalled = ACEGenerator("CheckDLCIsInstalled", /** @type {const} */({
category: "steam",
@@ -1789,6 +1846,8 @@ const Config = /** @type {const} */({
...ActivateToWebPage.actions,
...ActivateToStore.actions,
...TriggerScreenshot.actions,
+ ...SaveScreenshotFromURL.actions,
+ ...AddScreenshotToLibrary.actions,
...CheckDLCIsInstalled.actions,
...CreateWorkshopItem.actions,
...UpdateWorkshopItem.actions,
@@ -1856,6 +1915,8 @@ const Config = /** @type {const} */({
...ActivateToWebPage.conditions,
...ActivateToStore.conditions,
...TriggerScreenshot.conditions,
+ ...SaveScreenshotFromURL.conditions,
+ ...AddScreenshotToLibrary.conditions,
...CheckDLCIsInstalled.conditions,
...CreateWorkshopItem.conditions,
...UpdateWorkshopItem.conditions,
@@ -1994,6 +2055,8 @@ const Config = /** @type {const} */({
...ActivateToWebPage.expressions,
...ActivateToStore.expressions,
...TriggerScreenshot.expressions,
+ ...SaveScreenshotFromURL.expressions,
+ ...AddScreenshotToLibrary.expressions,
...CheckDLCIsInstalled.expressions,
...CreateWorkshopItem.expressions,
...UpdateWorkshopItem.expressions,