آگاه‌سازی ایمیلی برای کامنت‌دونی

طی هفته‌های گذشته کامنت‌دونی دیسکاس را با یک کامنت‌دونی دست‌ساز جایگزین کردم. این یادداشت گزارش پیشرفت کوتاهی است در مورد افزودن قابلیت جواب دادن به یک دیدگاه و اطلاع‌رسانی به نویسنده پیام اولیه در این مورد.

مروری کلی بر آنچه انجام داده‌ام

برای پیاده‌سازی قابلیت پاسخ دادن به نظرات کاربران من به طور کلی دو کار انجام داده‌ام:

  • تغییرات ظاهری شامل افزودن دگمه پاسخ و نمایش تودرتوی پاسخ و دیدگاه مرجع.
  • نوشتن یک سرویس که گوش به زنگ ارسال پیام است و ایمیل ارسال می‌کند.

البته نمایش تودرتوی پاسخ‌ها ربطی به سرویس ارسال ایمیل ندارد و مستقل است.

تغییرات ظاهری

تغییر ظاهری بخش ساده‌ی کار بود. به هر دیدگاه یک شماره‌ی یکتا اختصاص داده‌ام و دگمه‌ای برای پاسخ به هر دیدگاه اضافه کرده‌ام. با فشردن آن یک تابع جاوااسکریپت فیلدی پنهانی بنام reply-to را در فرم مقداردهی می‌کند که حاوی شماره‌ی یکتای دیدگاه مرجع است. نام نویسنده‌ی دیدگاه مرجع را نیز در فرم نمایش می‌دهم که خواننده بداند مشغول پاسخ به یک دیدگاه دیگر است.

تغییرات کوچکی هم در اسکریپت بیلد کامنت‌ها داده‌ام که این فیلد جدید را نیز بخواند و مانند سایر مقادیر دیدگاه‌ها در مخزن گیت وبسایت ذخیره کند. بیشتر این تغییرات در فایل کامنت‌دونی قابل مشاهده است. (این فایل جزو تم وبسایت است نه خود این وبسایت)

تا همین جا هم با ثبت یک دیدگاه در پاسخ یک دیدگاه دیگر، بعد از بیلد مجدد، دیدگاه جدید با کوت (نقل قول) دیدگاه ثابت منتشر می‌شود. ادامه کار مربوط به آگاه‌سازی به وسیله ایمیل است.

سرویس ارسال ایمیل

کمتر خواننده‌ای به صفحه‌ای که در آن پیامی نوشته دوباره سر می‌زند تا از سایر پاسخ‌ها مطلع بشود. به همین خاطر این قابلیت را به کامنت‌دونی اضافه کردم. از جایی که این سایت استاتیک است از خودش سرور مستقل ندارد. اما سرویس‌دهنده فعلی من امکان این را به من می‌دهد که یک Web Hook را پس از ثبت هر فرم صدا بزنم. وب‌هوک‌ها هم چیزی نیستند جز سرورهایی که گوش به زنگ دریافت HTTP POST هستند.

ابتدا سعی کردم اینکار را به وسیله سرویس zapier انجام بدم. کار را انجام دادم ولی در نهایت متوجه شدم که اجرای سرویس من با پلن رایگان آنها میسر نیست و باید ماهیانه ۲۰ دلار پرداخت کنم!

اینجا بود که گفتم خودم یکی می‌نویسم!

با صرف چند ساعت وقت یک برنامه‌ی ساده با Node.js نوشتم. مراحل کار برنامه این است:

  • برنامه به محض اجرا منتظر دریافت درخواست‌های HTTP POST می‌ماند.
  • با دریافت یک درخواست جدید وجود مقدار reply-to را کنترل می‌کند.
  • در صورت وجود، به کمک API شرکت Netlify (که سرویس‌دهنده من است) دیدگاه مرجع را دانلود می‌کند.
  • ایمیل کامنت‌گذار مرجع را از اطلاعات دانلود شده استخراج می‌کند.
  • با کمک اطلاعات دانلود شده و درخواست اولیه (که شامل جواب است) یک پیام می‌سازد.
  • پیام را به کامنت‌گذار مرجع ایمیل می‌کند.

کد برنامه

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

const express = require('express')
const request = require('request')
const bodyParser = require('body-parser')
const sendmail = require('sendmail')()

const app = express()
app.use(bodyParser.json())

const ACCESS_TOKEN = "xxxxxxxxxxxxxxxxxxxxxx"
const SITE_ID = "xxxxxxxxxxxxxxxxxxxxxx"
const FORM_ID = "xxxxxxxxxxxxxxxxxxxxxx"

app.post('/', (req, res) => {
  res.json(req.body)
  let replyTo = false
  if ('data' in req.body) {
    replyTo = req.body['data']['reply-to']
  }
  if (replyTo) {
    let query = "https://api.netlify.com/api/v1/sites/" + SITE_ID + "/forms/" + FORM_ID + "/submissions/" + replyTo + "?access_token=" + ACCESS_TOKEN
    request(query, (err, resp, body) => {
      if (err) {
        console.log(err)
        return
      }
      body = JSON.parse(body)
      let replyeeEmail = body['email']
      let replierName = req.body['data']['name']
      let replyLink = req.body['site_url'] + req.body['data']['page_id'] + ".html#" + req.body['id']
      let emailBody = '<div dir="rtl">' +
      "برای دیدگاه شما در سایت مهدیکس " + replierName + " " +
      "<a href='" + replyLink  + "'>" + "جوابی" + "</a>" + " نوشت:" +
      "<blockquote>" + req.body['data']['message'] + "</blockquoe>" +
      '</div>'
      sendmail({
        from: 'noreply@mehdix.ir',
        to: replyeeEmail,
        subject: 'پاسخی برای دیدگاه شما در سایت مهدیکس',
        html: emailBody
      }, (err, info) => {
        console.log(err, info)
      })
    })
  }
})
app.listen(3000, () => console.log('Send Mail Hook listening on port 3000!'))

اگر کسی فیلدها را دستکاری کند چه؟

هیچ! پیامش نمایش داده نمی‌شود، هرچند در حال حاضر در مخزن گیت ذخیره می‌شود.

امیدوارم که این مطلب برایتان سودمند باشد و شما هم در مورد کارهایی جالبی که می‌کنید بنویسید. اگر پسندیدید به اشتراک بگذارید یا پیامی بنویسید تا این قابلیت را با هم امتحان کنیم :)