電算倶楽部 富山県のコンピュータ社会人サークル

富山県、特に滑川市、富山市、魚津市周辺で活動している社会人サークルです。

GROWIのAPIを使ってwiki管理を自動化

はじめに

倶楽部の情報管理に、メルカリが作った社内wiki「Crowi」の派生である、「GROWI」を使用しています。 このCrowiおよびGROWI、通常はページの作成や閲覧はインターネットブラウザを使用して行います。 しかし、実は公式には書かれていませんが、ページの取得や作成といった操作を実行できるAPIが公開されています。

倶楽部の定例会を行う場合、イベントページを作成するのですが、以下の操作がほぼルーチンとなっています。

  1. Templateページを複写してイベントページを作成
  2. ページ名とページ内の日にち情報を、次のイベントの日付に変更
  3. 次のテーマやスピーカーを記載
  4. SlackにイベントページのURLと次のイベント日付を含むお知らせメッセージを投稿

これ等の操作を公開APIを使って自動化できないか挑戦してみました。

※GROWIとして記載しますが、多分Crowiでも同じことができます。

GROWIのAPIについて

公式の文書がないので有志の作った記事やGithubで公開されているソースコードを解析するしかありません。

例えばページ関係のAPIは以下に記載されています。 https://github.com/crowi/crowi/blob/master/lib/controllers/page.ts ページを@apiで検索すると該当する関数が見つかります。

ページを作成するpages.listに注目してみます。 リクエストメソッドはGET、引数はpathuserということがわかります。

これを用いて、ページ一覧を取得するには以下のアドレスにアクセスすればいいです。

(プロトコル)://(ホストアドレス)/_api/pages.list?access_token=(アクセストークン)&path=/

書き忘れていましたが、アクセストークンを予め取得しておく必要があります。 アクセストークンはあなたのGROWIにアクセスし、右上の「あなたの名前」「ユーザ設定」「API設定」で取得できます。 URLのaccess_tokenに設定してください。

userpathは選択のようで、今回はpath/を指定して、すべてのページを取得しました。

もう一つ、ページを作成するpages.createが見つかります。 リクエストメソッドはPOST、引数はbody,path,grantのようです。

postなのでURL直打ちで実行はできません。サクッとプログラムを書いてみましょう。 言語はPythonです。

import requests

protocol = 'https'
host_address = 'naisho.com'
access_token = 'hImItSuHiMiTsUhImItSuHiMiTsU'

def pages_create(path, body):
    url = f'{protocol}://{host_address}/_api/pages.create'
    res = requests.post(url, data={'body':body, 'path':path, 'access_token':access_token})
    print(res.json())

pages_create('/test', '# Test\n\nこのページは自動作成のテストによってい生成されたページです。')

ちゃんと作成されました。誤植までバッチリです。

f:id:s-densan:20191112214917p:plain

自動化プログラムの作成

  • /event/template/定例会テンプレートにある定例会イベントのテンプレートをコピーして、次回の定例会ページを/event作成します。
  • 新規ページのパスや内容で使用する年月日情報はユーザが入力できるようにする。

まずはAPIでTemplateページのコピーをしたいと思いましたが、コピー用のAPIは無い?ようです。なので、ページ情報取得のpages.getpages.createを組み合わせて作ります。 pages.getを調べておきます。 リクエストメソッドはGET、引数はpage_idpathrevision_idとのこと。おそらくpage_idpathは選択で、revision_idはオプションでしょう。

https://wiki.s-densan.tk/_api/pages.get?access_token=uxPFdApsClWsUvpCImD1G7pNh6j9/STajo/5NhvUyUg=&path=(ここにtemplateページのパス)

ちゃんとデータが表示されます。

プログラムで書くとこうなります。

import requests

protocol = 'https'
host_address = 'naisho.com'
access_token = 'hImItSuHiMiTsUhImItSuHiMiTsU'

def pages_get(path):
    url = f'{protocol}://{host_address}/_api/pages.get'
    res = requests.get(url, params={'path':path, 'access_token':access_token})
    return res.json()

print(pages_get('/event/templates/定例会テンプレート')['page']['revision']['body'])

さて、ここまでできれば材料が揃いました。 あと実施することは以下の通り。

  • 標準入力で、次の定例会の日時をyyyymmdd形式で入力させる
  • ページのパスを/event/yyyymmdd_mm月定例会となるよう組み立てる
  • ページ内の{yyyy}をyyyy、{mm}をmm、{dd}をddに置き換える。
  • pages.createを呼び出す
import requests

protocol = 'https'
host_address = 'naisho.com'
access_token = 'hImItSuHiMiTsUhImItSuHiMiTsU'

def pages_create(path, body):
    url = f'{protocol}://{host_address}/_api/pages.create'
    requests.post(url, data={'body':body, 'path':path, 'access_token':access_token})

def pages_get(path):
    url = f'{protocol}://{host_address}/_api/pages.get'
    res = requests.get(url, params={'path':path, 'access_token':access_token})
    return res.json()

yyyymmdd = input('Enter yyyymmdd: ')
if yyyymmdd.isdecimal() and len(yyyymmdd) == 8:
    yyyy = yyyymmdd[0:4]
    mm = yyyymmdd[4:6]
    dd = yyyymmdd[6:8]
    template_body = pages_get('/event/templates/定例会テンプレート')['page']['revision']['body']
    template_body = template_body.replace('{yyyy}', yyyy)
    template_body = template_body.replace('{mm}', mm)
    template_body = template_body.replace('{dd}', dd)
    page_path = f'/event/{yyyymmdd}_{mm}月定例会'
    
    pages_create(page_path, template_body)

まとめ

GROWIは使いやすくて気に入っていましたが、画面操作があるので定例作業は面倒だと感じていました。 APIを使うと面倒な作業はプログラムに任せ、コンテンツの作成に集中できます。 Google App Scriptの定期実行機能やSlackの連携機能など組み合わせることで、もっと面白いことができそうですね。