4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ChatGPTにDiscordトレンドAIニュース自動配信Botを作ってもらった【ChatGPT・GitHub Actions・Discord】

Posted at

はじめに

Python初心者のWebエンジニアが、ChatGPTの力を借りてDiscordのAIニュース自動配信Botを作成した体験談です。
「AIの情報を追うの疲れた...」「お金をかけたくない...」という方の参考になれば幸いです。

目次

筆者について

  • オープン系Webエンジニア(Javaなど)
  • Pythonはほぼ初心者

きっかけ

YouTubeでこちらの動画を見て面白そうだったのがきっかけです。

YouTube動画
【簡単】自分好みのAIニュースが勝手に届く自動化の仕方
]
https://www.youtube.com/watch?v=qKMc-uzDxEk

この動画でも十分わかりやすいのですが、
無料で作成できたら良いなと思い自分のつかえる環境で作ってみることにしました。

作ったもの

  • RSSからAIニュースを自動取得(Qiita、Zenn)
  • Gemini APIで要約・トレンド判定
  • Discord Webhookで通知
  • GitHub Actionsで毎日15:00に自動実行

使った技術

ChatGPT

  • モデル:GPT-5.1
  • 無料版でもコード生成可能
  • 用途:Pythonコード生成

筆者はChatGPT Plusを契約していますが、無料版でもコード生成が可能です。

Gemini API

  • モデル:gemini-2.0-flash
  • 無料枠あり
  • API Key 取得方法:Google AI Studio
  • 用途:RSS記事の要約生成

GitHub Actions

  • パブリックリポジトリなら無料
  • プライベートリポジトリは制限範囲内であれば無料
  • 用途:Pythonスクリプトの定期実行

Discord Webhook

  • チャンネル設定 → 連携サービス → Webhookから取得
  • 用途:AIニュースの通知先

実際の作業フロー

0. GitHubリポジトリの作成

事前にGitHubでリポジトリを作成します。

作成手順:

  1. GitHubにログインして右上の+ボタン → New repositoryをクリック
  2. リポジトリ名を入力(例:rss-notify-gemini)
  3. privateまたはPublicを選択(Publicなら無料、privateは範囲内なら無料)
  4. Add a README fileにチェック(任意)
  5. Create repositoryをクリック

リポジトリが作成できたら、ローカルにクローンするか、Web上で直接ファイルを作成していきます。

1. ChatGPTにコード生成を依頼

こんな感じでプロンプトを投げました:

「PythonでRSSフィードを取得して、Gemini APIで要約して、Discord Webhookに投稿するコードを書いて」

ChatGPTが基本的なコードを生成してくれたので、それをベースに修正していきました。
main.pyファイルを作成し以下のpythonコードを記述。リポジトリのルートにコミット。

pythonサンプルコード(長いので折りたたみ)

main.py

import feedparser
import requests
import google.generativeai as genai
import os
from datetime import datetime
from typing import List, Dict

# Secrets
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
WEBHOOK_URL = os.getenv("DISCORD_WEBHOOK")

# RSS Sources
RSS_SOURCES = [
    {
        "url": "https://qiita.com/popular-items/feed.atom",
        "name": "Qiita",
        "color": 0x55C500,
        "icon": "https://cdn.qiita.com/assets/favicons/public/production-c620d3e403342b1022967ba5e3db1aaa.ico"
    },
    {
        "url": "https://zenn.dev/feed",
        "name": "Zenn",
        "color": 0x3EA8FF,
        "icon": "https://zenn.dev/images/logo-transparent.png"
    },
]

# Gemini Init
genai.configure(api_key=GEMINI_API_KEY)
MODEL_NAME = "gemini-2.0-flash"


def summarize(text: str) -> str:
    """記事内容を100字以内で要約"""
    model = genai.GenerativeModel(MODEL_NAME)
    prompt = (
        "以下の記事内容を100字以内で簡潔に日本語で要約してください。\n\n"
        + text
    )
    try:
        resp = model.generate_content(prompt)
        return resp.text.strip()
    except Exception as e:
        print(f"要約エラー: {e}")
        return "要約を取得できませんでした"


def create_embed(source: Dict, entries: List) -> Dict:
    """Embed形式のペイロードを作成"""
    embed = {
        "title": f"📚 {source['name']} - 新着記事 ({len(entries)}件)",
        "color": source['color'],
        "timestamp": datetime.utcnow().isoformat(),
        "footer": {
            "text": f"{source['name']} RSS Bot",
            "icon_url": source.get('icon', '')
        },
        "fields": []
    }
    
    for i, entry in enumerate(entries, 1):
        field_value = (
            f"📝 {entry['summary']}\n"
            f"🔗 [記事を読む]({entry['link']})"
        )
        
        embed['fields'].append({
            "name": f"{i}. {entry['title']}",
            "value": field_value,
            "inline": False
        })
    
    return embed


def send_discord_embed(embeds: List[Dict]):
    """Discord Webhookに投稿"""
    payload = {
        "embeds": embeds,
        "username": "Tech News Bot",
        "avatar_url": "https://cdn-icons-png.flaticon.com/512/2504/2504929.png"
    }
    
    r = requests.post(WEBHOOK_URL, json=payload)
    r.raise_for_status()
    print(f"✅ Discord送信完了: {len(embeds)}件")


def check_rss():
    """RSS取得 → 要約 → 通知"""
    all_embeds = []
    
    for source in RSS_SOURCES:
        print(f"\n📡 取得中: {source['name']}")
        feed = feedparser.parse(source['url'])
        
        entries_data = []
        
        # 最新5件を処理
        for entry in feed.entries[:5]:
            print(f"  - 要約中: {entry.title[:30]}...")
            summary = summarize(getattr(entry, "summary", ""))
            
            entries_data.append({
                'title': entry.title,
                'link': entry.link,
                'summary': summary
            })
        
        if entries_data:
            embed = create_embed(source, entries_data)
            all_embeds.append(embed)
    
    # Discord送信
    if all_embeds:
        print(f"\n📤 Discord送信中... (合計 {len(all_embeds)}件)")
        send_discord_embed(all_embeds)
        print("✨ 完了!")
    else:
        print("⚠️ 新着記事が見つかりませんでした")


if __name__ == "__main__":
    check_rss()

2. GitHub Actionsのワークフロー設定

毎日15:00に実行されるように設定します。

作成方法:

.github/workflows/rss.ymlファイルを作成し、以下の内容を記述してコミット

.ymlサンプルコード

name: RSS Notify

on:
  schedule:
    - cron: "0 6 * * *"   # 毎日 06:00 UTC = 日本時間 15:00
  workflow_dispatch:       # 手動実行用(テストに使う)

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout repository
      uses: actions/checkout@v3

    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: "3.10"

    - name: Install dependencies
      run: |
        pip install feedparser google-generativeai requests

    - name: Run script
      env:
        GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
        DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
      run: python main.py

ポイント:

  • cron: "0 6 * * *":毎日UTC 06:00(日本時間15:00)に実行
  • workflow_dispatch:手動実行ボタンでテスト可能

3. GitHub Secretsの設定

重要:APIキーは直接コードに書かず、GitHub Secretsに設定

設定手順:

  1. GitHubリポジトリのSettingsタブを開く
  2. 左メニューからSecrets and variablesActionsをクリック
  3. New repository secretボタンをクリック
  4. 以下の2つのSecretを追加:
Name Value
GEMINI_API_KEY Google AI Studioで取得したAPIキー
DISCORD_WEBHOOK DiscordチャンネルのWebhook URL

スクリーンショット 2025-11-23 105408.jpg

APIキーやWebhook URLは絶対にコードに直接書かないでください。
GitHub Secretsに設定することで、公開リポジトリでも安全に管理できます。

4. 動作確認

設定が完了したら、手動実行でテストしてみましょう。

テスト手順:

  1. GitHubリポジトリのActionsタブをクリック
  2. 左側のワークフロー一覧からRSS Notifyを選択
  3. 右上のRun workflowボタンをクリック
    スクリーンショット 2025-11-23 110003.jpg
  4. Run workflow(緑のボタン)を再度クリックして実行開始
  5. 実行中のジョブが表示されるので、クリックして詳細を確認

実行結果の見方:

  • 成功:緑のチェックマークが表示される
  • 失敗:赤いバツマークが表示される(ログの最後にエラー原因が記載されています)

初回実行時はGemini APIの呼び出しに時間がかかるため、2〜3分ほど待ってください。

成功すると、Discordのチャンネルにニュースが届きます

スクリーンショット 2025-11-23 110524.jpg

スクリーンショット 2025-11-23 110539.jpg

ハマったポイント

Geminiモデルの指定ミス

ワークフロー実行が失敗しこんなエラーが出ました:

スクリーンショット 2025-11-23 110122.jpg

google.api_core.exceptions.NotFound: 404 models/gemini-1.5-flash is not found for API version v1beta, or is not supported for generateContent.

原因:モデル名の指定ミス
プロンプトにモデル名の指定をしなかったため、ChatGPTが最新版のgemini-1.5-flashを指定していました。無料枠で使える最新モデルはgemini-2.0-flashでした。

解決方法:
main.pyのモデル名修正

# 修正前
MODEL_NAME = "gemini-1.5-flash"

# 修正後
MODEL_NAME = "gemini-2.0-flash"

AIにモデル名を指定させる時は、必ず公式ドキュメントで最新情報を確認しましょう。

GitHub-actionsのワークフロー一覧に表示されない

Actionsのワークフロー一覧にRSS Notifyが表示されず…

原因:

単純なケアレスミスで、rss.ymlの配置先がなぜか.github/workflows/workflows/rss.ymlとなっていました。深夜作業は良くないですね...

解決方法:

正しいパスは.github/workflows/rss.ymlです。

ファイルパスを修正したところ、無事にワークフロー一覧に表示されて実行できました。

GitHub Actionsは.github/workflows/直下にymlファイルを置く必要があります。階層を間違えると認識されないので注意!

使ってみた感想

良かった点

  • ChatGPT:自動コード生成のおかげでPython初心者でもサクッと作れました
  • GitHub Actions:自動実行が無料で簡単に行えるので便利でした
  • Gemini API:個人利用なら無料枠で十分でした

改善点

正直、Discord投稿のデザインが見にくいです...

Embed形式で投稿しているものの、情報量が多くてゴチャゴチャしています。
実用化するには、もう少しデザインを工夫する必要がありそうです。

参考記事まとめ

最後に

今回はChatGPT Plusを契約していたのでChatGPTを活用しましたが、この規模のコード生成であればClaude、Geminiなどどの生成AIでも無料枠で十分対応できると思います。

ただ、AIが生成したコードをそのまま使うとハマることもあるので、エラーメッセージをちゃんと読んで対処することが大切です

実用化にはまだまだ改善の余地がありますが、自動化の第一歩としては満足です。

次は、Discord投稿のデザイン改善について検討していきたいと思います!

終わり

4
1
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
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?