adityajat/SaarvamAI_botPublic · Bot Template

ProfileTelegram

AISarvam AI is a multi‑purpose Telegram bot that lets users ask questions, get explanations, convert text to speech, and translate messages using the Sarvam AI API. It also offers group administration commands such as warn, mute, ban, pin, delete, and announcements, and can clear personal or group AI memory. The bot uses the TeleBotHost TBL framework with Bot, Api, db, and HTTP calls, and provides inline keyboards for language and voice selection.

Ai Assistantaivoicetranslatemoderationadminsarvam
34 commands4 envUpdated 15d agoCreated Sep 14, 2026
Back to folder

commands/_handle_message.js

javascript · 680 lines

Raw
1/**#command2name: /handle_message3answer: 4keyboard: 5parse_mode: markdown6aliases: 7allow_only_group: false8need_reply: false9is_web: 010#command**/11 12// ==========================================13// /handle_message14// MAIN MESSAGE + MEDIA HANDLER15// ==========================================16 17try {18 19  if (!update || !update.message) {20    return;21  }22 23  let m = update.message;24 25  if (!m.chat) {26    return;27  }28 29  let chatId = String(m.chat.id);30 31  let isGroup =32    m.chat.type === "group" ||33    m.chat.type === "supergroup";34 35  let username =36    bot && bot.username37      ? bot.username38      : "";39 40  // ==========================================41  // GROUP MENTION CHECK42  // ==========================================43 44  let text =45    typeof m.text === "string"46      ? m.text.trim()47      : "";48 49  let caption =50    typeof m.caption === "string"51      ? m.caption.trim()52      : "";53 54  let mentioned = false;55 56  if (username) {57 58    let mention =59      "@" + username;60 61    if (62      text &&63      text.toLowerCase().indexOf(64        mention.toLowerCase()65      ) !== -166    ) {67      mentioned = true;68 69      let escaped =70        username.replace(71          /[.*+?^${}()|[\]\\]/g,72          "\\$&"73        );74 75      text =76        text77          .replace(78            new RegExp(79              "@" + escaped,80              "ig"81            ),82            ""83          )84          .trim();85    }86 87    if (88      caption &&89      caption.toLowerCase().indexOf(90        mention.toLowerCase()91      ) !== -192    ) {93      mentioned = true;94 95      let escapedCaption =96        username.replace(97          /[.*+?^${}()|[\]\\]/g,98          "\\$&"99        );100 101      caption =102        caption103          .replace(104            new RegExp(105              "@" + escapedCaption,106              "ig"107            ),108            ""109          )110          .trim();111    }112  }113 114  // ==========================================115  // REPLY-TO-BOT CHECK116  // ==========================================117 118  let repliedToBot = false;119 120  if (121    m.reply_to_message &&122    m.reply_to_message.from &&123    username &&124    m.reply_to_message.from.username125  ) {126 127    repliedToBot =128      m.reply_to_message.from.username129        .toLowerCase() ===130      username.toLowerCase();131  }132 133  // ==========================================134  // GROUP NORMAL MESSAGE FILTER135  // ==========================================136 137  if (isGroup) {138 139    // In groups, only respond when:140    // 1. Bot is mentioned141    // 2. User replies to bot142    // 3. User sends media with bot mention143    if (144      !mentioned &&145      !repliedToBot146    ) {147      return;148    }149  }150 151  // ==========================================152  // CONVERSATION HISTORY153  // ==========================================154 155  let historyKey =156    "sarvam_history_" + chatId;157 158  let history =159    await db.user.get(160      historyKey,161      []162    );163 164  if (!Array.isArray(history)) {165    history = [];166  }167 168  if (history.length > 20) {169    history =170      history.slice(-20);171  }172 173  // ==========================================174  // SYSTEM PROMPT175  // ==========================================176 177  178let systemPrompt = `179You are Sarvam, a natural, helpful conversational AI assistant.180 181CONVERSATION:182- Understand the latest user message first.183- Use previous messages when they are relevant to the latest message.184- Understand follow-up questions, pronouns, and references using nearby relevant context.185- Do not bring unrelated older topics into a new conversation.186- If the user says "Hello", greet them naturally and briefly.187- Do not repeatedly introduce yourself.188- Answer the actual question directly.189- Keep simple responses short unless more detail is requested.190 191LANGUAGE AND GRAMMAR:192- Reply in the same language as the latest user message.193- If the user writes in English, reply in natural English.194- If the user writes in Hindi, reply in natural Hindi.195- If the user writes in Hinglish, natural Hinglish is allowed.196- Do not randomly switch languages.197- Do not invent words or create meaningless phrases.198- Do not mix Punjabi, Urdu, or other languages unless requested.199- Use correct, understandable grammar.200- Casual and harsh slang is allowed when appropriate, but clarity is essential.201 202TONE:203- Be friendly and conversational without forcing jokes.204- Do not add unrelated teasing, sarcasm, or exaggerated reactions.205- Match the user's tone naturally without copying errors or nonsensical language.206 207ACCURACY:208- Never knowingly give an incorrect answer.209- For calculations, calculate carefully rather than guessing.210- If uncertain, state the uncertainty instead of inventing facts.211 212MEDIA:213- Use only the media information actually supplied to you.214- Never claim to have inspected image, audio, video, or document contents that are not available.215 216OWNER:217The owner of this bot is @shecallsmecalm.218If asked who your owner is, answer:219"@shecallsmecalm is my owner, the owner of every creation."220`;221 222 223  // ==========================================224  // MEDIA CONTEXT225  // ==========================================226 227  let mediaContext = "";228 229  // ------------------------------------------230  // STICKER231  // ------------------------------------------232 233  if (m.sticker) {234 235    let emoji =236      m.sticker.emoji || "";237 238    mediaContext =239      "[USER SENT A STICKER]\n" +240      "Sticker emoji: " +241      (242        emoji || "unknown"243      ) +244      "\n";245 246    if (emoji) {247      mediaContext +=248        "Analyse and Interpret the sticker's likely emotional meaning and conversation context.\n";249    }250 251    // Reply with the Different sticker.252    // This makes sticker conversations feel natural.253    try {254 255      await Api.sendSticker({256        sticker:257          m.sticker.file_id258      });259 260    } catch (stickerError) {261      // Do not break AI response if sticker sending fails.262    }263  }264 265  // ------------------------------------------266  // PHOTO267  // ------------------------------------------268 269  else if (m.photo) {270 271    mediaContext =272      "[USER SENT A PHOTO]\n" +273      "The user sent a photo.";274 275    if (caption) {276      mediaContext +=277        "\nCaption/question: " +278        caption;279    }280 281    mediaContext +=282      "\nActual visual analysis is performed by sarvam-105b itself.";283  }284 285  // ------------------------------------------286  // DOCUMENT287  // ------------------------------------------288 289  else if (m.document) {290 291    mediaContext =292      "[USER SENT A DOCUMENT]\n" +293      "File name: " +294      (295        m.document.file_name ||296        "unknown"297      ) +298      "\nMIME type: " +299      (300        m.document.mime_type ||301        "unknown"302      );303 304    if (caption) {305      mediaContext +=306        "\nCaption/question: " +307        caption;308    }309  }310 311  // ------------------------------------------312  // VOICE313  // ------------------------------------------314 315  else if (m.voice) {316 317    mediaContext =318      "[USER SENT A VOICE MESSAGE]\n" +319      "Duration: " +320      (321        m.voice.duration || 0322      ) +323      " seconds.";324 325    if (caption) {326      mediaContext +=327        "\nCaption: " +328        caption;329    }330  }331 332  // ------------------------------------------333  // AUDIO334  // ------------------------------------------335 336  else if (m.audio) {337 338    mediaContext =339      "[USER SENT AUDIO]\n" +340      "Title: " +341      (342        m.audio.title ||343        "unknown"344      ) +345      "\nPerformer: " +346      (347        m.audio.performer ||348        "unknown"349      );350  }351 352  // ------------------------------------------353  // VIDEO354  // ------------------------------------------355 356  else if (m.video) {357 358    mediaContext =359      "[USER SENT VIDEO]\n" +360      "Duration: " +361      (362        m.video.duration || 0363      ) +364      " seconds.";365 366    if (caption) {367      mediaContext +=368        "\nCaption/question: " +369        caption;370    }371  }372 373  // ------------------------------------------374  // GIF / ANIMATION375  // ------------------------------------------376 377  else if (m.animation) {378 379    mediaContext =380      "[USER SENT AN ANIMATION / GIF]\n" +381      "The user sent a GIF/animation.";382 383    if (caption) {384      mediaContext +=385        "\nCaption/question: " +386        caption;387    }388  }389 390  // ------------------------------------------391  // OTHER MEDIA392  // ------------------------------------------393 394  else if (395    m.video_note396  ) {397 398    mediaContext =399      "[USER SENT A VIDEO NOTE]\n" +400      "The user sent a circular video message.";401  }402 403  // ==========================================404  // NORMAL TEXT405  // ==========================================406 407  let hasText =408    !!text;409 410  // For media without text,411  // still give AI the media context.412 413  if (414    !hasText &&415    !mediaContext416  ) {417    return;418  }419 420  // ==========================================421  // USER MESSAGE TO AI422  // ==========================================423 424  let userContent = "";425 426  if (text) {427    userContent += text;428  }429 430  if (caption) {431 432    if (userContent) {433      userContent +=434        "\n\n";435    }436 437    userContent +=438      "Caption: " +439      caption;440  }441 442  if (mediaContext) {443 444    if (userContent) {445      userContent +=446        "\n\n";447    }448 449    userContent +=450      mediaContext;451  }452 453  if (!userContent.trim()) {454    userContent =455      mediaContext;456  }457 458  // ==========================================459  // SAVE USER MESSAGE460  // ==========================================461 462  history.push({463    role: "user",464    content: userContent465  });466 467  if (history.length > 20) {468    history =469      history.slice(-20);470  }471 472  // ==========================================473  // BUILD AI REQUEST474  // ==========================================475 476  let messages = [477    {478      role: "system",479      content: systemPrompt480    }481  ];482 483  for (484    let i = 0;485    i < history.length;486    i++487  ) {488    messages.push(489      history[i]490    );491  }492 493  // ==========================================494  // SARVAM API495  // ==========================================496 497  let apiKey =498    process.env.SARVAM_API_KEY;499 500  if (!apiKey) {501 502    return Bot.sendMessage(503      "⚠️ SARVAM_API_KEY is not configured."504    );505  }506 507  let res =508    await HTTP.post(509      "https://api.sarvam.ai/v1/chat/completions",510      {511        headers: {512          "api-subscription-key":513            apiKey514        },515 516        body: {517          model:518            "sarvam-105b",519 520          messages:521            messages,522 523          max_tokens:524            70000525        },526 527        responseType:528          "json",529 530        timeout:531          30000532      }533    );534 535  // ==========================================536  // API FAILURE537  // ==========================================538 539  if (540    !res ||541    !res.ok542  ) {543 544    let status =545      res && res.status546        ? String(res.status)547        : "unknown";548 549    return Bot.sendMessage(550      "⚠️ Sarvam API error (" +551      status +552      "). Please try again."553    );554  }555 556  // ==========================================557  // READ RESPONSE558  // ==========================================559 560  let answer = "";561 562  if (563    res.data &&564    res.data.choices &&565    res.data.choices.length &&566    res.data.choices[0].message567  ) {568 569    answer =570      res.data571        .choices[0]572        .message573        .content || "";574  }575 576  if (577    !answer ||578    !String(answer).trim()579  ) {580 581    return Bot.sendMessage(582      "⚠️ I couldn't generate a response."583    );584  }585 586  answer =587    String(answer)588      .trim();589 590  // ==========================================591  // SAVE AI RESPONSE592  // ==========================================593 594  history.push({595    role: "assistant",596    content: answer597  });598 599  if (history.length > 20) {600    history =601      history.slice(-20);602  }603 604  await db.user.set(605    historyKey,606    history607  );608 609  // ==========================================610  // CLEAN MARKDOWN611  // ==========================================612 613  answer =614    answer615      .replace(/\*\*/g, "")616      .replace(/__/g, "")617      .replace(/`/g, "")618      .trim();619 620  // ==========================================621  // SEND TEXT RESPONSE622  // ==========================================623 624  return Bot.sendMessage(625    answer626  );627 628} catch (e) {629 630  return Bot.sendMessage(631    "⚠️ Message handler error: " +632    (633      e &&634      e.message635        ? e.message636        : String(e)637    )638  );639      }640 641 642const payment = update &&643  update.message &&644  update.message.successful_payment;645 646if (!payment) return;647 648if (649  payment.invoice_payload !== "sarvam_voice_credits_10_v1" ||650  payment.currency !== "XTR" ||651  payment.total_amount !== 50652) {653  return;654}655 656const chargeId = payment.telegram_payment_charge_id;657const key = "voice_paid_" + chargeId;658 659const alreadyProcessed = await db.user.get(key, false);660 661if (alreadyProcessed) return;662 663const saved = await db.user.set(key, true);664 665if (!saved || saved.ok === false) {666  Bot.sendMessage(667    "Payment received, but credit processing needs attention. Contact the bot owner with your payment receipt."668  );669  return;670}671 672await db.user.incr("voice_credits", 10);673 674const balance = await db.user.get("voice_credits", 0);675 676Bot.sendMessage(677  "✅ Payment successful!\n\n" +678  "Added: 10 voice credits\n" +679  "Your balance: " + balance680);