{ "kind": "open-flow-workflow", "version": 1, "name": "Telegram Spotify Player", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_ebf3545035a10b60": { "name": "Telegram song request", "kind": "integration", "config": { "updates": { "kind": "value", "value": [ "message" ] }, "dropPendingUpdates": { "kind": "value", "value": false }, "chatIds": { "kind": "value", "value": [] }, "userIds": { "kind": "value", "value": [] } }, "definition": { "configInputs": [ { "description": "Only accept updates from these numeric Telegram chat IDs. Empty means every chat.", "jsonSchema": { "type": "array", "items": { "type": "string", "pattern": "^-?[0-9]{1,20}$" }, "maxItems": 100, "uniqueItems": true }, "nullable": false, "handle": "chatIds", "value": [] }, { "description": "Discard updates queued before the webhook is created or resumed.", "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "dropPendingUpdates", "value": true }, { "description": "Telegram update types that trigger a Run. Use * for the Telegram default set.", "jsonSchema": { "type": "array", "items": { "enum": [ "*", "message", "edited_message", "channel_post", "edited_channel_post", "business_connection", "business_message", "edited_business_message", "deleted_business_messages", "guest_message", "message_reaction", "message_reaction_count", "inline_query", "chosen_inline_result", "callback_query", "shipping_query", "pre_checkout_query", "purchased_paid_media", "poll", "poll_answer", "my_chat_member", "chat_member", "chat_join_request", "chat_boost", "removed_chat_boost", "managed_bot", "subscription" ] }, "minItems": 1, "uniqueItems": true }, "nullable": false, "handle": "updates" }, { "description": "Only accept updates from these numeric Telegram user IDs. Empty means every user.", "jsonSchema": { "type": "array", "items": { "type": "string", "pattern": "^[0-9]{1,20}$" }, "maxItems": 100, "uniqueItems": true }, "nullable": false, "handle": "userIds", "value": [] } ], "definitionVersion": 2, "description": "Triggers when the connected Telegram bot receives a selected update.", "displayName": "Bot Update", "key": "telegram.on_update", "name": "on_update", "outputs": [ { "jsonSchema": { "type": "object" }, "nullable": false, "handle": "body" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "deliveryId" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "event" } ], "provider": "telegram", "type": "integration", "endpoint": { "body": { "allowArray": false, "allowEmpty": false, "formats": [ "json" ] }, "methods": [ "POST" ], "successStatus": 200 } } }, "n_849365c4bd9e12e0": { "inputs": { "update": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ebf3545035a10b60", "output": "body" } ] } }, "name": "Read text and reply chat", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "object" }, "nullable": false, "handle": "update" } ], "outputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "text" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "chatId" } ], "name": "Read text and reply chat", "moduleId": "n_c7d37900feb39629", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_6199232fb14f9654": { "inputs": { "text": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_849365c4bd9e12e0", "output": "text" } ] } }, "name": "Identify artist and song query", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "items": { "type": "object" }, "type": "array" }, "nullable": true, "handle": "messages", "value": null }, { "jsonSchema": { "items": { "type": "object" }, "minItems": 1, "type": "array" }, "nullable": false, "handle": "template", "value": [ { "role": "user", "content": "get artist and song name from '{{text}}'. Reply only eg. 'track:song name artist:artist name'" } ] }, { "jsonSchema": { "type": "object" }, "nullable": false, "handle": "model", "value": { "model": "gpt-4o-mini" } }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "text" } ], "outputs": [ { "description": "Generated response.", "jsonSchema": { "type": "string" }, "nullable": false, "handle": "output" } ], "name": "Identify artist and song query", "executor": { "kind": "llm", "mode": "chat" } } }, "n_440eae4c36ab0149": { "inputs": { "completion": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_6199232fb14f9654", "output": "output" } ] } }, "name": "Check search query", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "completion" } ], "outputs": [ { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "query" } ], "name": "Check search query", "moduleId": "n_5ea66f7d4b4f6595", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_2549bb8a6c133171": { "inputs": { "query": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_440eae4c36ab0149", "output": "query" } ] }, "types": { "kind": "value", "value": [ "track" ] }, "limit": { "kind": "value", "value": 1 }, "offset": { "kind": "value", "value": 0 } }, "name": "Search first Spotify track", "onError": "error", "kind": "task", "task": { "inputs": [ { "description": "Search query text.", "jsonSchema": { "type": "string", "minLength": 1, "description": "Search query text." }, "nullable": false, "handle": "query" }, { "description": "Spotify resource types to search.", "jsonSchema": { "type": "array", "items": { "type": "string", "enum": [ "album", "artist", "playlist", "track", "show", "episode", "audiobook" ], "description": "Schema for searchTypeEnum." }, "minItems": 1, "description": "Spotify resource types to search." }, "nullable": false, "handle": "types" }, { "description": "Maximum number of items to return.", "jsonSchema": { "type": "integer", "minimum": 1, "maximum": 50, "description": "Maximum number of items to return." }, "nullable": true, "handle": "limit", "value": null }, { "description": "Zero-based index of the first item to return.", "jsonSchema": { "type": "integer", "minimum": 0, "description": "Zero-based index of the first item to return." }, "nullable": true, "handle": "offset", "value": null }, { "description": "An ISO 3166-1 alpha-2 country code or from_token to apply market filtering.", "jsonSchema": { "anyOf": [ { "const": "from_token", "description": "A union variant." }, { "type": "string", "minLength": 2, "maxLength": 2, "description": "An ISO 3166-1 alpha-2 country code." } ], "description": "An ISO 3166-1 alpha-2 country code or from_token to apply market filtering." }, "nullable": true, "handle": "market", "value": null }, { "description": "Whether to include externally hosted audio results when supported.", "jsonSchema": { "type": "boolean", "description": "Whether to include externally hosted audio results when supported." }, "nullable": true, "handle": "includeExternalAudio", "value": null } ], "outputs": [ { "description": "Search query text that was sent to Spotify.", "jsonSchema": { "type": "string", "description": "Search query text that was sent to Spotify." }, "nullable": false, "handle": "query" }, { "description": "Spotify resource types requested in the search.", "jsonSchema": { "type": "array", "items": { "type": "string", "enum": [ "album", "artist", "playlist", "track", "show", "episode", "audiobook" ], "description": "Schema for searchTypeEnum." }, "description": "Spotify resource types requested in the search." }, "nullable": false, "handle": "types" }, { "description": "Album search results.", "jsonSchema": { "type": "object", "properties": { "href": { "type": "string", "description": "Spotify API URL for this page." }, "limit": { "type": "integer", "description": "Maximum number of items returned." }, "next": { "type": [ "string", "null" ], "description": "URL for the next page when available." }, "offset": { "type": "integer", "description": "Zero-based index of the first returned item." }, "previous": { "type": [ "string", "null" ], "description": "URL for the previous page when available." }, "total": { "type": "integer", "description": "Total number of matched items." }, "items": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Spotify resource ID." }, "name": { "type": "string", "description": "Spotify resource name." }, "uri": { "type": "string", "description": "Spotify resource URI." }, "href": { "type": "string", "description": "Spotify resource API URL." }, "type": { "type": "string", "description": "Spotify resource type." }, "external_urls": { "type": "object", "additionalProperties": { "type": "string", "description": "A record value." }, "description": "External URLs for the resource." } }, "additionalProperties": true, "description": "Simplified Spotify search resource." }, "description": "Search results for this resource type." } }, "required": [ "href", "limit", "offset", "total", "items" ], "additionalProperties": true, "description": "Album search results." }, "nullable": true, "handle": "albums" }, { "description": "Artist search results.", "jsonSchema": { "type": "object", "properties": { "href": { "type": "string", "description": "Spotify API URL for this page." }, "limit": { "type": "integer", "description": "Maximum number of items returned." }, "next": { "type": [ "string", "null" ], "description": "URL for the next page when available." }, "offset": { "type": "integer", "description": "Zero-based index of the first returned item." }, "previous": { "type": [ "string", "null" ], "description": "URL for the previous page when available." }, "total": { "type": "integer", "description": "Total number of matched items." }, "items": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Spotify resource ID." }, "name": { "type": "string", "description": "Spotify resource name." }, "uri": { "type": "string", "description": "Spotify resource URI." }, "href": { "type": "string", "description": "Spotify resource API URL." }, "type": { "type": "string", "description": "Spotify resource type." }, "external_urls": { "type": "object", "additionalProperties": { "type": "string", "description": "A record value." }, "description": "External URLs for the resource." } }, "additionalProperties": true, "description": "Simplified Spotify search resource." }, "description": "Search results for this resource type." } }, "required": [ "href", "limit", "offset", "total", "items" ], "additionalProperties": true, "description": "Artist search results." }, "nullable": true, "handle": "artists" }, { "description": "Playlist search results.", "jsonSchema": { "type": "object", "properties": { "href": { "type": "string", "description": "Spotify API URL for this page." }, "limit": { "type": "integer", "description": "Maximum number of items returned." }, "next": { "type": [ "string", "null" ], "description": "URL for the next page when available." }, "offset": { "type": "integer", "description": "Zero-based index of the first returned item." }, "previous": { "type": [ "string", "null" ], "description": "URL for the previous page when available." }, "total": { "type": "integer", "description": "Total number of matched items." }, "items": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Spotify resource ID." }, "name": { "type": "string", "description": "Spotify resource name." }, "uri": { "type": "string", "description": "Spotify resource URI." }, "href": { "type": "string", "description": "Spotify resource API URL." }, "type": { "type": "string", "description": "Spotify resource type." }, "external_urls": { "type": "object", "additionalProperties": { "type": "string", "description": "A record value." }, "description": "External URLs for the resource." } }, "additionalProperties": true, "description": "Simplified Spotify search resource." }, "description": "Search results for this resource type." } }, "required": [ "href", "limit", "offset", "total", "items" ], "additionalProperties": true, "description": "Playlist search results." }, "nullable": true, "handle": "playlists" }, { "description": "Track search results.", "jsonSchema": { "type": "object", "properties": { "href": { "type": "string", "description": "Spotify API URL for this page." }, "limit": { "type": "integer", "description": "Maximum number of items returned." }, "next": { "type": [ "string", "null" ], "description": "URL for the next page when available." }, "offset": { "type": "integer", "description": "Zero-based index of the first returned item." }, "previous": { "type": [ "string", "null" ], "description": "URL for the previous page when available." }, "total": { "type": "integer", "description": "Total number of matched items." }, "items": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Spotify resource ID." }, "name": { "type": "string", "description": "Spotify resource name." }, "uri": { "type": "string", "description": "Spotify resource URI." }, "href": { "type": "string", "description": "Spotify resource API URL." }, "type": { "type": "string", "description": "Spotify resource type." }, "external_urls": { "type": "object", "additionalProperties": { "type": "string", "description": "A record value." }, "description": "External URLs for the resource." } }, "additionalProperties": true, "description": "Simplified Spotify search resource." }, "description": "Search results for this resource type." } }, "required": [ "href", "limit", "offset", "total", "items" ], "additionalProperties": true, "description": "Track search results." }, "nullable": true, "handle": "tracks" }, { "description": "Show search results.", "jsonSchema": { "type": "object", "properties": { "href": { "type": "string", "description": "Spotify API URL for this page." }, "limit": { "type": "integer", "description": "Maximum number of items returned." }, "next": { "type": [ "string", "null" ], "description": "URL for the next page when available." }, "offset": { "type": "integer", "description": "Zero-based index of the first returned item." }, "previous": { "type": [ "string", "null" ], "description": "URL for the previous page when available." }, "total": { "type": "integer", "description": "Total number of matched items." }, "items": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Spotify resource ID." }, "name": { "type": "string", "description": "Spotify resource name." }, "uri": { "type": "string", "description": "Spotify resource URI." }, "href": { "type": "string", "description": "Spotify resource API URL." }, "type": { "type": "string", "description": "Spotify resource type." }, "external_urls": { "type": "object", "additionalProperties": { "type": "string", "description": "A record value." }, "description": "External URLs for the resource." } }, "additionalProperties": true, "description": "Simplified Spotify search resource." }, "description": "Search results for this resource type." } }, "required": [ "href", "limit", "offset", "total", "items" ], "additionalProperties": true, "description": "Show search results." }, "nullable": true, "handle": "shows" }, { "description": "Episode search results.", "jsonSchema": { "type": "object", "properties": { "href": { "type": "string", "description": "Spotify API URL for this page." }, "limit": { "type": "integer", "description": "Maximum number of items returned." }, "next": { "type": [ "string", "null" ], "description": "URL for the next page when available." }, "offset": { "type": "integer", "description": "Zero-based index of the first returned item." }, "previous": { "type": [ "string", "null" ], "description": "URL for the previous page when available." }, "total": { "type": "integer", "description": "Total number of matched items." }, "items": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Spotify resource ID." }, "name": { "type": "string", "description": "Spotify resource name." }, "uri": { "type": "string", "description": "Spotify resource URI." }, "href": { "type": "string", "description": "Spotify resource API URL." }, "type": { "type": "string", "description": "Spotify resource type." }, "external_urls": { "type": "object", "additionalProperties": { "type": "string", "description": "A record value." }, "description": "External URLs for the resource." } }, "additionalProperties": true, "description": "Simplified Spotify search resource." }, "description": "Search results for this resource type." } }, "required": [ "href", "limit", "offset", "total", "items" ], "additionalProperties": true, "description": "Episode search results." }, "nullable": true, "handle": "episodes" }, { "description": "Audiobook search results.", "jsonSchema": { "type": "object", "properties": { "href": { "type": "string", "description": "Spotify API URL for this page." }, "limit": { "type": "integer", "description": "Maximum number of items returned." }, "next": { "type": [ "string", "null" ], "description": "URL for the next page when available." }, "offset": { "type": "integer", "description": "Zero-based index of the first returned item." }, "previous": { "type": [ "string", "null" ], "description": "URL for the previous page when available." }, "total": { "type": "integer", "description": "Total number of matched items." }, "items": { "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "description": "Spotify resource ID." }, "name": { "type": "string", "description": "Spotify resource name." }, "uri": { "type": "string", "description": "Spotify resource URI." }, "href": { "type": "string", "description": "Spotify resource API URL." }, "type": { "type": "string", "description": "Spotify resource type." }, "external_urls": { "type": "object", "additionalProperties": { "type": "string", "description": "A record value." }, "description": "External URLs for the resource." } }, "additionalProperties": true, "description": "Simplified Spotify search resource." }, "description": "Search results for this resource type." } }, "required": [ "href", "limit", "offset", "total", "items" ], "additionalProperties": true, "description": "Audiobook search results." }, "nullable": true, "handle": "audiobooks" } ], "name": "Search first Spotify track", "executor": { "kind": "connector", "action": "spotify.search_items" } } }, "n_529fe13eaab784e2": { "inputs": {}, "name": "Search request succeeded", "kind": "condition", "matchMode": "first", "cases": [ { "output": "succeeded", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_2549bb8a6c133171", "output": "error", "system": true } }, "operator": "isNull" } ] } ] } ] }, "n_c330ea4b0ad4a8be": { "inputs": { "tracks": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_2549bb8a6c133171", "output": "tracks" } ] } }, "name": "Select first track", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "object" }, "nullable": true, "handle": "tracks" } ], "outputs": [ { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "found" }, { "jsonSchema": { "type": "object" }, "nullable": true, "handle": "track" } ], "name": "Select first track", "moduleId": "n_5c5b21fc59b92eba", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_c514199cdcb8f775": { "inputs": {}, "name": "Track was found", "kind": "condition", "matchMode": "first", "cases": [ { "output": "found", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_c330ea4b0ad4a8be", "output": "found" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_ea35b73d1d348a9a": { "inputs": { "track": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_c330ea4b0ad4a8be", "output": "track" } ] } }, "name": "Prepare selected track URI", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "object" }, "nullable": true, "handle": "track" } ], "outputs": [ { "jsonSchema": { "type": "string", "minLength": 1 }, "nullable": false, "handle": "uri" } ], "name": "Prepare selected track URI", "moduleId": "n_7462d66967e281a2", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_d4bfced01779d0df": { "inputs": { "uri": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_ea35b73d1d348a9a", "output": "uri" } ] } }, "name": "Add track to playback queue", "onError": "error", "kind": "task", "task": { "inputs": [ { "description": "Spotify device ID to target. When omitted, Spotify uses the active device.", "jsonSchema": { "type": "string", "minLength": 1, "description": "Spotify device ID to target. When omitted, Spotify uses the active device." }, "nullable": true, "handle": "deviceId", "value": null }, { "description": "Spotify track or episode URI to add to the queue.", "jsonSchema": { "type": "string", "minLength": 1, "description": "Spotify track or episode URI to add to the queue." }, "nullable": false, "handle": "uri" } ], "outputs": [ { "description": "Whether the operation completed successfully.", "jsonSchema": { "type": "boolean", "description": "Whether the operation completed successfully." }, "nullable": false, "handle": "success" } ], "name": "Add track to playback queue", "executor": { "kind": "connector", "action": "spotify.add_item_to_playback_queue" } } }, "n_f70f79e019665c2b": { "inputs": {}, "name": "Queue request succeeded", "kind": "condition", "matchMode": "first", "cases": [ { "output": "succeeded", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_d4bfced01779d0df", "output": "error", "system": true } }, "operator": "isNull" } ] } ] } ] }, "n_6cb488969e81926e": { "inputs": {}, "name": "Queue command confirmed", "kind": "condition", "matchMode": "first", "cases": [ { "output": "succeeded", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_d4bfced01779d0df", "output": "success" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_df81f33513d9eac2": { "inputs": {}, "name": "Skip to next track", "onError": "error", "kind": "task", "task": { "inputs": [ { "description": "Spotify device ID to target. When omitted, Spotify uses the active device.", "jsonSchema": { "type": "string", "minLength": 1, "description": "Spotify device ID to target. When omitted, Spotify uses the active device." }, "nullable": true, "handle": "deviceId", "value": null } ], "outputs": [ { "description": "Whether the operation completed successfully.", "jsonSchema": { "type": "boolean", "description": "Whether the operation completed successfully." }, "nullable": false, "handle": "success" } ], "name": "Skip to next track", "executor": { "kind": "connector", "action": "spotify.skip_to_next" } } }, "n_03631f23cc103f6b": { "inputs": {}, "name": "Skip request succeeded", "kind": "condition", "matchMode": "first", "cases": [ { "output": "succeeded", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_df81f33513d9eac2", "output": "error", "system": true } }, "operator": "isNull" } ] } ] } ] }, "n_99b485704cd9629a": { "inputs": {}, "name": "Skip command confirmed", "kind": "condition", "matchMode": "first", "cases": [ { "output": "succeeded", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_df81f33513d9eac2", "output": "success" } }, "operator": "==", "right": { "kind": "value", "value": true } } ] } ] } ] }, "n_9ee2d5abe061bd49": { "inputs": {}, "name": "Resume active device", "onError": "error", "kind": "task", "task": { "inputs": [ { "description": "Spotify device ID to target. When omitted, Spotify uses the active device.", "jsonSchema": { "type": "string", "minLength": 1, "description": "Spotify device ID to target. When omitted, Spotify uses the active device." }, "nullable": true, "handle": "deviceId", "value": null }, { "description": "Spotify album, artist, or playlist URI to start.", "jsonSchema": { "type": "string", "minLength": 1, "description": "Spotify album, artist, or playlist URI to start." }, "nullable": true, "handle": "contextUri", "value": null }, { "description": "Spotify URIs in the order Spotify should use.", "jsonSchema": { "type": "array", "items": { "type": "string", "minLength": 1, "description": "Spotify URI." }, "minItems": 1, "maxItems": 100, "description": "Spotify URIs in the order Spotify should use." }, "nullable": true, "handle": "uris", "value": null }, { "description": "Offset within the selected context.", "jsonSchema": { "type": "object", "properties": { "position": { "type": "integer", "minimum": 0, "description": "Zero-based index within the context." }, "uri": { "type": "string", "minLength": 1, "description": "Spotify track URI to target within the context." } }, "additionalProperties": false, "description": "Offset within the selected context." }, "nullable": true, "handle": "offset", "value": null }, { "description": "Playback position in milliseconds.", "jsonSchema": { "type": "integer", "minimum": 0, "description": "Playback position in milliseconds." }, "nullable": true, "handle": "positionMs", "value": null } ], "outputs": [ { "description": "Whether the operation completed successfully.", "jsonSchema": { "type": "boolean", "description": "Whether the operation completed successfully." }, "nullable": false, "handle": "success" } ], "name": "Resume active device", "executor": { "kind": "connector", "action": "spotify.start_resume_playback" } } }, "n_c6c509d33cf9bb6f": { "inputs": {}, "name": "Read currently playing item", "onError": "error", "kind": "task", "task": { "inputs": [ { "description": "An ISO 3166-1 alpha-2 country code or from_token to apply market filtering.", "jsonSchema": { "anyOf": [ { "const": "from_token", "description": "A union variant." }, { "type": "string", "minLength": 2, "maxLength": 2, "description": "An ISO 3166-1 alpha-2 country code." } ], "description": "An ISO 3166-1 alpha-2 country code or from_token to apply market filtering." }, "nullable": true, "handle": "market", "value": null }, { "description": "Additional item types Spotify should return for the current item.", "jsonSchema": { "type": "array", "items": { "type": "string", "enum": [ "track", "episode" ], "description": "An array item." }, "minItems": 1, "description": "Additional item types Spotify should return for the current item." }, "nullable": true, "handle": "additionalTypes", "value": null } ], "outputs": [ { "description": "Currently playing item, or null when nothing is playing.", "jsonSchema": { "type": [ "object", "null" ], "additionalProperties": { "description": "A record value." }, "description": "Currently playing item, or null when nothing is playing." }, "nullable": true, "handle": "output" } ], "name": "Read currently playing item", "executor": { "kind": "connector", "action": "spotify.get_currently_playing_track", "outputMode": "value" } } }, "n_fb7a94a564a0847d": { "inputs": {}, "name": "Player state request succeeded", "kind": "condition", "matchMode": "first", "cases": [ { "output": "succeeded", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_c6c509d33cf9bb6f", "output": "error", "system": true } }, "operator": "isNull" } ] } ] } ] }, "n_93f35b21836553a2": { "inputs": { "mode": { "kind": "value", "value": "not_found" }, "playback": { "kind": "value", "value": null } }, "name": "Report song not found", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "mode" }, { "jsonSchema": { "type": "object" }, "nullable": true, "handle": "playback" } ], "outputs": [ { "jsonSchema": { "type": "string", "minLength": 1, "maxLength": 4096 }, "nullable": false, "handle": "reply" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "status" } ], "name": "Report song not found", "moduleId": "n_57e903a4365803bf", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_2a89ea5c8b9e4edd": { "inputs": { "mode": { "kind": "value", "value": "search" }, "playback": { "kind": "value", "value": null } }, "name": "Report search failure", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "mode" }, { "jsonSchema": { "type": "object" }, "nullable": true, "handle": "playback" } ], "outputs": [ { "jsonSchema": { "type": "string", "minLength": 1, "maxLength": 4096 }, "nullable": false, "handle": "reply" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "status" } ], "name": "Report search failure", "moduleId": "n_1c0bf3e2ecfe4ee1", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_549ce58e744b01b9": { "inputs": { "mode": { "kind": "value", "value": "queue" }, "playback": { "kind": "value", "value": null } }, "name": "Report queue uncertainty", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "mode" }, { "jsonSchema": { "type": "object" }, "nullable": true, "handle": "playback" } ], "outputs": [ { "jsonSchema": { "type": "string", "minLength": 1, "maxLength": 4096 }, "nullable": false, "handle": "reply" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "status" } ], "name": "Report queue uncertainty", "moduleId": "n_d0557d7607ab510b", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_7e8aaf2d2e979106": { "inputs": { "mode": { "kind": "value", "value": "skip" }, "playback": { "kind": "value", "value": null } }, "name": "Report skip uncertainty", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "mode" }, { "jsonSchema": { "type": "object" }, "nullable": true, "handle": "playback" } ], "outputs": [ { "jsonSchema": { "type": "string", "minLength": 1, "maxLength": 4096 }, "nullable": false, "handle": "reply" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "status" } ], "name": "Report skip uncertainty", "moduleId": "n_67f54d3cd40e0798", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_4d647b00dff36069": { "inputs": { "mode": { "kind": "value", "value": "current" }, "playback": { "kind": "value", "value": null } }, "name": "Report player state failure", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "mode" }, { "jsonSchema": { "type": "object" }, "nullable": true, "handle": "playback" } ], "outputs": [ { "jsonSchema": { "type": "string", "minLength": 1, "maxLength": 4096 }, "nullable": false, "handle": "reply" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "status" } ], "name": "Report player state failure", "moduleId": "n_2bde6c39e8767155", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_e53c33878e9cc4fa": { "inputs": { "mode": { "kind": "value", "value": "observed" }, "playback": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_c6c509d33cf9bb6f", "output": "output" } ] } }, "name": "Format observed player state", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "mode" }, { "jsonSchema": { "type": "object" }, "nullable": true, "handle": "playback" } ], "outputs": [ { "jsonSchema": { "type": "string", "minLength": 1, "maxLength": 4096 }, "nullable": false, "handle": "reply" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "status" } ], "name": "Format observed player state", "moduleId": "n_6847b256f1a758a7", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_f5549a4636341866": { "inputs": { "chatId": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_849365c4bd9e12e0", "output": "chatId" } ] }, "text": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_93f35b21836553a2", "output": "reply" }, { "kind": "node", "nodeId": "n_2a89ea5c8b9e4edd", "output": "reply" }, { "kind": "node", "nodeId": "n_549ce58e744b01b9", "output": "reply" }, { "kind": "node", "nodeId": "n_7e8aaf2d2e979106", "output": "reply" }, { "kind": "node", "nodeId": "n_4d647b00dff36069", "output": "reply" }, { "kind": "node", "nodeId": "n_e53c33878e9cc4fa", "output": "reply" } ] }, "parseMode": { "kind": "value", "value": "HTML" } }, "name": "Reply to original Telegram chat", "kind": "task", "task": { "inputs": [ { "description": "The target Telegram chat ID or channel username.", "jsonSchema": { "anyOf": [ { "type": "integer", "description": "A numeric Telegram chat identifier." }, { "type": "string", "pattern": "^-?[0-9]+$", "description": "A numeric Telegram chat identifier encoded as a string." }, { "type": "string", "pattern": "^@[A-Za-z0-9_]+$", "description": "A Telegram @username that identifies a public chat or channel." } ], "description": "The target Telegram chat ID or channel username." }, "nullable": false, "handle": "chatId" }, { "description": "The text of the message to send.", "jsonSchema": { "type": "string", "maxLength": 4096, "minLength": 1, "description": "The text of the message to send." }, "nullable": false, "handle": "text" }, { "description": "The unique identifier of the Telegram business connection.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The unique identifier of the Telegram business connection." }, "nullable": true, "handle": "businessConnectionId", "value": null }, { "description": "The parse mode used for message entities.", "jsonSchema": { "type": "string", "enum": [ "Markdown", "MarkdownV2", "HTML" ], "description": "The parse mode used for message entities." }, "nullable": true, "handle": "parseMode", "value": null }, { "description": "Whether to send the message silently.", "jsonSchema": { "type": "boolean", "description": "Whether to send the message silently." }, "nullable": true, "handle": "disableNotification", "value": null }, { "description": "Whether to protect the sent message from forwarding and saving.", "jsonSchema": { "type": "boolean", "description": "Whether to protect the sent message from forwarding and saving." }, "nullable": true, "handle": "protectContent", "value": null }, { "description": "Whether to disable link previews in the message.", "jsonSchema": { "type": "boolean", "description": "Whether to disable link previews in the message." }, "nullable": true, "handle": "disableWebPagePreview", "value": null }, { "description": "The forum topic ID for the target message thread.", "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "The forum topic ID for the target message thread." }, "nullable": true, "handle": "messageThreadId", "value": null }, { "description": "The message ID to reply to.", "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "The message ID to reply to." }, "nullable": true, "handle": "replyToMessageId", "value": null } ], "outputs": [ { "description": "A normalized Telegram message record.", "jsonSchema": { "type": "object", "properties": { "messageId": { "type": "integer", "description": "The unique message identifier inside the chat." }, "date": { "type": "integer", "description": "The Unix timestamp when the message was sent." }, "chat": { "type": "object", "properties": { "id": { "type": "integer", "description": "The unique identifier of the chat." }, "type": { "type": "string", "description": "The chat type." }, "title": { "type": "string", "description": "The chat title." }, "username": { "type": "string", "description": "The public username of the chat." }, "firstName": { "type": "string", "description": "The first name for a private chat counterpart." }, "lastName": { "type": "string", "description": "The last name for a private chat counterpart." } }, "required": [ "id", "type" ], "additionalProperties": true, "description": "A Telegram chat record." }, "businessConnectionId": { "type": "string", "minLength": 1, "description": "The unique identifier of the Telegram business connection." }, "from": { "type": "object", "properties": { "id": { "type": "integer", "description": "The unique identifier of the user or bot." }, "isBot": { "type": "boolean", "description": "Whether the account is a bot." }, "firstName": { "type": "string", "description": "The first name of the user or bot." }, "username": { "type": "string", "description": "The username of the user or bot." } }, "required": [ "id", "isBot", "firstName" ], "additionalProperties": true, "description": "A Telegram user record." }, "senderChat": { "type": "object", "properties": { "id": { "type": "integer", "description": "The unique identifier of the chat." }, "type": { "type": "string", "description": "The chat type." }, "title": { "type": "string", "description": "The chat title." }, "username": { "type": "string", "description": "The public username of the chat." }, "firstName": { "type": "string", "description": "The first name for a private chat counterpart." }, "lastName": { "type": "string", "description": "The last name for a private chat counterpart." } }, "required": [ "id", "type" ], "additionalProperties": true, "description": "A Telegram chat record." }, "text": { "type": "string", "description": "The message text, when present." }, "caption": { "type": "string", "description": "The media caption, when present." }, "photo": { "type": "array", "items": { "type": "object", "properties": { "fileId": { "type": "string", "description": "The file identifier used to download or reuse the photo." }, "fileUniqueId": { "type": "string", "description": "The stable unique identifier of the photo." }, "width": { "type": "integer", "description": "The photo width in pixels." }, "height": { "type": "integer", "description": "The photo height in pixels." }, "fileSize": { "type": "integer", "description": "The photo file size in bytes." } }, "required": [ "fileId", "fileUniqueId", "width", "height" ], "additionalProperties": true, "description": "A Telegram photo or thumbnail size." }, "description": "The available sizes of the attached photo." }, "document": { "type": "object", "properties": { "fileId": { "type": "string", "description": "The file identifier used to download or reuse the document." }, "fileUniqueId": { "type": "string", "description": "The stable unique identifier of the document." }, "fileName": { "type": "string", "description": "The original document filename." }, "mimeType": { "type": "string", "description": "The MIME type of the document." }, "fileSize": { "type": "integer", "description": "The document file size in bytes." } }, "required": [ "fileId", "fileUniqueId" ], "additionalProperties": true, "description": "A Telegram document file." }, "location": { "type": "object", "properties": { "latitude": { "type": "number", "description": "The latitude of the location." }, "longitude": { "type": "number", "description": "The longitude of the location." }, "horizontalAccuracy": { "type": "number", "description": "The radius of uncertainty in meters." }, "livePeriod": { "type": "integer", "description": "The live location update period in seconds." }, "heading": { "type": "integer", "description": "The direction of travel in degrees." }, "proximityAlertRadius": { "type": "integer", "description": "The proximity alert radius in meters." } }, "required": [ "latitude", "longitude" ], "additionalProperties": true, "description": "A Telegram geographic location." }, "poll": { "type": "object", "properties": { "id": { "type": "string", "description": "The unique poll identifier." }, "question": { "type": "string", "description": "The poll question." }, "options": { "type": "array", "items": { "type": "object", "properties": { "text": { "type": "string", "description": "The poll option text." }, "voterCount": { "type": "integer", "description": "The number of votes for the option." } }, "required": [ "text", "voterCount" ], "additionalProperties": true, "description": "A Telegram poll option." }, "description": "The available poll options." }, "totalVoterCount": { "type": "integer", "description": "The total number of poll voters." }, "isClosed": { "type": "boolean", "description": "Whether the poll is closed." }, "isAnonymous": { "type": "boolean", "description": "Whether the poll is anonymous." }, "type": { "type": "string", "enum": [ "regular", "quiz" ], "description": "The poll type." }, "allowsMultipleAnswers": { "type": "boolean", "description": "Whether the poll allows multiple answers." }, "closeDate": { "type": "integer", "description": "The Unix timestamp when the poll closes." }, "openPeriod": { "type": "integer", "description": "The number of seconds the poll remains open." }, "explanation": { "type": "string", "description": "The explanation shown for a quiz poll." }, "correctOptionId": { "type": "integer", "description": "The zero-based identifier of the correct quiz option." } }, "required": [ "id", "question", "options", "totalVoterCount", "isClosed", "isAnonymous", "type", "allowsMultipleAnswers" ], "additionalProperties": true, "description": "A Telegram poll." }, "entities": { "type": "array", "items": { "type": "object", "properties": {}, "additionalProperties": true, "description": "A Telegram MessageEntity object." }, "description": "The entities parsed from the message text." }, "captionEntities": { "type": "array", "items": { "type": "object", "properties": {}, "additionalProperties": true, "description": "A Telegram MessageEntity object." }, "description": "The entities parsed from the media caption." }, "forwardDate": { "type": "integer", "description": "The Unix timestamp of the original forwarded message." }, "forwardFrom": { "type": "object", "properties": { "id": { "type": "integer", "description": "The unique identifier of the user or bot." }, "isBot": { "type": "boolean", "description": "Whether the account is a bot." }, "firstName": { "type": "string", "description": "The first name of the user or bot." }, "username": { "type": "string", "description": "The username of the user or bot." } }, "required": [ "id", "isBot", "firstName" ], "additionalProperties": true, "description": "A Telegram user record." }, "forwardFromChat": { "type": "object", "properties": { "id": { "type": "integer", "description": "The unique identifier of the chat." }, "type": { "type": "string", "description": "The chat type." }, "title": { "type": "string", "description": "The chat title." }, "username": { "type": "string", "description": "The public username of the chat." }, "firstName": { "type": "string", "description": "The first name for a private chat counterpart." }, "lastName": { "type": "string", "description": "The last name for a private chat counterpart." } }, "required": [ "id", "type" ], "additionalProperties": true, "description": "A Telegram chat record." }, "forwardFromMessageId": { "type": "integer", "description": "The original message identifier inside the source chat." }, "forwardSignature": { "type": "string", "description": "The original author signature for a forwarded channel post." }, "forwardSenderName": { "type": "string", "description": "The display name of a forwarded sender who disallows linking." }, "linkPreviewOptions": { "type": "object", "properties": {}, "additionalProperties": true, "description": "The link preview options attached to the message." }, "video": { "type": "object", "properties": { "fileId": { "type": "string", "description": "The file identifier used to download or reuse the video." }, "fileUniqueId": { "type": "string", "description": "The stable unique identifier of the video." }, "width": { "type": "integer", "description": "The video width in pixels." }, "height": { "type": "integer", "description": "The video height in pixels." }, "duration": { "type": "integer", "description": "The video duration in seconds." }, "thumbnail": { "type": "object", "properties": { "fileId": { "type": "string", "description": "The file identifier used to download or reuse the photo." }, "fileUniqueId": { "type": "string", "description": "The stable unique identifier of the photo." }, "width": { "type": "integer", "description": "The photo width in pixels." }, "height": { "type": "integer", "description": "The photo height in pixels." }, "fileSize": { "type": "integer", "description": "The photo file size in bytes." } }, "required": [ "fileId", "fileUniqueId", "width", "height" ], "additionalProperties": true, "description": "A Telegram photo or thumbnail size." }, "cover": { "type": "array", "items": { "type": "object", "properties": { "fileId": { "type": "string", "description": "The file identifier used to download or reuse the photo." }, "fileUniqueId": { "type": "string", "description": "The stable unique identifier of the photo." }, "width": { "type": "integer", "description": "The photo width in pixels." }, "height": { "type": "integer", "description": "The photo height in pixels." }, "fileSize": { "type": "integer", "description": "The photo file size in bytes." } }, "required": [ "fileId", "fileUniqueId", "width", "height" ], "additionalProperties": true, "description": "A Telegram photo or thumbnail size." }, "description": "The available sizes of the video cover." }, "startTimestamp": { "type": "integer", "description": "The start timestamp for the video in the message." }, "qualities": { "type": "array", "items": { "type": "object", "properties": { "fileId": { "type": "string", "description": "The file identifier used to download or reuse this video quality." }, "fileUniqueId": { "type": "string", "description": "The stable unique identifier of this video quality." }, "width": { "type": "integer", "description": "The video width in pixels." }, "height": { "type": "integer", "description": "The video height in pixels." }, "codec": { "type": "string", "description": "The codec used to encode the video." }, "fileSize": { "type": "integer", "description": "The video quality file size in bytes." } }, "required": [ "fileId", "fileUniqueId", "width", "height", "codec" ], "additionalProperties": true, "description": "A Telegram video file at one available quality." }, "description": "The available encoded video qualities." }, "fileName": { "type": "string", "description": "The original video filename." }, "mimeType": { "type": "string", "description": "The MIME type of the video." }, "fileSize": { "type": "integer", "description": "The video file size in bytes." } }, "required": [ "fileId", "fileUniqueId", "width", "height", "duration" ], "additionalProperties": true, "description": "A Telegram video file." }, "audio": { "type": "object", "properties": { "fileId": { "type": "string", "description": "The file identifier used to download or reuse the audio." }, "fileUniqueId": { "type": "string", "description": "The stable unique identifier of the audio." }, "duration": { "type": "integer", "description": "The audio duration in seconds." }, "performer": { "type": "string", "description": "The performer of the audio." }, "title": { "type": "string", "description": "The audio track title." }, "fileName": { "type": "string", "description": "The original audio filename." }, "mimeType": { "type": "string", "description": "The MIME type of the audio." }, "fileSize": { "type": "integer", "description": "The audio file size in bytes." }, "thumbnail": { "type": "object", "properties": { "fileId": { "type": "string", "description": "The file identifier used to download or reuse the photo." }, "fileUniqueId": { "type": "string", "description": "The stable unique identifier of the photo." }, "width": { "type": "integer", "description": "The photo width in pixels." }, "height": { "type": "integer", "description": "The photo height in pixels." }, "fileSize": { "type": "integer", "description": "The photo file size in bytes." } }, "required": [ "fileId", "fileUniqueId", "width", "height" ], "additionalProperties": true, "description": "A Telegram photo or thumbnail size." } }, "required": [ "fileId", "fileUniqueId", "duration" ], "additionalProperties": true, "description": "A Telegram audio file." }, "voice": { "type": "object", "properties": { "fileId": { "type": "string", "description": "The file identifier used to download or reuse the voice message." }, "fileUniqueId": { "type": "string", "description": "The stable unique identifier of the voice message." }, "duration": { "type": "integer", "description": "The voice message duration in seconds." }, "mimeType": { "type": "string", "description": "The MIME type of the voice message." }, "fileSize": { "type": "integer", "description": "The voice message file size in bytes." } }, "required": [ "fileId", "fileUniqueId", "duration" ], "additionalProperties": true, "description": "A Telegram voice message file." }, "animation": { "type": "object", "properties": { "fileId": { "type": "string", "description": "The file identifier used to download or reuse the animation." }, "fileUniqueId": { "type": "string", "description": "The stable unique identifier of the animation." }, "width": { "type": "integer", "description": "The animation width in pixels." }, "height": { "type": "integer", "description": "The animation height in pixels." }, "duration": { "type": "integer", "description": "The animation duration in seconds." }, "thumbnail": { "type": "object", "properties": { "fileId": { "type": "string", "description": "The file identifier used to download or reuse the photo." }, "fileUniqueId": { "type": "string", "description": "The stable unique identifier of the photo." }, "width": { "type": "integer", "description": "The photo width in pixels." }, "height": { "type": "integer", "description": "The photo height in pixels." }, "fileSize": { "type": "integer", "description": "The photo file size in bytes." } }, "required": [ "fileId", "fileUniqueId", "width", "height" ], "additionalProperties": true, "description": "A Telegram photo or thumbnail size." }, "fileName": { "type": "string", "description": "The original animation filename." }, "mimeType": { "type": "string", "description": "The MIME type of the animation." }, "fileSize": { "type": "integer", "description": "The animation file size in bytes." } }, "required": [ "fileId", "fileUniqueId", "width", "height", "duration" ], "additionalProperties": true, "description": "A Telegram animation file." }, "contact": { "type": "object", "properties": { "phoneNumber": { "type": "string", "description": "The contact phone number." }, "firstName": { "type": "string", "description": "The contact first name." }, "lastName": { "type": "string", "description": "The contact last name." }, "userId": { "type": "integer", "description": "The Telegram user identifier associated with the contact." }, "vcard": { "type": "string", "description": "Additional contact data in vCard format." } }, "required": [ "phoneNumber", "firstName" ], "additionalProperties": true, "description": "A Telegram contact." }, "venue": { "type": "object", "properties": { "location": { "type": "object", "properties": { "latitude": { "type": "number", "description": "The latitude of the location." }, "longitude": { "type": "number", "description": "The longitude of the location." }, "horizontalAccuracy": { "type": "number", "description": "The radius of uncertainty in meters." }, "livePeriod": { "type": "integer", "description": "The live location update period in seconds." }, "heading": { "type": "integer", "description": "The direction of travel in degrees." }, "proximityAlertRadius": { "type": "integer", "description": "The proximity alert radius in meters." } }, "required": [ "latitude", "longitude" ], "additionalProperties": true, "description": "A Telegram geographic location." }, "title": { "type": "string", "description": "The venue name." }, "address": { "type": "string", "description": "The venue address." }, "foursquareId": { "type": "string", "description": "The Foursquare place identifier." }, "foursquareType": { "type": "string", "description": "The Foursquare place type." }, "googlePlaceId": { "type": "string", "description": "The Google Places identifier." }, "googlePlaceType": { "type": "string", "description": "The Google Places type." } }, "required": [ "location", "title", "address" ], "additionalProperties": true, "description": "A Telegram venue." }, "dice": { "type": "object", "properties": { "emoji": { "type": "string", "description": "The emoji used for the animation." }, "value": { "type": "integer", "description": "The generated dice value." } }, "required": [ "emoji", "value" ], "additionalProperties": true, "description": "A Telegram animated dice result." } }, "required": [ "messageId", "date", "chat" ], "additionalProperties": true, "description": "A normalized Telegram message record." }, "nullable": false, "handle": "output" } ], "name": "Reply to original Telegram chat", "executor": { "kind": "connector", "action": "telegram.send_message", "outputMode": "value" } } }, "n_1d8152d2507fcb6d": { "name": "Song request result", "kind": "outputs", "outputDefs": [ { "jsonSchema": { "type": "string", "minLength": 1, "maxLength": 4096 }, "nullable": false, "handle": "reply" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "status" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "query" } ], "outputMappings": { "reply": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_93f35b21836553a2", "output": "reply" }, { "kind": "node", "nodeId": "n_2a89ea5c8b9e4edd", "output": "reply" }, { "kind": "node", "nodeId": "n_549ce58e744b01b9", "output": "reply" }, { "kind": "node", "nodeId": "n_7e8aaf2d2e979106", "output": "reply" }, { "kind": "node", "nodeId": "n_4d647b00dff36069", "output": "reply" }, { "kind": "node", "nodeId": "n_e53c33878e9cc4fa", "output": "reply" } ] }, "status": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_93f35b21836553a2", "output": "status" }, { "kind": "node", "nodeId": "n_2a89ea5c8b9e4edd", "output": "status" }, { "kind": "node", "nodeId": "n_549ce58e744b01b9", "output": "status" }, { "kind": "node", "nodeId": "n_7e8aaf2d2e979106", "output": "status" }, { "kind": "node", "nodeId": "n_4d647b00dff36069", "output": "status" }, { "kind": "node", "nodeId": "n_e53c33878e9cc4fa", "output": "status" } ] }, "query": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_440eae4c36ab0149", "output": "query" } ] } } } }, "edges": [ { "source": "n_ebf3545035a10b60", "target": "n_849365c4bd9e12e0" }, { "source": "n_849365c4bd9e12e0", "target": "n_6199232fb14f9654" }, { "source": "n_6199232fb14f9654", "target": "n_440eae4c36ab0149" }, { "source": "n_440eae4c36ab0149", "target": "n_2549bb8a6c133171" }, { "source": "n_2549bb8a6c133171", "target": "n_529fe13eaab784e2" }, { "source": "n_529fe13eaab784e2", "target": "n_c330ea4b0ad4a8be", "sourceHandle": "succeeded" }, { "source": "n_529fe13eaab784e2", "target": "n_2a89ea5c8b9e4edd", "sourceHandle": "otherwise" }, { "source": "n_c330ea4b0ad4a8be", "target": "n_c514199cdcb8f775" }, { "source": "n_c514199cdcb8f775", "target": "n_ea35b73d1d348a9a", "sourceHandle": "found" }, { "source": "n_ea35b73d1d348a9a", "target": "n_d4bfced01779d0df" }, { "source": "n_c514199cdcb8f775", "target": "n_93f35b21836553a2", "sourceHandle": "otherwise" }, { "source": "n_d4bfced01779d0df", "target": "n_f70f79e019665c2b" }, { "source": "n_f70f79e019665c2b", "target": "n_6cb488969e81926e", "sourceHandle": "succeeded" }, { "source": "n_6cb488969e81926e", "target": "n_df81f33513d9eac2", "sourceHandle": "succeeded" }, { "source": "n_6cb488969e81926e", "target": "n_549ce58e744b01b9", "sourceHandle": "otherwise" }, { "source": "n_f70f79e019665c2b", "target": "n_549ce58e744b01b9", "sourceHandle": "otherwise" }, { "source": "n_df81f33513d9eac2", "target": "n_03631f23cc103f6b" }, { "source": "n_03631f23cc103f6b", "target": "n_99b485704cd9629a", "sourceHandle": "succeeded" }, { "source": "n_99b485704cd9629a", "target": "n_9ee2d5abe061bd49", "sourceHandle": "succeeded" }, { "source": "n_99b485704cd9629a", "target": "n_7e8aaf2d2e979106", "sourceHandle": "otherwise" }, { "source": "n_03631f23cc103f6b", "target": "n_7e8aaf2d2e979106", "sourceHandle": "otherwise" }, { "source": "n_9ee2d5abe061bd49", "target": "n_c6c509d33cf9bb6f" }, { "source": "n_c6c509d33cf9bb6f", "target": "n_fb7a94a564a0847d" }, { "source": "n_fb7a94a564a0847d", "target": "n_e53c33878e9cc4fa", "sourceHandle": "succeeded" }, { "source": "n_fb7a94a564a0847d", "target": "n_4d647b00dff36069", "sourceHandle": "otherwise" }, { "source": "n_93f35b21836553a2", "target": "n_f5549a4636341866" }, { "source": "n_2a89ea5c8b9e4edd", "target": "n_f5549a4636341866" }, { "source": "n_549ce58e744b01b9", "target": "n_f5549a4636341866" }, { "source": "n_7e8aaf2d2e979106", "target": "n_f5549a4636341866" }, { "source": "n_4d647b00dff36069", "target": "n_f5549a4636341866" }, { "source": "n_e53c33878e9cc4fa", "target": "n_f5549a4636341866" }, { "source": "n_f5549a4636341866", "target": "n_1d8152d2507fcb6d" } ] } }, "modules": { "n_c7d37900feb39629": { "name": "Read text and reply chat", "imports": [], "source": "export default function readRequest({ update }) {\n const message = update?.message;\n if (!message || typeof message.text !== 'string' || !message.text.trim()) throw new Error('Send a nonempty text song request.');\n if (!Number.isSafeInteger(message.chat?.id)) throw new Error('The Telegram message has no valid chat ID.');\n return { text: message.text, chatId: message.chat.id };\n}\n" }, "n_5ea66f7d4b4f6595": { "name": "Check search query", "imports": [], "source": "export default function prepareQuery({ completion }) {\n if (typeof completion !== 'string' || !completion.trim()) throw new Error('The model did not return a search query.');\n return { query: completion.trim() };\n}\n" }, "n_5c5b21fc59b92eba": { "name": "Select first track", "imports": [], "source": "export default function chooseTrack({ tracks }) {\n if (!tracks || typeof tracks !== 'object' || !Array.isArray(tracks.items)) throw new Error('Spotify search did not return a track list.');\n const first = tracks.items[0];\n if (first === undefined) return { found: false, track: null };\n if (!first || typeof first !== 'object' || Array.isArray(first)) throw new Error('The first search result must be a track object.');\n return { found: true, track: first };\n}\n" }, "n_7462d66967e281a2": { "name": "Prepare selected track URI", "imports": [], "source": "export default function prepareQueueItem({ track }) {\n if (!track || typeof track.id !== 'string' || !/^[A-Za-z0-9]+$/.test(track.id)) throw new Error('The selected track has no valid ID.');\n return { uri: 'spotify:track:' + track.id };\n}\n" }, "n_57e903a4365803bf": { "name": "Report song not found", "imports": [], "source": "export default function formatReply({ mode, playback }) {\n const failures = {\n search: 'Spotify search failed. No playback commands were attempted.',\n queue: 'Spotify could not confirm adding the track to the queue. Check Spotify before repeating the request.',\n skip: 'Spotify could not confirm skipping to the next track. An earlier queue command may already have completed.',\n current: 'Playback commands were sent, but the current state could not be read. Check Spotify before repeating the request.',\n };\n let text, status;\n if (mode === 'not_found') { text = 'Song not found.'; status = 'not_found'; }\n else if (Object.hasOwn(failures, mode)) { text = failures[mode]; status = 'failed'; }\n else if (mode === 'observed') {\n if (playback !== null && (!playback || typeof playback !== 'object' || Array.isArray(playback) || playback.error)) throw new Error('Invalid Spotify playback response.');\n if (playback?.is_playing !== undefined && typeof playback.is_playing !== 'boolean') throw new Error('Invalid Spotify play/pause status.');\n const item = playback?.item;\n if (item == null) {\n text = 'Playback commands were sent, but Spotify reported no current item.'; status = 'unavailable';\n } else {\n if (typeof item.name !== 'string' || !item.name) throw new Error('The current Spotify item has no title.');\n const artists = Array.isArray(item.artists) ? item.artists.map(artist => artist?.name).filter(name => typeof name === 'string' && name) : [];\n const album = typeof item.album?.name === 'string' ? item.album.name : '';\n const state = playback.is_playing === true ? 'playing' : playback.is_playing === false ? 'paused' : 'unknown';\n text = 'Spotify reports: ' + item.name + (artists.length ? ' — ' + artists.join(', ') : '') + (album ? '\\nAlbum: ' + album : '') + '\\nPlayback: ' + state;\n status = 'observed';\n }\n } else throw new Error('Unknown Spotify reply mode.');\n const reply = text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');\n if (reply.length > 4096) throw new Error('The Spotify status exceeds Telegram’s message limit.');\n return { reply, status };\n}\n" }, "n_1c0bf3e2ecfe4ee1": { "name": "Report search failure", "imports": [], "source": "export default function formatReply({ mode, playback }) {\n const failures = {\n search: 'Spotify search failed. No playback commands were attempted.',\n queue: 'Spotify could not confirm adding the track to the queue. Check Spotify before repeating the request.',\n skip: 'Spotify could not confirm skipping to the next track. An earlier queue command may already have completed.',\n current: 'Playback commands were sent, but the current state could not be read. Check Spotify before repeating the request.',\n };\n let text, status;\n if (mode === 'not_found') { text = 'Song not found.'; status = 'not_found'; }\n else if (Object.hasOwn(failures, mode)) { text = failures[mode]; status = 'failed'; }\n else if (mode === 'observed') {\n if (playback !== null && (!playback || typeof playback !== 'object' || Array.isArray(playback) || playback.error)) throw new Error('Invalid Spotify playback response.');\n if (playback?.is_playing !== undefined && typeof playback.is_playing !== 'boolean') throw new Error('Invalid Spotify play/pause status.');\n const item = playback?.item;\n if (item == null) {\n text = 'Playback commands were sent, but Spotify reported no current item.'; status = 'unavailable';\n } else {\n if (typeof item.name !== 'string' || !item.name) throw new Error('The current Spotify item has no title.');\n const artists = Array.isArray(item.artists) ? item.artists.map(artist => artist?.name).filter(name => typeof name === 'string' && name) : [];\n const album = typeof item.album?.name === 'string' ? item.album.name : '';\n const state = playback.is_playing === true ? 'playing' : playback.is_playing === false ? 'paused' : 'unknown';\n text = 'Spotify reports: ' + item.name + (artists.length ? ' — ' + artists.join(', ') : '') + (album ? '\\nAlbum: ' + album : '') + '\\nPlayback: ' + state;\n status = 'observed';\n }\n } else throw new Error('Unknown Spotify reply mode.');\n const reply = text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');\n if (reply.length > 4096) throw new Error('The Spotify status exceeds Telegram’s message limit.');\n return { reply, status };\n}\n" }, "n_d0557d7607ab510b": { "name": "Report queue uncertainty", "imports": [], "source": "export default function formatReply({ mode, playback }) {\n const failures = {\n search: 'Spotify search failed. No playback commands were attempted.',\n queue: 'Spotify could not confirm adding the track to the queue. Check Spotify before repeating the request.',\n skip: 'Spotify could not confirm skipping to the next track. An earlier queue command may already have completed.',\n current: 'Playback commands were sent, but the current state could not be read. Check Spotify before repeating the request.',\n };\n let text, status;\n if (mode === 'not_found') { text = 'Song not found.'; status = 'not_found'; }\n else if (Object.hasOwn(failures, mode)) { text = failures[mode]; status = 'failed'; }\n else if (mode === 'observed') {\n if (playback !== null && (!playback || typeof playback !== 'object' || Array.isArray(playback) || playback.error)) throw new Error('Invalid Spotify playback response.');\n if (playback?.is_playing !== undefined && typeof playback.is_playing !== 'boolean') throw new Error('Invalid Spotify play/pause status.');\n const item = playback?.item;\n if (item == null) {\n text = 'Playback commands were sent, but Spotify reported no current item.'; status = 'unavailable';\n } else {\n if (typeof item.name !== 'string' || !item.name) throw new Error('The current Spotify item has no title.');\n const artists = Array.isArray(item.artists) ? item.artists.map(artist => artist?.name).filter(name => typeof name === 'string' && name) : [];\n const album = typeof item.album?.name === 'string' ? item.album.name : '';\n const state = playback.is_playing === true ? 'playing' : playback.is_playing === false ? 'paused' : 'unknown';\n text = 'Spotify reports: ' + item.name + (artists.length ? ' — ' + artists.join(', ') : '') + (album ? '\\nAlbum: ' + album : '') + '\\nPlayback: ' + state;\n status = 'observed';\n }\n } else throw new Error('Unknown Spotify reply mode.');\n const reply = text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');\n if (reply.length > 4096) throw new Error('The Spotify status exceeds Telegram’s message limit.');\n return { reply, status };\n}\n" }, "n_67f54d3cd40e0798": { "name": "Report skip uncertainty", "imports": [], "source": "export default function formatReply({ mode, playback }) {\n const failures = {\n search: 'Spotify search failed. No playback commands were attempted.',\n queue: 'Spotify could not confirm adding the track to the queue. Check Spotify before repeating the request.',\n skip: 'Spotify could not confirm skipping to the next track. An earlier queue command may already have completed.',\n current: 'Playback commands were sent, but the current state could not be read. Check Spotify before repeating the request.',\n };\n let text, status;\n if (mode === 'not_found') { text = 'Song not found.'; status = 'not_found'; }\n else if (Object.hasOwn(failures, mode)) { text = failures[mode]; status = 'failed'; }\n else if (mode === 'observed') {\n if (playback !== null && (!playback || typeof playback !== 'object' || Array.isArray(playback) || playback.error)) throw new Error('Invalid Spotify playback response.');\n if (playback?.is_playing !== undefined && typeof playback.is_playing !== 'boolean') throw new Error('Invalid Spotify play/pause status.');\n const item = playback?.item;\n if (item == null) {\n text = 'Playback commands were sent, but Spotify reported no current item.'; status = 'unavailable';\n } else {\n if (typeof item.name !== 'string' || !item.name) throw new Error('The current Spotify item has no title.');\n const artists = Array.isArray(item.artists) ? item.artists.map(artist => artist?.name).filter(name => typeof name === 'string' && name) : [];\n const album = typeof item.album?.name === 'string' ? item.album.name : '';\n const state = playback.is_playing === true ? 'playing' : playback.is_playing === false ? 'paused' : 'unknown';\n text = 'Spotify reports: ' + item.name + (artists.length ? ' — ' + artists.join(', ') : '') + (album ? '\\nAlbum: ' + album : '') + '\\nPlayback: ' + state;\n status = 'observed';\n }\n } else throw new Error('Unknown Spotify reply mode.');\n const reply = text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');\n if (reply.length > 4096) throw new Error('The Spotify status exceeds Telegram’s message limit.');\n return { reply, status };\n}\n" }, "n_2bde6c39e8767155": { "name": "Report player state failure", "imports": [], "source": "export default function formatReply({ mode, playback }) {\n const failures = {\n search: 'Spotify search failed. No playback commands were attempted.',\n queue: 'Spotify could not confirm adding the track to the queue. Check Spotify before repeating the request.',\n skip: 'Spotify could not confirm skipping to the next track. An earlier queue command may already have completed.',\n current: 'Playback commands were sent, but the current state could not be read. Check Spotify before repeating the request.',\n };\n let text, status;\n if (mode === 'not_found') { text = 'Song not found.'; status = 'not_found'; }\n else if (Object.hasOwn(failures, mode)) { text = failures[mode]; status = 'failed'; }\n else if (mode === 'observed') {\n if (playback !== null && (!playback || typeof playback !== 'object' || Array.isArray(playback) || playback.error)) throw new Error('Invalid Spotify playback response.');\n if (playback?.is_playing !== undefined && typeof playback.is_playing !== 'boolean') throw new Error('Invalid Spotify play/pause status.');\n const item = playback?.item;\n if (item == null) {\n text = 'Playback commands were sent, but Spotify reported no current item.'; status = 'unavailable';\n } else {\n if (typeof item.name !== 'string' || !item.name) throw new Error('The current Spotify item has no title.');\n const artists = Array.isArray(item.artists) ? item.artists.map(artist => artist?.name).filter(name => typeof name === 'string' && name) : [];\n const album = typeof item.album?.name === 'string' ? item.album.name : '';\n const state = playback.is_playing === true ? 'playing' : playback.is_playing === false ? 'paused' : 'unknown';\n text = 'Spotify reports: ' + item.name + (artists.length ? ' — ' + artists.join(', ') : '') + (album ? '\\nAlbum: ' + album : '') + '\\nPlayback: ' + state;\n status = 'observed';\n }\n } else throw new Error('Unknown Spotify reply mode.');\n const reply = text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');\n if (reply.length > 4096) throw new Error('The Spotify status exceeds Telegram’s message limit.');\n return { reply, status };\n}\n" }, "n_6847b256f1a758a7": { "name": "Format observed player state", "imports": [], "source": "export default function formatReply({ mode, playback }) {\n const failures = {\n search: 'Spotify search failed. No playback commands were attempted.',\n queue: 'Spotify could not confirm adding the track to the queue. Check Spotify before repeating the request.',\n skip: 'Spotify could not confirm skipping to the next track. An earlier queue command may already have completed.',\n current: 'Playback commands were sent, but the current state could not be read. Check Spotify before repeating the request.',\n };\n let text, status;\n if (mode === 'not_found') { text = 'Song not found.'; status = 'not_found'; }\n else if (Object.hasOwn(failures, mode)) { text = failures[mode]; status = 'failed'; }\n else if (mode === 'observed') {\n if (playback !== null && (!playback || typeof playback !== 'object' || Array.isArray(playback) || playback.error)) throw new Error('Invalid Spotify playback response.');\n if (playback?.is_playing !== undefined && typeof playback.is_playing !== 'boolean') throw new Error('Invalid Spotify play/pause status.');\n const item = playback?.item;\n if (item == null) {\n text = 'Playback commands were sent, but Spotify reported no current item.'; status = 'unavailable';\n } else {\n if (typeof item.name !== 'string' || !item.name) throw new Error('The current Spotify item has no title.');\n const artists = Array.isArray(item.artists) ? item.artists.map(artist => artist?.name).filter(name => typeof name === 'string' && name) : [];\n const album = typeof item.album?.name === 'string' ? item.album.name : '';\n const state = playback.is_playing === true ? 'playing' : playback.is_playing === false ? 'paused' : 'unknown';\n text = 'Spotify reports: ' + item.name + (artists.length ? ' — ' + artists.join(', ') : '') + (album ? '\\nAlbum: ' + album : '') + '\\nPlayback: ' + state;\n status = 'observed';\n }\n } else throw new Error('Unknown Spotify reply mode.');\n const reply = text.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>');\n if (reply.length > 4096) throw new Error('The Spotify status exceeds Telegram’s message limit.');\n return { reply, status };\n}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }