DEV Community

Hasan Gök
Hasan Gök

Posted on

Building a Telegram bot for Joplin in 15 minutes 🤖

Everybody is trying to make their lives better and be organized using several productivity apps. So do I. And personally, I'm a man who lives in a digital notebook.

It has been a while that I'm searching for alternatives to MS OneNote, the tool I use for last 5 years. But time to move on for me. I decided to move into Joplin. It has its pros and cons but I'm not here to talk about comparing note taking apps. I was playing around with Joplin past several days, and I can say that I'm satisfied with its features.

Anyways, I do a lot of work related research on my phone. I mean, A LOT! I put the resources I found to Google Keep, MS To-do. Sometimes, I like a content on Twitter to come back and read later. Sometimes, I send a message to myself to not forget about something and so on... This became more and more disaster for me, using countless tools and different platforms. It's all became frustrating. So I began to consolidate all of this incoming information to my Joplin notebook. When it comes to dealing information on mobile phone, I want simplicity and quickness. So, playing with Joplin API (which is used by its screen clipper app), I wanted to create a Telegram bot, which I can handle my notebook using my phone.

Idea

It has been a few months that I'm using Telegram, and I like its bots, very useful like any other bots 😃. You can ask for anything and get the answer back immediately. So I thought it would be great if I can communicate with my notebook via Telegram messages. After a quick research, I saw it is possible!

First things first! Install Joplin!

The easiest step of this walk-through! Just go to joplinapp.org and hit download! After installing it (you can also use the portable app), open the app, go to Tools > Options and then jump to the Web Clipper tab.

Clipper Service

Click the "Enable Web Clipper Service" button and ta-da! You have a JSON web service, serving at 41184 port, that you can communicate with your notebook. You have authorization token down below the page. Note that token, we'll be using it!

Advanced Settings

Before we move on, let's test our web service. Open an app like postman and make a GET request to this URL: http://localhost:41184/notes?token={your_token}

request to notes

Looks nice! We have our notes via web service!

Create the Telegram bot!

The second easiest part. Let's chit-chat to Telegram's @BotFather. Father welcomes us with the information we need. Let's create our bot with answering @BotFather's questions.

creating bot conversation

Okay, our bot is ready! Let's do some coding to make our bot work as we want.

Let's create a simple nodejs application

Open your console, type npm init, give your application a name and finish the wizard. We are going to use 2 dependencies for our bot. telegraf.js for communicating with Telegram, axios to make http calls to Joplin's web service. Let's install them as below:

npm install telegraf --save
npm install axios --save

Create an index.js file on the root of your project directory and check out documentation on telegraf.js for 5 minutes.

const { Telegraf } = require('telegraf')

const bot = new Telegraf(process.env.BOT_TOKEN)
bot.start((ctx) => ctx.reply('Welcome'))
bot.help((ctx) => ctx.reply('Send me a sticker'))
bot.on('sticker', (ctx) => ctx.reply('👍'))
bot.hears('hi', (ctx) => ctx.reply('Hey there'))
bot.launch()

These lines tell us that the bot will welcomes user with the message Welcome. If the user sends the command /help, bot will reply Send me a sticker. If the user sends a sticker, bot will reply with a 'thumbs up' emoji, and if the user says hi, bot will reply Hey there.

Okay, I want my bot to create a note with the content of the message (if it's a text message). For that, we'll be using bot.on('text', (ctx) => {...}. And I can send image files, so if it receives an image file, I want it to create a note titled with caption of the image and put the image in the note. For that, we'll be using bot.on('photo', (ctx) => {...}.

First, we define a Note class. According to the Joplin API, create requests should have the following data (title, body, base64_image). We create a function to set note's image via incoming photo, if available.

class Note {
  constructor(title, body) {
    this.title = title
    this.body = body
    this.image_data_url = null
  }

  async setImageData(ctx) {
    if (ctx.message.photo) {
      // get largest possible
      let largest = ctx.message.photo.reduce((prev, current) => (+prev.width > +current.width) ? prev : current)
      let image_url = await ctx.telegram.getFileLink(largest.file_id)
      let image_result = await axios.get(image_url, { responseType: 'arraybuffer' });
      this.image_data_url = "data:image/png;base64," + Buffer.from(image_result.data).toString('base64');
    }
  }
}

Then, we configure our bot to communicate with our Joplin notebook as follows.

const { Telegraf } = require('telegraf')
const axios = require('axios');

const bot = new Telegraf("your_telegram_token")
const request_url = 'http://localhost:41184/notes?token={your_joplin_token}'

bot.start((ctx) => {
  ctx.reply('Welcome to your Joplin notebook!, just type /help for available commands 😊')
})
bot.help((ctx) => ctx.reply('Use /notes to gel all your notes, or send a text or image message to create a note...'))
bot.command('notes', async ctx => {
  let notes = await axios.get(request_url)
  ctx.reply(notes.data.map(p => p.title).join('\n'))
})
bot.on('text', async ctx => {
  let note = new Note(ctx.message.text.slice(0, 255), ctx.message.text)
  await axios.post(request_url, note)
  ctx.reply('You created a new text note successfully!')
})
bot.on('photo', async ctx => {
  let caption = ctx.message.caption ? ctx.message.caption : 'No title'
  let note = new Note(caption, caption, ctx.message.photo)
  await note.setImageData(ctx)
  await axios.post(request_url, note);
  ctx.reply('You created a new image note successfully!')
})
bot.launch()

Let's talk with Joplin 😊

texting on telegram

We are all set! Run node index.js or hit F5 (on vscode) to run application. Our bot now can handle text messages to create notes and image messages to create image notes. I pushed this code to this Github repo. I'll hopefully be adding more features like searching via keyword, get note details, tag notes etc if I can make time. Contributions are always welcome 😊

I know Joplin has sync features and a mobile app, but it's good to communicate with somebody even if it's a bot, especially in these days, right? 😉

Thanks for reading!
Hasan

Top comments (2)

Collapse
 
mohamadi_arch profile image
mohammad

I think we can not deploy this bot into a host (like heruko) because Joplin need a localhost. is it right?

Collapse
 
hasangok profile image
Hasan Gök

I wouldn't say Joplin needs localhost, but it somehow should be communicating with the bot itself. If you mean a VPS server by "host" for example, you can install Joplin there and serve the bot application in same host.