20
loading...
This website collects cookies to deliver better user experience
/start
tells Botfather to boot up and show you all of its available commands./newbot
. Give your bot a display name, then a username that will be registered with Telegram. The latter has to end with "bot." I chose sanity_gc_memebot
for the purposes of this tutorial.index.js
file. Let's get to work!TELEGRAM_BOT_KEY
and paste the value you received from Botfather.index.js
file write the following code:// index.js
// imports the node package for us
const TelegramBot = require('node-telegram-bot-api');
// grabs the environment variable
const token = process.env.TELEGRAM_BOT_KEY;
// starts a new Telegram bot instance that "polls" for updates
const bot = new TelegramBot(token, {polling: true});
package.json
initializes, and the node-telegram-bot-api
package on npm is installed. Usually you have to do both of these things by hand. Pretty sweet
, comes with great documentation. Let's start with one of the methods from the README. We'll tell our bot to send an introduction anytime a user runs /start
.// index.js
// ... after everything we wrote already
// we're using the API's in-built "onText" method
// it takes in a regex and the message
bot.onText(/\/start/, (msg) => {
// listens for "/start" and responds with the greeting below.
bot.sendMessage(msg.chat.id,
"Hey, I'm a brand new Telegram bot. I live inside a Sanity tutorial.");
});
t.me/your_bot
.)// index.js
// ... at the bottom
bot.on('message', (msg) => {
console.log(msg);
bot.sendMessage(msg.chat.id, "Message logged to console!")
})
msg
object logged in the right hand side. This is helpful for debugging when our bot becomes more complex.sanity init
. Name it anything you want and select the blog schema.meme.js
.// your-studio-folder/schemas/meme.js
export default {
name: "meme",
title: "Meme",
type: "document",
fields: [
{
name: "mainImage",
title: "Main image",
type: "image",
},
{
name: "publishedAt",
title: "Published at",
type: "datetime",
},
{
name: "author",
title: "Author",
type: "string",
},
],
};
schema.js
file (also in your schemas directory), import the meme.js
file and export it along with your blog information.// your-studio-folder/schemas/schema.js
import meme from "./meme.js"
//and export it with the rest of the schema
//...
meme,
//...
sanity deploy
and take our studio live.SANITY_WRITE_TOKEN
. Paste your very powerful, very secret value in the field provided and we'll be ready to test it out.helpers.js
.// helpers.js
const sanityClient = require('@sanity/client')
const client = sanityClient({
projectId: 'your_project_id',
dataset: 'production',
//define your apiVersion as the current date
apiVersion: '2021-04-05',
token: process.env.SANITY_WRITE_TOKEN,
useCdn: false,
})
module.exports = { client }
npm install
the Sanity client.// index.js
// ...
const { client } = require('./helpers')
// ...
bot.on('message', (msg) => {
//here, an in-built method from Sanity creates a new doc for us
client.create({
_type: 'post',
title: msg.text
})
//when it's done, the bot sends a success message
.then(res=>bot.sendMessage(msg.chat.id, "Doc was published!"))
.catch(error => console.error(error));
})
// helpers.js
const fs = require('fs')
const request = require('request')
const sanityClient = require('@sanity/client')
const client = sanityClient({
// ...
})
const download = (url, path, callback) => {
//the "request" library helps us make HTTP requests in node
//though it is deprecated, it works for our purposes.
//more here: https://www.npmjs.com/package/request
request.head(url, (err, res, body) => {
request(url)
//using Node's .pipe() method, we connect the
//readable stream to a writeable stream.
.pipe(fs.createWriteStream(path))
.on('close', callback)
})
}
module.exports = { client, download }
request
library to fetch the URL of the file we want to download. Then we tell Node to create a new file from the data we've fetched and place it at the path we specify. images
and make that the file path.// index.js
// ...
bot.on('message', (msg) => {
// this will give us easier access to the chat ID
const chatId = msg.chat.id;
// checking if the msg has a photo
if (msg.photo) {
bot.sendMessage(chatId, "Hey, that's a picture.")
}
else {bot.sendMessage(chatId, "If it's not a picture, I'm not concerned.")}
})
fetch
method, we need to add it ourselves. We'll also add Node's file system module so we can manipulate image files on Replit.// index.js
// ...
const fetch = require("node-fetch");
const fs = require('fs')
// ...
bot.on(...)
code with the following:bot.on('message', (msg) => {
// this will give us easier access to the chat ID
const chatId = msg.chat.id;
// checking if the msg has a photo
if (msg.photo) {
bot.sendMessage(
chatId,
"Hey, that's a picture. I'm gonna download it to Replit...")
//retrieves the file ID from the photo
const imageID = msg.photo[0].file_id;
//finds the file in the Telegram servers
const imageSender =
fetch(
`https://api.telegram.org/bot${token}/getFile?file_id=${imageID}`
)
.then(res => res.json())
.then(data => {
//sets the file path on Telegram servers
const filePath = data.result.file_path;
//finds the URL to download the image from Telegram servers
const url =
`https://api.telegram.org/file/bot${token}/${filePath}`;
//defines where we want Node to download the image
const path = `./temp/image.png`
//uses our helper function to download file
download(url, path, () => {
bot.sendMessage(chatId, '✅ Downloaded image to Replit!')
})
})
}
})
temp
folder. The Sanity client makes asset uploading relatively painless, so this is simpler than it could be!// index.js
// ...
// inside bot.on('message'...
download(url, path, () => {
bot.sendMessage(chatId, '✅ Downloaded image to Replit!');
//using Sanity's upload methods
client.assets
.upload('image',
//tell Node to read the image and create a new file in Sanity
fs.createReadStream(path), {filename: `img-${imageID}.png`})
.then((document) => {
bot.sendMessage(chatId, 'Creating meme document...', document)
//destructure the image ID from document object
const {_id} = document;
//create the meme document!
client.create({
_type: 'meme',
mainImage: {
asset: {
_type: 'reference',
//feed the image ID into the mainImage field as its reference
_ref: _id,
}
},
//fill out the author and publishedAt fields
author: `${msg.from.first_name} ${msg.from.last_name}`,
publishedAt: new Date().toISOString()
})
//let us know when it's received
.then(res=>bot.sendMessage(chatId, `✅ Doc was published to Sanity!
ID: ${res._id}`))
//catch any errors
.catch(error => {
bot.sendMessage(chatId, `❌ Upload failed, check console.`);
console.error(error);
})
})
.catch((error) => {
bot.sendMessage(chatId, `❌ Upload failed, check console.`);
console.error('Upload failed:', error.message)
})
})
// ... end of bot.on('message'..) function
mainImage
field and it is attached to our new meme document. Then we create the meme, adding the name of the Telegram user as the author and the current datetime as our publishedAt
field..env
with your API keys, then add your Sanity project ID to the helpers.js
file./start
in the completed bot. See what happens? How do we get the "... I'm not concerned" message to not show up when the start command is issued? A conditional combined with a regex, maybe?