1
/
5

【Slack自動保存】サーバーレスでCronのように定期的にプログラムを実行しよう

どうもこんにちは。zonoと申します。普段は coconala.com の開発をしています。

おや、ブログの順番回ってきた。さて何書こうかな。

・・・よし、1人Slackとサーバーレスネタにしよう。

1人Slack

ここ数ヶ月、自分用のメモとしてSlackを使っています。

・・・と言っても会社のSlackではなく、自分1人だけのSlack。
Slackって個人でも使えるんですよ。知ってました?しかも無料。

他に誰もいないので好きなこと書き放題。スレッド機能があるのでTodoリストや日報的に使うもよし。色々なアプリケーションとも連動できるし、Twitterや記事のURLを渡せば記事やツイートの内容を自動で取ってきてくれるし。

とにかく適当につらつらーーっと何か書きとどめておけるのが大変便利なのです。

例:日報的に使ってみる

大体始業前に「今日はこれやるぞ」と決めているので、Slackにざらざらとリストを書きます。
1タスク1発言がオススメ。

で、1日が終わる時はこれにリアクションをつけます。NGとかWIPとかDoneとかとか。

各タスクについて何か書きたい時はスレッドにしちゃえばOK。
というわけで、意外と使えて便利なんです。

落とし穴

1. メッセージ保存数

便利なんですが、「無料」には落とし穴があるわけで。
無料版のSlackには下記の制限があります。

https://slack.com/intl/ja-jp/pricing

一番大きいのは「チームの直近のコミュニケーション10,000件」ですかね。
直近1万件を超えたメッセージは閲覧できなくなります。

2. 検索がつらい

チャットツールにありがちなのですが、検索が大変使いにくい。

解決策を探してみる

上記2点を解決すべく、思いついたのがEvernote。SlackとEvernoteを連携すると

  • 「/clip today」
  • 「/clip yesterday」

といったコマンドで一日のSlackの投稿をEvernoteに保存できます。

メッセージ数の上限は気にしなくてよくなるし、Evernoteの検索は少なくともSlackより良い。

というわけで、1日に1度「/clip」コマンドを実行すればOKになりました。

やっぱりそれでも面倒くさい

手動めんどくさい。

やだ。

忘れる。

だるい。

自動で毎日実行させたい。
(ものぐさの極地)

やっと本題

そんなこんなで本題です。外からSlackのコマンドを実行させるようにします。
ちなみに素直に「/clip」とAPIに投げると...

「/clip」とつぶやくだけ。寂しい!

Slack API

(表だって公開はされていない?) チャットコマンド実行用のSlack APIがあるようです。

ErikKalkoken/slackApiDoc
slackApiDoc - Documentation of undocumented Slack API methods
https://github.com/ErikKalkoken/slackApiDoc/blob/master/chat.command.md

こいつをたたくと実行できるのかな?

定期でコマンド実行させるには

下記を使います。

この2つを使えばサーバーレスで、かつ定期でコマンド実行できちゃう!しかも無料枠で十分補える!

え?AWSの契約?個人で契約していますが何か。 (セキュリティはしっかりね!)

Lambda用のコードを書く

というわけでまずはさくっとLambda用のコードを書きましょう。
Node.jsは得意じゃないのでPythonで。

slack_command.py

Slack APIをたたくための処理です。

# -*- coding: utf-8 -*-
import urllib.request
import json

API_URL = 'https://slack.com/api/chat.command'

def execute_command(token, channel_id, command, text = ''):
    params = {
        'token' : token,
        'channel' : channel_id,
        'command' : command,
        'text'  : text
    }

    req = urllib.request.Request('{}?{}'.format(API_URL, urllib.parse.urlencode(params)))
    with urllib.request.urlopen(req) as res:
        body = res.read()

    return json.loads(body)

handler.py

Lambda起動用メソッドをさくっと書きます。
環境変数から各種値を受け取り、さっき書いた処理に渡しているだけですね。

# -*- coding: utf-8 -*-
import os
import json
from slack_command import execute_command

def handler(event, context):
    slack_command = os.environ['COMMAND']
    slack_text = os.environ['TEXT']
    token = os.environ['TOKEN']
    channel_id = os.environ['CHANNEL_ID']

    result = execute_command(token, channel_id, slack_command, slack_text)
    if result['ok']:
        print('Command "%s %s" OK' % (slack_command, slack_text))
    else:
        print('Command "%s %s" NG' % (slack_command, slack_text))

この2ファイルあればOK。

Lambdaの設定

コードをアップロード

2ファイルをzipに固めてアップロードします。

  • コードエントリタイプ ... zipファイルをアップロード
  • ランタイム ... Python3.6
  • ハンドラ ... 起動ファイル名と起動メソッドをピリオドでくっつけたもの。今回は「handler.py」の中の「handler」メソッドなので「handler.handler」とします。

環境変数設定

handler.py内で取得している4つの環境変数をセットします。

これで「保存」を押せば完了。

CloudWatch Eventsの設定

今回のLambda関数は登録しただけでは動きません。外部から何かトリガーをひいてあげる必要があります。

Cronのように定期的に関数を実行したいのでCloudWatch Eventsを設定します。

「ルールの作成」からイベントを作成します。

「イベントソース」は「スケジュール」にします。
決まった時間に実行したいならば「Cron式」を選びましょう。

式の内容は cron(* * * * * *)
です。Cron式を書かないといけないので注意。

参考: ルールのスケジュール式 - Amazon CloudWatch Events

ターゲットに先ほど作ったLambdaを選択し、決定すれば完了です。

一日一回、0時30分に実行するように設定しました。
(時刻はUTCで設定しないといけないので注意)

テストで時間を「数分後」に設定して待っていると...

動いた!clipされてる!!

というわけでCloudWatch EventとLambdaを組み合わせたら、サーバー管理無し+好きなタイミングでプログラムを走らせることができました。あらステキ。

AWS Lambdaは無料枠の容量が大変多いので、個人でもおおいに活用しましょう!オススメ!

最後に

ココナラでは一緒に事業を成長させてくれるエンジニアの仲間を探し中でございます。 少しでも興味がありましたら、カジュアルにお話しましょう!!

Androidエンジニア
大きなマーケットに小さなチームで挑みませんか?Kotlinエンジニア募集
『一人ひとりが自分のストーリーを生きていく世の中をつくる』 わたしたちはこのビジョンのもと、個人の 知識・スキル・経験を可視化し、必要とする全ての人に結びつけ、個人をエンパワーメントするプラットフォームとしてスキルマーケット「ココナラ」を中心とした事業を運営しています。 2012年7月のローンチ以来順調に成長し、ユーザー数は423万人(2023年8月時点)に達するなど、知識・スキル・経験を売買できる国内最大級のマーケットプレイスへと成長を遂げています。2021年3月には東証マザーズ(現:グロース市場)への上場も果たしました。 近年、政府が提唱する「持続可能な開発目標(SDGs)」のアクションプランにおいても「一人ひとりの可能性の発揮と絆の強化を通じた行動の加速」「個人が輝き、誰もがどこでも豊かさを実現できる社会の実現」といった言葉が掲げられるようになりました。同様の課題感を持ち続けてきたわたしたちとしても、事業推進を通じて個人が輝く社会の実現に努力していきたいと考えています。 直近の動きとしては、これまで個人対個人(CtoC)だった取引を法人利用へ本格的に拡大(BtoC)させる取り組みとして2021年8月にココナラビジネスのサービスを開始。2023年1月には、ITフリーランスと企業の業務委託案件をつなぐエージェント事業ココナラテックをスタート。 今後もこれまで以上のチャレンジを続けながら、「困ったら"ココナラ"だね」と日本中で言ってもらえる総合相談プラットフォーム構築を実現していきます。
株式会社ココナラ


フロントエンドエンジニア
Vue,Nuxt/ココナラの使い心地を担うフロントエンドエンジニア募集!
『一人ひとりが自分のストーリーを生きていく世の中をつくる』 わたしたちはこのビジョンのもと、インターネット上で個人の知識・スキル・経験を売り買いできるマーケットプレイス、「ココナラ」を運営しています。 2012年7月のローンチ以来順調に成長し、ユーザー数は80万人に達し、累積の取引件数が200万件を超えるなど、知識・スキル・経験を売買できる国内最大級のマーケットプレイスに成長しています。昨年、デロイトトーマツによる2017年度日本テクノロジーFast50(3年間の収益成長率)では、第1位(1,252%)を受賞しました。 ▼ 弊社サイト https://coconala.com/ ▼ 成長率1位はココナラ トーマツがVBランキング https://www.nikkei.com/article/DGXMZO22398130Y7A011C1X50000/ ▼ "相談"がお金に変わる、無形のシェアリングビジネス「coconala」が描く未来 http://news.mynavi.jp/articles/2015/11/24/coconala/
株式会社ココナラ


Swiftエンジニア
日々サービスを成長させ続けるチームで一緒に働きませんか?Swift職人募集
私たちは、「一人ひとりが自分のストーリーを生きていく世の中をつくる」というビジョンのもと、インターネット上で個人の知識・スキル・経験を売り買いできるマーケットプレイスである「ココナラ」を運営しています。 それまでは、自分の得意を活かしてビジネスをしたいと考えても、Web サイトの作成、決済手段の導入、集客活動などのコストを考えるとハードルが高いため、ちょっとしたサービスを単独で成立させることには難しさがありました。 ココナラは、どなたでも自分の得意を活かした相談サービスをネット上で気軽に提供できるようにと、簡単な出品の仕組みを持ち、初期費用や月会費は無料、サービス提供価格は500円からという、チャレンジしやすい価格設定からはじめた日本初のサイトです。 2012年7月のローンチ以来順調に成長し、ユーザー数は70万人に達し、最近では累積の取引件数が200万件を超えるなど、知識・スキル・経験を売買できる国内最大級のマーケットプレイスに成長しています。 2015年11月には5.4億円の資金調達と今後の事業戦略を発表。また、2016年8月には新規サービスである『ココナラ法律相談』、2017年3月には弊社初の物販となる『ココナラハンドメイド』を相次いでリリースするなど、事業も組織も急速に拡大しています。 最近では、デロイトトーマツによる2017年度日本テクノロジーFast50(3年間の収益成長率)で、第1位(1,252%)を受賞しました。 <参考記事> 成長率1位はココナラ トーマツがVBランキング https://www.nikkei.com/article/DGXMZO22398130Y7A011C1X50000/ スキルのC2Cサービス「ココナラ」が物販にも進出ーー今春からハンドメイド作品の取り扱いを開始 http://jp.techcrunch.com/2017/01/26/coconala-handmade/ 「500円のスキル売買」から「相談のゲートウェイ」に——ココナラが8月下旬にも法律相談サービス開始 http://jp.techcrunch.com/2016/07/25/coconala/ "相談"がお金に変わる、無形のシェアリングビジネス「coconala」が描く未来 http://news.mynavi.jp/articles/2015/11/24/coconala/
株式会社ココナラ


※本投稿は、ココナラよもやまブログ から移植したものです

株式会社ココナラ's job postings
9 Likes
9 Likes

Weekly ranking

Show other rankings
Invitation from 株式会社ココナラ
If this story triggered your interest, have a chat with the team?