コロナウイルスの影響により、最近はコミュニティイベントをオンラインで行うケースが増えています。この時、一つ問題になるのが受付システムです。オフラインのイベントでは受付を設けて、そこでチェックできたのですが、オンラインイベントではZoomやGoogle MeetなどのURLに直接アクセスするので、受付できないのが問題でした。
そこで、mBaaSを使ってチェックイン後に動画配信のURLを共有するシステムを作ってみたので紹介します。
仕組みについて
このシステムは3つの段階に分かれています。
- connpassにログインする
- connpassから参加者一覧を取得する
- 参加者がチェックインする
1と2についてはmBaaSのスクリプト機能を使っています。スクリプト機能ではNode.jsとRubyが選べますが、参加者一覧はCSVなので、標準でCSVパーサーが含まれているRubyを利用しました。
connpassにログインする
ここで行うのはconnpassにログインし、そのセッションIDをデータストアに保存することです。今回は不特定多数がログインする想定ではないので、Configというクラスを作って、その中にIDとパスワードを入れています。カラム名はそれぞれusernameとpasswordです。
このIDとパスワードを使ってログインします。
# connpassにログインする処理 def login_to_connpass(config) # CSRFを取得 response = HTTParty.get 'https://connpass.com/login/' cookies = parse_set_cookie response.headers['set-cookie'] login_doc = Nokogiri::HTML response.body csrfmiddlewaretoken = login_doc.css('[name=csrfmiddlewaretoken]').first.attribute('value') # ログイン処理を実行 response2 = HTTParty.post 'https://connpass.com/login/', body: { csrfmiddlewaretoken: csrfmiddlewaretoken, username: config.username, password: config.password }, headers: { 'Cookie': cookies.map{|k, v| "#{k}=#{v}"}.join("; "), 'Content-Type': 'application/x-www-form-urlencoded', 'Referer': 'https://connpass.com/login/' }, follow_redirects: false # Cookieを返却 parse_set_cookie response2.headers['set-cookie'] end # Cookieのパース処理 def parse_set_cookie(all_cookies_string) cookies = Hash.new all_cookies_string.split(',').each {|single_cookie_string| cookie_part_string = single_cookie_string.strip.split(';')[0] cookie_part = cookie_part_string.strip.split('=') key = cookie_part[0] value = cookie_part[1] cookies[key] = value } # 日付に含まれるカンマで余計なデータが入るので排除 cookies.reject! {|key, value| value.nil? } end
セッションIDは同じConfigクラスの中に保存しておきます。カラム名はsessionidになります。
connpassから参加者一覧を取得する
続いて、セッションIDを使って参加者一覧のCSVを取得します。まずEventというクラスを作成して、設定をします。
- key
ユニークなキー(任意) - name
イベント名 - url
イベントのURL(connpassのもの) - classname
参加者のデータを入れるクラス名 - video_url
オンラインイベント会場のURL
全体の流れは次のようになります。
def call(env) req = Rack::Request.new(env) # 設定(セッションID)を取得 query = NCMB::DataStore.new 'Config' config = query.limit(1).get.first # CSV取得対象のイベントデータを取得 query = NCMB::DataStore.new 'Event' event = query.equalTo('key', req.params['key']).get.first rows = get_csv(config.sessionid, event) # 古いデータの削除 query = NCMB::DataStore.new event.classname query.equalTo('key', event.key).get.each do |p| p.delete end # CSVデータの保存 rows.each do |row| p = NCMB::Object.new event.classname p.set 'key', event.key p.set 'name', row['表示名'] p.set 'paticipate', row['参加ステータス'] p.set 'attend', row['出欠ステータス'] p.set 'no', row['受付番号'] p.save end [ 200, {"Content-Type" => "application/json"}, [{attendees: rows.length}.to_json] ] end
参加者一覧の取得処理は次のようになります。
def get_csv(sessionid, event) puts "#{event.url}participants_csv/" id = event.url.match(/https:\/\/.*?\.connpass\.com\/event\/([0-9]+)(\/|$)/)[1] response = HTTParty.get "https://connpass.com/event/#{id}/participants_csv/", headers: { 'Cookie': "sessionid=#{sessionid}", 'Referer': event.url } CSV.parse response.body.encode(Encoding::UTF_8, Encoding::SJIS, replace: '?', invalid: :replace), headers: true end
なお、この処理はシステムから呼び出すこともできますが、基本的に管理画面から実行することを想定しています。
参加者がチェックインする
参加者がチェックインするための画面(HTML)とJavaScriptファイルを準備します。HTMLファイルはBootstrapを使ったシンプルなもので、ファイルストアにアップロードします。
<html> <head> <base target="_top"> <title>connpass受付システム</title> <!-- 必要なライブラリの読み込み(省略)--> <meta charset="utf-8"/> </head> <body> <div class="container"> <div class="row justify-content-center"> <div class="col-8 event"> <form class="form-signin"> <h1 class="h3 mb-3 title"></h1> <h3>受付番号は<a href="" class="url" target="_blank">connpassのイベントページ</a>で確認できます</h3> <br> <label for="inputNumber" class="sr-only">受付番号</label> <input type="number" id="ticket_number" class="form-control" placeholder="受付番号" required="" autofocus=""> <button class="btn btn-lg btn-primary btn-block" type="submit">チェックイン</button> <p class="mt-5 mb-3 text-muted">© MOONGIFT 2020</p> </form> </div> </div> </div> <!-- Bootstrapのモーダル --> <div class="modal fade" id="modal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="exampleModalLabel">受付完了!</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <strong><span id="username">name</span>さん、受付完了しました</strong> <div> <a id="onlineUrl" href="" target="_blank">配信会場はこちらです。クリックしてご参加ください</a> </div> </div> </div> </div> </div> <script src="./app.js"></script> </body> </html>
次にJavaScriptです。初期表示時に指定されたイベントを取得します。
$(async () => { const applicationKey = 'b6f...ee6'; const clientKey = '955...202'; const ncmb = new NCMB(applicationKey, clientKey); const key = url('?key'); if (!key) { alert('イベントキーが指定されていません'); return; } const event = await ncmb.DataStore('Event').equalTo('key', key).fetch(); $('.event .title').html(`${event.get('name')}受付`); $('.event .url').attr('href', `${event.get('url')}ticket`); });
次にフォームを送信した際のイベントで、データストアに受付番号の有無を確認します。もしあれば新しいクラスにチェックインデータを書き込みます。そしてモーダルウィンドウを開いて完了です。
$('form').on('submit', async (e) => { e.preventDefault(); const number = $('#ticket_number').val(); const attendee = await ncmb.DataStore(event.get('classname')) .equalTo('key', key) .equalTo('no', number) .fetch(); if (Object.keys(attendee).length == 0) { alert('受付番号が確認できません。番号を確認いただくか、運営者にお問い合わせください'); return; } attend = new (ncmb.DataStore(`${event.get('classname')}Attend`)); await attend .set('attendee', attendee) .set('event', event) .save(); $('#username').html(attendee.get('name')); $('#onlineUrl').attr('href', event.get('video_url')); $('#modal').modal('show'); });
大事なポイントとして、ファイルストアの設定で、HTTPSアクセスを有効にします。
そうすると、HTTPアクセスできるURLが表示されますので、このURL + ?key=(イベントのキー) でアクセスしてみます。
例えば以下のようになります。
イベントがあれば、イベント名が表示されます。そして自分の受付番号を入力すると、挨拶メッセージとイベントアクセス用のURLが表示されます。
まとめ
チェックインしたというデータが残っていれば、後でconnpassに反映するのは難しくないでしょう。今回の仕組みはスクリプト、データストア、ファイルストアを使っており、サーバレスで運用できます。オンラインイベントを盛り上げるためにもぜひmBaaSを役立ててください。
今回のコードはNCMBMania/online_checkin: mBaaSを用いたオンラインチェックインシステムです。にアップロードしてあります。利用時の参考にしてください。