برنامه نویسی

چگونه من 10 ساعت در هفته با اسکریپت های اتوماسیون Node.js ذخیره می کنم

این یک شب به من ضربه زد که من به صورت دستی در حال تغییر مکان 47 تصویر محصول روز برای فروشگاه فروشگاه مشتری بودم. من نزدیک به دو ساعت را صرف کار کرده بودم که باید دقایقی طول بکشد. به عنوان یک توسعه دهنده مستقل که چندین مشتری را به هم می زند ، این وظایف تکراری “سریع” بی سر و صدا در بهره وری من غذا می خورد.

نکته مهم زمانی پیش آمد که من محاسبه کردم که چقدر وقت خود را صرف این فعالیت های دنیوی می کردم: کشیدن گزارش های تجزیه و تحلیل هفتگی ، اصلاح صفحات گسترده ، تغییر اندازه تصاویر ، به روزرسانی لیست محصولات … تقریباً 10 ساعت در هفته اضافه می شود. این در واقع یک روز کاری کامل است!

بنابراین من کاری را انجام دادم که هر توسعه دهنده احترام به خود انجام می داد-من جهنم را با Node.js. خودکار کردم.

در این پست ، من شما را از طریق سه اسکریپت اتوماسیون در دنیای واقعی که ساختم ، طی می کنم که گردش کار من را دگرگون کرده و بخش مهمی از هفته خود را آزاد می کند. اینها نمونه های نظری نیستند – آنها راه حل های واقعی هستند که من امروز با مشتری استفاده می کنم.

از پرونده شماره 1 استفاده کنید: گزارش های مشتری تولید خودکار

مشکل

یکی از مشتری های من ، یک آژانس بازاریابی محتوا ، به گزارش های فعالیت هفتگی نیاز دارد که از API CMS آنها گرفته شده است. این روند دردناک بود: ورود به سیستم آنها ، صادر کردن داده ها ، تمیز کردن آن در اکسل ، قالب بندی آن به زیبایی و ارسال ایمیل به آن. کل مصیبت هر هفته حدود 45 دقیقه طول کشید.

راه حل

من یک اسکریپت node.js نوشتم که کل گردش کار را بر عهده دارد. این داده ها را به دست می آورد ، آن را به یک گزارش تمیز می پردازد و هر روز دوشنبه به طور خودکار آن را ایمیل می کند. من آن را با یک کار Cron در VPS 5 دلار در ماه تنظیم کردم و از آن زمان دیگر نیازی به فکر کردن در مورد آن ندارم.

در اینجا هسته فیلمنامه وجود دارد:

const axios = require('axios');
const nodemailer = require('nodemailer');
const fs = require('fs');
const moment = require('moment');

async function generateReport() {
  // Get date range for the past week
  const endDate = moment().format('YYYY-MM-DD');
  const startDate = moment().subtract(7, 'days').format('YYYY-MM-DD');

  console.log(`Generating report for ${startDate} to ${endDate}...`);

  try {
    // Fetch data with proper authentication
    const { data } = await axios.get('https://client-cms.com/api/posts', {
      headers: { 'Authorization': `Bearer ${process.env.API_KEY}` },
      params: { start: startDate, end: endDate }
    });

    // Process the data into a readable format
    const reportData = {
      totalPosts: data.length,
      viewCount: data.reduce((sum, post) => sum + post.views, 0),
      topPerforming: data.sort((a, b) => b.views - a.views).slice(0, 5),
      dateRange: { startDate, endDate }
    };

    // Write formatted report
    const reportPath = `./reports/weekly-report-${endDate}.json`;
    fs.writeFileSync(reportPath, JSON.stringify(reportData, null, 2));

    return reportPath;
  } catch (error) {
    console.error('Error generating report:', error.message);
    throw error;
  }
}

async function sendEmail(reportPath) {
  // Create reusable transporter using environment variables for security
  let transporter = nodemailer.createTransport({
    service: 'gmail',
    auth: {
      user: process.env.EMAIL_USER,
      pass: process.env.EMAIL_PASS,
    },
  });

  // Format date for email subject
  const reportDate = moment().format('MMMM D, YYYY');

  // Send mail with defined transport object
  await transporter.sendMail({
    from: '"Weekly Report Bot" ',
    to: 'client@example.com, account-manager@youragency.com',
    subject: `Content Performance Report - Week of ${reportDate}`,
    text: `Please find attached the weekly content performance report for ${reportDate}.`,
    attachments: [{ filename: `weekly-report-${reportDate}.json`, path: reportPath }],
  });

  console.log('Report sent successfully!');
}

// Run the workflow
generateReport()
  .then(sendEmail)
  .catch(err => console.error('Workflow failed:', err));
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

مشتری هیجان زده شد – نه تنها اکنون گزارش های خود را به طور مداوم دریافت می کنند ، بلکه آنها به جای هر زمان که به آن می رسیدند ، صبح روز دوشنبه به اولین چیز می رسند.

از مورد شماره 2 استفاده کنید: تصاویر با رزرو خودکار برای تجارت الکترونیکی

مشکل

یک مشتری تجارت الکترونیکی نیازهای جدی برای تصاویر محصول در فروشگاه Shopify خود داشت. هر تصویری که باید دقیقاً 1200x1200px با پس زمینه سفید باشد. آنها هر هفته ساعت ها را به صورت دستی در ویرایش عکس ها در فتوشاپ می گذراندند.

راه حل

من یک سیستم پوشه ساعت ساده ساختم. اکنون آنها فقط عکس های محصول خام را در یک پوشه مشخص می کنند ، و اسکریپت من به طور خودکار آنها را پردازش می کند:

const chokidar = require('chokidar');
const sharp = require('sharp');
const path = require('path');
const fs = require('fs');

// Create output directory if it doesn't exist
const outputDir = './processed-images';
if (!fs.existsSync(outputDir)) {
  fs.mkdirSync(outputDir);
}

// Set up file watcher
const watcher = chokidar.watch('./incoming-images', {
  ignored: /(^|\/)\.[^\/\.]/g, // ignore dotfiles
  persistent: true
});

// Process function to resize and center image on white background
async function processImage(filePath) {
  const fileName = path.basename(filePath);
  const outputPath = path.join(outputDir, fileName);

  try {
    // Get image dimensions
    const metadata = await sharp(filePath).metadata();

    // Create 1200x1200 white canvas
    const canvas = sharp({
      create: {
        width: 1200,
        height: 1200,
        channels: 4,
        background: { r: 255, g: 255, b: 255, alpha: 1 }
      }
    });

    // Resize original image to fit within 1100x1100 (leaving some margins)
    const resized = await sharp(filePath)
      .resize(1100, 1100, { 
        fit: 'contain',
        background: { r: 0, g: 0, b: 0, alpha: 0 }
      })
      .toBuffer();

    // Composite resized image onto white canvas (centered)
    await canvas.composite([{ 
      input: resized,
      gravity: 'center'
    }])
    .toFile(outputPath);

    console.log(`✅ Processed: ${fileName}`);
  } catch (err) {
    console.error(`❌ Error processing ${fileName}:`, err);
  }
}

// Set up watcher events
watcher
  .on('add', filePath => {
    console.log(`File added: ${filePath}`);
    processImage(filePath);
  })
  .on('error', error => console.error(`Watcher error: ${error}`));

console.log('Image processor running! Drop files into ./incoming-images');
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

این اسکریپت هر هفته حدود 3 ساعت آنها را ذخیره می کند. بهترین قسمت این است که به صورت محلی در رایانه آنها اجرا می شود ، بنابراین نیازی به نگرانی در مورد بارگذاری تصاویر در یک سرور نیست.

از مورد شماره 3 استفاده کنید: آپلود دسته ای داده های محصول

مشکل

تیم بازاریابی مشتری من به طور مرتب قیمت گذاری محصول و توضیحات را به روز می کند. آنها این داده ها را در صفحات گسترده حفظ کردند ، اما مجبور بودند هر به روزرسانی را به صورت دستی کپی کنند و به روزرسانی در صفحه مدیر تجارت الکترونیکی خود بپردازند. با صدها محصول ، این یک کار چند ساعته مستعد خطاها بود.

راه حل

من یک اسکریپت نوشتم که پرونده CSV آنها را می خواند و به طور خودکار پایگاه داده محصول آنها را از طریق API به روز می کند:

const csv = require('csvtojson');
const axios = require('axios');
const fs = require('fs');
const path = require('path');

// Configuration
const API_ENDPOINT = 'https://api.client-store.com/products';
const API_KEY = process.env.PRODUCT_API_KEY;
const csvFilePath = process.argv[2] || './product-updates.csv';

if (!fs.existsSync(csvFilePath)) {
  console.error(`Error: File not found at ${csvFilePath}`);
  process.exit(1);
}

// Setup API client
const api = axios.create({
  baseURL: API_ENDPOINT,
  headers: {
    'Authorization': `Bearer ${API_KEY}`,
    'Content-Type': 'application/json'
  }
});

async function updateProducts() {
  // Keep track of success/failure
  const results = {
    success: 0,
    failed: 0,
    errors: []
  };

  try {
    // Parse CSV to JSON
    const products = await csv().fromFile(csvFilePath);
    console.log(`Found ${products.length} products to update`);

    // Process each product
    for (let [index, product] of products.entries()) {
      try {
        // Simple validation
        if (!product.id || !product.sku) {
          throw new Error('Missing required product identifier (id or sku)');
        }

        console.log(`[${index + 1}/${products.length}] Updating product ${product.sku}...`);

        // Send update to API
        await api.put(`/${product.id}`, product);
        results.success++;

      } catch (err) {
        results.failed++;
        results.errors.push(`Product ${product.sku || index}: ${err.message}`);
        console.error(`  Failed: ${err.message}`);
      }

      // Small delay to avoid rate limiting
      await new Promise(resolve => setTimeout(resolve, 100));
    }

    // Log results
    console.log('\n--- Update Complete ---');
    console.log(`✅ Successfully updated: ${results.success} products`);
    console.log(`❌ Failed updates: ${results.failed} products`);

    if (results.errors.length > 0) {
      fs.writeFileSync(
        './update-errors.log', 
        results.errors.join('\n'), 
        'utf8'
      );
      console.log('See update-errors.log for details on failed updates');
    }

  } catch (err) {
    console.error('Fatal error:', err);
  }
}

updateProducts();
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

تیم بازاریابی اکنون این هفته را با صفحات گسترده به روز شده خود اجرا می کند و هر بار حدود 2-3 ساعت صرفه جویی می کند.

تأثیر واقعی اتوماسیون

وقتی تمام وقت این اسکریپت ها (و تعداد انگشت شماری از دیگران) مرا و مشتری هایم نجات داده ام ، تقریباً 10 ساعت در هفته می رسد. اما مزایا فراتر از صرفه جویی در وقت است:

  1. خطاهای کمتری: انسان هنگام انجام کارهای تکراری اشتباه می کند. اسکریپت های من نیستند (خوب ، مگر اینکه کد حشره ای بنویسم).

  2. کیفیت ثابت: هر گزارش از همان قالب پیروی می کند ، هر تصویر دقیقاً به همان روش پردازش می شود.

  3. روابط بهتر مشتری: کارها به صورت برنامه ای انجام می شود ، حتی وقتی مشغول تعطیلات یا تعطیلات هستم.

  4. فضای بیشتر مغز: من دیگر از نظر ذهنی از کار خسته کننده تخلیه نشده ام و انرژی خلاق تری را برای حل مشکلات جالب به جا می گذارم.

  5. حاشیه سود بهتر: من می توانم بدون کار ساعات بیشتری به مشتریان بیشتری خدمت کنم.

درسهایی که در مورد اتوماسیون آموخته ام

پس از ساخت ده ها مورد از این اسکریپت های اتوماسیون کوچک ، من برخی از قوانین شخصی را تدوین کردم:

1. قانون سه

اگر مجبور باشم بیش از دو بار یک کار را انجام دهم ، بار سوم آن را خودکار می کنم. دو مورد اول به من کمک می کند تا قبل از رمزگذاری روند ، تفاوت های ظریف و لبه ها را درک کنم.

2. همه چیز را وارد کنید

اتوماسیون فقط در صورتی مفید است که بتوانید به آن اعتماد کنید. من به هر اسکریپت ورود گسترده ای اضافه می کنم تا بتوانم تأیید کنم که کارها به درستی کار می کنند و به سرعت عیب یابی را در صورت عدم موفقیت انجام می دهند.

// Bad
await processFile(filePath);

// Good
console.log(`Starting to process: ${filePath}`);
try {
  await processFile(filePath);
  console.log(`Successfully processed: ${filePath}`);
} catch (err) {
  console.error(`Failed to process ${filePath}: ${err.message}`);
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

3. هرگز اسرار کد سخت

من تعداد زیادی از repos github را با کلیدهای API متعهد به کنترل منبع دیده ام. من همیشه از متغیرهای محیط یا فایل های پیکربندی برای هرگونه اطلاعات حساس استفاده می کنم.

4. آن را قابل استفاده مجدد کنید

من اسکریپت هایی را با پیکربندی در ذهن می سازم تا بتوانم با حداقل تغییرات از آنها در مشتری های مختلف استفاده مجدد کنم.

آماده خودکار کردن وظایف خود هستید؟

اگر احساس الهام برای ایجاد اسکریپت های صرفه جویی در وقت خود دارید ، من الگوهای استارت را برای نمونه های فوق در GitHub منتشر کرده ام: github.com/skanderbenali/node.js-automation-tools

برخی از بسته های مفید برای شروع کار:

  • گره: برای برنامه ریزی کارهای مکرر
  • تیز: چاقوی ارتش سوئیس پردازش تصویر
  • محور: برای درخواست HTTP
  • csvtoson: برای کار با پرونده های CSV
  • چوکیدار: برای تماشای پرونده
  • شماره گیر: برای ارسال ایمیل

چه چیزی می توانید خودکار کنید؟

من کنجکاو هستم – چه کارهای تکراری وقت شما را می خورند؟ نظر زیر را رها کنید و من ممکن است گردش کار شما را در مقاله اتوماسیون بعدی خود ارائه دهم.

فقط به یاد داشته باشید ، هدف این نیست که همه چیز را خودکار کنید. این برای خودکار سازی وسایل خسته کننده است تا بتوانید روی کارهایی که در واقع به خلاقیت و تخصص شما نیاز دارد ، تمرکز کنید.

اتوماسیون مبارک!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا