# YouTube to Blog Post, Twitter Thread & Show Notes Generator (`toshiusklay/wisprs-youtube-repurposer`) Actor

Turn any YouTube video into a blog post, Twitter/X thread, LinkedIn post, or show notes via automation. Transcribes first — no hallucinations, every claim is traceable to a timestamp. 100+ languages. No Wisprs account needed.

- **URL**: https://apify.com/toshiusklay/wisprs-youtube-repurposer.md
- **Developed by:** [Gitonga Mwaura](https://apify.com/toshiusklay) (community)
- **Categories:** AI, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-usage

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## YouTube to Blog Post, Twitter Thread & Show Notes Generator

Turn any YouTube video into a ready-to-publish Twitter/X thread, LinkedIn article, podcast show notes, or timestamped chapter list — generated from the actual transcript, not inferred from metadata. No hallucinations. No fabricated quotes.

This Actor transcribes your YouTube video using the [Wisprs API](https://wisprs.co), then passes the real transcript to the Wisprs repurpose engine to generate structured content. Every tweet, every paragraph, every quote is drawn from what was actually said in the video. The output is grounded in the source material — not invented by an LLM reading a title and description.

---

### What does this Actor do?

Generic AI writing tools that claim to "turn your YouTube video into a thread" have a structural problem: they do not actually watch the video. They read metadata and generate plausible-sounding content around a topic. The output feels authentic until you notice that the specific statistics your guest cited, the exact analogy they used, the memorable line that made the episode worth sharing — none of it is there. It was made up.

This Actor solves that by transcribing the source material first, then generating content from the real transcript.

1. Accepts YouTube video URLs (also works with podcast episodes, Loom recordings, direct mp3/mp4)
2. Transcribes the audio asynchronously via Wisprs (no timeouts — handles videos of any length)
3. Generates your chosen output format from the transcript:
   - **Thread** — 8–15 tweet Twitter/X thread with hook, body, and CTA
   - **Blog** — LinkedIn article or blog post in Markdown, 600–1,200 words
   - **Show notes** — structured podcast-style notes with summary, chapters, and verbatim quotes
   - **Summary** — 2–4 sentences for newsletter intros or email subjects
   - **Chapters** — timestamped chapter markers for YouTube descriptions
   - **Quotes** — top verbatim quotes with speaker attribution and timestamps
4. Saves the generated content plus transcript to your Apify Dataset

---

### How do I use this Actor to repurpose a YouTube video?

**Step 1 — Run the Actor**

To generate a Twitter/X thread from a YouTube video:

```json
{
  "startUrls": [
    { "url": "https://www.youtube.com/watch?v=EXAMPLE" }
  ],
  "repurposeMode": "thread"
}
````

To generate a LinkedIn article:

```json
{
  "startUrls": [
    { "url": "https://www.youtube.com/watch?v=EXAMPLE" }
  ],
  "repurposeMode": "blog"
}
```

**Step 2 — Check your Dataset**

Each video produces one dataset row with the generated content and the source transcript.

***

### What data does the Actor extract?

| Field | Description |
|---|---|
| `url` | The submitted video URL |
| `jobId` | Wisprs job identifier |
| `transcriptionId` | Transcription identifier |
| `status` | `completed` or `failed` |
| `durationSeconds` | Video duration |
| `detectedLanguage` | Detected language ISO code |
| `repurposed_thread` | Array of `{ tweetNumber, text }` (mode=thread) |
| `repurposed_blog` | Markdown string (mode=blog) |
| `repurposed_show_notes` | `{ summary, chapters, quotes, showNotes }` (mode=show\_notes) |
| `repurposed_summary` | Plain text summary (mode=summary) |
| `repurposed_chapters` | Array of `{ title, startSeconds, description }` |
| `repurposed_quotes` | Array of `{ speaker, text, startSeconds }` |
| `transcript_txt` | Full transcript (if includeTranscript=true) |

***

### Twitter/X thread output example

```json
{
  "thread": [
    { "tweetNumber": 1, "text": "The biggest mistake founders make in year one? Optimizing for signups instead of retention. Here's what we learned the hard way. [Thread]" },
    { "tweetNumber": 2, "text": "We hit 500 signups in week 2. Felt amazing. Then checked week-3 usage. 12 people. The signup metric was lying to us." },
    { "tweetNumber": 3, "text": "The question that changed everything: 'If this product disappeared tomorrow, would you be disappointed?' We asked 50 users. 48 said no." },
    { "tweetNumber": 10, "text": "TL;DR: Track the metric that breaks your heart when it's low. That's your north star.\n\nFollow for more." }
  ]
}
```

Every tweet is drawn from what was actually said in the video. Speaker-aware quotes pull the exact sentence with the speaker's name. Claims can be traced to a timestamp in the source.

***

### How much will it cost to repurpose a 20-minute video?

Pricing is pay-per-event:

- **$0.005** per video submitted
- **$0.015 per audio minute** (20-min video = $0.30)
- **$0.075** per repurpose result generated

**Example: 20-minute YouTube video → Twitter thread**

- Submit: $0.005
- Audio: 20 × $0.015 = $0.30
- Thread: $0.075
- **Total: ~$0.38 per video**

**Example: 10 videos → LinkedIn articles**

- Submit: 10 × $0.005 = $0.05
- Audio: 10 × 20 × $0.015 = $3.00
- Blog posts: 10 × $0.075 = $0.75
- **Total: ~$3.80 for 10 LinkedIn articles**

***

### What can I build with this?

**Daily thread content operation** — connect to a YouTube channel RSS feed Actor, submit new video URLs as they publish, deliver a draft thread to the creator via Slack or email within 5 minutes of upload. Charge creators $19/month for this one automation.

**Ghostwriting tool** — ghostwriters charge $500–2,000 per thread for high-profile clients. Submit the client's YouTube appearance or interview, get a draft thread in minutes, edit to voice, publish. Handle 5× the client volume.

**Podcast-to-LinkedIn pipeline** — take any interview podcast, transcribe the episodes, generate LinkedIn posts attributed to the guest's exact words. Guest gets content distribution. You get an automated content operation.

**YouTube chapter automation** — submit videos in batch and get back `chapters` arrays for every video. Inject into YouTube video descriptions via the YouTube Data API. An entire channel's chapters in one run.

**Newsletter from YouTube content** — submit relevant videos published that week, generate `summary` outputs, curate the best into a newsletter section automatically. Spend your time on selection and framing, not transcription.

***

### Supported URL formats

- YouTube videos, Shorts, and long-form
- Podcast RSS episode links
- Loom recordings
- Direct mp3, mp4, wav, m4a
- TikTok, Vimeo, and most public video/audio hosts

***

### Language support

100+ languages with automatic detection. Repurpose output is generated in the same language as the transcript. An English video produces an English thread; a Spanish video produces Spanish output.

***

### Related Actors

- [Wisprs — Podcast Show Notes Generator](https://apify.com/wisprs/podcast-show-notes) — podcast-optimized with chapters, quotes, and diarization
- [Wisprs — Audio & Video Transcription](https://apify.com/wisprs/audio-video-transcription) — transcript-only with all export formats
- [Wisprs — Social Media Transcriber](https://apify.com/wisprs/social-media-transcriber) — TikTok, Reels, Shorts

***

### FAQ

**Is the generated content based on the real transcript?**
Yes. Wisprs transcribes the audio first, then generates content from the actual words spoken. It cannot invent quotes or statistics that weren't in the video.

**Can I repurpose videos in languages other than English?**
Yes. Wisprs supports 100+ languages. The repurposed output is in the same language as the video.

**What if the video is long (90+ minutes)?**
The async job queue handles videos of any length. A 90-minute video typically completes transcription in 5–10 minutes. Set `maxPollSeconds` to 3600 for very long content.

**Can I process a full YouTube channel at once?**
Yes — pair this Actor with Apify's [YouTube Scraper](https://apify.com/streamers/youtube-scraper) to extract all video URLs from a channel, then pass them into this Actor.

***

### Support

- Documentation: [wisprs.co/docs](https://wisprs.co/docs)
- Email: tosh@belvadigital.com

***

*Real transcripts. Real content. No hallucinations.*

# Actor input Schema

## `startUrls` (type: `array`):

List of YouTube video URLs to transcribe and repurpose. Also supports podcast RSS episode links, Loom, mp3, and most video/audio URLs.

## `repurposeMode` (type: `string`):

What to generate from the transcript. 'thread' = Twitter/X thread (8–15 tweets). 'blog' = LinkedIn article or blog post in Markdown. 'show\_notes' = structured podcast-style show notes with chapters and quotes. 'summary' = 2–4 sentence overview. 'chapters' = timestamped chapter markers. 'quotes' = top verbatim quotes with timestamps.

## `language` (type: `string`):

ISO 639-1 language code (e.g. 'en', 'es'). Leave as 'auto' to detect automatically.

## `includeTranscript` (type: `boolean`):

Also save the plain-text transcript alongside the repurposed content.

## `webhookUrl` (type: `string`):

URL to POST a completion notification to for each video.

## `maxPollSeconds` (type: `integer`):

Maximum time to wait for each video to complete. Default 900 seconds (15 minutes).

## `pollIntervalSeconds` (type: `integer`):

How often to check job status. Default 10 seconds.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.youtube.com/watch?v=EXAMPLE"
    }
  ],
  "repurposeMode": "thread",
  "language": "auto",
  "includeTranscript": false,
  "maxPollSeconds": 900,
  "pollIntervalSeconds": 10
}
```

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrls": [
        {
            "url": "https://www.youtube.com/watch?v=EXAMPLE"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("toshiusklay/wisprs-youtube-repurposer").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "startUrls": [{ "url": "https://www.youtube.com/watch?v=EXAMPLE" }] }

# Run the Actor and wait for it to finish
run = client.actor("toshiusklay/wisprs-youtube-repurposer").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://www.youtube.com/watch?v=EXAMPLE"
    }
  ]
}' |
apify call toshiusklay/wisprs-youtube-repurposer --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=toshiusklay/wisprs-youtube-repurposer",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "YouTube to Blog Post, Twitter Thread & Show Notes Generator",
        "description": "Turn any YouTube video into a blog post, Twitter/X thread, LinkedIn post, or show notes via automation. Transcribes first — no hallucinations, every claim is traceable to a timestamp. 100+ languages. No Wisprs account needed.",
        "version": "1.0",
        "x-build-id": "AguZY5hjnnOrhChOC"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/toshiusklay~wisprs-youtube-repurposer/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-toshiusklay-wisprs-youtube-repurposer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/toshiusklay~wisprs-youtube-repurposer/runs": {
            "post": {
                "operationId": "runs-sync-toshiusklay-wisprs-youtube-repurposer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/toshiusklay~wisprs-youtube-repurposer/run-sync": {
            "post": {
                "operationId": "run-sync-toshiusklay-wisprs-youtube-repurposer",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "startUrls",
                    "repurposeMode"
                ],
                "properties": {
                    "startUrls": {
                        "title": "YouTube Video URLs",
                        "type": "array",
                        "description": "List of YouTube video URLs to transcribe and repurpose. Also supports podcast RSS episode links, Loom, mp3, and most video/audio URLs.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "repurposeMode": {
                        "title": "Output Format",
                        "enum": [
                            "thread",
                            "blog",
                            "show_notes",
                            "summary",
                            "chapters",
                            "quotes"
                        ],
                        "type": "string",
                        "description": "What to generate from the transcript. 'thread' = Twitter/X thread (8–15 tweets). 'blog' = LinkedIn article or blog post in Markdown. 'show_notes' = structured podcast-style show notes with chapters and quotes. 'summary' = 2–4 sentence overview. 'chapters' = timestamped chapter markers. 'quotes' = top verbatim quotes with timestamps.",
                        "default": "thread"
                    },
                    "language": {
                        "title": "Language",
                        "type": "string",
                        "description": "ISO 639-1 language code (e.g. 'en', 'es'). Leave as 'auto' to detect automatically.",
                        "default": "auto"
                    },
                    "includeTranscript": {
                        "title": "Include Raw Transcript",
                        "type": "boolean",
                        "description": "Also save the plain-text transcript alongside the repurposed content.",
                        "default": false
                    },
                    "webhookUrl": {
                        "title": "Webhook URL (optional)",
                        "type": "string",
                        "description": "URL to POST a completion notification to for each video."
                    },
                    "maxPollSeconds": {
                        "title": "Max Poll Time (seconds)",
                        "minimum": 60,
                        "maximum": 3600,
                        "type": "integer",
                        "description": "Maximum time to wait for each video to complete. Default 900 seconds (15 minutes).",
                        "default": 900
                    },
                    "pollIntervalSeconds": {
                        "title": "Poll Interval (seconds)",
                        "minimum": 5,
                        "maximum": 60,
                        "type": "integer",
                        "description": "How often to check job status. Default 10 seconds.",
                        "default": 10
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
