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

Discord日程調整Botの開発からSynology NASでのホスティングまで

Last updated at Posted at 2025-04-04

Discord日程調整Botの開発からSynology NASでのホスティングまで

こんにちは!この記事では、Discordサーバーでのスケジュール調整に役立つ投票Botを開発し、Synology NASでホスティングする方法を紹介します。時間枠の重複ありで投票を自動作成する機能を持ち、サーバーメンバーの予定調整を効率化するBotです。

目次

1. Discord Botの概要

このBotは以下の機能を持ちます:

  • 週間投票作成: 指定日から1週間の予定投票を作成
  • 期間投票作成: 指定した期間(最大31日間)の予定投票を作成
  • カスタム投票: 任意のタイトルと選択肢による投票の作成
  • 時間枠: 9:00-21:00の2時間枠(重複あり)
  • 簡単操作: 絵文字リアクションによる投票システム

2. 開発環境の準備

まず必要なライブラリをインストールします:

pip install discord.py pytz

discord.pyはDiscord APIを操作するためのライブラリ、pytzはタイムゾーン処理のためのライブラリです。

3. Discord Developer Portalでの設定

Botを作成するには、Discord Developer Portalでの設定が必要です:

  1. Discord Developer Portalにアクセス
  2. 「New Application」をクリックし、アプリケーション名を入力
  3. 左側のメニューから「Bot」をクリック
  4. 「Add Bot」ボタンをクリックしてBotを作成
  5. 「Reset Token」をクリックしてトークンを取得(これは安全に保管!)
  6. 「MESSAGE CONTENT INTENT」を有効にする
  7. 左側の「OAuth2」→「URL Generator」で権限を設定
    • スコープ: bot
    • 権限:
      • Read Messages
      • View Channels
      • Send Messages
      • Manage Messages
      • Add Reactions
  8. 生成されたURLでBotをサーバーに招待

4. Botのコード実装

完全なコードは以下のGitHubリポジトリで公開しています:

https://github.com/k1nsenka/discord-vote-bot

ここでは主要なコードを解説します。vote-bot.pyとして保存してください:

import discord
from discord.ext import commands
import datetime
import pytz
import asyncio
import os
import json

# 設定ファイルからトークンを読み込む
def load_config():
    try:
        with open('config.json', 'r') as f:
            return json.load(f)
    except FileNotFoundError:
        print("エラー: config.jsonファイルが見つかりません。")
        print("config.json.exampleをconfig.jsonにリネームし、Botトークンを設定してください。")
        exit(1)
    except json.JSONDecodeError:
        print("エラー: config.jsonの形式が正しくありません。")
        exit(1)

# Botの設定
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix='!', intents=intents)

# タイムゾーンの設定(日本時間)
JST = pytz.timezone('Asia/Tokyo')

# 投票用絵文字(追加の絵文字を含む)
EMOJI_NUMBERS = ['1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣', '6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟', '🇦', '🇧', '🇨', '🇩', '🇪']

@bot.event
async def on_ready():
    print(f'{bot.user} としてログインしました')

@bot.command(name='週間投票作成')
async def create_weekly_poll(ctx, : int, : int, : int):
    # コマンド実行開始を通知
    await ctx.send("投票を作成しています。しばらくお待ちください...")

@bot.command(name='期間投票作成')
async def create_period_poll(ctx, 開始年: int, 開始月: int, 開始日: int, 終了年: int, 終了月: int, 終了日: int):
    """
    指定した期間の9:00-21:00の2時間枠(重複あり)の投票を作成します
    使用例: !期間投票作成 2025 4 7 2025 4 15
    """
    # コマンド実行開始を通知
    await ctx.send("投票を作成しています。しばらくお待ちください...")
    
    # 開始日と終了日の設定
    try:
        start_date = datetime.datetime(開始年, 開始月, 開始日, tzinfo=JST)
        end_date = datetime.datetime(終了年, 終了月, 終了日, tzinfo=JST)
    except ValueError as e:
        await ctx.send(f"日付の指定が正しくありません: {str(e)}")
        return
    
    # 日数を計算
    delta = end_date - start_date
    days = delta.days + 1  # 終了日も含める
    
    if days <= 0:
        await ctx.send("終了日は開始日以降に設定してください。")
        return
    
    if days > 31:
        await ctx.send("期間が長すぎます。最大31日間までにしてください。")
        return
    
    # 投票メッセージを送信
    try:
        intro_msg = await ctx.send(f"**{開始年}{開始月}{開始日}日から{終了年}{終了月}{終了日}日までの予定投票**\n各日の参加可能な時間帯に投票してください(複数選択可)")
        await asyncio.sleep(1)  # 少し待機
    except Exception as e:
        await ctx.send(f"メッセージ送信中にエラーが発生しました: {str(e)}")
        return  # エラーがあれば中断
    
    # 曜日の日本語表記
    weekdays = ['', '', '', '', '', '', '']
    
    # 指定された期間の投票を作成
    for day_offset in range(days):
        current_date = start_date + datetime.timedelta(days=day_offset)
        weekday = weekdays[current_date.weekday()]
        
        # 各日の投票メッセージ
        poll_message = f"**{current_date.month}{current_date.day}日({weekday})の参加可能時間帯**"
        
        # 9:00から21:00まで、2時間枠(重複あり)の選択肢を作成
        options = []
        for hour in range(9, 20):
            # 利用可能な絵文字数を超えないようにする
            if len(options) < len(EMOJI_NUMBERS):
                options.append(f"{hour:02d}:00-{hour+2:02d}:00")
        
        # 投票メッセージに選択肢を追加
        for i, option in enumerate(options):
            poll_message += f"\n{EMOJI_NUMBERS[i]} {option}"
        
        # 投票メッセージを送信
        try:
            poll = await ctx.send(poll_message)
            
            # リアクションを1つずつ追加(レート制限対策)
            for i in range(len(options)):
                await poll.add_reaction(EMOJI_NUMBERS[i])
                await asyncio.sleep(1)  # 各リアクション間に1秒待機
        except Exception as e:
            await ctx.send(f"エラーが発生しました: {str(e)}")
            return
        
        # 各投票の間に少し待機(レート制限対策)
        await asyncio.sleep(3)
        
        # エラーがあれば報告
        try:
            for i in range(len(options)):
                await poll.add_reaction(EMOJI_NUMBERS[i])
                await asyncio.sleep(1)  # 各リアクション追加の間に待機
        except Exception as e:
            await ctx.send(f"エラーが発生しました: {str(e)}")

@bot.command(name='投票作成')
async def create_poll(ctx, タイトル, *選択肢):
    """
    カスタム投票を作成します
    使用例: !投票作成 "好きな食べ物は?" "ラーメン" "寿司" "カレー"
    """
    if len(選択肢) > 10:
        await ctx.send("選択肢は最大10個までです。")
        return
    
    # 投票メッセージを作成
    poll_message = f"**{タイトル}**"
    for i, option in enumerate(選択肢):
        poll_message += f"\n{EMOJI_NUMBERS[i]} {option}"
    
    # 投票メッセージを送信
    poll = await ctx.send(poll_message)
    
    # リアクションを追加
    for i in range(len(選択肢)):
        await poll.add_reaction(EMOJI_NUMBERS[i])

@bot.command(name='ヘルプ')
async def help_command(ctx):
    """ボットのコマンド一覧と使い方を表示します"""
    help_message = """
**投票ボットの使い方**

**`!週間投票作成 [年] [月] [日]`**
指定した日から一週間の9:00-21:00の2時間枠(重複あり)の投票を作成します
例: `!週間投票作成 2025 4 7`

**`!期間投票作成 [開始年] [開始月] [開始日] [終了年] [終了月] [終了日]`**
指定した期間の9:00-21:00の2時間枠(重複あり)の投票を作成します(最大31日間)
例: `!期間投票作成 2025 4 7 2025 4 15`

**`!投票作成 [タイトル] [選択肢1] [選択肢2] ...`**
カスタム投票を作成します(最大10個の選択肢)
例: `!投票作成 "今週末の活動は?" "オンライン会議" "Discord通話" "スキップ"`

**`!ヘルプ`**
このヘルプメッセージを表示します
"""
    await ctx.send(help_message)

# 設定を読み込み
config = load_config()

# Botを実行
bot.run(config['token'])

またBotのトークンを安全に管理するため、以下のconfig.json.exampleファイルも作成します:

{
  "token": "YOUR_DISCORD_BOT_TOKEN_HERE"
}

このファイルをコピーしてconfig.jsonを作成し、実際のトークンを設定してください。

5. GitHubでのコード管理

GitHubでコードを管理するために、以下の手順で設定します。今回はMacBookでリポジトリを作ったのでMac関連の内容になっています。:

1. .gitignoreファイルの作成

# Discord Bot設定ファイル(トークンを含む)
config.json

# Python関連
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg

# Mac関連
.DS_Store
.AppleDouble
.LSOverride
Icon
._*
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# エディタ/IDE関連
.idea/
.vscode/
*.swp
*.swo
*~
.project
.classpath
.settings/

# 仮想環境
venv/
ENV/
.env

# ログファイル
*.log

2. README.mdファイルの作成

# Discord 投票Bot

Discordサーバーで時間枠の投票を簡単に作成するためのBotです。9:00から21:00までの2時間枠(重複あり)で、一週間分または指定した期間の投票を自動生成することができます。

## 📢 アップデート情報 (2025/04/04)

- **新機能**: 期間投票作成コマンドを追加
  - `!期間投票作成` コマンドで開始日から終了日までの任意の期間で投票を作成可能に
  - 最大31日間までの期間指定に対応
- **改善**: エラーハンドリング強化
  - 無効な日付や期間の入力に対するエラーメッセージを追加
  - Discord APIのレート制限対策を強化

## 機能

- 指定した日から一週間分の時間枠投票を自動作成
- 指定した期間(最大31日間)の時間枠投票を自動作成
- 各日の9:00から21:00までの2時間枠(重複あり)を選択肢として表示
- カスタム投票の作成
- 絵文字リアクションによる簡単な投票システム

## インストール方法

1. リポジトリをクローン
   $ git clone https://github.com/your-username/discord-poll-bot.git
   $ cd discord-poll-bot

2. 必要なライブラリをインストール
   $ pip install discord.py pytz

3. 設定ファイルのセットアップ
   $ cp config.json.example config.json
   
   `config.json`を編集し、あなたのBotトークンを設定してください。

## 使用方法

Botを起動:
$ python vote-bot.py

### コマンド

- `!週間投票作成 [年] [月] [日]`: 指定した日から一週間分の投票を作成
  例: `!週間投票作成 2025 4 7`

- `!期間投票作成 [開始年] [開始月] [開始日] [終了年] [終了月] [終了日]`: 指定した期間の投票を作成
  例: `!期間投票作成 2025 4 7 2025 4 15`

- `!投票作成 [タイトル] [選択肢1] [選択肢2] ...`: カスタム投票を作成
  例: `!投票作成 "好きな食べ物は?" "ラーメン" "寿司" "カレー"`

- `!ヘルプ`: コマンド一覧と使い方を表示

3. GitHubへのプッシュ

ターミナルで以下のコマンドを実行します:

# リポジトリの初期化
git init

# ファイルをステージング
git add .

# 初回コミット
git commit -m "初期コミット: Discord投票Bot"

# GitHubリポジトリの作成後、リモートを追加
git remote add origin https://github.com/あなたのユーザー名/discord-vote-bot.git

# プッシュ
git branch -M main
git push -u origin main

これで、コードはGitHubで管理され、いつでもアクセスできるようになります。

6. Synology NASでのホスティング

Synology NASを使ってBotを24時間稼働させる設定を行います。

1. 必要なファイルの転送

  1. GitHubからコードをクローンするか、手動でファイルをNASに転送
  2. config.jsonを作成し、Botトークンを設定

2. Python環境の準備

Synology NASのパッケージセンターから「Python 3.9」をインストールし、必要なライブラリをインストールします。pipが使えるようになるまでは他の記事を参考にしてみてください。:

# SSHでNASに接続後
pip install discord.py pytz

3. 起動スクリプトの作成

起動用のシェルスクリプトを作成します:

# NASのホームディレクトリ等に移動
cd /volume1/homes/あなたのユーザー名/

# スクリプトファイルを作成
nano start_discord_bot.sh

スクリプトの内容(ここら辺のpythonパスはちょっと厄介、起動しなかったら調べましょう):

#!/bin/bash
cd /volume1/homes/あなたのユーザー名/discord-vote-bot
/volume1/@appstore/Python3.9/usr/bin/python3.9 vote-bot.py >> /volume1/homes/あなたのユーザー名/discord-bot.log 2>&1 &

スクリプトに実行権限を付与:

chmod +x start_discord_bot.sh

4. 自動起動の設定

Synology DSMの管理画面からタスクスケジューラを使って、NAS起動時にBotが自動的に起動するように設定します:

  1. DSMにログインコントロールパネルタスクスケジューラ
  2. 作成トリガーされたタスクブートアップ
  3. 設定内容:
    • 全般タブ:
      • タスク名: Discord Bot 自動起動
      • ユーザー: admin(またはroot権限を持つユーザー)
      • 有効: チェックを入れる
    • タスク設定タブ:
      • 実行コマンド: /volume1/homes/あなたのユーザー名/start_discord_bot.sh
      • ユーザー定義のスクリプトを実行: チェックを入れる
  4. OKをクリックして保存

これで5分ごとにBotの状態を確認し、動作していなければ再起動します。

6. サーバーでの使用方法

Botをサーバーに招待したら、以下のコマンドで使用できます:

  • 週間投票の作成:

    !週間投票作成 2025 4 7
    

    2025年4月7日から一週間分の投票を作成します。

  • 期間指定での投票作成:

    !期間投票作成 2025 4 7 2025 4 15
    

    2025年4月7日から15日までの投票を作成します。

  • カスタム投票の作成:

    !投票作成 "週末の活動" "オンラインゲーム" "映画鑑賞" "雑談"
    
  • ヘルプの表示:

    !ヘルプ
    

メンバーは表示された選択肢に対応する絵文字をクリックするだけで投票できます。複数の時間帯に参加可能な場合は、複数の絵文字を選択できます。

7. まとめ

この記事では、以下の内容について解説しました:

  1. Discord投票Botの開発方法
  2. Botのコード実装と機能説明
  3. GitHubでのコード管理
  4. Synology NASでのホスティング方法

このBotを使えば、Discordサーバーでのスケジュール調整が格段に効率化されます。また、Synology NASを使ったホスティングにより、PC起動不要で24時間稼働する安定したBotサービスを提供できます。

ぜひ自分のサーバーに導入して、メンバーのスケジュール調整を効率化してみてください!


参考リンク

コードはGitHubでも公開されています。ぜひ参考にしてください。

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