PotatoHotDog ofrece una API gratuita de Generate AI Images API que puedes llamar directamente desde Streamer.bot, sin necesitar ningún middleware de terceros. Esta guía muestra cómo agregar un pequeño script C# personalizado a una subacción Execute Code de Streamer.bot que genera una imagen de IA a partir de un texto de entrada y la descarga en disco.
El script solo necesita tu clave API de PotatoHotDog y un prompt que describa la imagen que quieres generar, y guarda la imagen descargada en una carpeta dedicada dentro del directorio de instalación de Streamer.bot.
Prepara una clave API
Si aún no tienes una, genera una clave API desde tu panel de control y tenla a mano; la necesitarás en el siguiente paso.
Ir a las claves de API
Argumentos Previos
Para generar una imagen con IA, se deben especificar dos argumentos en Streamer.bot antes de que se ejecute la subacción Execute Code. O, en otras palabras, estas dos cosas deben estar especificadas:
- Una clave API.
- Las instrucciones del prompt que describen la imagen que quieres generar.
Estos corresponden a los siguientes argumentos de Streamer.bot:
- potatoKey
- potatoInstructions
Especificas argumentos para tu acción haciendo clic derecho en Sub Actions, luego seleccionando Add, Core, Arguments y por último Set Argument.
Agregar una acción de ejecutar código en Streamer.bot
Abre Streamer.bot y ve a la pestaña Acciones. Crea una acción nueva, o abre una existente, y dale un nombre que reconozcas más tarde, como "PotatoHotDog AI Image".
Con la acción seleccionada, haz clic en Añadir dentro de Subacciones, luego elige Core y después Ejecutar código C#. Esto añade una subacción donde puedes pegar código C# en crudo que Streamer.bot compila y ejecuta al vuelo.
Pega el script a continuación en el editor de código. Lee los argumentos potatoKey y potatoInstructions, llama a nuestra API de Generación de Imágenes con IA para generar la imagen y obtener su URL, y luego descarga la imagen resultante en una carpeta llamada temp_potatohotdog_images dentro del directorio de instalación de Streamer.bot.
using System;
using System.IO;
using System.Net.Http;
using Newtonsoft.Json.Linq;
public class CPHInline
{
// Tracks the version of this script for troubleshooting and support.
private const string VERSION = "1.0.0";
// Base URL for the endpoint that generates an AI image.
private const string BASE_URL_GENERATE = "https://api-generate-image-v1.potatohotdog.com/";
// Tracks the next numbered log argument.
private int logIndex = 0;
// Reuses one HTTP client for all API requests.
private static readonly HttpClient httpClient = new HttpClient
{
Timeout = TimeSpan.FromSeconds(30)
};
// Adds a log message as a numbered action argument.
private void Log(string message)
{
// Stores the message under a numbered key.
CPH.SetArgument($"potatoLog{logIndex}", message);
// Advances the log index for the next message.
logIndex++;
// Keeps the total log count in sync.
CPH.SetArgument("potatoLogCount", logIndex);
}
// Ensures a required action argument exists and is not empty.
private bool RequireArgument(string name, out string value)
{
// Fails when the argument is missing or blank.
if (!CPH.TryGetArg(name, out value) || string.IsNullOrWhiteSpace(value))
{
value = "";
return false;
}
return true;
}
// URL-encodes a value so it can safely be used in a query string.
private string EncodeUrlValue(string value)
{
// Escapes reserved characters for safe use in a URL.
return Uri.EscapeDataString(value);
}
// Performs an HTTP GET request and returns the response body.
private string HttpGet(string url)
{
try
{
Log($"GET {url}");
// Sends the HTTP request synchronously.
HttpResponseMessage response =
httpClient.GetAsync(url).GetAwaiter().GetResult();
// Reads the complete response body.
string responseBody =
response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
Log($"HTTP status: {(int)response.StatusCode} {response.ReasonPhrase}");
// Stops when the server returns an unsuccessful status code.
if (!response.IsSuccessStatusCode)
{
Log($"Error: HTTP request failed with status {(int)response.StatusCode} {response.ReasonPhrase}.");
// Logs the server error response when available.
if (!string.IsNullOrWhiteSpace(responseBody))
{
Log($"Error response: {responseBody}");
}
return null;
}
Log($"Received {responseBody.Length} characters.");
return responseBody;
}
catch (Exception exception)
{
// Logs network, timeout, and other HTTP-related exceptions.
Log($"Error: HTTP request failed: {exception.Message}");
return null;
}
}
// Downloads a file from a URL and saves it to disk.
private bool DownloadFile(string url, string destinationPath)
{
try
{
Log($"Downloading image from \"{url}\".");
Log($"Saving image to \"{destinationPath}\".");
// Sends the image download request.
HttpResponseMessage response =
httpClient.GetAsync(url).GetAwaiter().GetResult();
Log($"Image download HTTP status: {(int)response.StatusCode} {response.ReasonPhrase}");
// Reads the complete image response into memory.
byte[] fileData = response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();
// Stops when the image server returns an unsuccessful status.
if (!response.IsSuccessStatusCode)
{
Log($"Error: Image download failed with status {(int)response.StatusCode} {response.ReasonPhrase}.");
return false;
}
// Rejects an empty image response.
if (fileData == null || fileData.Length == 0)
{
Log("Error: The downloaded image file is empty.");
return false;
}
// Writes the downloaded image bytes to the destination file.
File.WriteAllBytes(destinationPath, fileData);
Log($"Downloaded {fileData.Length} image bytes.");
// Confirms that the image file now exists on disk.
if (!File.Exists(destinationPath))
{
Log("Error: The image download completed, but the file does not exist on disk.");
return false;
}
// Reports the final file size from disk.
FileInfo fileInfo = new FileInfo(destinationPath);
Log($"Image file saved successfully. File size: {fileInfo.Length} bytes.");
return true;
}
catch (Exception exception)
{
// Logs download, filesystem, and permission errors.
Log($"Error: Could not download the image file: {exception.Message}");
return false;
}
}
// Extracts a required string value from a JSON response.
private bool TryGetJsonString(string json, string propertyName, out string value)
{
value = "";
try
{
// Parses the response body as a JSON object.
JObject jsonObject = JObject.Parse(json);
// Retrieves the requested JSON property.
JToken property = jsonObject[propertyName];
if (property == null)
{
Log($"Error: JSON response does not contain \"{propertyName}\".");
return false;
}
value = property.ToString();
// Rejects empty JSON string values.
if (string.IsNullOrWhiteSpace(value))
{
Log($"Error: JSON property \"{propertyName}\" is empty.");
value = "";
return false;
}
return true;
}
catch (Exception exception)
{
// Logs malformed JSON and property conversion errors.
Log($"Error: Could not parse JSON property \"{propertyName}\": {exception.Message}");
return false;
}
}
// Creates and returns the dedicated PotatoImage folder.
private string GetImageFolder()
{
// Uses Streamer.bot's application directory instead of the process working directory.
string streamerBotFolder = AppDomain.CurrentDomain.BaseDirectory;
// Places generated image files inside a dedicated subfolder.
string imageFolder = Path.Combine(streamerBotFolder, "temp_potatohotdog_images");
Log($"Streamer.bot folder: \"{streamerBotFolder}\".");
Log($"Image folder: \"{imageFolder}\".");
// Creates the image folder if it does not already exist.
if (!Directory.Exists(imageFolder))
{
Log("Image folder does not exist. Creating it...");
Directory.CreateDirectory(imageFolder);
Log("Image folder created.");
}
else
{
Log("Image folder already exists.");
}
return imageFolder;
}
// Runs the main PotatoHotdog AI image action.
public bool Execute()
{
// Resets log numbering for this execution.
logIndex = 0;
CPH.SetArgument("potatoLogCount", 0);
Log("Starting script...");
// Logs the script version so runs can be tracked over time.
Log($"Version: {VERSION}");
// Retrieves the PotatoHotdog API key.
if (!RequireArgument("potatoKey", out string potatoKey))
{
Log("Error: potatoKey variable is missing. Please login to potatohotdog.com, generate an API key, create a set variable action and save the variable \"potatoKey\" with your key.");
return false;
}
// Retrieves the prompt instructions describing the image to generate.
if (!RequireArgument("potatoInstructions", out string potatoInstructions))
{
Log("Error: potatoInstructions variable is missing. Create a set variable action and save the variable \"potatoInstructions\" with a description of the image you want generated.");
return false;
}
// Logs the non-secret input values.
Log("potatoKey was provided.");
Log($"potatoInstructions=\"{potatoInstructions}\"");
// Builds the API URL used to generate the AI image.
string generateUrl = BASE_URL_GENERATE + "?key=" + EncodeUrlValue(potatoKey) + "&instructions=" + EncodeUrlValue(potatoInstructions);
// Requests generation of the AI image.
string generateJson = HttpGet(generateUrl);
if (generateJson == null)
{
Log("Error: Failed to generate the AI image.");
return false;
}
Log($"Generate response: {generateJson}");
// Extracts the generated item's ID, reused below as the local filename.
if (!TryGetJsonString(generateJson, "itemID", out string itemID))
{
Log("Error: Could not retrieve itemID from the generate response.");
return false;
}
Log($"itemID=\"{itemID}\"");
// Logs the generation duration when present, purely for troubleshooting.
if (TryGetJsonString(generateJson, "duration", out string duration))
{
Log($"duration={duration} second(s)");
}
// Extracts the generated image URL from the response.
if (!TryGetJsonString(generateJson, "imageURL", out string imageURL))
{
Log("Error: Could not retrieve imageURL from the generate response.");
return false;
}
Log($"imageURL=\"{imageURL}\"");
string imageFolder;
try
{
// Resolves and creates the dedicated PotatoImage directory.
imageFolder = GetImageFolder();
}
catch (Exception exception)
{
Log($"Error: Could not create or access the image folder: {exception.Message}");
return false;
}
// Reuses the item's own ID as the local filename instead of minting a new one.
string imageFileName = $"{itemID}.png";
// Combines the image folder and unique filename.
string imageFilePath = Path.Combine(imageFolder, imageFileName);
Log($"Generated image filename: \"{imageFileName}\".");
Log($"Local image path: \"{imageFilePath}\".");
// Downloads the generated image file to the PotatoImage folder.
if (!DownloadFile(imageURL, imageFilePath))
{
Log("Error: Failed to download the generated AI image.");
return false;
}
// Stores the remote image URL as a final action argument.
CPH.SetArgument("potatoGeneratedImageURL", imageURL);
// Stores the absolute local file path as a final action argument.
CPH.SetArgument("potatoGeneratedImageFile", imageFilePath);
Log($"potatoGeneratedImageURL=\"{imageURL}\"");
Log($"potatoGeneratedImageFile=\"{imageFilePath}\"");
Log("Finished.");
return true;
}
}
Después de pegar el script, recuerda hacer clic en Find Refs y Compile y asegúrate de que se compila correctamente. Guarda la acción, luego ejecútalo manualmente o vincúlalo a un comando o a una recompensa de puntos de canal para probar que la imagen se genera correctamente.
Revisa la imagen descargada
Una vez que la acción se haya ejecutado, puedes inspeccionar las variables de Action a través de Action History para confirmar que todo funcionó como se esperaba.
Allí encontrarás la ruta local donde se guardó la imagen generada en disco, dentro de la carpeta temp_potatohotdog_images en el directorio de instalación de Streamer.bot.
Abre esa carpeta para ver la imagen descargada directamente.
Solución de problemas
Si el script no se comporta como se espera, la mejor forma de solucionarlo es revisando los registros de acciones.
Puedes hacer esto inspeccionando tus variables de Acción a través del Historial de Acción.
Esta guía fue publicada por primera vez el 2026-07-19 y fue modificada por última vez el 2026-07-19.
Otros Guías Similares
Aquí tienes otras guías paso a paso que podrían resultarte útiles.