uz
Feedback
ToCode

ToCode

Kanalga Telegramโ€™da oโ€˜tish

ื˜ื™ืคื™ื ืงืฆืจื™ื ืœืžืชื›ื ืชื™ื ืžืืช ื™ื ื•ืŸ ืคืจืง

Ko'proq ko'rsatish
1 418
Obunachilar
-224 soatlar
-37 kunlar
-630 kunlar
Postlar arxiv
ToCode
1 418
ืœืคื ื™ ืฉื ืชื™ื™ื ื‘ืขื•ืœื ืฉืœ ื”ืื™ื ื˜ืจื ื˜ ืฉื ืชื™ื™ื ื–ื” ื”ืžื•ืŸ ื–ืžืŸ. ืงื•ื“ ืฉื ื›ืชื‘ ืœืคื ื™ ืฉื ืชื™ื™ื ื”ื•ื ื™ืฉืŸ, ื’ืจื•ืข, ืœื ืžืชื•ื—ื–ืง, ืžื›ื•ืขืจ. ืื‘ืœ ื‘ืขื•ืœื ื”ืืžื™ืชื™? ื‘ืขื•ืœื ื”ืืžื™ืชื™ ื™ืฉ ืžืขืจื›ื•ืช ืฉื ื›ืชื‘ื• ื’ื ืœืคื ื™ ืขืฉืจ ืฉื ื™ื ื•ื”ืŸ ืขื“ื™ื™ืŸ ืžืชื•ื—ื–ืงื•ืช. ื‘ืขื•ืœื ื”ืืžื™ืชื™ ืžืขืจื›ื•ืช ืืœื” ืžืžืฉื™ื›ื•ืช ืœืงื‘ืœ ืชื™ืงื•ื ื™ื, ืขื“ื›ื•ื ื™ื ื•ืคื™ืฆ'ืจื™ื ื—ื“ืฉื™ื. ื‘ืขื•ืœื ื”ืืžื™ืชื™ ืื ื—ื ื• ืœื ื–ื•ืจืงื™ื ืœืคื— ืงื•ื“ ืจืง ื‘ื’ืœืœ ืฉืžื™ืฉื”ื• ื”ื—ืœื™ื˜ ืฉืฆืจื™ืš ืœื”ืคืกื™ืง ืœื›ืชื•ื‘ ืจื™ืืงื˜ ืขื class ื•ืฆืจื™ืš ืœื”ืฉืชืžืฉ ื‘ use. ื‘ื˜ื•ื•ื— ื”ืจื—ื•ืง ื™ืฉ ื“ื‘ืจื™ื ืื—ืจื™ื ืฉืžืคืจื™ืขื™ื ืœื™ ื‘ืงื•ื“: 1. ืงื•ืžืคื•ื ื ื˜ื” ืฉืœ ืžืขืœ 100 ืฉื•ืจื•ืช. 2. ืœื•ื’ื™ืงื” ื‘ืชื•ืš JSX. 3. ืงื•ืžืคื•ื ื ื˜ื” ืฉืžืงื‘ืœืช ื™ื•ืชืจ ืž-4 ืคืจื•ืคืก. 4. ืคืจื•ืค ื“ืจื™ืœื™ื ื’ - ืงื•ืžืคื•ื ื ื˜ื” ืฉืœื•ืงื—ืช ืคืจื•ืคืก ืจืง ื‘ืฉื‘ื™ืœ ืœื”ืขื‘ื™ืจ ืื•ืชื ืœื™ืœื“ื™ื. 5. ืœื•ื’ื™ืงื” (ืคื•ื ืงืฆื™ื•ืช) ื‘ืชื•ืš ืงื•ืžืคื•ื ื ื˜ื”, ื‘ืžืงื•ื ื‘ Custom Hook ืื• ืงื•ื‘ืฅ ื ืคืจื“. ื›ืœ ื”ื“ื‘ืจื™ื ื”ืืœื” ื ื—ืฉื‘ื• ื‘ืขื™ื™ืชื™ื™ื ื’ื ืœืคื ื™ ืฉื ืชื™ื™ื ื•ื’ื ืœืคื ื™ ืขืฉืจ ืฉื ื™ื. ื‘ื—ืฉื™ื‘ื” ืงื“ื™ืžื” ื›ื“ื™ ืฉื”ื™ื™ืฉื•ื ืฉืœื ื• ื™ื—ื–ื™ืง ืœืื•ืจืš ื–ืžืŸ ืœื ืงืจื™ื˜ื™ ืœื”ืฉืชืžืฉ ื‘ API ื”ื›ื™ ืžื•ื“ืจื ื™ (ื”ื•ื ืžืžื™ืœื ื™ืจืื” ื™ืฉืŸ ืขื•ื“ ืฉื ืชื™ื™ื). ื›ืŸ ื—ืฉื•ื‘ ืœื”ืฉืชืžืฉ ื‘ Best Practices ืฉืœ ืคื™ืชื•ื— ืชื•ื›ื ื” - ืืœื” ืขืงืจื•ื ื•ืช ืฉื™ื™ืฉืืจื• ืื™ืชื ื• ืœื ืฆื—.

ToCode
1 418
1. ืงื•ื“ ืฆื“ ืฉืจืช ืžื›ื™ืจ ืืช ืงื‘ืฆื™ ื” JSX ืื• TSX ืฉืœ ื”ืคืจื•ื™ืงื˜ ื•ืžืจื™ืฅ ืื•ืชื ื‘ืชื’ื•ื‘ื” ืœื‘ืงืฉื” ืžื“ืคื“ืคืŸ ื›ื“ื™ ืœื”ื—ื–ื™ืจ ืœื“ืคื“ืคืŸ ื“ืฃ HTML ืžื•ื›ืŸ ืœื”ืฆื’ื”. 2. ืงื•ื“ JavaScript ื™ืฆื•ืจืฃ ืœืขืžื•ื“ ื” HTML ืฉื ืฉืœื— ื›ื“ื™ ืœื”ื•ืกื™ืฃ ืื™ื ื˜ืจืงื˜ื™ื‘ื™ื•ืช ืœืขืžื•ื“ (ืงื•ืžืคื•ื ื ื˜ื•ืช ืฆื“ ืœืงื•ื—). ืงื•ื“ ื” JavaScript ืžืชื—ื™ืœ ืชืžื™ื“ ืž State ืจืืฉื•ื ื™ ืฉื ื˜ืขืŸ ืžื”ืฉืจืช. 3. ืคืขื•ืœื•ืช ื‘ืฆื“ ื”ืœืงื•ื— ื™ื›ื•ืœื•ืช ืœื”ืฉืคื™ืข ืขืœ ื”ืฉืจืช, ื•ืื– ื ืฉืชืžืฉ ื‘ืžื ื’ื ื•ื ื™ื ืฉืœ ืจื™ืืงื˜ (Server Actions) ื›ื“ื™ ืœืฉืœื•ื— ื”ื•ื“ืขื” ืžื”ืœืงื•ื— ืœืฉืจืช, ื”ื•ื“ืขื” ืฉืžื‘ื—ื™ื ืช ื”ืงื•ื“ ื ืจืื™ืช ื›ืžื• ืงืจื™ืื” ืจื’ื™ืœื” ืœืคื•ื ืงืฆื™ื”. ื”ืคืจื™ื™ืžื•ื•ืจืง ืื—ืจืื™ ืขืœ ื›ืชื™ื‘ืช ืงื•ื“ ื” fetch ื•ืคื™ืขื ื•ื— ื”ืชืฉื•ื‘ื” ื‘ืฉื‘ื™ืœื ื•. 4. ืื™ืŸ ื›ืžืขื˜ ื”ืฆื“ืงื” ืœื”ืฉืชืžืฉ ื‘ Redux ืื• ืกืคืจื™ื•ืช ื ื™ื”ื•ืœ ืกื˜ื™ื™ื˜ ืฆื“ ืœืงื•ื— ืžืชื•ื—ื›ืžื•ืช ื‘ืืคืœื™ืงืฆื™ื•ืช ื›ืืœื”, ื›ื™ ืื™ืŸ ื›ืžืขื˜ ืกื˜ื™ื™ื˜. ื›ืœ ืฉื™ื ื•ื™ ื‘ืฆื“ ืœืงื•ื— ืžื™ื“ ืžื“ื•ื•ื— ืœืฉืจืช ืื• ืžื ื•ื”ืœ ื‘ืจืžืช ื”ืงื•ืžืคื•ื ื ื˜ื”. ื”ื™ืชืจื•ืŸ ื”ืžืจื›ื–ื™ ื‘ืืคืœื™ืงืฆื™ื•ืช Full Stack ื”ื•ื ื”ืคืฉื˜ื•ืช. ืืคืœื™ืงืฆื™ื” ื›ื–ืืช ื“ื•ืจืฉืช ื”ืจื‘ื” ืคื—ื•ืช ื—ื™ื‘ื•ืจื™ื ื‘ืฉื‘ื™ืœ ืœืขื‘ื•ื“ ื•ื›ื•ืœืœืช ื”ืจื‘ื” ืคื—ื•ืช ืงื•ื“ ื‘ื”ืฉื•ื•ืื” ืœืืคืœื™ืงืฆื™ื” ื‘ืงื•ื“ ื” Front End ืžื•ืคืจื“ ืžืงื•ื“ ื” Back End. ื”ื—ื™ืกืจื•ืŸ ื”ื•ื ื”ื ืขื™ืœื” ืœืชื•ืš ื”ืคืจื™ื™ืžื•ื•ืจืง ื•ื”ืงื•ืฉื™ ืœืฉืœื‘ ืืช ื”ืงื•ื“ ืขื Clients ืื—ืจื™ื ื›ืžื• ืืคืœื™ืงืฆื™ื™ืช ืžื•ื‘ื™ื™ืœ.

ToCode
1 418
ืืจื›ื™ื˜ืงื˜ื•ืจื” ืœื™ื™ืฉื•ืžื™ ืจื™ืืงื˜ ื™ื—ื“ ืขื ื”ืžืขื•ืจื‘ื•ืช ืฉืœ Vercel ื‘ืœื™ื‘ื” ืฉืœ ืจื™ืืงื˜ ืื ื—ื ื• ืจื•ืื™ื ื’ื ืฉื™ื ื•ื™ ืืจื›ื™ื˜ืงื˜ื•ืจื” ื‘ืคื™ืชื•ื— ื™ื™ืฉื•ืžื™ ืจื™ืืงื˜ - ืžืขื‘ืจ ืžืกืคืจื™ื” ืœืคื™ืชื•ื— ืงื•ื“ ืฆื“ ืœืงื•ื— ืœืคืจื™ื™ืžื•ื•ืจืง ืœืคื™ืชื•ื— Full Stack. ื‘ื•ืื• ื ืจืื” ืžื” ื”ืืคืฉืจื•ื™ื•ืช ืฉืœื ื• ื”ื™ื•ื ื•ืžืชื™ ื›ื“ืื™ ืœื‘ื—ื•ืจ ื›ืœ ืืคืฉืจื•ืช. ืคื™ืชื•ื— Front End ื‘ืจื™ืืงื˜ ื•ืงื•ื“ ืฆื“ ืฉืจืช ื‘ืชื•ืจ REST API ืจื™ืืงื˜ ืžืกื•ื’ืœืช ืœืขื‘ื•ื“ ื‘ืชื•ืจ ืกืคืจื™ื™ืช ืฆื“-ืœืงื•ื— ื•ืœื”ืฉืชืœื‘ ื‘ื›ืœ ืคืจื•ื™ืงื˜ ืฆื“ ืฉืจืช ืฉื ื‘ื ื”. ื”ืื™ื ื˜ื’ืจืฆื™ื” ื‘ื™ืŸ ืงื•ื“ ืฆื“ ื”ืฉืจืช ืœืงื•ื“ ืฆื“ ื”ืœืงื•ื— ืžืชื‘ืฆืขืช ื‘ืžืกืคืจ ืฉืœื‘ื™ื: 1. ื‘ืฉืœื‘ ื”ื‘ื ื™ื™ื” ื™ื”ื™ื” ืœื ื• ืžื ื’ื ื•ืŸ ืฉื™ื‘ื ื” ืืช ืงื‘ืฆื™ ื”ืžืงื•ืจ (JSX ืื• TSX) ื•ื™ืžื™ืจ ืื•ืชื ืœืงื‘ืฆื™ JavaScript ืฉื“ืคื“ืคืŸ ื™ื›ื•ืœ ืœืงื‘ืœ. ืœืจื•ื‘ ืื—ืจื™ ื”ื‘ื ื™ื” ืื•ืชื• ืžื ื’ื ื•ืŸ ื’ื ื™ืขืชื™ืง ืืช ื›ืœ ื”ืงื‘ืฆื™ื ืฉื ื•ืฆืจื• ืœืชื™ืงื™ื™ื” ืœื”ืคืฆื” ื›ืžื• dist ืื• public. 2. ื‘ืฉืœื‘ ื”ืคืจื•ื“ืงืฉืŸ ืœืงื•ื— ื™ืงื‘ืœ ืืคืœื™ืงืฆื™ื™ืช ืจื™ืืงื˜ ืกื˜ื˜ื™ืช, ื”ืืคืœื™ืงืฆื™ื” ืชืคื ื” ืœืฉืจืช ื›ื“ื™ ืœืžืฉื•ืš ืžื™ื“ืข ื‘ื“ืจืš ื›ืœืœ ื‘ REST API ื•ืชืฉืชืžืฉ ื‘ืžื™ื“ืข ื–ื” ื›ื“ื™ ืœื”ืฆื™ื’ ื“ื‘ืจื™ื ืขืœ ื”ืžืกืš. ืฉื™ื ื•ื™ื™ื ืฉืงื•ืจื™ื ื‘ืืคืœื™ืงืฆื™ื” ื™ื ื•ื”ืœื• ืขื ืกืคืจื™ื•ืช ื ื™ื”ื•ืœ State ื‘ืฆื“ ืœืงื•ื— ื›ืžื• ืจื™ื“ืืงืก. 3. ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ืžืงื•ื‘ืœืช ื‘ืฉืœื‘ ื–ื” ื”ื™ื ืœืฉื™ื ืืช ื”ืžื™ื“ืข ื”ืจืืฉื•ื ื™ ืฉื”ืืคืœื™ืงืฆื™ื” ืฆืจื™ื›ื” ื‘ืชื•ืš ื” JavaScript ื‘ืืžืฆืขื•ืช ื”ื’ื“ืจืช ืžืฉืชื ื” ืขืœ window ืžืชื•ืš ืงื•ื‘ืฅ ื” HTML, ืžื” ืฉืื•ืžืจ ืฉืงื•ื‘ืฅ ื” HTML ื™ื•ื’ืฉ ืžื”ืฉืจืช ื•ืœื ืžืงื•ื‘ืฅ ืกื˜ื˜ื™. ื”ื ื” ื“ื•ื’ืžื” ืž PHP ืœืฉืชื•ืœ ืžื™ื“ืข ืœืชื•ืš ื” JavaScript
<?php
// Example PHP data - you can modify this according to your needs
$data = [
    'user' => [
        'id' => 1,
        'name' => 'John Doe',
        'email' => 'john@example.com',
        'preferences' => [
            'theme' => 'dark',
            'notifications' => true
        ]
    ],
    'settings' => [
        'language' => 'en',
        'timezone' => 'UTC'
    ],
    'meta' => [
        'lastUpdated' => date('Y-m-d H:i:s'),
        'version' => '1.0.0'
    ]
];
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>State Management Example</title>
</head>
<body>
    <!-- Your HTML content here -->

    <script>
        // Initialize window.__state__ object
        window.__state__ = window.__state__ || {};
        
        // Safely encode PHP data as JSON and inject it into window.__state__
        window.__state__.data = <?php echo json_encode($data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP | JSON_PRETTY_PRINT); ?>;

        // Example of accessing the data
        console.log('User name:', window.__state__.data.user.name);
        console.log('Current theme:', window.__state__.data.user.preferences.theme);
    </script>
</body>
</html>
ื‘ืฆื“ ืฉืœ ืจื™ืืงื˜ ืื• ืจื™ื“ืืงืก, ืื ื—ื ื• ืœื•ืงื—ื™ื ืืช ื”ืžืฉืชืชื ื” window.__state__ ื‘ืชื•ืจ ื”ืขืจืš ื”ืจืืฉื•ื ื™ ืฉืžืžื ื• ื‘ื•ื ื™ื ืืช ื” Store ื•ืžืžืฉื™ื›ื™ื ืœื ื”ืœ ืืช ื”ืฉื™ื ื•ื™ื™ื ื›ืจื’ื™ืœ ืœืคื™ ืคืขื•ืœื•ืช ืžืฉืชืžืฉ ื‘ืืคืœื™ืงืฆื™ื”. ื”ื™ืชืจื•ื ื•ืช ื‘ื’ื™ืฉื” ื–ื•: 1. ืืคืฉืจ ืœืคืชื— ื•ืœื‘ื“ื•ืง ืงื•ื“ ืฆื“ ืœืงื•ื— ื•ืงื•ื“ ืฆื“ ืฉืจืช ื‘ื ืคืจื“. 2. ืืคืฉืจ ืœื”ืฉืชืžืฉ ื‘ืื•ืชื• API ื‘ืฆื“ ืฉืจืช ื’ื ืœืืคืœื™ืงืฆื™ื™ืช ืžื•ื‘ื™ื™ืœ, ืืคื™ืœื• ืฉื”ื™ื ื›ืชื•ื‘ื” ื‘ืฉืคื” ืื—ืจืช ืœื’ืžืจื™. ืคื™ืชื•ื— ืžืขืจื›ืช Full Stack ื‘ืจื™ืืงื˜ ืขื Next ื”ื™ืชืจื•ื ื•ืช ื‘ื’ื™ืฉืช ื” API ื‘ืจื•ืจื™ื ืื‘ืœ ืžื”ื ื’ื ื‘ืจื•ืจ ืœื ื• ืžื” ื”ื—ืกืจื•ื ื•ืช: ื”ืžืขืจื›ืช ืฉืœื ื• ืฆืจื™ื›ื” ืœื›ืœื•ืœ ืงื•ื“ ืฉื™ืžืฉื•ืš ืžื™ื“ืข ืžื”ืฉืจืช ื•ื™ืคืขื ื— ืื•ืชื•, ื ื“ืจืฉ ืชื™ืื•ื ื‘ื™ืŸ ืงื•ื“ ืฆื“ ืœืงื•ื— ืœืงื•ื“ ืฆื“ ืฉืจืช ื‘ืžืžืฉืงื™ื (ืžื” ืฉืžืฉืคื™ืข ืขืœ ืงืฆื‘ ื”ืคื™ืชื•ื— ื•ืขืœ ืงืฆื‘ ื”ืขื‘ื•ื“ื” ื‘ Refactoring). ื‘ื ื•ืกืฃ ื“ืคื“ืคืŸ ืฉืžื’ื™ืข ืœืืชืจ ืžืงื‘ืœ ืงื‘ืฆื™ JavaScript ื•ืจืง ืื—ืจื™ ืคื™ืขื ื•ื— ื•ื”ืจืฆืช ื” JavaScript ืืคืฉืจ ืœืจืื•ืช ืืช ื”ืืชืจ. ืงื•ื“ ื” JavaScript ืขืฉื•ื™ ืœื”ื™ื•ืช ืืจื•ืš ื‘ื”ืจื‘ื” ืžื” HTML ืฉื”ื•ื ื™ื•ืฆืจ ื•ื›ืš ืื ื—ื ื• ืžืขื‘ื™ืจื™ื ืขื•ื“ืฃ ืžื™ื“ืข ื‘ืจืฉืช. ื‘ืชื™ืขื•ื“ ืฉืœ ืจื™ืืงื˜ ื”ื“ืฃ ืฉืžืกืคืจ ืขืœ ื™ืฆื™ืจืช ืคืจื•ื™ืงื˜ ืžืžืœื™ืฅ ืขืœ ืฉื™ืžื•ืฉ ื‘ืคืจื™ื™ืžื•ื•ืจืง - ื›ืœื•ืžืจ ืžืžืœื™ืฅ ืœื™ืฆื•ืจ ืคืจื•ื™ืงื˜ ืขื next, remix ืื• expo. ื”ื‘ืœื•ืง ื”ืื—ืจื•ืŸ ื‘ืขืžื•ื“ ืžื–ื›ื™ืจ ืืช Tanstack Start ื• Redwood, ืฉื ื™ ืคืจื™ื™ืžื•ื•ืจืงื™ื ื ื•ืกืคื™ื ืœืคื™ืชื•ื— Full Stack. ื‘ื”ืชื™ื—ืก ืœ vite, ืฉื–ื• ื”ืื•ืคืฆื™ื” ื”ืงืœืืกื™ืช ืœืคื™ืชื•ื— ืงื•ื“ ืฆื“ ืœืงื•ื— ื‘ืœื‘ื“, ืžืกืคืจื™ื ืœื ื• ืฉื ืฉื”ื ืžืžืœื™ืฆื™ื ืขืœ vite ืจืง ื›ืฉืžื•ืกื™ืคื™ื ืืช ืจื™ืืงื˜ ืœืคืจื•ื™ืงื˜ ืงื™ื™ื ืื• ืื ื‘ื•ื ื™ื ืคืจื™ื™ืžื•ื•ืจืง, ืžื” ืฉืžืจืื” ืœื ื• ื‘ืฆื•ืจื” ื‘ืจื•ืจื” ืืช ื”ื›ื™ื•ื•ืŸ ืฉืœ ืฆื•ื•ืช ืจื™ืืงื˜. ืœื›ืŸ ื”ืื•ืคืฆื™ื” ื”ืฉื ื™ื” ื•ื”ื™ื•ื ืœืคื—ื•ืช ืœืคื™ ื”ืชื™ืขื•ื“ ืฉืœ React ื”ื™ื ื’ื ื”ืžื•ืžืœืฆืช ื”ื™ื ืคื™ืชื•ื— ืžื•ืฆืจ Full Stack ืขื ืจื™ืืงื˜ ื›ื—ืœืง ืžืคืจื™ื™ืžื•ื•ืจืง ื’ื“ื•ืœ ื™ื•ืชืจ. ืคืจื™ื™ืžื•ื•ืจืงื™ื ืžืฆื™ืขื™ื ืœื ื• ืืช ื”ืื•ืคืฆื™ื” ืœื‘ื ื•ืช ืืช ื”ืคืจื•ื™ืงื˜ ื‘ืชื•ืจ ืงื•ื“ ืฆื“ ืœืงื•ื— ื‘ืœื‘ื“, ืื‘ืœ ืœืจื•ื‘ ื”ื ื™ืขื•ื“ื“ื• ืื•ืชื ื• ืœื‘ื—ื•ืจ ื‘ืืจื›ื™ื˜ืงื˜ื•ืจื” ืžืงื™ืคื” ื”ื›ื•ืœืœืช ืงื•ื“ ืฉืจืช ื•ืงื•ื“ ืœืงื•ื—, ื•ื–ื” ืื•ืžืจ:

ToCode
1 418
ื”ืงื•ื“ ืœื•ืงื— ืืช ื”ืขืจืš ืœืžืฉืชื ื” temp_dir, ื•ืื– ืžื•ื—ืง ืืช ื” / ืžืชื—ื™ืœืช ื”ื ืชื™ื‘ ื•ืžื—ื‘ืจ ืืช ื–ื” ืœืชื™ืงื™ื™ื” ื‘ื” ื ืžืฆืืช ืกืคืจื™ื™ืช podcastfy ืขืฆืžื”. ืื ื™ ืœื ืžื‘ื™ืŸ ืœืžื” ื”ื ืขืฉื• ืืช ื–ื” ืื‘ืœ ื‘ืคื•ืขืœ ื–ื” ืื•ืžืจ ืฉืงื‘ืฆื™ื ื–ืžื ื™ื™ื ื™ื™ืฉืžืจื• ืœืชืช ืชื™ืงื™ื™ื” ื‘ืชื•ืš ืชื™ืงื™ื™ืช ื”ื™ื™ืฉื•ื, ืžื” ืฉืœื ืขื•ื‘ื“ ื‘ Lambda. ื‘ืฉื‘ื™ืœ ืœื‘ืจื•ื— ื‘ื›ืœ ื–ืืช ืœืชื™ืงื™ื™ืช /tmp ื‘ืœื™ ืœื›ืชื•ื‘ ืืช ืกื™ืžืŸ / ื‘ืชื—ื™ืœืช ืฉื•ืจืช ื”ื ืชื™ื‘ ื”ืฉืชืžืฉืชื™ ื‘ืกื™ืžืŸ .. ืฉืขื•ื‘ืจ ืชื™ืงื™ื™ื” ืื—ืช ืœืžืขืœื”, ื•ื›ืš ื ืงื‘ืœ ื ืชื™ื‘ ืฉื ืจืื” ื‘ืขืจืš ื›ืš:
/var/task/app/podcastfy/../../../../../../../tmp/podcastfy-demo/tmp
ื•ื”ืงื‘ืฆื™ื ื™ื™ืฉืžืจื• ื‘ืชื™ืงื™ื™ืช /tmp ื“ืจืš ื”ื ืชื™ื‘ ื”ื™ื—ืกื™. ืžื” ื ืฉืืจ ื”ืคื•ื ืงืฆื™ื” ืขื•ื‘ื“ืช ืžื›ืคืชื•ืจ Test ื‘ืžืžืฉืง ืฉืœ Lambda ื•ื–ื” ื˜ื•ื‘, ืขื“ื™ื™ืŸ ื ืฉืืจื• ืฉื ื™ ื“ื‘ืจื™ื ื›ื“ื™ ืฉื ื•ื›ืœ ืœื”ืฉืชืžืฉ ื‘ื” ื‘ืฆื•ืจื” ื ื›ื•ื ื”: 1. ื™ืฉ ืœื—ื‘ืจ ืืช ื”ืคื•ื ืงืฆื™ื” ืœืื™ืจื•ืข ื—ื™ืฆื•ื ื™ ืฉื™ื˜ืจื™ื’ ืื•ืชื”. ื‘ืงื•ื“ ื”ื“ื•ื’ืžื” ื”ื™ื ืžื•ืคืขืœืช ื“ืจืš API Gateway ื‘ืœื™ ืื•ืชื ื˜ื™ืงืฆื™ื”, ื›ืš ืฉื›ืœ ืื—ื“ ืžื›ืœ ื”ืื™ื ื˜ืจื ื˜ ื™ื›ื•ืœ ืœื”ืคืขื™ืœ ืืช ื”ืคื•ื ืงืฆื™ื”. ืฆืจื™ืš ืœืขื“ื›ืŸ ืืช ื–ื” ื›ื“ื™ ืฉื”ื™ื ืชื•ืคืขืœ ืื• ืžืชื•ืš ืื™ืจื•ืข ืฉืžื’ื™ืข ืžืชื•ืจ ืื• ืœืคื—ื•ืช ื‘ืฆื•ืจื” ืžื•ื’ื ืช ื“ืจืš API Gateway ื›ืš ืฉืจืง ื”ืฉืจืช ืฉืœื™ ื™ื•ื›ืœ ืœื”ื˜ืจื™ื’ ืืช ื”ื”ืคืขืœื”. 2. ื”ืคื•ื ืงืฆื™ื” ืžืฉืชืžืฉืช ื‘ืงื•ื‘ืฅ .env ื‘ืชื™ืงื™ื™ื” ื”ืžืงื•ืžื™ืช ื›ื“ื™ ืœื”ื’ื“ื™ืจ ืขืจื›ื™ื ืœ API Keys ืฉื”ื™ื ืฆืจื™ื›ื”. ืœ AWS ื™ืฉ ืžื ื’ื ื•ืŸ ื™ื•ืชืจ ืžืื•ื‘ื˜ื— ื‘ืฉื Secrets Manager. ื‘ืขื•ืœื ื”ืืžื™ืชื™ ื ืจืฆื” ืœื”ืฉืชืžืฉ ื‘ื• ื›ื“ื™ ืฉืœื ื™ื’ื ื‘ื• ืœื ื• ืืช ืžืคืชื—ื•ืช ื” API.

ToCode
1 418
"iam:PutRolePolicy",
                "iam:DeleteRolePolicy",
                "iam:PassRole",
                "iam:TagRole",
                "iam:UntagRole",
                "iam:AttachRolePolicy",
                "iam:DetachRolePolicy"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudformation:CreateChangeSet",
                "cloudformation:CreateStack",
                "cloudformation:UpdateStack",
                "cloudformation:DeleteStack",
                "cloudformation:DescribeStacks",
                "cloudformation:ListStacks",
                "cloudformation:GetTemplateSummary",
                "cloudformation:ValidateTemplate",
                "s3:CreateBucket",
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject",
                "lambda:CreateFunction",
                "lambda:UpdateFunctionCode",
                "lambda:UpdateFunctionConfiguration",
                "lambda:DeleteFunction",
                "lambda:GetFunction",
                "lambda:ListFunctions",
                "lambda:PublishVersion",
                "lambda:CreateAlias",
                "lambda:DeleteAlias",
                "lambda:UpdateAlias",
                "iam:CreateRole",
                "iam:DeleteRole",
                "iam:GetRole",
                "iam:PutRolePolicy",
                "iam:DeleteRolePolicy",
                "iam:PassRole"
            ],
            "Resource": "*"
        }
    ]
}
ืื—ืจื™ ืฉื™ืฉ ืžืฉืชืžืฉ ื ื›ื ืกื™ื ืœื˜ืื‘ Security Credentials ื•ื™ื•ืฆืจื™ื ืขื‘ื•ืจื• Access Key. ืžืฉื•ืจืช ื”ืคืงื•ื“ื” ื ืคืขื™ืœ:
aws configure
ื•ื ื›ื ื™ืก ืืช ื” Access Key ื•ืืช ื” Secret ื›ืฉื”ื•ื ืฉื•ืืœ ืื•ืชื ื•. ื”ืขืœืื” ืœ AWS ื•ื”ืจืฆืช ื‘ื“ื™ืงื” ืžื”ืžืžืฉืง ืฉืœื”ื ืื—ืจื™ ื—ื™ื‘ื•ืจ AWS ืืคืฉืจ ืœื”ืคืขื™ืœ:
sam deploy --guided
ื•ืœืขื ื•ืช ืขืœ ื”ืฉืืœื•ืช ื›ื“ื™ ืœื”ืขืœื•ืช ืืช ื”ืคื•ื ืงืฆื™ื” ืœ AWS. ืื—ืจื™ ืกื™ื•ื ื”ืขืœืื” ืชื•ื›ืœื• ืœืžืฆื•ื ืืช ื”ืคื•ื ืงืฆื™ื” ื‘ื“ืฃ ื”ืคื•ื ืงืฆื™ื•ืช ื‘ืกืจื‘ื™ืก Lambda ื‘ืžืžืฉืง ืฉืœ AWS, ื•ืฉื ื’ื ืชืžืฆืื• ื›ืคืชื•ืจ Test ืฉื™ืคืขื™ืœ ืืช ืคื•ื ืงืฆื™ื™ืช ื” Lambda ื”ื—ื“ืฉื” ืฉืœื ื•. ืชื™ืงื•ืŸ ื”ืงื•ื“ ื•ื”ืขืœืื” ืžื—ื“ืฉ ืœ Lambda ื™ืฉ ืžืกืคืจ ืžื’ื‘ืœื•ืช ื—ื“ืฉื•ืช ืฉืœื ืงื™ื™ืžื•ืช ื‘ื”ืคืขืœื” ืžืงื•ืžื™ืช ืขืœ SAM. ื”ืจืืฉื•ื ื” ื”ื™ื ืžื’ื‘ืœืช ื”ื–ื™ื›ืจื•ืŸ ื”ืžืงืกื™ืžืœื™ (ืกืื ืžืงื•ืžื™ ื™ื›ื•ืœ ืœืขื‘ื•ื“ ืขื ืขื“ 10 ื’'ื™ื’ื” ื–ื™ื›ืจื•ืŸ, ืื‘ืœ ื‘ืขื ืŸ ื”ื ื ืชื ื• ืœื™ ืจืง 3). ื”ืฉื ื™ื”, ื™ื•ืชืจ ื—ืฉื•ื‘ื”, ื”ื™ื ืฉืื™ ืืคืฉืจ ืœื™ืฆื•ืจ ืงื‘ืฆื™ื ืื™ืคื” ืฉืจื•ืฆื™ื ืืœื ืจืง ื‘ืชื™ืงื™ื™ืช /tmp. ื‘ืขื‘ื•ื“ื” ืขื podcastfy ืฆืจื™ืš ืœื”ื’ื™ื“ ืœื• ืœื™ืฆื•ืจ ืืช ื›ืœ ื”ืงื‘ืฆื™ื ืฉืœื• ืจืง ืฉื ื•ืืช ื–ื” ืขื•ืฉื™ื ื‘ืฉื•ืจื” ืฉื™ื•ืฆืจืช ืืช ื”ืคื•ื“ืงืกื˜ ืขื ืคืจืžื˜ืจ ื ื•ืกืฃ ืฉืœ ื”ื’ื“ืจื•ืช ืฉื™ื—ื”. ื–ื” ื ืจืื” ื›ืš:
    audio_file = generate_podcast(
            urls=["https://en.wikipedia.org/wiki/Podcast"],
            conversation_config={
                "text_to_speech": {
                    "temp_audio_dir": "../../../../../../../../../../../../tmp/podcastify-demo/tmp",
                    "output_directories": {
                        "transcripts": "/tmp/podcastify-demo/transcripts",
                        "audio": "/tmp/podcastify-demo/audio"
                        }
                    }
                }
            )
ืืช ืฉื ื™ ื”ืขืจื›ื™ื ื‘ืชื•ืš output_directories ืงืœ ืœื”ื‘ื™ืŸ, ืื‘ืœ ืžื” ื”ืกื™ืคื•ืจ ืขื ื›ืœ ื”ื ืงื•ื“ื•ืช ื‘ temp_audio_dir ? ื ื•, ื–ื” ืžืขื ื™ื™ืŸ. ื‘ืงื•ื“ ื”ืกืคืจื™ื” podcastfy ื”ืฉื•ืจื•ืช ื”ื‘ืื•ืช ืžื˜ืคืœื•ืช ื‘ืขืจืš ืฉืื ื™ ืžืขื‘ื™ืจ ื›ืืŸ:
def _setup_directories(self) -> None:
    """Setup required directories for audio processing."""
    self.output_directories = self.tts_config.get("output_directories", {})
    temp_dir = self.tts_config.get("temp_audio_dir", "data/audio/tmp/").rstrip("/").split("/")
    self.temp_audio_dir = os.path.join(*temp_dir)
    base_dir = os.path.abspath(os.path.dirname(__file__))
    self.temp_audio_dir = os.path.join(base_dir, self.temp_audio_dir)

ToCode
1 418
API Gateway Lambda Proxy Input Format

        Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format

    context: object, required
        Lambda Context runtime methods and attributes

        Context doc: https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html

    Returns
    ------
    API Gateway Lambda Proxy Output Format: dict

        Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
    """
    audio_file = generate_podcast(urls=["https://en.wikipedia.org/wiki/Podcast"])
    print(audio_file)

    return {
        "statusCode": 200,
        "body": json.dumps(
            {
                "message": "Audio File Created",
            }
        ),
    }
ื•ื‘ืขืฆื ื”ื•ื ืžื™ื™ืฆืจ ืคื•ื“ืงืกื˜ ืžื“ืฃ ื‘ wikipedia ืฉื•ืžืจ ืื•ืชื• ื‘ืชื™ืงื™ื™ื” ื”ืžืงื•ืžื™ืช ื•ื™ื•ืฆื. ืื ื™ ื™ื•ื“ืข ืœื ืžืœื”ื™ื‘ ื‘ืžื™ื•ื—ื“ ืื‘ืœ ืžืกืคื™ืง ื˜ื•ื‘ ื‘ืฉื‘ื™ืœ ื”ื“ื•ื’ืžื” ืฉืœื ื•. ืื—ืจื™ ืฉื‘ื ื™ืชื™ ืืช ื”ืื™ืžื’' ืื ื™ ื™ื›ื•ืœ ืœื”ืจื™ืฅ ืืช ื”ืคื•ื ืงืฆื™ื” ืขื:
sam local invoke HelloWorldFunction --debug
ื” --debug ื”ื•ื ืื•ืคืฆื™ื•ื ืืœื™ ืื‘ืœ ืžื•ืžืœืฅ ืžืื•ื“ ื›ื™ ื›ืฉื“ื‘ืจื™ื ื ืฉื‘ืจื™ื ืืชื ืจื•ืฆื™ื ืœื“ืขืช ืœืžื”. ืื ืœืงื—ืชื ืืช ืคืจื•ื™ืงื˜ ื”ื“ื•ื’ืžื” ืฉืœื™ ื–ื” ื›ื ืจืื” ื™ืขื‘ื•ื“ ื‘ื–ื›ื•ืช ืฉืชื™ ื”ื’ื“ืจื•ืช ื‘ืงื•ื‘ืฅ ื” template.yaml:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      PackageType: Image
      Timeout: 600
      MemorySize: 3008
ื”ื’ื“ืจืช ื” Timeout ื—ืฉื•ื‘ื” ื›ื™ ืœื™ืฆื•ืจ ืคื•ื“ืงืกื˜ื™ื ืœื•ืงื— ื–ืžืŸ ื•ื‘ืจื™ืจืช ื”ืžื—ื“ืœ 10 ืฉื ื™ื•ืช ืงืฆืจื” ืžื“ื™. ื’ื•ื“ืœ ื”ื–ื™ื›ืจื•ืŸ ื‘ื‘ืจื™ืจืช ื”ืžื—ื“ืœ ื”ื•ื 128 ืžื’ื” ืฉื–ื” ื’ื ืงื˜ืŸ ืžื“ื™, ืœืคื™ ื”ืชื™ืขื•ื“ ืืคืฉืจ ืœื”ืงืฆื•ืช ืขื“ 10 ื’'ื™ื’ื” ืื‘ืœ ืžื ื™ืกื•ื™ื™ื ืฉืœื™ 3 ื’'ื™ื’ื” ื”ื™ื” ื”ืžืงืกื™ืžื•ื ืฉื”ืฆืœื—ืชื™ ืœืงื‘ืœ ื•ืœื›ืŸ ื–ื” ื”ื’ื•ื“ืœ ืฉื”ืฉืืจืชื™. ืื ื”ืคื•ื ืงืฆื™ื” ืจืฆื” ืžืงื•ืžื™ืช ื•ื”ื›ืœ ืขื•ื‘ื“ ืืคืฉืจ ืœื”ืžืฉื™ืš ืœืฉืœื‘ ื”ื‘ื. ื™ืฆื™ืจืช ืžืฉืชืžืฉ AWS ื‘ืฉื‘ื™ืœ ืœื”ืขืœื•ืช ืืช ื”ืงื•ื“ ืœ Lambda ืขืœ AWS ื™ืฉ ืœื™ืฆื•ืจ ืžืฉืชืžืฉ ื‘ืกืจื‘ื™ืก IAM ืฉืœื”ื ื•ืœืชืช ืœื• ืžืกืคื™ืง ื”ืจืฉืื•ืช ื›ื“ื™ ืœื”ืขืœื•ืช ืืช ื”ืงื•ื“. ื™ื›ื•ืœ ืœื”ื™ื•ืช ืฉืืคืฉืจ ืœื”ืฉืชืžืฉ ืคื” ื‘ืžืฉืชืžืฉ ื”ืจืืฉื™ ืฉืœื›ื (ืœื ื ื™ืกื™ืชื™), ื•ื‘ื›ืœ ืžืงืจื” ืื ืืชื ื™ื•ืฆืจื™ื ืžืฉืชืžืฉ ื•ืื™ืŸ ืœื• ืžืกืคื™ืง ื”ืจืฉืื•ืช ืชืงื‘ืœื• ื”ื•ื“ืขืช ืฉื’ื™ืื” ื‘ deploy ื•ืื– ืืคืฉืจ ืœื”ื•ืกื™ืฃ ื”ืจืฉืื•ืช ืœืคื™ ืžื” ืฉื”ื•ื ืžื‘ืงืฉ ื•ื™ืฉ ื’ื ื›ืคืชื•ืจ ื‘ืžืžืฉืง ืฉืขื•ืฉื” ืืช ื–ื” ืื•ื˜ื•ืžื˜ื™ืช. ื”ื”ืจืฉืื•ืช ืฉืื ื™ ื ืชืชื™ ื‘ืกื•ืคื• ืฉืœ ื“ื‘ืจ ื”ื™ื•: 1. AmazonAPIGatewayAdministrator 2. AmazonS3FullAccess 3. AWSCloudFormationFullAccess 4. AWSLambda_FullAccess ื•ื‘ื ื•ืกืฃ ื’ื:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:CreateServiceLinkedRole"
            ],
            "Resource": "arn:aws:iam::*:role/aws-service-role/apigateway.amazonaws.com/AWSServiceRoleForAPIGateway",
            "Condition": {
                "StringLike": {
                    "iam:AWSServiceName": "apigateway.amazonaws.com"
                }
            }
        }
    ]
}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecr:CreateRepository",
                "ecr:GetAuthorizationToken",
                "ecr:InitiateLayerUpload",
                "ecr:UploadLayerPart",
                "ecr:CompleteLayerUpload",
                "ecr:PutImage",
                "ecr:BatchCheckLayerAvailability",
                "ecr:GetDownloadUrlForLayer",
                "ecr:TagResource",
                "ecr:DescribeRepositories",
                "ecr:DeleteRepository",
                "ecr:SetRepositoryPolicy",
                "ecr:GetRepositoryPolicy"
            ],
            "Resource": [
                "arn:aws:ecr:us-east-1:124355662604:repository/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "ecr:GetAuthorizationToken",
            "Resource": "*"
        }
    ]
}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:CreateServiceLinkedRole",
                "iam:CreateRole",
                "iam:DeleteRole",
                "iam:GetRole",

ToCode
1 418
ืžื“ืจื™ืš: ื”ื›ื ืช ืกื‘ื™ื‘ื” ื•ื”ืจืฆืช ืงื•ื“ ืคื™ื™ืชื•ืŸ ื‘ AWS Lambda ืื ื™ืฉ ืžืฉื”ื• ืฉืžืืคื™ื™ืŸ ืืช AWS ื–ื” ื”ืคืขืจ ื‘ื™ืŸ ื”ืชื™ืื•ืจื™ื” ืœืคืจืงื˜ื™ืงื”. ืงืœ ืžืื•ื“ ืœืชืืจ ืžื” ืื ื™ ืจื•ืฆื” ืœืขืฉื•ืช ืื‘ืœ ื‘ื“ืจืš ืœื”ืคื•ืš ืืช ื–ื” ืœืงื•ื“ ื”ืจื‘ื” ื“ื‘ืจื™ื ืžืกืชื‘ื›ื™ื. ื‘ืžื“ืจื™ืš ื”ื™ื•ื ื ืจืื” ืื™ืš ืœื”ืคืขื™ืœ ืชื•ื›ื ื™ืช ืคื™ื™ืชื•ืŸ ืขืœ Lambda, ืžื” ื™ื›ื•ืœ ืœื”ืฉืชื‘ืฉ ื‘ื“ืจืš ื•ืื™ืš ืœืชืงืŸ. ื”ืชืงื ืช ื”ื›ืœื™ื ืœืฆื•ืจืš ื”ืžื“ืจื™ืš ืื ื™ ืžื ื™ื— ืฉื™ืฉ ืœื›ื ืขืœ ื”ืžื›ื•ื ื” ืืช ื”ื›ืœื™ื ื”ื‘ืื™ื ืžื•ืชืงื ื™ื: 1. ื›ืœื™ ืฉื•ืจืช ื”ืคืงื•ื“ื” ืฉืœ AWS. ื”ืชืงื ื” ืžื›ืืŸ: https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html. 2. ื›ืœื™ ืฉื•ืจืช ื”ืคืงื•ื“ื” SAM. ื”ืชืงื ื” ืžื›ืืŸ: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/install-sam-cli.html 3. ื“ื•ืงืจ. ื”ืชืงื ื” ืžื›ืืŸ: https://docs.docker.com/ 4. ืžืื•ื“ ืžื•ืžืœืฅ ืœื”ืจื™ืฅ ืืช ื”ืžื“ืจื™ืš ืžืžื›ื•ื ืช ืœื™ื ื•ืงืก ื‘ืืจื›ื™ื˜ืงื˜ื•ืจื” x86_64 ื›ื™ ื–ื• ื”ืืจื›ื™ื˜ืงื˜ื•ืจื” ืขืœื™ื” ืจืฅ ื” Lambda. ื‘ืขื‘ื•ื“ื” ืขืœ ื”ืžืง ื ืชืงืœืชื™ ื‘ื”ืžื•ืŸ ืชืงืœื•ืช ืžื•ื–ืจื•ืช ืชื•ืš ื›ื“ื™ ืฉื ืขืœืžื• ืœื’ืžืจื™ ื›ืฉืขื‘ืจืชื™ ืœืœื™ื ื•ืงืก. ื•ื›ืžื•ื‘ืŸ ืื ื™ ืžื ื™ื— ืฉื™ืฉ ืœื›ื ืžืฉืชืžืฉ ืขืœ AWS. ื‘ืคื•ืกื˜ ื ืฉืชืžืฉ ื‘ SAM ืฉื”ื•ื ื”ืจื—ื‘ื” ืฉืœ CloudFormation, ื›ืœื•ืžืจ ื›ืœื™ ืœืชื™ืื•ืจ ืืจื›ื™ื˜ืงื˜ื•ืจื” ื‘ืืžืฆืขื•ืช ืงื•ื‘ืฅ yml ื•ื”ืจืฆืชื” ืžืงื•ืžื™ืช ืžื—ื•ืฅ ืœ AWS ื›ื“ื™ ืœื‘ื“ื•ืง ืฉืคื•ื ืงืฆื™ื•ืช ื” Lambda ืฉื™ืฆืจื ื• ืขื•ื‘ื“ื•ืช. ื‘ื”ืฉื•ื•ืื” ืœ localstack ืขืœื™ื• ื›ืชื‘ืชื™ ื‘ืคื•ืกื˜ื™ื ืงื•ื“ืžื™ื, ืกืื ืžืจื™ืฅ ืจืง ืคื•ื ืงืฆื™ื•ืช Lambda ื•ืœื ื›ื•ืœืœ ืืช ืฉื™ืจื•ืชื™ AWS ื”ืื—ืจื™ื. ืชื‘ื ื™ืช ื”ืคืจื•ื™ืงื˜ ื‘ืฉื‘ื™ืœ ื”ื“ื•ื’ืžื” ืื ื™ ื‘ื•ื ื” ืคืจื•ื™ืงื˜ ืฉื™ื•ืฆืจ ืคื•ื“ืงืกื˜ ืขื ืกืคืจื™ื™ืช podcastfy. ื™ืฆืจืชื™ ืืช ืชื‘ื ื™ืช ื”ืคืจื•ื™ืงื˜ ื“ืจืš ื›ืœื™ ืฉื•ืจืช ื”ืคืงื•ื“ื” SAM ืขื ื”ืคืงื•ื“ื”:
$ sam init
ืืชื ื™ื›ื•ืœื™ื ืœืขืฉื•ืช ืืช ื–ื” ื•ืœื‘ื—ื•ืจ ืžื”ืชืคืจื™ื˜ ืœื™ืฆื•ืจ ืคืจื•ื™ืงื˜ ืคื™ื™ืชื•ืŸ ืขืœ ื‘ืกื™ืก Image, ืื• ืœืงื—ืช ืืช ื”ืงื‘ืฆื™ื ืžืชื‘ื ื™ืช ื”ืคืจื•ื™ืงื˜ ืฉืœ ื”ืคื•ืกื˜ ื‘ื’ื™ื˜ื”ืื‘ ื›ืืŸ: https://github.com/ynonp/lambda-podcastfy/tree/main ืœืฆื•ืจืš ื”ื“ื•ื’ืžื” ืื ื™ ืืจื™ืฅ ืชื•ื›ื ื™ืช ืคื™ื™ืชื•ืŸ ืฉืžืฉืชืžืฉืช ื‘ืกืคืจื™ื™ืช podcastfy ืœื™ืฆื™ืจืช ืคื•ื“ืงืกื˜ื™ื. ื”ืกืคืจื™ื” ืชืชืŸ ืœื ื• ื”ื–ื“ืžื ื•ืช ืœื’ืขืช ื‘ืžืกืคืจ ื ืงื•ื“ื•ืช ืจื’ื™ืฉื•ืช ืฉืœ Lambda. ืื ืืชื ืœื•ืงื—ื™ื ืืช ื”ืงื•ื“ ืฉืœื™ ืžื’ื™ื˜ื”ืื‘ ืชืฆื˜ืจื›ื• ืœื™ืฆื•ืจ ื‘ืชื•ืš ืชื™ืงื™ื™ื” hello_world ืงื•ื‘ืฅ .env ื‘ืžื‘ื ื” ื”ื‘ื:
GEMINI_API_KEY=
OPENAI_API_KEY=
ื•ื›ืŸ ื™ืฉ ืœืžืœื ืืช ื”ืžืคืชื—ื•ืช ื‘ืคื ื™ื ื‘ืฉื‘ื™ืœ ืฉื–ื” ื™ืขื‘ื•ื“. ื‘ื ื™ื™ื” ื•ื”ืจืฆื” ืžืงื•ืžื™ืช ื‘ืฉื‘ื™ืœ ืœื‘ื ื•ืช ืืช ื”ืคืจื•ื™ืงื˜ ืžืงื•ืžื™ืช ื ื•ื›ืœ ืœื”ืจื™ืฅ:
$ sam build --use-container
ื”ืชื•ืกืคืช --use-container ื’ื•ืจืžืช ืœ SAM ืœื”ืจื™ืฅ ืืช ื”ื‘ื ื™ื™ื”. ื‘ื ื™ื™ื” ื‘ื”ืงืฉืจ ื”ื–ื” ื–ื” ื‘ื ื™ื™ื” ืฉืœ ืื™ืžื’' ืฉื‘ืชื•ื›ื• ืชืจื•ืฅ ื” Lambda ืฉืœื ื•. ืืคืฉืจ ืœืจืื•ืช ื•ืœืขื“ื›ืŸ ืืช ื” Dockerfile ื‘ืงื•ื‘ืฅ hello_world/Dockerfile ื•ื”ืชื•ื›ืŸ ืฉืœื• ื‘ืคืจื•ื™ืงื˜ ื”ื“ื•ื’ืžื” ื”ื•ื:
FROM public.ecr.aws/lambda/python:3.12

WORKDIR /var/task

RUN mkdir -p /var/task/ffmpeg && \
    cd /var/task/ffmpeg && \
    curl -O https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz && \
    python -c "import tarfile; tarfile.open('ffmpeg-release-amd64-static.tar.xz').extractall()" && \
    mv ffmpeg-*-amd64-static/* . && \
    rm -rf ffmpeg-*-amd64-static && \
    rm ffmpeg-release-amd64-static.tar.xz

ENV PATH="/var/task/ffmpeg:${PATH}"
RUN chmod -R +x /var/task/ffmpeg

COPY app.py requirements.txt ./
COPY .env ./

RUN python3.12 -m pip install -r requirements.txt -t .

* Command can be overwritten by providing a different command in the template directly. *
CMD ["app.lambda_handler"]
ื‘ืคืจื•ื™ืงื˜ ื”ื“ื•ื’ืžื” ืื ื™ ืจื•ืฆื” ืœื”ืชืงื™ืŸ ืืช ืกืคืจื™ื™ืช podcastfy ื•ื”ื™ื ื“ื•ืจืฉืช ื”ืชืงื ื” ืฉืœ ffmpeg ืขืœ ื”ืžื›ื•ื ื”. ืื ื—ื ื• ืžืชื—ื™ืœื™ื ืขื ืื™ืžื’' ืฉืœ ืคื™ื™ืชื•ืŸ ืžืืžื–ื•ืŸ ื•ื‘ืชื•ื›ื• ืื™ืŸ ื›ืžืขื˜ ื›ืœื•ื, ื”ื ื›ืŸ ืฉืžื• curl ืื‘ืœ ืืคื™ืœื• tar ืœื ืžื•ืชืงืŸ ืขืœ ื”ืื™ืžื’' ื•ืœื›ืŸ ื‘ืฉื‘ื™ืœ ืœื”ืชืงื™ืŸ ืืช ffmpeg ืื ื™ ืžื•ืจื™ื“ ืืช ื”ื‘ื™ื ืืจื™ ืฉืœื• ื•ืžืฉืชืžืฉ ื‘ python -c ื›ื“ื™ ืœืคืชื•ื— ืืช ื”ืืจื›ื™ื•ืŸ. ืžื•ืกื™ืคื™ื ืืช ffmpeg ืœืจืฉื™ืžืช ื”ื ืชื™ื‘ื™ื ืœื”ืจืฆื” ื•ืžืชืงื ื™ื ื”ืจืฉืื•ืช ื•ืื– ืžืžืฉื™ื›ื™ื ืœื”ืขืชืงืช ืงื‘ืฆื™ ื”ืชื•ื›ื ื™ืช (ื‘ืคืจื•ื™ืงื˜ ืฉืœื™ ื–ื” ืจืง app.py) ื•ืงื•ื‘ืฅ ืžืฉืชื ื™ ื”ืกื‘ื™ื‘ื”. ืื—ืจื™ ื–ื” ื”ืชืงื ืช ื”ืชืœื•ื™ื•ืช ื•ื”ืคืขืœืช ื”ืคื•ื ืงืฆื™ื” ื”ืžืจื›ื–ื™ืช ืžืชื•ืš app. ื”ืงื•ื“ ื‘ app.py ื‘ื–ืžืŸ ื”ื‘ื ื™ื” ื”ืžืงื•ืžื™ืช ื”ื•ื:
import json
from podcastfy.client import generate_podcast
import os

def lambda_handler(event, context):
    """Sample pure Lambda function

    Parameters
    ----------
    event: dict, required

ToCode
1 418
ื”ื‘ื ื” ื“ื•ืจืฉืช ืฉื™ื ื•ืŸ ื”ืจื‘ื” ื”ืชืœื”ื‘ื•ืช ื‘ืจืฉืช ืกื‘ื™ื‘ ื” AI ืžืœื•ื•ื” ื‘ืชื—ื•ืฉื” ืฉืื ื—ื ื• ืžืชืงืจื‘ื™ื ืœืขื™ื“ืŸ ื‘ื• ื™ื”ื™ื” ืงืœ ื™ื•ืชืจ ืœื›ืชื•ื‘ ืงื•ื“ (ื™ืฉ ื‘ื–ื” ืžืฉื”ื•) ื•ืื•ืœื™ ืืคื™ืœื• ืฉื ื•ื›ืœ ืœื›ืชื•ื‘ ืงื•ื“ ื‘ืœื™ ืœื”ืชืขืกืง ื‘ืคืจื˜ื™ื ื”ืงื˜ื ื™ื ืฉืœ ื”ืขื‘ื•ื“ื”. ืื ื—ื ื• ื ืชืืจ ื‘ื’ื“ื•ืœ ืืช ื”ืืจื›ื™ื˜ืงื˜ื•ืจื” ื•ืžื” ื›ืœ ื“ื‘ืจ ืฆืจื™ืš ืœืขืฉื•ืช ื•ื” AI ื™ื”ืคื•ืš ืืช ื–ื” ืœื”ื•ืจืื•ืช ืžืกื•ื“ืจื•ืช. ืงืฆืช ื›ืžื• ืฉืื ื—ื ื• ืœื ืฆืจื™ื›ื™ื ืœื”ื›ื™ืจ ืืกืžื‘ืœื™ ื‘ืฉื‘ื™ืœ ืœื›ืชื•ื‘ C, ื•ืœื ืฆืจื™ื›ื™ื ืœื”ื›ื™ืจ C ื‘ืฉื‘ื™ืœ ืœื›ืชื•ื‘ Java. ืื‘ืกื˜ืจืงืฆื™ื•ืช ื ื‘ื ื•ืช ืขืœ ืจืขื™ื•ื ื•ืช ื‘ืกื™ืกื™ื™ื ื™ื•ืชืจ ื•ืื—ืจื™ ืฉื‘ื ื™ื ื• ืืช ื”ืื‘ืกื˜ืจืงืฆื™ื” ืืคืฉืจ ืœื”ืžืฉื™ืš ื”ืœืื”. ื•ืื•ืœื™ ื›ืœ ืžื” ืฉืื ื—ื ื• ื™ื•ื“ืขื™ื ืขืœ ืงื•ื“ ื”ื•ืœืš ืœื”ืฉืชื ื•ืช ื•ื ื•ื›ืœ ืœื”ืžืฉื™ืš ื”ืœืื” ืœื›ืชื•ื‘ ื‘ืœื™ ืœื”ื›ื™ืจ ืืช ื”ืคืจื˜ื™ื? ืื•ืœื™ ื ื•ื›ืœ ืœื›ืชื•ื‘ ืจืง ืขื "ื”ื‘ื ื”"? ื”ื‘ืขื™ื” ืขื ื”ืชื™ืื•ืจื™ื” ื”ื–ืืช ื”ื™ื ืฉื”ืžื™ืœื” "ื”ื‘ื ื”" ื‘ืขืฆื ืžืกืชื™ืจื” "ืื™ ื”ื‘ื ื”". ื‘ื•ืื• ื ื™ืงื— ืืช ื–ื” ืœื“ื•ื’ืžื” ืกืคืฆื™ืคื™ืช: ื ื ื™ื— ืฉืื ื™ ืžืชื›ื ืช ืจื™ืืงื˜ ื•ืื ื™ ืจื•ืฆื” ืœืœืžื•ื“ Vue. ืื ื™ ืžื‘ื™ืŸ ืžื” ื–ื” ืคืจื™ื™ืžื•ื•ืจืง ืžื‘ื•ืกืก ืงื•ืžืคื•ื ื ื˜ื•ืช ื•ืžื” ื–ื” Virtual DOM, ื•ืื•ืœื™ ืื ื™ ืืคื™ืœื• ืžืขื™ืฃ ืžื‘ื˜ ื–ืจื™ื– ื‘ืชื™ืขื•ื“ ืฉืœ Vue ื•ืจื•ืื” ืฉืื™ืŸ ืฉื ื”ืคืชืขื•ืช ื’ื“ื•ืœื•ืช. ื”ืื ืขื›ืฉื™ื• ืื ื™ "ืžื‘ื™ืŸ" ืืช Vue? ื‘ืจื•ืจ ืฉืœื, ืžืขื•ืœื ืœื ืขื‘ื“ืชื™ ืื™ืชื•. ืื ื™ ื›ืŸ ื™ื›ื•ืœ ืœืœื›ืช ืœ AI ื•ืœื›ืชื•ื‘ ืชื•ื›ื ื™ื•ืช ื‘ Vue ืขืœ ื‘ืกื™ืก ื”ื™ื“ืข ื•ื”ื”ื‘ื ื” ืฉื™ืฉ ืœื™ ืขืœ ืจื™ืืงื˜. ืื ื™ ื™ื›ื•ืœ ืœื”ื™ืขื–ืจ ื‘ AI ื›ื“ื™ ืœื“ื‘ื’ ืงื•ื“ Vue ืฉืžื™ืฉื”ื• ืื—ืจ ื›ืชื‘ ืขื‘ื•ืจื™, ื•ื’ื ืœื›ืชื•ื‘ ื‘ื“ื™ืงื•ืช ืื•ื˜ื•ืžื˜ื™ื•ืช. ืื‘ืœ ืืฃ ืื—ืช ืžื”ืžืฉื™ืžื•ืช ื”ืืœื” ืœื ืชืขื–ื•ืจ ืœื™ ืœื”ื‘ื™ืŸ ื˜ื•ื‘ ื™ื•ืชืจ ืืช Vue. ืขื›ืฉื™ื• ื‘ื•ืื• ื ื ืกื” ืžืฉื—ืง ืื—ืจ, ื ื ื™ื— ืฉื‘ืžืงื•ื ืœืชืช ืœ AI ืœื›ืชื•ื‘ ืืช ื”ืงื•ื“ ืื ื™ ืžื‘ืงืฉ ืžืžื ื• ืฉื™ืฆื™ืข ืœื™ 10 ืชื•ื›ื ื™ื•ืช ืžืืชื’ืจื•ืช ืœื›ืชื•ื‘ ื‘ Vue. ืื ื™ ื”ื•ืœืš ืœื›ืชื•ื‘ ืืช ื›ื•ืœืŸ ื•ื‘ื“ืจืš ืฆื•ืœืœ ืœืชื•ืš ื”ืชื™ืขื•ื“ ื›ื“ื™ ืœื”ื‘ื™ืŸ ืืช ื”ืคืจื˜ื™ื, ื•ืžืžืฉื™ืš ืœื›ืชื•ื‘ ืขื•ื“ 20-30 ืชื•ื›ื ื™ื•ืช ืžืชื•ืš ืจืขื™ื•ื ื•ืช ืฉืขืœื• ืœื™ ื‘ื–ืžืŸ ืฉื›ืชื‘ืชื™ ืืช ื” 10 ื”ืจืืฉื•ื ื•ืช. ืื—ืจื™ ื›ืœ ืชื•ื›ื ื™ืช ืื ื™ ืคื•ื ื” ืœ AI ื•ืžื‘ืงืฉ ืฉื™ืืชื’ืจ ืื•ืชื™ - ืฉื™ืกื‘ื™ืจ ืžื” ืœื“ืขืชื• ืขื•ื“ ืืคืฉืจ ืœืฉืคืจ ื‘ืงื•ื“. ืื—ืจื™ ื–ื” ืื—ืคืฉ ื‘ืจืฉืช ื›ืœ ื”ืฆืขื” ืฉืœื• ื•ืื ืกื” ืœืžืžืฉ ืื•ืชื” ื‘ืขืฆืžื™. ืื—ืจื™ ื›ืžื” ืฉื‘ื•ืขื•ืช ืื• ื—ื•ื“ืฉื™ื ื›ืืœื” ื‘ืจื•ืจ ืฉืื ื™ ืžื‘ื™ืŸ ืืช Vue ื“ื™ ื˜ื•ื‘, ืื‘ืœ ื’ื ื‘ืจื•ืจ ืฉืขื‘ื“ืชื™ ืงืฉื” ื‘ืฉื‘ื™ืœ ื”ื”ื‘ื ื” ื”ื–ืืช. ื•ื–ื” ืœื ื‘ืžืงืจื”. ื›ืŸ ื‘ืจื•ืจ ืฉืื ื™ืฉ ืœื›ื ื”ื‘ื ื” ื˜ื•ื‘ื” ืฉืœ ื ื•ืฉื, ื›ื–ืืช ืฉื”ืชืืžืฆืชื ืœื‘ื ื•ืช ืœืื•ืจืš ื—ื•ื“ืฉื™ื ืื• ืฉื ื™ื ื•ืฉืขืœืชื” ืœื›ื ื‘ื“ื, ื™ื–ืข ื•ื“ืžืขื•ืช ืื– AI ื™ื•ื›ืœ ืœืขื–ื•ืจ ืœื›ื ืœื›ืชื•ื‘ ืงื•ื“ ื™ื•ืชืจ ืžื”ืจ, ื•ืžืžื™ืœื ืชื•ื›ืœื• ืœื›ื•ื•ืŸ ืื•ืชื• ื‘ื“ื™ื•ืง ืื™ืš ืœืขื‘ื•ื“ ื›ื“ื™ ืœื ืœืขืฉื•ืช ืฉื˜ื•ื™ื•ืช. ื•ื‘ืจื•ืจ ืฉืขื AI ืืคืฉืจ ืœื›ืชื•ื‘ ื“ื‘ืจื™ื ื’ื ื›ืฉืœื ืžื‘ื™ื ื™ื ื›ืœื•ื ื•ืœืคืขืžื™ื ื–ื” ืขื•ื‘ื“, ื›ืžื• ืฉืคืขื ื”ื™ื” ืืคืฉืจ ืœื”ืขืชื™ืง ืงื˜ืขื™ ืงื•ื“ ืž Stack Overflow ื•ืœืคืขืžื™ื ื–ื” ืขื‘ื“. ืฉื ื™ ื”ืžืงืจื™ื ืœื ื™ื”ืคื›ื• ืืชื›ื ืœืžืชื›ื ืชื™ื ืžื‘ืจื™ืงื™ื. ื”ื‘ื ื” ื–ื” ืื—ืœื”. ืชืฉืงื™ืขื• ื‘ืœื”ื‘ื™ืŸ. ืœื ื‘"ืœื”ื‘ื™ืŸ ื‘ื’ื“ื•ืœ ืื™ืš ื–ื” ืขื•ื‘ื“ ื•ืœื”ืคืขื™ืœ AI". ืœื”ื‘ื™ืŸ ื‘ืืžืช. ื–ืืช ื”ื“ืจืš ื”ื˜ื•ื‘ื” ื‘ื™ื•ืชืจ ืœืงื‘ืœ ืขืจืš ืž AI

ToCode
1 418
ื˜ื™ืค ื•ื™ื•: ืœืืŸ ื ืขืœืžื” ื”ื˜ืžืคืœื™ื™ื˜ ื”ืงื•ื“ ื”ื‘ื ื‘ Vue ืžืจืื” ืขืœ ื”ืžืกืš ืืช ื”ื˜ืงืกื˜ Hello Vue:
<template>
    <template v-if="true">
        <p>Hello Vue</p>
    </template>
</template>
ืื‘ืœ ื–ื” ื›ื‘ืจ ืœื ืžืจืื” ื›ืœื•ื:
<template>
    <template>
        <p>Hello Vue</p>
    </template>
</template>
ื‘ื•ืื• ื ืจืื” ืœืžื”. ืืœืžื ื˜ template ื‘ HTML ื‘ HTML ื™ืฉ ืืœืžื ื˜ ื‘ืฉื template ืฉืžืืคืฉืจ ื‘ื ื™ื” ืฉืœ Web Components. ื”ืงื•ื“ ืฉื ืžืฆื ื‘ืชื•ืš ื˜ืžืคืœื™ื™ื˜ ื‘ HTML ืืžื•ืจ ืœื”ื™ื˜ืขืŸ ืžืชื•ืš ืงื•ื“ JavaScript ื›ื“ื™ ืœื™ืฆื•ืจ ืืœืžื ื˜ ื‘ DOM ื‘ืฉืœื‘ ืžืื•ื—ืจ ื™ื•ืชืจ. ื”ืงื•ื“ ื”ื–ื” ืœื›ืŸ ื”ื•ื HTML ืชืงื ื™ ืœื’ืžืจื™, ืฉืœืœื JavaScript ืœื ืžืจืื” ื›ืœื•ื ืขืœ ื”ืžืกืš:
<my-counter></my-counter>
<my-counter></my-counter>
<my-counter></my-counter>

<template id="counter">
  <p>I'm a counter. value = <span class="value">0</span>
    <button class="inc">+1</button>
    <button class="dec">-1</button>
  </p>
</template>
ืืœืžื ื˜ template ื‘ Vue ื‘ Vue ืœืืœืžื ื˜ template ื™ืฉ ืžืกืคืจ ืชืคืงื™ื“ื™ื, ื”ืฉื ื™ื™ื ืฉืจืœื•ื•ื ื˜ื™ื™ื ืœื“ื•ื’ืžื” ืฉืœื ื• ื”ื: 1. ืืœืžื ื˜ template ืžืืคืฉืจ ืœื—ื‘ืจ ื™ื—ื“ ื›ืžื” ืืœืžื ื˜ื™ื ืขื‘ื•ืจ Directive ืื—ื“, ืœื“ื•ื’ืžื” ืœื”ืฆื™ื’ ืื• ืœื”ืกืชื™ืจ ืžืกืคืจ ืืœืžื ื˜ื™ื ืœืคื™ ืชื ืื™ ื‘ v-if ืื• ืœื—ื–ื•ืจ ืขืœ ืžืกืคืจ ืืœืžื ื˜ื™ื ื‘ืœื•ืœืื” ื‘ v-for. 2. ืืœืžื ื˜ template ืžืืคืฉืจ ื‘ื ื™ื™ื” ืฉืœ ืชื’ื™ืช template ื‘ HTML. ื•ืื™ืš ื•ื™ื• ืžื‘ื™ืŸ ืœืื™ื–ื” ืžืฉื ื™ ื”ืชืคืงื™ื“ื™ื ื”ืชื›ื•ื•ื ื•? ืœืคื™ ื” Directives: ืื ื™ืฉ ื‘ template ืคืงื•ื“ื•ืช ื›ืžื• v-if ืื• v-for ื”ื•ื ื ื—ืฉื‘ ืœื˜ืžืคืœื™ื™ื˜ ืฉืžื—ื‘ืจ ื›ืžื” ื“ื‘ืจื™ื ื™ื—ื“, ืื ืื™ืŸ ืื– ื”ื•ื ื™ื•ืคื™ืข ื‘ืชื•ืจ ืืœืžื ื˜ template ื‘ HTML. ื‘ ESLint ื™ืฉ ื›ืœืœ ื‘ืฉื vue/no-lone-template ืฉืžื–ื”ื” ืฉื™ืžื•ืฉ ื‘ template ื‘ืœื™ directives ื•ืžืขื™ืจ ืขืœื™ื•. ืืคืฉืจ ืœืงืจื•ื ืขืœื™ื• ื›ืืŸ: https://eslint.vuejs.org/rules/no-lone-template

ToCode
1 418
subject: "[ืคื•ืกื˜ ื—ื“ืฉ] #{@post.title}",
  template_data: recipients_with_tokens.map { |email, token| { "email" => email, "token" => token } }.to_json
)
ื” token ื‘ื›ืœ ืงื˜ืขื™ ื”ืงื•ื“ ื”ืืœื” ื”ื•ื ืคืจืžื˜ืจ ืฉื™ื™ืฉืชืœ ืœื›ืœ ืื™ืžื™ื™ืœ ื•ื‘ืขื–ืจืชื• ื ืžืขื ื™ื ื™ื›ื•ืœื™ื ืœื”ืกื™ืจ ืืช ืขืฆืžื ืžื”ืจืฉื™ืžื”, ื›ืืฉืจ ืœื›ืœ ื ืžืขืŸ ื™ืฉ token ืฉื•ื ื”. ืืคืฉืจ ืœื”ื•ืกื™ืฃ ืื™ื–ื” ืคืจืžื˜ืจื™ื ืฉืจื•ืฆื™ื ืฉื ื•ื‘ืฉื‘ื™ืœ ืœืฉืชื•ืœ ืื•ืชื ื‘ื’ื•ืฃ ื”ืžื™ื™ืœ ืื ื—ื ื• ืฆืจื™ื›ื™ื ืจืง ืœืฆื™ื™ืŸ ืืช ืฉืžื ื‘ืชื•ืš ืกื•ื’ืจื™ื™ื ืžืกื•ืœืกืœื™ื ื›ืคื•ืœื™ื ืœื“ื•ื’ืžื”:
<%= subscriptions_edit_url %>?token={{token}}&remove=all
ืชื•ื›ื ื™ื•ืช ืœืขืชื™ื“ ืขืœ ื”ื“ืจืš ื•ืขื ื›ืœ ื”ื”ืชืขืกืงื•ืช ืขื ืงื•ื“ ื”ืžื™ื™ืœื™ื ื”ื•ืกืคืชื™ ื’ื ืžื ื’ื ื•ืŸ ืฉืœ ืื™ืžื•ืช ื›ืคื•ืœ ืœืžื™ ืฉืจื•ืฆื” ืœืงื‘ืœ ืืช ื”ืคื•ืกื˜ื™ื ืœืžื™ื™ืœ, ื›ืš ืฉืขื›ืฉื™ื• ืื ืชืจืฉืžื• ืืช ื”ืžื™ื™ืœ ืฉืœื›ื ื‘ืชื™ื‘ืช ื”ืจื™ืฉื•ื ืชืงื‘ืœื• ื”ื•ื“ืขื” ืฉืืชื ืฆืจื™ื›ื™ื ืœืืžืช ืืช ื›ืชื•ื‘ืช ื”ืžื™ื™ืœ, ื”ืžืขืจื›ืช ืชืฉืœื— ืœื›ื ืื™ืžื™ื™ืœ ื•ืจืง ืื—ืจื™ ืœื—ื™ืฆื” ืขืœ ื”ื›ืคืชื•ืจ ืฉื‘ืžื™ื™ืœ ื‘ืืžืช ืื•ืกื™ืฃ ืืชื›ื ืœืจืฉื™ืžืช ื”ืชืคื•ืฆื”. ื‘ืฆื•ืจื” ื›ื–ืืช ืื ื™ ืžืงื•ื•ื” ืœืฉืœื•ื— ืืช ื”ืžื™ื™ืœื™ื ืœื™ื•ืชืจ ืื ืฉื™ื ืจืœื•ื•ื ื˜ื™ื ื•ืœืคื—ื•ืช ื‘ื•ื˜ื™ื. ื‘ื ื•ืกืฃ ื›ื ืจืื” ืฉื”ืžืขื‘ืจ ืœ AWS ืฉื™ื ื” ื—ืœืง ืžื”ื’ื“ืจื•ืช ื”ืฉื•ืœื— ืฉืœื™ ื•ืœื›ืŸ ื—ืœืง ืžื›ื ืื•ืœื™ ืจื•ืื™ื ืืช ื”ืžื™ื™ืœื™ื ื”ืืœื” ืžื›ืชื•ื‘ืช ืื—ืจืช ืื• ืืคื™ืœื• ื‘ืชื™ื‘ืช ื”ืกืคืื. ืื ื–ื” ื”ืžืฆื‘ ื‘ื‘ืงืฉื” ืชืกืžื ื• ืœื’ื•ื’ืœ ืื• ืœืžื™ ืฉืฆืจื™ืš ืฉื”ืžื™ื™ืœ ืื™ื ื• ืกืคืื ื•ืชื’ืจืจื• ืื•ืชื• ืœืชื™ื‘ืช ื”ื“ื•ืืจ ื”ื ื›ื ืก. ืœืกื™ื•ื ืื ืžืื™ื–ื•ืฉื”ื™ ืกื™ื‘ื” ื›ืชื•ืฆืื” ืžื›ืœ ื”ืฉื™ื ื•ื™ื™ื ื”ืื—ืจื•ื ื™ื ื”ืžื™ื™ืœ ืžืžื ื™ ืžืคืกื™ืง ืœื”ื’ื™ืข ืืœ ืชื”ื™ื• ืžื•ื“ืื’ื™ื, ืœื›ื• ืœืืชืจ ืœืงืจื•ื ืืช ื”ืคื•ืกื˜ ื•ื›ืชื‘ื• ืœื™ (ืืคืฉืจ ืœื”ื’ื™ื‘ ืœื›ืœ ืื—ื“ ืžื”ืžื™ื™ืœื™ื ื”ื™ืฉื ื™ื ืฉื›ืŸ ื™ืฉ ืœื›ื ื‘ืชื™ื‘ื”) ื›ื“ื™ ืฉืื‘ื“ื•ืง ืžื” ืงืจื” ื•ืื ืฆืจื™ืš ืื•ืกื™ืฃ ืืชื›ื ืžื—ื“ืฉ ืœืจืฉื™ืžื”.

ToCode
1 418
ืฉืœื™ื—ืช ืžื™ื™ืœ ืž Rails ื“ืจืš AWS SES ื‘ื™ืžื™ื ื”ืื—ืจื•ื ื™ื ืื ื™ ืขื•ื‘ื“ ืขืœ ืฉื™ื ื•ื™ ืžื ื’ื ื•ืŸ ืฉืœื™ื—ืช ื”ืžื™ื™ืœื™ื ืฉืœ ื”ืืชืจ ื•ืœืฉืœื•ื— ื“ืจืš AWS ื‘ืžืงื•ื ื“ืจืš Mailgun. ื–ื” ืงื•ืจื” ืงืฆืช ื‘ื’ืœืœ ื”ืขืœืื•ืช ืžื—ื™ืจ ืฉืœ ืžื™ื™ืœื’ืืŸ ื•ื”ืจื‘ื” ื‘ื’ืœืœ ืฉืจืฆื™ืชื™ ืœืฉื—ืง ืขื ืขื•ื“ ืกืจื‘ื™ืก ืฉืœ AWS. ื›ืžื• ืชืžื™ื“ ืืฆืœื ื“ื‘ืจื™ื ืžืกืชื‘ื›ื™ื ื•ื”ืคื•ืกื˜ ื”ื–ื” ืžืกื›ื ืืช ื”ื”ืกืชื‘ื›ื•ื™ื•ืช ื”ืžืจื›ื–ื™ื•ืช ื•ื’ื ืชื•ื›ื ื™ื•ืช ืœืขืชื™ื“ ืœื’ื‘ื™ ื”ืžื™ื™ืœื™ื. ืฉืœื™ื—ืช ืžื™ื™ืœ ื™ื—ื™ื“ ื‘ืืžืฆืขื•ืช SMTP ื ืชื—ื™ืœ ืขื ืžื” ืฉืคืฉื•ื˜: ื’ื Mailgun ื•ื’ื SES (ืฉื™ืจื•ืช ื”ืžื™ื™ืœื™ื ืฉืœ AWS) ืชื•ืžื›ื™ื ื‘ืคืจื•ื˜ื•ืงื•ืœ SMTP ื•ื“ืจืš ื›ืคืชื•ืจื™ื ื‘ืžืžืฉืง ื•ื•ื‘ ืืคืฉืจ ืœืงื‘ืœ ืฉื ืžืฉืชืžืฉ ื•ืกื™ืกืžื” ืœืฉืจืช SMTP ืฉื™ืฉืœื— ืืช ื”ืžื™ื™ืœื™ื ื‘ืฉื‘ื™ืœื›ื. ื–ื” ืื•ืžืจ ืฉื‘ืจื™ื™ืœืก ื›ืœ ืžื” ืฉืื ื™ ืฆืจื™ืš ื‘ืฉื‘ื™ืœ ืœืฉืœื•ื— ืžื™ื™ืœ ื™ื—ื™ื“ ื”ื•ื ืœืฉื ื•ืช ืฉืชื™ ืคืงื•ื“ื•ืช ื‘ืงื•ื‘ืฅ ื”ืงื•ื ืคื™ื’ื•ืจืฆื™ื” ืฉืœ ื”ืกื‘ื™ื‘ื” ื•ืœื›ืชื•ื‘ ืžืฉื”ื• ื›ืžื•:
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  address:         "email-smtp.eu-north-1.amazonaws.com",
  port:            587,
  user_name:       Rails.application.credentials.dig(:aws, :ses, :user_name),
  password:        Rails.application.credentials.dig(:aws, :ses, :password),
  authentication:  "plain",
  enable_starttls: true,
  open_timeout:    5,
  read_timeout:    5 
}
ืžื›ืืŸ ื›ืœ ืฉืœื™ื—ืช ืžื™ื™ืœ ื“ืจืš ืชืฉืชื™ืช ื”ืžื™ื™ืœื™ื ื”ืžื•ื‘ื ื™ืช ื‘ Rails ืชืฉืชืžืฉ ื‘ืคืจื˜ื™ ื”ืžืฉืชืžืฉ ื•ื”ืกื™ืกืžื” ืฉื”ื’ื“ืจืชื™ ื‘ืงื•ื‘ืฅ ื”ืกื™ืกืžืื•ืช ื•ืชืขื‘ื•ืจ ื“ืจืš ื”ืฉืจืช ืฉืœ ืืžื–ื•ืŸ. ืฉืœื™ื—ืช ืžื™ื™ืœ ืœื”ืจื‘ื” ืื ืฉื™ื ืขื ืคืจืžื˜ืจื™ื ื”ืกื™ืคื•ืจ ื”ื™ื•ืชืจ ืžืกื•ื‘ืš ื”ื™ื” ืœืฉืœื•ื— ืžื” ืฉื”ื ืงื•ืจืื™ื Bulk Email. ื–ื” ื”ืžื ื’ื ื•ืŸ ืื™ืชื• ืื ื™ ืฉื•ืœื— ืœื›ื ืืช ื”ืคื•ืกื˜ ื”ื–ื” ืœืื™ืžื™ื™ืœ. ืœืžื™ื™ืœื’ืืŸ ื™ืฉ ืžื ื’ื ื•ืŸ ืžื•ื‘ื ื” ืฉืžืืคืฉืจ ื‘ืงืจื™ืืช API ืื—ืช ืœื”ื•ืฆื™ื ืื™ืžื™ื™ืœ ืœืžืื•ืช ืื ืฉื™ื. ื‘ SES ื–ื” ืงืฆืช ื™ื•ืชืจ ืžื•ืจื›ื‘ ื›ื™ ืงืจื™ืืช ื” API ื”ื™ื—ื™ื“ื” ืฉืœื”ื ืžื•ื’ื‘ืœืช ืœ 50 ื ืžืขื ื™ื (ืœืคื™ ื”ืชื™ืขื•ื“, ืœื ื ื™ืกื™ืชื™ ื™ื•ืชืจ). ื•ืขื“ื™ื™ืŸ ืžื›ืœ ืžื” ืฉื—ื™ืคืฉืชื™ ื‘ืจืฉืช ืฉืœื™ื—ืช ืžื™ื™ืœ ืœื›ืžื•ืช ื’ื“ื•ืœื” ืฉืœ ื ืžืขื ื™ื ืชื”ื™ื” ื”ืจื‘ื” ื™ื•ืชืจ ืžื”ื™ืจื” ื•ื™ืขื™ืœื” ื“ืจืš ื” API ืฉืœื”ื. ื‘ืฉื‘ื™ืœ ืœืฉืœื‘ ืืช ื” SDK ืฉืœ SES ื‘ืชื•ืš ืจื™ื™ืœืก ื”ื™ื” ืฆืจื™ืš ืœื™ืฆื•ืจ ืžืฉื”ื• ืฉื ืงืจื Delivery Method, ืฉื–ื” ื”ืžื—ืœืงื” ืฉืื•ืžืจืช ืœืจื™ื™ืœืก ืื™ืš ืœืฉืœื•ื— ืžื™ื™ืœื™ื. ืื ืืชื ื–ื•ื›ืจื™ื ืžื”ืคื™ืกืงื” ื”ืงื•ื“ืžืช ื‘ืฉื‘ื™ืœ ืœืฉืœื•ื— ืžื™ื™ืœ ื‘ืืžืฆืขื•ืช SMTP ื›ืชื‘ืชื™:
config.action_mailer.delivery_method = :smtp
ื–ื” ืื•ืžืจ ืฉื‘ืฉื‘ื™ืœ ืœืฉืœื•ื— ืžื™ื™ืœ ื‘ืฉื™ื˜ื” ื—ื“ืฉื” ืฉืœื™ ืืฆื˜ืจืš ืœื‘ื ื•ืช ืžืฉื”ื• ืฉืขื•ืฉื” ืืช ืžื” ืฉืžื—ืœืงืช ื” SMTP ืฉืœ ืจื™ื™ืœืก ืขื•ืฉื”. ื‘ืขื–ืจืช ืชื™ืขื•ื“ ื• AI ื›ืชื‘ืชื™ ืืช ื”ืงื•ื“ ื”ื‘ื ื‘ืชื•ืš ืงื•ื‘ืฅ ื‘ืฉื ses_delivery_method ื‘ืชื™ืงื™ื™ืช lib:
class SesDeliveryMethod
  attr_accessor :settings

  def initialize(options = {})
    @settings = options.merge(
      access_key_id: Rails.application.credentials.dig(:aws, :ses, :access_key_id),
      secret_access_key: Rails.application.credentials.dig(:aws, :ses, :access_key_secret),
      region: 'eu-north-1'
    )
    @client = Aws::SESV2::Client.new(region: @settings[:region], credentials: aws_credentials)
  end

  def deliver!(mail)
    template_data = JSON.parse(mail['template-data'].value)


    options = {
      from_email_address: mail.from.first,
      # default_email_tags: tags,
      default_content: {
        template: {
          template_data: {"token" => ""}.to_json,
          template_content: {
            subject: mail.subject,
            text: mail.text_part.body.decoded,
            html: mail.html_part.body.decoded
          }
        }
      },
      bulk_email_entries: template_data.map do |recipient|
        {
          destination: { to_addresses: Array.wrap(recipient["email"]) },
          replacement_email_content: {
            replacement_template: {
              replacement_template_data: {"token" => recipient["token"]}.to_json
            }
          }
        }
      end
    }

    response = @client.send_bulk_email(options)
  rescue => err
    Rails.logger.info("SES Error")
    Rails.logger.error(err)
    raise err
  end

  private

  def aws_credentials
    Aws::Credentials.new(@settings[:access_key_id], @settings[:secret_access_key])
  end

  def template_data(mail)
    { "subject" => mail.subject, "body" => mail.body.raw_source }.to_json
  end
end

* Register with ActionMailer *
ActionMailer::Base.add_delivery_method :ses, SesDeliveryMethod
ื•ื›ืš ื‘ืฉื‘ื™ืœ ืœืฉืœื•ื— ืžื™ื™ืœ ื“ืจืš SES ื›ืœ ืžื” ืฉืฆืจื™ืš ืœืขืฉื•ืช ื‘ืงื•ื“ ื”ื™ื™ืฉื•ื ื”ื•ื ืงืจื™ืืช ืคื•ื ืงืฆื™ื” ืฉื ืจืื™ืช ื‘ืขืจืš ื›ืš:
mail(
  to:,
  from: 'Ynon Perek <ynon@tocode.co.il>',
  delivery_method: :ses,

ToCode
1 418
ื’ื“ื™ืœื” ืื•ืคืงื™ืช ื”ื™ื ืœื ื”ืคื™ืชืจื•ืŸ (ืขื“ื™ื™ืŸ) ื›ืฉื›ื— ืžื™ื—ืฉื•ื‘ ื”ืชื—ื™ืœ ืœื”ื™ื•ืช ื–ื•ืœ ื‘ื–ื›ื•ืช ื™ืจื™ื“ืช ืžื—ื™ืจื™ื ื•ื•ื™ืจื˜ื•ืืœื™ื–ืฆื™ื” ื’ื™ืœื™ื ื• ืฉืœื”ื•ืกื™ืฃ ืขื•ื“ ืžื›ื•ื ื” ื™ื›ื•ืœ ืœื”ื™ื•ืช ื”ืจื‘ื” ื™ื•ืชืจ ื–ื•ืœ ืžืืฉืจ ืœื—ื–ืง ืืช ื”ืฉืจืช ื”ืงื™ื™ื. ื—ื‘ืจื•ืช ืขื ืŸ ืื™ืคืฉืจื• ืœื ื• ืœื”ืจื™ืฅ ืงื•ื“ ืขืœ ืขืฉืจื•ืช ืื• ืžืื•ืช ืžื›ื•ื ื•ืช ื‘ืžืงื‘ื™ืœ, ื‘ืœื™ ืฉื ืฆื˜ืจืš ืœื“ืขืช ื›ืžื” ืžื›ื•ื ื•ืช ื™ืฉ ืœื ื• ืื• ืžื” ื›ืœ ืžื›ื•ื ื” ืขื•ืฉื”. ื’ืŸ ื”ืขื“ืŸ ืฉืœ ืžื™ื—ืฉื•ื‘ ืื•ื˜ื•ืžื˜ื™ ื ืจืื” ืงืจื•ื‘ ืžืชืžื™ื“. ืจืง ืฉื ื™ ื“ื‘ืจื™ื ื”ืคืจื™ืขื• ืœื—ื’ื™ื’ื”: 1. ื‘ Scale ื’ื“ื•ืœ ืฉืจืชื™ ืขื ืŸ ื™ื•ืฆืื™ื ืžืื•ื“ ื™ืงืจื™ื ื‘ื”ืฉื•ื•ืื” ืœืขื‘ื•ื“ื” ืขืœ ืฉืจืชื™ื ืคื™ื–ื™ื™ื. 2. ืคื™ืชื•ื— ืžืขืจื›ื•ืช ืžื‘ื•ื–ืจื•ืช ื”ื•ื ื™ื•ืชืจ ืžื•ืจื›ื‘ ืžืคื™ืชื•ื— ืžืขืจื›ื•ืช ืขืœ ืฉืจืช ื™ื—ื™ื“. ื”ืžืขื‘ืจ ืžืืจื›ื™ื˜ืงื˜ื•ืจืช ืฉืจืช ื™ื—ื™ื“ ืœืืจื›ื™ื˜ืงื˜ื•ืจืช ืขื ืŸ ืžืกื•ื‘ืš ื”ืจื‘ื” ื™ื•ืชืจ ืž"ื‘ื•ืื• ื ื•ืกื™ืฃ ืฉืจืชื™ื". ืขืœื™ื ื• ืœื™ื™ืฆืจ ืžืขืจื›ื•ืช ื ื™ื”ื•ืœ, ืžืขืจื›ื•ืช ืžืขืงื‘, ืœื˜ืคืœ ื‘ื‘ืขื™ื•ืช ืกื™ื ื›ืจื•ืŸ ื•ื‘ื›ื™ืฉืœื•ื ื•ืช, ืœื ื”ืœ ื˜ืจื ื–ืืงืฆื™ื•ืช ืื• ืœื‘ื˜ืœ ืื•ืชืŸ. ืžื”ืจ ืžืื•ื“ ืชื•ืกืคืช ืฉืจืชื™ื ื“ื•ืจืฉืช ืชื•ืกืคืช ืฉืœ ืขื•ื“ ื•ืขื•ื“ ืฉื™ืจื•ืชื™ ื ื™ื”ื•ืœ ื•ืžืžืฉืงื™ื ืขืœ ืื•ืชื ืฉืจืชื™ื. ืงื•ื“ ื’ืจื•ืข ืœื ืžืฉืชืคืจ ืจืง ื›ื™ ืื ื—ื ื• ืžืจื™ืฆื™ื ืื•ืชื• ืขืœ ื™ื•ืชืจ ืžื›ื•ื ื•ืช ืื• ืขืœ ืžื›ื•ื ื•ืช ื™ื•ืชืจ ื—ื–ืงื•ืช. ืจื•ื‘ ื”ื–ืžืŸ ืืคื™ืœื• ืงื•ืจื” ื”ื”ื™ืคืš. ืœืคื ื™ ืฉืขื•ื‘ืจื™ื ืœืขื ืŸ ื‘ื•ืื• ื ื•ื•ื“ื ืฉืขืฉื™ื ื• ื›ืœ ืžื” ืฉืืคืฉืจ ื›ื“ื™ ืœืฉืคืจ ืืช ื”ื‘ื™ืฆื•ืขื™ื ืฉืœ ื”ืžืขืจื›ืช ืฉืœื ื• ื‘ืจืžืช ื”ืงื•ื“ ื•ืื ื—ื ื• ืžื ืฆืœื™ื ืืช ื”ืžืฉืื‘ื™ื ืฉื™ืฉ ืœื ื• ื‘ืื•ืคืŸ ื”ื˜ื•ื‘ ื‘ื™ื•ืชืจ. ืื•ืœื™ ืื—ืจื™ ืื•ืคื˜ื™ืžื™ื–ืฆื™ื” ื‘ืงื•ื“ ื•ื‘ื ื™ื”ื•ืœ ืžืฉืื‘ื™ื ื ื’ืœื” ืฉืื ื—ื ื• ื‘ืขืฆื ืžื”ื™ืจื™ื ืžืกืคื™ืง ื•ืœื ืฆืจื™ื›ื™ื ืืช ื”ืขื ืŸ.