FlutterでOGPデータを取得してNotionの拡張機能である「Save to Notion」的なものを作る

## Flutter Webとは
通常のFlutterとほぼほぼ同じソースコードでWebアプリを作れるものです。
元々Flutterはモバイルアプリ用のDart言語のフレームワークでしたが、進化してWebアプリも作れるようになり、今ではデスクトップアプリも作ることができます。

最初に記述している通り、ソースコードはほとんど同じなので、あらかじめWebアプリとモバイルアプリ両方を作る予定のアプリだとFlutterを選択肢に入れるのはかなりアリだと思ってます。
一つのソースコードでiOS、Android、Webを全て作れるので開発コストはかなり抑えられますし、アプリのパフォーマンス面もReact Native + React Native for Webより良いです。
※ただFlutter Webはまだまだ改善の余地があります。

https://docs.flutter.dev/platform-integration/web/building

## 作りたいもの
Notionの拡張機能である「Save to Notion」的なものを作ります。
「Save to Notion」はブラウザページを管理できるもので、Chromeに拡張機能として追加することで使うことができるのですが、めちゃくちゃ便利ですので利用したことない人はぜひ入れてみてください。
※但し対応しているブラウザは限られているのでChrome以外を使ってる人は使えないです。（Safariなど）

今回はFlutter Webの勉強がてら、Save to Notionのようなブラウザを管理できるアプリを作ってみました。

https://chrome.google.com/webstore/detail/save-to-notion/ldmmifpegigmeammaeckplhnjbbpccmm?hl=ja

https://www.savetonotion.so/

## OGPデータとは？
正式には「Open Graph Protcol」といい、HTMLのmetaタグ情報のことを指します。
ブラウザページ情報を登録するときに、そのブラウザの情報を取得する必要があるのですが、metaタグを参照してページのタイトルやサムネイル画像、詳細情報などを取得できます。

ブラウザページをSNSとかで共有したときに、カードで表示される内容がOGPデータです。（タイトルとかサムネイルとか..）
このデータを取得して、ブラウザの管理をできるようにします。

## Flutter自体の設定をいじる必要あり
下の**実装**に書いてあることをやるだけではうまくできなくて、以下のエラーが返されてしまいます。
```
Error: XMLHttpRequest error.
    dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 264:20      get current
packages/http/src/browser_client.dart 84:22                                       <fn>
dart-sdk/lib/async/zone.dart 1450:54      
...
```

そのため、Flutter自体の設定をいじってWebページ情報を取得できるようにする必要があります。

#### 1. cacheファイルを削除
flutterのパッケージが入っているdevelopmentフォルダ内のflutterに移動。
```
cd development/flutter
```
キャッシュファイルに移動
```
cd bin/cache
```
flutter_tools.stampというファイルがあるので、そのファイルを削除
```
rm -rf flutter_tools.stamp 
```

#### 2. 設定ファイルを変更
flutterフォルダに戻って以下のフォルダに移動
```
cd packages/flutter tools/lib/src/web
```

chrome.dartというファイルを開く
```
code chrome.dart
```

「--disable-extensions」を削除して、「--disable-web-security」を追加する
![スクリーンショット 2023-07-30 21.03.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/832f8b4f-6412-b9a3-004b-92e037d4e1a6.png)

これで設定はOK。

## 実装
実際に取得してターミナルでの表示確認まで行います。
あらかじめ一個上の「**Flutter自体の設定をいじる必要あり**」を見て、設定を変更しておいてください。

#### 1. Flutterのプロジェクト作成
今回はWebアプリを作りますが、通常のFlutterプロジェクト作成コマンドと一緒です。

```
flutter create <プロジェクト名>
```

#### 2. 起動確認
```
cd <プロジェクト名>
```

```
flutter run
```

上記のコマンドを叩くとおそらく以下のような画面になると思うので、chromeの[2]を選択。
ちなみにXcodeとかAndroid Studioを立ち上げているとそっちを優先して立ち上げるので注意。
![スクリーンショット 2023-07-30 20.30.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/2e97d945-bb4d-c327-56fb-7ac7711409f3.png)

#### 3. 必要なライブラリの導入

```
flutter pub add metadata_fetch
```
今回はこのライブラリを利用しましたが、GitHubを見てみたところ2年前から更新がされてないので、扱いには注意が必要です。
ライブラリを使わずに自前で全て実装することもできますが、今回はこのライブラリを使うことにします。

https://pub.dev/packages/metadata_fetch/install

#### 4. ライブラリを利用してOGPデータを取得する
実行するためのボタンは適当に用意してください。
以下の関数がブラウザのOGPデータを取得するための処理です。

```Dart
Future<void> getOgpDataFromWebPage (inputUrl) async {
    final response = await MetadataFetch.extract(inputUrl);
    print(response?.title);
    print(response?.description);
    print(response?.image);
}
```

#### 5. 確認
```https://flutter.dev/```をinputUrlに入れて、実行してみました。
上からブラウザのタイトル、詳細内容、サムネイルの画像パスを取得できました。
![スクリーンショット 2023-07-30 20.47.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812049/066e41a6-fa6f-52dd-a410-97011948d002.png)

## 最後に
Flutter自体の設定をいじっているので、あまりいい方法ではないかも知れないですが、今のところこの方法しかないようです。
ブラウザの情報とかはバックエンド側で取得して、APIを叩いて取得するとかが良いかも知れないです。
ご参考までに。