LINE WORKS WOFF アプリを Google Colab を使って簡単に試す

# LINE WORKS WOFF を Google Colab で簡単に試してみます

LINE WORKS の WOFF (WORKS Front-end Framework) を試す環境を Google Colab 上で構築する手順を解説します。この手順では、Flask サーバーを起動し、Cloudflare トンネルを用いて外部からアクセス可能な URL を取得します。

## 手順概要
1. WOFF 用の HTML ファイルを準備する  
2. Google Colab 上でサーバーを起動する  
3. LINE WORKS Developer Console に WOFF を登録し、テストを実行する  

## 1. WOFF 用の HTML ファイルを準備する
以下の `index.html` ファイルをローカルに保存します。このファイルは、LINE WORKS の WOFF SDK を活用し、ユーザー情報の取得や位置情報の取得、QRコードのスキャン機能を提供します。

woffId は書き換えてください。
```html
    <script>
        // WOFF アプリ ID を設定する
        const woffId = "6WiqzH3CzFx-LTigKHUxSQ";
    </script>
```

### `index.html`
```html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WOFF アプリ サンプル</title>
    <script>
        // WOFF アプリ ID を設定する
        const woffId = "6WiqzH3CzFx-LTigKHUxSQ";
    </script>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Orbitron&display=swap');

        :root {
            --fluorescent-green: #66ff00;
        }

        body {
            font-family: 'Orbitron', sans-serif;
            margin: 0;
            padding: 0;
            background: linear-gradient(45deg, #09c6f9, #045de9);
            color: #e0e0e0;
        }

        header {
            background-color: #333;
            color: white;
            text-align: center;
            padding: 10px 0;
        }

        header h1 {
            margin: 0;
            font-size: 24px;
        }

        .container {
            max-width: 400px;
            margin: 20px auto;
            padding: 10px;
        }

        .section {
            background-color: rgba(10, 10, 10, 0.5);
            border-radius: 10px;
            margin-bottom: 20px;
            padding: 20px;
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
            border: 2px solid var(--fluorescent-green);
            display: flex;
            flex-direction: column;
        }

        .btn {
            display: block;
            margin: 20px 0;
            padding: 15px 30px;
            background-color: transparent;
            color: #00c6ff;
            text-align: center;
            border: 2px solid #00c6ff;
            border-radius: 5px;
            cursor: pointer;
            transition: background-color 0.3s, color 0.3s;
            align-self: center;
            font-size: 18px;
        }


        .btn:hover {
            background-color: var(--fluorescent-green);
            color: #020b2e;
        }

        #sendLocationBtn,
        #sendQRDataBtn {
            display: none;
        }

        #sendQRBtn {
            display: none;
        }
    </style>
</head>

<body>

    <header>
        <h1>WOFF アプリ サンプル</h1>
    </header>

    <div class="container">
        <!-- ユーザープロフィール情報のセクション -->
        <div class="section" id="userProfileSection">
            <h2>ユーザーのプロフィール情報</h2>
            <p>woff.getProfile() メソッドでログイン中のユーザーのプロフィール情報を取得して表示しています。</p>
            <div id="userProfileInfo"></div>
        </div>

        <!-- 位置情報のセクション -->
        <div class="section">
            <h2>位置情報の取得</h2>
            <p>Geolocation API で位置情報を取得します。</p>
            <button class="btn" id="getLocationBtn">位置情報を取得</button>
            <div id="locationInfo"></div>
            <button class="btn" id="sendLocationBtn">取得した位置情報を送信</button>
        </div>

        <!-- QRコードリーダーのセクション -->
        <div class="section">
            <h2>QRコードをスキャンする</h2>
            <p>woff.scanQR() メソッドで QR コードリーダーを起動して QR コードの読み込みを行います。</p>
            <button class="btn" id="scanQRBtn">QR コードリーダーを起動</button>
            <div id="qrResult"></div>
            <button class="btn" id="sendQRDataBtn">取得したQRコード情報を送信</button>
        </div>

        <!-- アプリ終了のセクション -->
        <div class="section">
            <h2>アプリを終了する</h2>
            <p>woff.closeWindow() メソッドで WOFF アプリを終了します。</p>
            <button class="btn" id="exitAppBtn">アプリを終了</button>
        </div>
    </div>

    <script>
        function getLocation() {
            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(showPosition);
            } else {
                document.getElementById("locationInfo").innerHTML = "このブラウザはGeolocationをサポートしていません。";
            }
        }

        function showPosition(position) {
            document.getElementById("locationInfo").innerHTML = "Latitude: " + position.coords.latitude +
                ", Longitude: " + position.coords.longitude;
            document.getElementById("sendLocationBtn").style.display = "block";
        }

        function sendLocationToWOFF() {
            const locationInfoElem = document.getElementById("locationInfo");
            const messageContent = locationInfoElem.textContent;

            woff.sendMessage({
                content: messageContent
            })
                .then(() => {
                    alert('Sent successfully');
                })
                .catch((err) => {
                    alert('error: ' + err);
                });
        }

        function scanQRCode() {
            woff.scanQR()
                .then((result) => {
                    document.getElementById("qrResult").innerHTML = "Scanned Info: " + result.value;
                    document.getElementById("sendQRDataBtn").style.display = "block";
                })
                .catch((err) => {
                    alert('error: ' + err);
                });
        }

        function sendQRToWOFF() {
            const qrResultElem = document.getElementById("qrResult");
            const messageContent = qrResultElem.textContent;

            woff.sendMessage({
                content: messageContent
            })
                .then(() => {
                    alert('QRコードの情報を送信しました');
                })
                .catch((err) => {
                    alert('error: ' + err);
                });
        }

        document.getElementById("exitAppBtn").addEventListener("click", function () {
            woff.closeWindow();
        });

        window.onload = function () {
            woff
                .init({
                    woffId: woffId
                })
                .then(() => {
                    woff.getProfile().then(profile => {
                        const profileInfoElem = document.getElementById("userProfileInfo");
                        profileInfoElem.innerHTML = `
                    ドメイン ID: ${profile.domainId} <br>
                    ユーザー ID: ${profile.userId} <br>
                    ユーザー名: ${profile.displayName}
                `;
                    }).catch(error => {
                        console.error('Profile error:', error);
                    });
                })
                .catch((err) => {
                    console.log(err.code, err.message);
                });

            document.getElementById("getLocationBtn").addEventListener("click", getLocation);
            document.getElementById("sendLocationBtn").addEventListener("click", sendLocationToWOFF);
            document.getElementById("scanQRBtn").addEventListener("click", scanQRCode);
            document.getElementById("sendQRDataBtn").addEventListener("click", sendQRToWOFF);
        };
    </script>
    <script charset="utf-8" src="https://static.worksmobile.net/static/wm/woff/edge/3.6/sdk.js"></script>
</body>

</html>
```

## 2. Google Colab 上でサーバーを起動する
以下の Python スクリプトを Google Colab で実行します。このスクリプトは Flask サーバーを起動し、Cloudflare トンネルを通じて外部アクセス可能な URL を提供します。

以下の URL で Google Colab ノートブックで試せます。
[Google Colab ノートブック: WOFF_Cloudflare_Tunnel.ipynb](https://colab.research.google.com/drive/17LeUFtkfC-Cm968EdExX6ONHjGc3LFms?usp=sharing)

```python
import os

# ディレクトリを作成
os.makedirs('/content/woff', exist_ok=True)

from google.colab import files

# ファイルをアップロード
uploaded = files.upload()

# アップロードされたファイルを /content/woff に移動
for filename in uploaded.keys():
    os.rename(filename, f'/content/woff/{filename}')

# 必要なライブラリのインストール（既にインストール済みならスキップされます）
!pip install flask

# Cloudflareトンネルツールをダウンロード、設定（既にダウンロード済みならスキップ）
!wget -N https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64
!chmod +x cloudflared-linux-amd64

# Flaskアプリの構築
from flask import Flask, send_from_directory
import threading

app = Flask(__name__)

# ルートエンドポイントを設定して、index.htmlを自動提供
@app.route('/')
def serve_index():
    return send_from_directory('/content/woff', 'index.html')

# woffフォルダのファイルを提供するためのエンドポイントを設定
@app.route('/<path:filename>')
def serve_file(filename):
    return send_from_directory('/content/woff', filename)

# サーバーを起動する関数
def run():
    app.run(host='0.0.0.0', port=5000)

# Flaskアプリを別スレッドで実行
thread = threading.Thread(target=run)
thread.start()

# Cloudflareトンネルを起動し、外部アクセス用のURLを取得
!./cloudflared-linux-amd64 tunnel --url http://127.0.0.1:5000

```

## 3. LINE WORKS Developer Console にアプリを登録する
1. [LINE WORKS Developer Console](https://dev.worksmobile.com/jp/console/openapi/v2/app/list/view) にアクセスします。  
2. 新規 WOFF アプリを登録します。  
   - **Endpoint URL** に、Cloudflare トンネルの URL を設定します  
   - サイズや、Scan QR を設定します  
3. WOFF アプリを保存します。

## 4. WOFF アプリをテストする
1. LINE WORKS 上で登録したアプリを起動します。  
2. 機能（ユーザー情報の取得、位置情報の送信、QRコードのスキャン）が動作することを確認します。

## 補足
- **Cloudflare トンネル** は一時的な環境のため、長期間の利用には専用サーバーを使用することをお勧めします。  
- WOFF SDK の詳細については、[LINE WORKS WOFF ガイド](https://developers.worksmobile.com/jp/docs/woff-guide) を参照してください。

この手順を参考に、Google Colab を使って WOFF アプリを試してみてください！質問があればお気軽にどうぞ。