2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【個人開発】毎朝7時に「最新AIトレンド(エージェント・デザイン・開発)」を要約してPDFでLINEに送る完全自動botを作ってみた(GAS + Gemini API)

Last updated at Posted at 2025-12-10

はじめに

AI界隈の進化が速すぎて、毎日の情報収集が追いつかないことはありませんか? 特に「AIエージェント」「デザイン」「コーディング」など、自分が関心のある分野に絞って効率よく情報を得たいと思い、寝ている間に勝手にニュースを集め、要約し、PDFレポートにしてLINEに届けてくれる仕組みをGoogle Apps Script (GAS) で自作しました。

今回は、その構築手順と、開発中にハマった「Geminiのモデル指定エラー(404/429)」の解決策も含めて共有します。

※これは全てGemini 3 proで生成したものです。

作ったもの

毎朝7時に自動で実行され、以下のフローで処理を行います。

  1. 収集: GoogleニュースのRSSから「AI (エージェント OR デザイン OR コーディング)」の記事を収集。
  2. 思考: Googleの生成AI Gemini が、記事の内容をビジネスパーソン向けに要約・構造化。
  3. 加工: Googleドキュメント経由でPDFファイルを自動生成。
  4. 配信: LINE Messaging API を使って、自分のLINEにPDFのリンクをプッシュ通知。

使用した技術スタック

  • Google Apps Script (GAS): サーバーレスで無料。今回のハブになります。
  • Gemini API: ニュースの要約担当。無料枠で利用可能。
  • LINE Messaging API: 通知担当。以前のLINE Notifyが終了予定のため、こちらを使用。

手順1:各APIキーの取得

開発には以下の3つの「鍵」が必要です。

  1. LINE Channel Access Token (長期):

    • LINE Developers Consoleで「Messaging APIチャネル」を作成し、発行します。
    • ※注意:短い「Channel Secret」ではなく、めっちゃ長い「アクセストークン」の方を使います(ここでハマりました)。
      スクリーンショット 2025-12-10 13.19.14.png
      スクリーンショット 2025-12-10 13.19.26.png

    LINE公式アカウントを作成するから、必要な情報を入力して公式アカウントを作成します。
    その後、管理画面>右上の設定>Messaging APIの有効化します。
    LINE-Messaging.png
    その後、LINE Developper Consoleに戻り、アクセストークンを取得します。
    スクリーンショット 2025-12-10 13.27.20.png
    名称未設定のデザイン.png
    一番下までスクロールして、
    ここに.png

  2. LINE User ID:

    • 同じくLINE Developers Consoleのチャネル基本設定タブの下の方にあります(Uから始まるID)。
      スクリーンショット 2025-12-10 13.33.17.png
      一番下までスクロールして、
      ここに.png
  3. Gemini API Key:

    • Google AI Studioで発行します。
      1. 右上のAPIキーを作成をクリック
      2. 「キー名の設定」と「インポートしたプロジェクトを選択」から新しくプロジェクトを作成し、キーを作成をクリック
        スクリーンショット 2025-12-10 13.38.55.png
        作成したAPIキーを取得する。
        スクリーンショット 2025-12-10 13.39.33.png

手順2:Google DriveでPDFを保存するフォルダを準備

上記URLの「folders/」以降をコピー保存しておく
ここに.png

手順3:GASの実装

Apps Scriptで新規にスクリプトを作成し、以下のコードを記述します。

コード.gs
// --- 設定エリア ---
const LINE_CHANNEL_ACCESS_TOKEN = 'ここにLINEチャンネルアクセストークンを貼り付け';
const USER_ID = 'ここにあなたのLINEユーザーIDを貼り付け';
const GEMINI_API_KEY = 'ここにGemini_APIキーを貼り付け';
const FOLDER_ID = 'PDFを保存するGoogleドライブのフォルダID';
// ------------------------------------------

function main() {
  console.log("処理を開始します...");
  
  // 1. ニュースを取得
  const newsText = fetchAiNews();
  if (!newsText) return;

  // 2. Geminiで要約
  const summary = summarizeWithGemini(newsText);
  if (!summary) return;
  
  // 3. PDF作成
  const pdfUrl = createPdf(summary);
  
  // 4. LINE送信
  sendToLine(summary, pdfUrl);
}

// RSSからニュースを取得(関心分野に絞り込み)
function fetchAiNews() {
  const query = 'AI (エージェント OR デザイン OR コーディング)';
  const encodedQuery = encodeURIComponent(query);
  const feedUrl = `https://news.google.com/rss/search?q=${encodedQuery}&hl=ja&gl=JP&ceid=JP:ja`;
  
  try {
    const xml = UrlFetchApp.fetch(feedUrl).getContentText();
    const document = XmlService.parse(xml);
    const items = document.getRootElement().getChild('channel').getChildren('item');
    
    let textData = "";
    // 上位7件を取得
    for (let i = 0; i < Math.min(7, items.length); i++) {
      const title = items[i].getChildText('title');
      const link = items[i].getChildText('link');
      textData += `記事${i+1}: ${title} (${link})\n`;
    }
    return textData;
  } catch (e) {
    console.error("RSS取得エラー: " + e);
    return null;
  }
}

// Gemini APIで要約
function summarizeWithGemini(text) {
  // モデル名の指定(ここが重要!)
  // バージョン指定エラーを避けるため、最新の安定版へのエイリアスを使用
  const model = 'gemini-flash-latest';
  const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${GEMINI_API_KEY}`;
  
  const prompt = `
  以下のニュース記事リストから、特に「AIエージェント」「デザイン(UI/UXや生成デザイン)」「コーディング・開発」に関連する情報を中心に抽出し、忙しいビジネスパーソン向けに要約してください。
  
  # 制約
  - 全体で500文字程度にまとめること。
  - 上記の関心分野ごとに見出しを分けて整理すること。
  - PDFにするので、読みやすい構成にすること。
  
  # ニュースリスト
  ${text}
  `;

  const payload = {
    "contents": [{"parts": [{"text": prompt}]}]
  };

  const options = {
    'method': 'post',
    'contentType': 'application/json',
    'payload': JSON.stringify(payload),
    'muteHttpExceptions': true
  };

  try {
    const response = UrlFetchApp.fetch(url, options);
    const json = JSON.parse(response.getContentText());
    
    if (json.candidates && json.candidates[0].content) {
      return json.candidates[0].content.parts[0].text;
    } else {
      console.error("生成失敗: " + response.getContentText());
      return null;
    }
  } catch (e) {
    console.error("通信エラー: " + e);
    return null;
  }
}

// Googleドキュメント作成 → PDF化
function createPdf(content) {
  const dateStr = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy-MM-dd');
  const docName = `AIトレンドまとめ_${dateStr}`;
  
  // 一時ドキュメント作成
  const doc = DocumentApp.create(docName);
  const body = doc.getBody();
  body.appendParagraph(docName).setHeading(DocumentApp.ParagraphHeading.HEADING1);
  body.appendParagraph(content);
  doc.saveAndClose();
  
  // PDF変換して保存
  const folder = DriveApp.getFolderById(FOLDER_ID);
  const pdfBlob = doc.getAs('application/pdf');
  const file = folder.createFile(pdfBlob);
  
  // ゴミ掃除
  DriveApp.getFileById(doc.getId()).setTrashed(true);
  
  return file.getUrl();
}

// LINE Messaging APIでプッシュ通知
function sendToLine(summary, pdfUrl) {
  const url = 'https://api.line.me/v2/bot/message/push';
  
  const payload = {
    'to': USER_ID,
    'messages': [
      {
        'type': 'text',
        'text': `【今日のAIトレンド】\n自動まとめが完了しました。\n\n▼PDFレポートはこちら\n${pdfUrl}`
      }
    ]
  };

  const options = {
    'method': 'post',
    'headers': {
      'Authorization': 'Bearer ' + LINE_CHANNEL_ACCESS_TOKEN,
      'Content-Type': 'application/json'
    },
    'payload': JSON.stringify(payload),
    'muteHttpExceptions': true
  };
  
  UrlFetchApp.fetch(url, options);
}

トリガーを設定して、毎朝6時に通知が来るように設定

スクリーンショット 2025-12-10 13.54.29.png

完成形

S__5963799.jpg

開発中にハマったポイント(Troubleshooting)

今回の開発で一番時間を溶かしたのは、Gemini APIのモデル指定とQuota(割り当て)のエラーでした。

  1. 「404 Not Found」エラー
    • 現象: models/gemini-pro や models/gemini-1.5-flash を指定すると 404 Not Found が返ってくる。
    • 原因: APIキーを作成したプロジェクトや時期によって、使用可能なモデル名(またはバージョン)が異なる場合があるようです。特に v1 と v1beta のURLの違いも影響します。
    • 対策: モデル名を決め打ちせず、gemini-flash-latest というエイリアス(その時点での最新安定版Flashモデルを指す名前)を使うことで解決しました。
  2. 「429 Resource Exhausted」エラー
    • 現象: 最新の gemini-2.0-flash-exp などを使おうとすると、limit: 0 と言われて弾かれる。
    • 原因: 発表されたばかりの実験的モデルや特定のモデルは、無料枠(Free Tier)ではアクセス権限が開放されていないことがあります。
    • 対策: 素直に安定版のモデル(Flashなど)を使うのが吉です。

さいごに

これで、毎朝7時に自分の関心領域(AIエージェント、デザイン、コーディング)に特化したニュースが、綺麗にPDFにまとまってLINEに届くようになりました。

GASの「トリガー」機能を使えば、完全放置で運用できます。 「情報収集を自動化したい」と考えているエンジニアの方は、ぜひ試してみてください。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?