// Version: 1.0.0 import 'dart:async'; import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:googleapis_auth/google_auth.dart'; import 'package:googleapis/gmail/v1.dart'; /// Gmail API を介した同期用メールリレー /// /// P2P 通信不要なノード識別システムを提供します。 /// BCC の Gmail アドレスをノードの一意キーとして使用。 class GmailWrapper { final String _gmailAddress; // BCC 用 gmail アドレス(ノードキー) final GAuthClient? _authClient; // OAuth 認証クライアント final GmailService? _gmail; /// 新しいインスタンスを作成 factory GmailWrapper({ required String gmailAddress, bool useOAuth = true, }) async { if (useOAuth) { try { final client = GAuthClient.fromFile('credentials.json'); return GmailWrapper._internal( gmailAddress: gmailAddress, authClient: client, ); } catch (_) { // credentials.json がない場合、後で認証フローを実行できるように null を保持 print('[Gmail] credentials.json 未見。認証画面から開始してください'); return GmailWrapper._internal( gmailAddress: gmailAddress, authClient: null, ); } } else { throw UnsupportedError('OAuth 方式でのみサポートされています'); } } GmailWrapper._internal({ required this._gmailAddress, GAuthClient? authClient, }) : _authClient = authClient, _gmail = authClient != null ? GmailService(authClient) : null; /// ノード ID(BCC アドレス)を取得 String get gmailAddress => _gmailAddress; /// 認証状態を確認 bool get isAuthorized => _authClient != null && _gmail != null; /// チャットメッセージをノードに配送する Future sendMessage({ required String fromNode, required String message, String? toNode, }) async { if (_gmail == null) return; try { // シンプルなテキストの送信(HTML のため簡易 escaping) final body = base64Encode(utf8.encode(message)); final msg = EmailMessage( subject: '[SalesAssist1] チャット:$fromNode', to: toNode, cc: null, bcc: _gmailAddress, // BCC でノード識別 htmlBody: '

$message

', ); final response = await _gmail.users.messages.send( userId: 'me', body: msg, ).root; print('[Gmail] メッセージ送信完了 (from=$fromNode to=${toNode ?? 'BCC キー'})'); } catch (e) { print('[Gmail] 送信失敗:$e'); rethrow; } } /// ノードリストを取得(自己認識用) Future> getNodes() async { // 現在接続可能なノードを返す(ハートビートの結果などから集約) return []; // ここに母艦が管理するノードリストを読み込むロジック } /// 認証フローを起動(初回実行時) Future authenticate() async { try { final client = GAuthClient.fromFile('credentials.json'); print('[Gmail] 認証済みクライアント使用'); return client; } catch (e) { print('[Gmail] 認証フロー起動:$e'); // GoogleSignIn で認証画面をポップアップさせる処理(後実装) return null; } } } /// メール送信用モデル(Googleapis ライブラリの仕様に従う) class EmailMessage { String? subject; List? to; String? cc; String? bcc; String? htmlBody; EmailMessage({ this.subject, this.to, this.cc, this.bcc, this.htmlBody, }); }