Node.js、Telegraf、Jimp、およびPexelsを使用してTelegramQuotesGeneratorボットを構築する方法

提供:Dev Guides
移動先:案内検索

著者は、 Write for DOnations プログラムの一環として、 Free and Open SourceFundを選択して寄付を受け取りました。

序章

このチュートリアルでは、 Node.jstelegrafjimp 、および PexelsAPIを使用してTelegramを構築しますファクトがオーバーレイされたランダムに選択された画像を送信するチャットボット。 Telegramボットは、好みのTelegramクライアントを介してカスタムスラッシュコマンドを使用して対話できるボットです。 Telegramを使用してボットを作成し、JavaScriptを使用してランダムな動物の画像と動物のファクトを選択するロジックを定義します。

このチュートリアルの最後に、次のようなTelegramチャットボットがあります。

ボットを完成させると、カスタムのTelegramスラッシュコマンドを送信するたびに、動物に関する事実を受け取ることができます。

前提条件

このチュートリアルに従うには、読者は次のツールが必要になります。

このチュートリアルは、Nodev12.18.2およびnpmv6.14.8で検証されました。

ステップ1—プロジェクトルートディレクトリを作成する

このセクションでは、チャットボットをビルドするディレクトリを作成し、Nodeプロジェクトを作成して、必要な依存関係をインストールします。

ターミナルウィンドウを開き、facts-botという名前の新しいディレクトリを作成します。

mkdir facts-bot

ディレクトリに移動します。

cd facts-bot

tempという名前のディレクトリを作成します。

mkdir temp

上記のコマンドを使用して、tempという名前のディレクトリを作成しました。 このディレクトリには、ボットがユーザーに送信する画像を一時的に保存します。

次に、新しいNode.jsプロジェクトを作成します。 npmのinitコマンドを実行すると、package.jsonファイルが作成され、依存関係とメタデータが管理されます。

初期化コマンドを実行します。

npm init

デフォルト値を受け入れるには、ENTERを押してすべてのプロンプトを表示します。 または、応答をパーソナライズすることもできます。 これを行うには、チュートリアルnpmおよびpackage.jsonでNode.jsモジュールを使用する方法のステップ1でnpmの初期化設定を確認します。

package.jsonファイルを開き、編集します。

nano package.json

次に、package.jsonファイルのプロパティを更新します。 ファイル内の内容を強調表示されたコードに置き換えます。

package.json

{
  "name": "facts-bot",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "start": "nodemon main.js"
  },
  "author": "",
  "license": "ISC"
}

ここでは、mainおよびscriptsプロパティを変更しました。 mainプロパティを変更することにより、アプリケーションのメインファイルをmain.jsに設定しました。 これにより、main.jsファイルがプログラムへの主要なエントリポイントであることがノードに通知されます。 scriptsプロパティに、startという名前のscriptを追加しました。これにより、アプリケーションの起動時に実行されるはずのコマンドを設定できます。 scriptを呼び出すと、コマンドnodemonは、次のステップで作成するmain.jsファイルを実行します。

package.jsonファイルで設定が定義されたら、環境変数を保存するファイルを作成します。 ターミナルで、.envという名前のファイルを作成します。

touch .env

.envファイルに、TelegramボットトークンとPexelsAPIキーを保存します。 Telegram Botトークンを使用すると、Telegramボットと対話できます。 Pexels APIキーを使用すると、PexelsAPIを操作できます。 後のステップで環境変数を保存します。

今回は、npmを使用して、依存関係telegrafdotenvpexelsjimp、および[をインストールします。 X112X]。 また、--saveフラグを使用して依存関係を保存します。 ターミナルで、次のコマンドを実行します。

npm install telegraf dotenv pexels jimp uuid --save

このコマンドでは、以下をインストールしました。

  • telegraf :JavaScriptまたはTypeScriptを使用して独自のTelegramボットを開発するのに役立つライブラリ。 これを使用してボットを構築します。
  • dotenv :環境変数を.envファイルからprocess.envにロードするゼロ依存モジュール。 このモジュールを使用して、作成した.envファイルからボットトークンとPexelsAPIキーを取得します。
  • pexels :Node.jsのサーバーとブラウザーの両方で使用できるPexelsAPIの便利なラッパー。 このモジュールを使用して、Pexelsから動物の画像を取得します。
  • jimp :Node用にJavaScriptで完全に記述された画像処理ライブラリで、外部またはネイティブの依存関係はありません。 このライブラリを使用して、Pexelsから取得した画像を編集し、動物に関する事実を挿入します。
  • uuid :JavaScriptでRFC準拠のUUIDを生成できるようにするモジュール。 このモジュールを使用して、Pexelsから取得した画像の一意の名前を作成します。

次に、nodemonを開発依存関係としてインストールします。

npm install nodemon --save-dev

nodemon は、ディレクトリ内のファイルの変更を検出したときにNodeアプリケーションを自動的に再起動することにより、Node.jsベースのアプリケーションを開発するツールです。 このモジュールを使用して、ボットをテストしながらアプリを起動して実行し続けます。

注:これを書いている時点では、使用されているモジュールのバージョンは次のとおりです。telegraf:4.3.0; dotenv:8.2.0; pexels:1.2.1; jimp:0.16.1; uuid:8.3.2; nodemon:2.0.12。


このステップでは、プロジェクトディレクトリを作成し、ボットのNode.jsプロジェクトを初期化しました。 ボットの構築に必要なモジュールもインストールしました。 次のステップでは、ボットをTelegramに登録し、PexelsAPIのAPIキーを取得します。

ステップ2—ボットを登録してPexelsAPIからAPIキーを取得する

このセクションでは、最初にボットを BotFather に登録し、次にPexelsAPIのAPIキーを取得します。 BotFatherは、Telegramによって管理されるチャットボットであり、ユーザーがチャットボットを作成および管理できるようにします。

お好みのテレグラムクライアントを開き、@BotFatherを検索して、チャットを開始します。 /newbotスラッシュコマンドを送信し、BotFatherから送信された指示に従います。

ボット名とユーザー名を選択すると、ボットアクセストークンを含むメッセージが表示されます。

ボットトークンをコピーして、.envファイルを開きます。

nano .env

BOT_TOKENという名前の変数にボットトークンを保存します。

.env

BOT_TOKEN = "Your bot token"

ボットトークンを.envファイルに保存したので、次はPexelsAPIキーを取得します。

Pexels に移動し、Pexelsアカウントにログインします。 クリックしてください画像と動画のAPI タブをクリックして、新しいAPIキーを作成します。

APIキーをコピーし、.envファイルを開きます。

nano .env

APIキーをPEXELS_API_KEYという名前の変数に保存します。 .envは次のようになります。

.env

BOT_TOKEN = "Your_bot_token"
PEXELS_API_KEY = "Your_Pexels_API_key"

このセクションでは、ボットを登録し、Pexels APIキーを取得し、ボットトークンとPexelsAPIキーを.envファイルに保存しました。 次のセクションでは、ボットの実行を担当するファイルを作成します。

ステップ3—main.jsファイルを作成する

このセクションでは、ボットを作成して構築します。 main.jsというラベルのファイルを作成します。これには、ボットのロジックが含まれます。

プロジェクトのルートディレクトリで、お好みのテキストエディタを使用してmain.jsファイルを作成して開きます。

nano main.js

main.jsファイル内に、使用するライブラリをインポートするための次のコードを追加します。

main.js

const { Telegraf } = require('telegraf')
const { v4: uuidV4 } = require('uuid')
require('dotenv').config()
let factGenerator = require('./factGenerator')

このコードブロックでは、telegrafuuiddotenvモジュール、およびfactGenerator.jsという名前のファイルが必要です。 telegrafモジュールを使用してボットを起動および管理し、uuidモジュールを使用してイメージの一意のファイル名を生成し、dotenvモジュールを使用して.envファイルに保存されているテレグラムボットトークンとPexelsAPIキー。 factGenerator.jsファイルは、Pexelsからランダムな動物の画像を取得し、動物に関する事実を挿入し、ユーザーに送信された後に画像を削除するために使用されます。 このファイルは次のセクションで作成します。

requireステートメントの下に、次のコードを追加してボットのインスタンスを作成します。

main.js

. . .

const bot = new Telegraf(process.env.BOT_TOKEN)

bot.start((ctx) => {
    let message = ` Please use the /fact command to receive a new fact`
    ctx.reply(message)
})

ここでは、BotFatherが送信したBOT_TOKENを取得して使用し、新しいボットインスタンスを作成して、botという変数に割り当てました。 新しいボットインスタンスを作成した後、/startコマンドのコマンドリスナーを追加しました。 このコマンドは、ユーザーとボットの間の会話を開始する役割を果たします。 ユーザーが/startを含むメッセージを送信すると、ボットは/factコマンドを使用して新しいファクトを受信するようにユーザーに求めるメッセージで応答します。

これで、チャットボットとの対話を開始するコマンドハンドラーが作成されました。 それでは、ファクトを生成するためのコマンドハンドラーを作成しましょう。 .start()コマンドの下に、次のコードを追加します。

main.js

. . .

bot.command('fact', async (ctx) => {
    try {
        ctx.reply('Generating image, Please wait !!!')
        let imagePath = `./temp/${uuidV4()}.jpg`
        await factGenerator.generateImage(imagePath)
        await ctx.replyWithPhoto({ source: imagePath })
        factGenerator.deleteImage(imagePath)
    } catch (error) {
        console.log('error', error)
        ctx.reply('error sending image')
    }
})

bot.launch()

このコードブロックでは、カスタム/factスラッシュコマンドのコマンドリスナーを作成しました。 このコマンドがTelegramユーザーインターフェイスからトリガーされると、ボットはユーザーにメッセージを送信します。 uuidモジュールは、イメージ名とパスを生成するために使用されます。 画像は、ステップ1で作成した/tempディレクトリに保存されます。 その後、画像パスがgenerateImage()という名前のメソッドに渡され、factGenerator.jsファイルで定義して、動物に関する事実を含む画像を生成します。 画像が生成されると、画像がユーザーに送信されます。 次に、factGenerator.jsファイルのdeleteFileという名前のメソッドに画像パスが渡され、画像が削除されます。 最後に、bot.launch()メソッドを呼び出してボットを起動しました。

main.jsファイルは次のようになります。

main.js

const { Telegraf } = require('telegraf')
const { v4: uuidV4 } = require('uuid')
require('dotenv').config()
let factGenerator = require('./factGenerator')


const bot = new Telegraf(process.env.BOT_TOKEN)

bot.start((ctx) => {
    let message = ` Please use the /fact command to receive a new fact`
    ctx.reply(message)
})


bot.command('fact', async (ctx) => {
    try {
        ctx.reply('Generating image, Please wait !!!')
        let imagePath = `./temp/${uuidV4()}.jpg`
        await factGenerator.generateImage(imagePath)
        await ctx.replyWithPhoto({ source: imagePath })
        factGenerator.deleteImage(imagePath)
    } catch (error) {
        console.log('error', error)
        ctx.reply('error sending image')
    }
});


bot.launch()

ボットの実行と管理を担当するファイルを作成しました。 ここで、動物のファクトを設定し、factGenerator.jsファイルでボットのロジックを構築します。

ステップ4—ファクトジェネレータファイルの作成とボットロジックの構築

このセクションでは、fact.jsおよびfactGenerator.jsという名前のファイルを作成します。 fact.jsは、動物に関する事実を1つのデータソースに保存します。 factGenerator.jsファイルには、ファイルから動物に関するランダムなファクトを取得し、Pexelsから画像を取得し、jimpを使用して取得した画像にファクトを書き込み、削除するために必要なコードが含まれます。画像。

プロジェクトのルートディレクトリで、お好みのテキストエディタを使用してfacts.jsファイルを作成して開きます。

nano facts.js

facts.jsファイル内に、次のコードを追加してデータソースを作成します。

facts.js

const facts = [
    {
        fact: "Mother pandas keep contact with their cub nearly 100% of the time during their first month - with the cub resting on her front and remaining covered by her paw, arm or head.",
        animal: "Panda"
    },
    {
        fact: "The elephant's temporal lobe (the area of the brain associated with memory) is larger and denser than that of people - hence the saying 'elephants never forget'.",
        animal: "Elephant"
    },
    {
        fact: "On average, males weigh 190kg and females weigh 126kg . They need this weight and power behind them to hunt large prey and defend their pride.  ",
        animal: "Lion"
    },
    {
        fact: "The Amazon river is home to four species of river dolphin that are found nowhere else on Earth. ",
        animal: "Dolphin"
    },
]

module.exports = { facts }

このコードブロックでは、動物に関する事実を含む配列を使用してオブジェクトを定義し、factsという名前の変数に格納しました。 各オブジェクトには、factおよびanimalのプロパティがあります。 factという名前のプロパティでは、その値は動物に関する事実であり、プロパティanimalには動物の名前が格納されます。 最後に、factsアレイをエクスポートしています。

次に、factGenerator.jsという名前のファイルを作成します。

nano factGenerator.js

factGenerator.jsファイル内に、動物の画像を作成するためのロジックを構築するために使用する依存関係に必要な次のコードを追加します。

factGenerator.js

let { createClient } = require('pexels')
let Jimp = require('jimp')
const fs = require('fs')
let { facts } = require('./facts')

ここでは、pexelsjimpfsモジュール、およびfacts.jsファイルが必要です。 pexelsモジュールを使用してPexelsから動物の画像を取得し、jimpモジュールを使用してPexelsから取得した画像を編集し、fsモジュールを使用してファイルから画像を削除します。ユーザーに送信された後のディレクトリ。

requireステートメントの下に、次のコードを追加して画像を生成します。

factGenerator.js

. . .

async function generateImage(imagePath) {
  let fact = randomFact()
  let photo = await getRandomImage(fact.animal)
  await editImage(photo, imagePath, fact.fact)
}

このコードブロックでは、generateImage()という名前の関数を作成しました。 この関数は、ファイルディレクトリ内のPexelイメージのパスを引数として取ります。 この関数が呼び出されると、randomFact()という名前の関数が呼び出され、返された値がfactという名前の変数に格納されます。 randomFact()関数は、facts.jsファイル内のオブジェクトをランダムに選択します。 オブジェクトを受け取った後、そのプロパティanimalgetRandomImage()という名前の関数に渡されます。 getRandomImage()関数は、pexelsモジュールを使用して、渡された動物の名前を含む画像を検索し、ランダムな画像を選択します。 返された値は、photoという名前の変数に格納されます。 最後に、photoimagePath、およびfacts.jsファイルのfactプロパティが、editImage()という名前の関数に渡されます。 editImage()機能は、jimpモジュールを使用してランダムファクトをランダム画像に挿入し、編集した画像をimagePathに保存します。

ここでは、/factスラッシュコマンドをボットに送信するときに呼び出される関数を作成しました。 次に、関数getRandomImage()およびeditImage()を作成し、ランダムな画像の選択と編集の背後にあるロジックを構築します。

generateImage()関数の下に、次のコードを追加してランダム化ロジックを設定します。

factGenerator.js

. . .

function randomFact() {
  let fact = facts[randomInteger(0, (facts.length - 1))]
  return fact
}


function randomInteger(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

これで、関数randomFact()およびrandomInteger()が作成されました。 randomFact()関数は、randomInteger()関数を呼び出して、facts.jsファイル内のランダムなfactを選択し、このオブジェクトを返します。 randomInteger()関数は、0の間隔のランダムな整数とfacts.jsファイル内のファクトの数を返します。

ランダムなファクトとランダムな整数を返す関数を定義したので、Pexelsからランダムな画像を取得する関数を作成する必要があります。 randomInteger()関数の下に、次のコードを追加してランダムな画像を取得します。

factGenerator.js

. . .

async function getRandomImage(animal) {
  try {
    const client = createClient(process.env.PEXELS_API_KEY)
    const query = animal
    let image

    await client.photos.search({ query, per_page: 10 }).then(res => {
      let images = res.photos
      image = images[randomInteger(0, (images.length - 1))]

    })

    return image

  } catch (error) {
    console.log('error downloading image', error)
    getRandomImage(animal)
  }
}

このコードブロックでは、getRandomImage()という名前の関数を作成しました。 この関数は、引数として動物の名前を取ります。 この関数が呼び出されると、clientオブジェクトは、pexelsモジュールのcreateClient()メソッドオブジェクトと.envファイルに格納されているPexelsAPIキーを使用して作成されます。 動物名はqueryという変数に格納され、clientオブジェクトを使用してqueryの値を含む画像が検索されます。 画像が見つかると、randomInteger()機能を使用してランダムな画像が選択されます。 最後に、ランダム画像がmain.jsファイルのgenerateImage()メソッドに返されます。

getRandomImage()機能を使用すると、選択した画像をTelegramボットに送信する前にテキストオーバーレイを作成する必要があります。 getRandomImage()関数の下に、次のコードを追加してオーバーレイを設定します。

factGenerator.js

. . .

async function editImage(image, imagePath, fact) {
  try {
    let imgURL = image.src.medium
    let animalImage = await Jimp.read(imgURL).catch(error => console.log('error ', error))
    let animalImageWidth = animalImage.bitmap.width
    let animalImageHeight = animalImage.bitmap.height
    let imgDarkener = await new Jimp(animalImageWidth, animalImageHeight, '#000000')
    imgDarkener = await imgDarkener.opacity(0.5)
    animalImage = await animalImage.composite(imgDarkener, 0, 0);


  } catch (error) {
    console.log("error editing image", error)
  } 

}

ここでは、editImage()という名前の関数を作成しました。 この関数は、引数としてimage、imagePath、およびこのランダムな動物に関するfactというラベルの付いたランダムな動物を取ります。 変数imgURLでは、中サイズの画像のURLがPexelsAPIから取得されます。 その後、jimpread()メソッドを使用して画像をロードします。 画像がanimalImageという名前の変数に読み込まれて保存されると、画像の幅と高さが取得され、それぞれ変数animalImageWidthanimalImageHeightに保存されます。 変数imgDarkenerは、Jimp()の新しいインスタンスを格納し、画像を暗くします。 jimpopacity()メソッドを使用して、imgDarkenerの不透明度を50%に設定します。 最後に、jimpcomposite()メソッドを使用して、animalImageの画像の上にimgDarkenerのコンテンツを配置します。 これにより、fact変数に格納されているテキストを追加する前に、animalImageの画像が暗くなり、画像上にテキストが表示されます。

注: Jimpはデフォルトで、画像の色調レベルを調整できるcolor()という名前のメソッドを提供します。 color()メソッドはここで必要な精度を提供しないため、このチュートリアルの目的のために、カスタムトーンアジャスターを作成します。


editImage()関数内のtryブロックの下部に、次のコードを追加します。

factGenerator.js

. . .

async function editImage(image, imagePath,fact) {
  try {
    . . .

    let posX = animalImageWidth / 15
    let posY = animalImageHeight / 15
    let maxWidth = animalImageWidth - (posX * 2)
    let maxHeight = animalImageHeight - posY

    let font = await Jimp.loadFont(Jimp.FONT_SANS_16_WHITE)
    await animalImage.print(font, posX, posY, {
      text: fact,
      alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
      alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE
    }, maxWidth, maxHeight)

    await animalImage.writeAsync(imagePath)
    console.log("Image generated successfully")
    

  } catch (error) {
    . . .
  }
}

このコードブロックでは、animalImageWidthanimalImageHeightを使用して、animalImageのテキストを中央に配置するために使用される値を取得しました。 その後、jimploadFont()メソッドを使用してフォントをロードし、fontという名前の変数にフォントを格納しました。 フォントの色は白、タイプはsans-serif(SANS)、サイズは16です。 最後に、jimpprint()メソッドを使用してfactanimalImageに挿入し、write()メソッドを使用して[ imagePathのX135X]。

画像の編集を担当する関数を作成したので、ユーザーに画像を送信した後、ファイル構造から画像を削除する関数が必要になります。 editImage()関数の下に、次のコードを追加します。

factGenerator.js

. . .

const deleteImage = (imagePath) => {
    fs.unlink(imagePath, (err) => {
        if (err) {
            return
        }
        console.log('file deleted')
    })
}


module.exports = { generateImage, deleteImage }

ここでは、deleteImage()という名前の関数を作成しました。 この関数は、引数として変数imagePathを取ります。 この関数が呼び出されると、fsモジュールを使用して、変数imagePathに格納されている画像が削除されます。 最後に、generateImage()関数とdeleteImage()関数をエクスポートしました。

関数を配置すると、factGenerator.jsファイルは次のようになります。

factGenerator.js

let { createClient } = require('pexels')
let Jimp = require('jimp')
const fs = require('fs')
let { facts } = require('./facts')

async function generateImage(imagePath) {
  let fact = randomFact()
  let photo = await getRandomImage(fact.animal)
  await editImage(photo, imagePath, fact.fact)
}


function randomFact() {
  let fact = facts[randomInteger(0, (facts.length - 1))]
  return fact
}


function randomInteger(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}


async function getRandomImage(animal) {
  try {
    const client = createClient(process.env.PEXELS_API_KEY)
    const query = animal
    let image

    await client.photos.search({ query, per_page: 10 }).then(res => {
      let images = res.photos
      image = images[randomInteger(0, (images.length - 1))]

    })

    return image

  } catch (error) {
    console.log('error downloading image', error)
    getRandomImage(animal)
  }
}


async function editImage(image, imagePath, fact) {
  try {
    let imgURL = image.src.medium
    let animalImage = await Jimp.read(imgURL).catch(error => console.log('error ', error))
    let animalImageWidth = animalImage.bitmap.width
    let animalImageHeight = animalImage.bitmap.height
    let imgDarkener = await new Jimp(animalImageWidth, animalImageHeight, '#000000')
    imgDarkener = await imgDarkener.opacity(0.5)
    animalImage = await animalImage.composite(imgDarkener, 0, 0);

    let posX = animalImageWidth / 15
    let posY = animalImageHeight / 15
    let maxWidth = animalImageWidth - (posX * 2)
    let maxHeight = animalImageHeight - posY

    let font = await Jimp.loadFont(Jimp.FONT_SANS_16_WHITE)
    await animalImage.print(font, posX, posY, {
      text: fact,
      alignmentX: Jimp.HORIZONTAL_ALIGN_CENTER,
      alignmentY: Jimp.VERTICAL_ALIGN_MIDDLE
    }, maxWidth, maxHeight)

    await animalImage.writeAsync(imagePath)
    console.log("Image generated successfully")

  } catch (error) {
    console.log("error editing image", error)
  }

}


const deleteImage = (imagePath) => {
  fs.unlink(imagePath, (err) => {
    if (err) {
      return
    }
    console.log('file deleted')
  })
}


module.exports = { generateImage, deleteImage }

factGenerator.jsファイルを保存します。 ターミナルに戻り、次のコマンドを実行してボットを起動します。

npm start

好みのTelegramクライアントを開き、ボットを検索します。 /startコマンドでメッセージを送信して会話を開始するか、開始ボタンをクリックします。 次に、/factコマンドでメッセージを送信して、画像を受信します。

次のような画像が表示されます。

これで、画像にファクトが課された、好みのTelegramクライアントに画像が表示されます。 facts.jsファイルからランダムなファクトを取得し、Pexelsから動物の画像を取得し、画像にファクトを挿入するファイルと関数を作成しました。

結論

このチュートリアルでは、カスタムのスラッシュコマンドを使用してファクトをオーバーレイした動物の画像を送信するTelegramチャットボットを作成しました。 telegrafモジュールを使用してボットのコマンドハンドラーを作成しました。 また、pexelsモジュールを使用してPexelsからランダムなファクト、ランダムな画像を取得し、jimpモジュールを使用してランダムな画像にファクトを挿入する関数を作成しました。 Pexels API、telegraf、およびjimpモジュールの詳細については、 Pexels APItelegraf 、jimp[のドキュメントを参照してください。 X160X]。