LoginSignup
9
10

More than 5 years have passed since last update.

Slackで送った文字を画像で返すbot作った

Last updated at Posted at 2017-12-09

ここでは

Slackで @textchan create 絵文字! と送ると、

絵文字!

という画像をアップしてくれるbotを作ってみる。

つくる理由

Slackで カスタム絵文字が多用されているようなチーム では、
文字だけを収めたカスタム絵文字が多く存在する。
またそれは、ユーザーの手作りであることが多い。

特にエンジニアが大活躍するようなところでは、
各エンジニアがPhotoshop等のデザインツールを持っていないことも珍しくないだろう。
カスタム絵文字の製作時間で職務に影響がでることは間違いない。効率化すべきである。

例)

/ 嬉しいときに


登校 / 登校したときに

何故、文字だけの絵文字が必要か

投稿に対して、すぐ読み取れるReactionを送ることができる
Reactionの例

今の気持ちとして、IDの横にStatusとして表示しておくことができる
Statusの例

つくる

テキストから画像を起こすという処理をするのあたり、
Node.js 上で canvas を生成できる node-canvasというのがいいと思った。
ウェブ上のJavaScriptで <canvas> を生成するのと同じ要領で使える。
のちのち、文字位置調整や、色、フォントの変更をする際も、比較的楽にできる。

また、Slack上で、Mentionを検知、画像をアップロードするために Botkit を使用する。

# node-canvas を動かすためのライブラリのインストール
# こちらは MacでHomebrewでインストールする場合
# その他 https://github.com/Automattic/node-canvas#installation
brew install pkg-config cairo pango libpng jpeg giflib

# node packageのインストール
npm install --save node-canvas botkit

参考にするもの

GitHub Repository 有り
Qiita上のコードは一部簡略化している

index.js
const Botkit = require('botkit')
const canvas = require('./canvas')

if (!process.env.token) {
  console.log('Error: Specify token in environment')
  process.exit(1)
}

const controller = Botkit.slackbot({
  debug: false
})

controller.spawn({
  token: process.env.token
}).startRTM(function (err) {
  if (err) {
    throw new Error(err)
  }
})

controller.hears('create(.*)', ['direct_message', 'direct_mention', 'mention'], function (bot, message) {
  var setting = {
    text: '',
    color: '#000',
    fontFamily: 'YuGothic'
  }

  var args = message.match[1]
  var reg = /\s+(["“”][^"“”]+["“”]|[^ ]+)/g
  var arg, i = 0

  while (arg = reg.exec(args)) {
    arg = arg[1].replace(/^["“”](.*)["“”]$/, '$1')

    switch (i) {
      case 0:
        setting.text = arg
        break
      case 1:
        setting.color = arg
        break
      case 2:
        setting.fontFamily = arg
        break
    }
    i++
  }

  canvas(setting).then(function (fileObj) {
    var messageObj = fileObj
    messageObj.channels = message.channel

    bot.api.files.upload(messageObj, function (err, res) {
      if (err) console.log(err)
    })
  })
})

▲Slack上でのMentionの検知や画像アップロードなどの処理などを記述

canvas.js
const Canvas = require('canvas')
const fs = require('fs')

var insertStr = function (str, index, insert) {
  return str.slice(0, index) + insert + str.slice(index, str.length);
}
var canvas_to_base64 = function (c) {
  return c.toDataURL().split(',')[1]
}
var decode_and_copy = function (string, filename) {
  return new Promise(function (resolve, reject) {
    var buffer = new Buffer(string, 'base64')
    fs.writeFile(filename, buffer, function (err) {
      if (err) {
        reject(err)
        return
      }
      resolve()
    })
  })
}

async function canvas(setting, next) {

  setting = setting || {
    text: 'えもじ!',
    color: '#000',
    fontFamily: 'YuGothic'
  }

  const text_n = insertStr(setting.text, 2, '\n')
  const filename = './' + setting.text + '.png'

  const c = new Canvas(128, 128)
  const ctx = c.getContext('2d')

  ctx.font = 'bold 60px ' + setting.fontFamily
  ctx.textAlign = 'center'
  ctx.fillStyle = setting.color
  ctx.fillText(text_n, 64, 56)

  await decode_and_copy(canvas_to_base64(c), filename)

  const fileObj = {
    file: fs.createReadStream(filename),
    filename: setting.text + '.png',
    title: setting.text
  }

  return fileObj
}

module.exports = canvas

▲テキストを画像にする処理を記述
今回は、全角4文字を 2文字・2文字の2行にする処理のみ

うごかす

# [Slack API Token] は適宜置き換え
token=[Slack API Token] node index.js
Slack
@textchan create 絵文字!
@textchan create 赤・明朝 red "YuMincho"

絵文字! 赤・明朝

恐らくこれらが返ってくるので
一旦ダウンロードし カスタム絵文字 として追加する

課題

  • 全角4文字以外でもキレイな画像を生成させる
  • canvasを一度画像ファイルで保存し、その画像ファイルを読み込んでいるが、恐らく不要な作業
  • 使用できるフォントが、マシンなりサーバーなりに依存する
  • 自動でカスタム絵文字追加させたい

おわり

楽しいカスタム絵文字ライフを。

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10