Logo OmniDevvKANA Web
Kembali ke katalog plugin

user

ingatkan

Pasang pengingat pribadi, KANA kirim saat waktunya tiba

Set a personal reminder, KANA sends it when it is due

plugins/user/ingatkan.js

Lokasi file di repo kana-md

2

Perintah termasuk alias

4.1 KB

Ukuran file sumber

4/11/2026

Update terakhir, commit 44f4010

Daftar perintah

Ketuk tombol salin untuk menyalin perintah, lalu tempel di chat WhatsApp bot KANA.

.ingatkan.remind

Cara pakai

.ingatkan <menit> <teks> | .ingatkan list | .ingatkan batal <n>

Contoh

.ingatkan 30 minum air ya

Kode sumber plugin

Unduh .js

Cara pasang: simpan file ini ke folder plugins/user/ di bot KANA kamu, lalu restart bot. Pemilik source code lain bisa mengambil update plugin terbaru dari halaman ini kapan saja.

import { sendButtons } from '../../src/ui/buttons.js'

export const config = {
  name: 'ingatkan',
  alias: ['remind'],
  category: 'user',
  description: { id: 'Pasang pengingat pribadi, KANA kirim saat waktunya tiba', en: 'Set a personal reminder, KANA sends it when it is due' },
  usage: '.ingatkan <menit> <teks> | .ingatkan list | .ingatkan batal <n>',
  example: '.ingatkan 30 minum air ya',
  cooldown: 3,
}

export const i18n = {
  id: {
    ingatkan: {
      usage: 'Pakai gini yaa:\n.ingatkan <menit> <teks pengingat>\n.ingatkan list\n.ingatkan batal <nomor>\nMenitnya 1 sampai 10080 (seminggu)~ ⏰',
      badMinutes: 'Menitnya harus angka bulat 1 sampai 10080 yaa~',
      saved: 'Siap! KANA ingatkan "{text}" dalam {minutes} menit, sekitar {time} WIB~ ⏰ (•̀ᴗ•́)و',
      empty: 'Belum ada pengingat aktif nih~ Pasang pakai .ingatkan <menit> <teks> yaa 🌸',
      listTitle: '⏰ Pengingat aktif {name}:',
      listItem: '{n}. {time} WIB : {text}',
      cancelled: 'Pengingat nomor {n} dibatalkan: "{text}"~',
      notFound: 'Pengingat nomor {n} nggak ada (╥﹏╥)',
      btnList: 'Pengingat Aktif',
      btnMenu: 'Menu User',
    },
  },
  en: {
    ingatkan: {
      usage: 'Use it like this:\n.ingatkan <minutes> <reminder text>\n.ingatkan list\n.ingatkan batal <number>\nMinutes from 1 to 10080 (a week)~ ⏰',
      badMinutes: 'The minutes must be a whole number from 1 to 10080~',
      saved: 'Got it! KANA will remind you "{text}" in {minutes} minutes, around {time} WIB~ ⏰ (•̀ᴗ•́)و',
      empty: 'No active reminders yet~ Set one with .ingatkan <minutes> <text> 🌸',
      listTitle: '⏰ {name} active reminders:',
      listItem: '{n}. {time} WIB : {text}',
      cancelled: 'Reminder number {n} cancelled: "{text}"~',
      notFound: 'Reminder number {n} does not exist (╥﹏╥)',
      btnList: 'Active Reminders',
      btnMenu: 'User Menu',
    },
  },
}

function formatWib(ts) {
  return new Intl.DateTimeFormat('en-GB', {
    timeZone: 'Asia/Jakarta',
    day: '2-digit',
    month: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    hour12: false,
  }).format(new Date(ts))
}

async function loadReminders(ctx) {
  const saved = await ctx.storage.get('reminders', ctx.senderDigits)
  return Array.isArray(saved) ? saved : []
}

async function withButtons(ctx, body) {
  return sendButtons(ctx.sock, ctx.chat, {
    title: 'KANA',
    body,
    footer: ctx.t('menu.footer'),
    replies: [
      { text: ctx.t('ingatkan.btnList'), id: '.ingatkan list' },
      { text: ctx.t('ingatkan.btnMenu'), id: '.menu user' },
    ],
    textFallback: body,
  })
}

export const test = { input: '.ingatkan list', expect: /pengingat/i }

export async function handler(ctx) {
  const sub = (ctx.args[0] || '').toLowerCase()

  if (sub === 'list') {
    const items = await loadReminders(ctx)
    if (!items.length) return withButtons(ctx, ctx.t('ingatkan.empty'))
    const body = [
      ctx.t('ingatkan.listTitle', { name: ctx.pushName || ctx.senderDigits }),
      ...items.map((it, i) => ctx.t('ingatkan.listItem', { n: i + 1, time: formatWib(it.at), text: it.text })),
    ].join('\n')
    return withButtons(ctx, body)
  }

  if (sub === 'batal') {
    const items = await loadReminders(ctx)
    const n = Number(ctx.args[1])
    if (!Number.isInteger(n) || n < 1 || n > items.length) return ctx.reply(ctx.t('ingatkan.notFound', { n: ctx.args[1] || '-' }))
    const [removed] = items.splice(n - 1, 1)
    if (items.length) await ctx.storage.set('reminders', ctx.senderDigits, items)
    else await ctx.storage.delete('reminders', ctx.senderDigits)
    return withButtons(ctx, ctx.t('ingatkan.cancelled', { n, text: removed.text }))
  }

  const minutes = Number(ctx.args[0])
  const text = ctx.args.slice(1).join(' ').trim()
  if (!text) return ctx.reply(ctx.t('ingatkan.usage'))
  if (!Number.isInteger(minutes) || minutes < 1 || minutes > 10080) return ctx.reply(ctx.t('ingatkan.badMinutes'))
  const items = await loadReminders(ctx)
  const at = Date.now() + minutes * 60000
  items.push({ at, text, chat: ctx.chat })
  await ctx.storage.set('reminders', ctx.senderDigits, items)
  return withButtons(ctx, ctx.t('ingatkan.saved', { text, minutes, time: formatWib(at) }))
}