main.py
This commit is contained in:
commit
bd3eb883c7
559
main.py
Normal file
559
main.py
Normal file
@ -0,0 +1,559 @@
|
|||||||
|
import discord
|
||||||
|
from discord.ext import commands, tasks
|
||||||
|
from discord import app_commands
|
||||||
|
from discord.ui import Button, View
|
||||||
|
import aiohttp
|
||||||
|
import asyncio
|
||||||
|
import platform
|
||||||
|
import psutil
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
import logging
|
||||||
|
|
||||||
|
# ロギングの設定
|
||||||
|
logging.basicConfig(
|
||||||
|
level=logging.INFO,
|
||||||
|
format='%(asctime)s - %(levelname)s - %(message)s',
|
||||||
|
handlers=[
|
||||||
|
logging.FileHandler("bot.log"),
|
||||||
|
logging.StreamHandler()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
# BOTの設定
|
||||||
|
TOKEN = 'あなたのDiscord Bot Token' # BOTトークン
|
||||||
|
CHANNEL_ID = 000000000000000000 # チャンネルID
|
||||||
|
CHECK_INTERVAL = 30 # 間隔(秒)
|
||||||
|
LOG_FILE = 'ip_changes.log' # IPアドレス変更ログファイル
|
||||||
|
|
||||||
|
last_ip = None
|
||||||
|
status_message = None
|
||||||
|
initialization_complete = False
|
||||||
|
|
||||||
|
intents = discord.Intents.all()
|
||||||
|
intents.message_content = True
|
||||||
|
intents.reactions = True
|
||||||
|
|
||||||
|
bot = commands.Bot(command_prefix='!', intents=intents)
|
||||||
|
|
||||||
|
# グローバルIPを取得
|
||||||
|
async def get_global_ip():
|
||||||
|
try:
|
||||||
|
async with aiohttp.ClientSession() as session:
|
||||||
|
async with session.get('https://api.ipify.org/?format=json', timeout=10) as response:
|
||||||
|
if response.status == 200:
|
||||||
|
data = await response.json()
|
||||||
|
return data['ip']
|
||||||
|
else:
|
||||||
|
logging.error(f"IPの取得に失敗しました: ステータスコード {response.status}")
|
||||||
|
return None
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"IPの取得中にエラーが発生しました: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# ログにIPアドレス変更を記録
|
||||||
|
def log_ip_change(old_ip, new_ip):
|
||||||
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
log_entry = f"[{timestamp}] IP変更: {old_ip} -> {new_ip}\n"
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(LOG_FILE, 'a', encoding='utf-8') as log_file:
|
||||||
|
log_file.write(log_entry)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"ログの書き込み中にエラーが発生しました: {e}")
|
||||||
|
|
||||||
|
# サーバーのステータスを取得
|
||||||
|
def get_server_status():
|
||||||
|
try:
|
||||||
|
# CPU使用率
|
||||||
|
cpu_percent = psutil.cpu_percent(interval=1)
|
||||||
|
|
||||||
|
# メモリ使用率
|
||||||
|
memory = psutil.virtual_memory()
|
||||||
|
memory_percent = memory.percent
|
||||||
|
memory_used = round(memory.used / (1024 * 1024 * 1024), 2) # GB
|
||||||
|
memory_total = round(memory.total / (1024 * 1024 * 1024), 2) # GB
|
||||||
|
|
||||||
|
# ディスク使用率
|
||||||
|
disk = psutil.disk_usage('/')
|
||||||
|
disk_percent = disk.percent
|
||||||
|
disk_used = round(disk.used / (1024 * 1024 * 1024), 2) # GB
|
||||||
|
disk_total = round(disk.total / (1024 * 1024 * 1024), 2) # GB
|
||||||
|
|
||||||
|
# システム稼働時間
|
||||||
|
boot_time = datetime.fromtimestamp(psutil.boot_time())
|
||||||
|
uptime = datetime.now() - boot_time
|
||||||
|
days = uptime.days
|
||||||
|
hours, remainder = divmod(uptime.seconds, 3600)
|
||||||
|
minutes, seconds = divmod(remainder, 60)
|
||||||
|
uptime_str = f"{days}日 {hours}時間 {minutes}分 {seconds}秒"
|
||||||
|
|
||||||
|
# OSバージョン
|
||||||
|
os_info = platform.platform()
|
||||||
|
|
||||||
|
return {
|
||||||
|
"cpu_percent": cpu_percent,
|
||||||
|
"memory_percent": memory_percent,
|
||||||
|
"memory_used": memory_used,
|
||||||
|
"memory_total": memory_total,
|
||||||
|
"disk_percent": disk_percent,
|
||||||
|
"disk_used": disk_used,
|
||||||
|
"disk_total": disk_total,
|
||||||
|
"uptime": uptime_str,
|
||||||
|
"os_info": os_info
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"サーバーステータスの取得中にエラーが発生しました: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 埋め込みメッセージ
|
||||||
|
def create_ip_embed(ip, old_ip=None, color=discord.Color.green()):
|
||||||
|
if not ip:
|
||||||
|
return discord.Embed(
|
||||||
|
title="⚠️ エラー",
|
||||||
|
description="グローバルIPアドレスの取得に失敗しました",
|
||||||
|
color=discord.Color.red()
|
||||||
|
)
|
||||||
|
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="🌐 グローバルIPアドレス",
|
||||||
|
description=f"**`{ip}`**",
|
||||||
|
color=color,
|
||||||
|
timestamp=datetime.now()
|
||||||
|
)
|
||||||
|
|
||||||
|
if old_ip and old_ip != ip:
|
||||||
|
embed.add_field(name="以前のIPアドレス", value=f"`{old_ip}`", inline=False)
|
||||||
|
embed.add_field(name="状態", value="⚠️ IPアドレスが変更されました", inline=False)
|
||||||
|
embed.color = discord.Color.orange()
|
||||||
|
|
||||||
|
embed.set_footer(text="最終更新")
|
||||||
|
|
||||||
|
return embed
|
||||||
|
|
||||||
|
# サーバーステータスの埋め込みメッセージ
|
||||||
|
def create_status_embed(status_data):
|
||||||
|
if not status_data:
|
||||||
|
return discord.Embed(
|
||||||
|
title="⚠️ エラー",
|
||||||
|
description="サーバーステータスの取得に失敗しました",
|
||||||
|
color=discord.Color.red()
|
||||||
|
)
|
||||||
|
|
||||||
|
embed = discord.Embed(
|
||||||
|
title="🖥️ サーバーステータス",
|
||||||
|
color=discord.Color.blue(),
|
||||||
|
timestamp=datetime.now()
|
||||||
|
)
|
||||||
|
|
||||||
|
# CPU使用率のプログレスバー
|
||||||
|
cpu_bar = create_progress_bar(status_data["cpu_percent"])
|
||||||
|
embed.add_field(name="CPU使用率", value=f"{cpu_bar} {status_data['cpu_percent']}%", inline=False)
|
||||||
|
|
||||||
|
# メモリ使用率のプログレスバー
|
||||||
|
memory_bar = create_progress_bar(status_data["memory_percent"])
|
||||||
|
embed.add_field(
|
||||||
|
name="メモリ使用率",
|
||||||
|
value=f"{memory_bar} {status_data['memory_percent']}%\n`{status_data['memory_used']}GB / {status_data['memory_total']}GB`",
|
||||||
|
inline=False
|
||||||
|
)
|
||||||
|
|
||||||
|
# ディスク使用率のプログレスバー
|
||||||
|
disk_bar = create_progress_bar(status_data["disk_percent"])
|
||||||
|
embed.add_field(
|
||||||
|
name="ディスク使用率",
|
||||||
|
value=f"{disk_bar} {status_data['disk_percent']}%\n`{status_data['disk_used']}GB / {status_data['disk_total']}GB`",
|
||||||
|
inline=False
|
||||||
|
)
|
||||||
|
|
||||||
|
# システム情報
|
||||||
|
embed.add_field(name="システム稼働時間", value=f"`{status_data['uptime']}`", inline=False)
|
||||||
|
embed.add_field(name="OS情報", value=f"`{status_data['os_info']}`", inline=False)
|
||||||
|
|
||||||
|
embed.set_footer(text="最終更新")
|
||||||
|
|
||||||
|
return embed
|
||||||
|
|
||||||
|
# プログレスバーを作成
|
||||||
|
def create_progress_bar(percent, bar_length=15):
|
||||||
|
filled_length = int(bar_length * percent / 100)
|
||||||
|
empty_length = bar_length - filled_length
|
||||||
|
|
||||||
|
if percent < 60:
|
||||||
|
color = "🟢" # 緑
|
||||||
|
elif percent < 80:
|
||||||
|
color = "🟡" # 黄
|
||||||
|
else:
|
||||||
|
color = "🔴" # 赤
|
||||||
|
|
||||||
|
bar = "▰" * filled_length + "▱" * empty_length
|
||||||
|
return f"[{bar}] {color}"
|
||||||
|
|
||||||
|
class IPControlView(View):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(timeout=None)
|
||||||
|
|
||||||
|
@discord.ui.button(label="今すぐ更新", style=discord.ButtonStyle.primary, custom_id="refresh_ip")
|
||||||
|
async def refresh_button(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||||
|
global last_ip
|
||||||
|
|
||||||
|
await interaction.response.defer(ephemeral=True)
|
||||||
|
|
||||||
|
current_ip = await get_global_ip()
|
||||||
|
|
||||||
|
if current_ip is None:
|
||||||
|
await interaction.followup.send("IPアドレスの取得に失敗しました", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
if last_ip and last_ip != current_ip:
|
||||||
|
log_ip_change(last_ip, current_ip)
|
||||||
|
|
||||||
|
old_ip = last_ip
|
||||||
|
last_ip = current_ip
|
||||||
|
|
||||||
|
embed = create_ip_embed(current_ip, old_ip)
|
||||||
|
await interaction.message.edit(embed=embed, view=self)
|
||||||
|
|
||||||
|
await interaction.followup.send("IPアドレス情報を更新しました", ephemeral=True)
|
||||||
|
|
||||||
|
@discord.ui.button(label="サーバーステータス", style=discord.ButtonStyle.success, custom_id="server_status")
|
||||||
|
async def status_button(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||||
|
await interaction.response.defer(ephemeral=True)
|
||||||
|
|
||||||
|
status_data = get_server_status()
|
||||||
|
|
||||||
|
if status_data is None:
|
||||||
|
await interaction.followup.send("サーバーステータスの取得に失敗しました", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
embed = create_status_embed(status_data)
|
||||||
|
|
||||||
|
view = CloseView()
|
||||||
|
|
||||||
|
await interaction.followup.send(embed=embed, view=view, ephemeral=False)
|
||||||
|
|
||||||
|
@discord.ui.button(label="PROXMOX", style=discord.ButtonStyle.secondary, custom_id="proxmox_link")
|
||||||
|
async def proxmox_button(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||||
|
global last_ip
|
||||||
|
|
||||||
|
await interaction.response.defer(ephemeral=True)
|
||||||
|
|
||||||
|
if not last_ip:
|
||||||
|
await interaction.followup.send("IPアドレスが取得されていません", ephemeral=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
proxmox_url = f"https://{last_ip}:8006"
|
||||||
|
|
||||||
|
await interaction.followup.send(
|
||||||
|
f"Proxmox管理画面にアクセス\n"
|
||||||
|
f"[Proxmox管理画面]({proxmox_url})\n\n"
|
||||||
|
f"または直接アクセス: `{proxmox_url}`",
|
||||||
|
ephemeral=True
|
||||||
|
)
|
||||||
|
|
||||||
|
class CloseView(View):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(timeout=None)
|
||||||
|
|
||||||
|
@discord.ui.button(label="閉じる", style=discord.ButtonStyle.danger, custom_id="close_status")
|
||||||
|
async def close_button(self, interaction: discord.Interaction, button: discord.ui.Button):
|
||||||
|
await interaction.response.defer(ephemeral=True)
|
||||||
|
await interaction.message.delete()
|
||||||
|
await interaction.followup.send("ステータス表示を終了しました", ephemeral=True)
|
||||||
|
|
||||||
|
async def clear_channel_messages():
|
||||||
|
try:
|
||||||
|
channel = bot.get_channel(CHANNEL_ID)
|
||||||
|
if channel is None:
|
||||||
|
logging.error(f"チャンネルが見つかりません: {CHANNEL_ID}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
deleted = 0
|
||||||
|
logging.info("チャンネル内のメッセージを削除中")
|
||||||
|
|
||||||
|
try:
|
||||||
|
logging.info("最近のメッセージを一削除中")
|
||||||
|
deleted_messages = await channel.purge(limit=100, bulk=True)
|
||||||
|
deleted += len(deleted_messages)
|
||||||
|
logging.info(f"{len(deleted_messages)}件のメッセージの削除完了")
|
||||||
|
|
||||||
|
remaining = []
|
||||||
|
async for message in channel.history(limit=10):
|
||||||
|
remaining.append(message)
|
||||||
|
|
||||||
|
if remaining:
|
||||||
|
logging.info(f"残り{len(remaining)}件の古いメッセージを削除中")
|
||||||
|
for message in remaining:
|
||||||
|
await message.delete()
|
||||||
|
deleted += 1
|
||||||
|
logging.info(f"メッセージを削除(合計: {deleted})")
|
||||||
|
await asyncio.sleep(0.5) # レート制限回避
|
||||||
|
|
||||||
|
except discord.Forbidden:
|
||||||
|
logging.error("Discordのメッセージ削除権限がありません")
|
||||||
|
return False
|
||||||
|
except discord.HTTPException as e:
|
||||||
|
logging.error(f"一括削除中にHTTPエラーが発生: {e}")
|
||||||
|
try:
|
||||||
|
async for message in channel.history(limit=100):
|
||||||
|
await message.delete()
|
||||||
|
deleted += 1
|
||||||
|
logging.info(f"個別削除:メッセージを削除(合計: {deleted})")
|
||||||
|
await asyncio.sleep(0.5)
|
||||||
|
except Exception as e2:
|
||||||
|
logging.error(f"個別削除中にエラーが発生: {e2}")
|
||||||
|
|
||||||
|
logging.info(f"{deleted}件のメッセージを削除")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"チャンネル内メッセージ削除中にエラーが発生: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
@bot.event
|
||||||
|
async def on_ready():
|
||||||
|
global initialization_complete
|
||||||
|
|
||||||
|
logging.info(f'{bot.user}')
|
||||||
|
logging.info(f'BOT ID: {bot.user.id}')
|
||||||
|
logging.info(f'送信先チャンネルID: {CHANNEL_ID}')
|
||||||
|
logging.info(f'間隔: {CHECK_INTERVAL}秒 ({CHECK_INTERVAL/60}分)')
|
||||||
|
logging.info('------')
|
||||||
|
logging.info('グローバルIP検出・変更通知BOT')
|
||||||
|
logging.info('© 2025 uttili_external_system')
|
||||||
|
logging.info('https://uttili.com')
|
||||||
|
logging.info('------')
|
||||||
|
|
||||||
|
if not initialization_complete:
|
||||||
|
logging.info("チャンネル内メッセージを削除中")
|
||||||
|
await clear_channel_messages()
|
||||||
|
|
||||||
|
logging.info("メッセージを送信中")
|
||||||
|
await send_initial_message()
|
||||||
|
|
||||||
|
if not check_ip_change.is_running():
|
||||||
|
check_ip_change.start()
|
||||||
|
logging.info("IP検出開始")
|
||||||
|
|
||||||
|
initialization_complete = True
|
||||||
|
logging.info("初期化が完了")
|
||||||
|
else:
|
||||||
|
if not check_ip_change.is_running():
|
||||||
|
check_ip_change.start()
|
||||||
|
logging.info("IP検出再開")
|
||||||
|
|
||||||
|
@tasks.loop(seconds=CHECK_INTERVAL)
|
||||||
|
async def check_ip_change():
|
||||||
|
global last_ip, status_message
|
||||||
|
|
||||||
|
try:
|
||||||
|
current_ip = await get_global_ip()
|
||||||
|
|
||||||
|
if current_ip is None:
|
||||||
|
logging.warning("IPアドレスの取得に失敗")
|
||||||
|
return
|
||||||
|
|
||||||
|
if last_ip is None:
|
||||||
|
last_ip = current_ip
|
||||||
|
logging.info(f"初期IPアドレスを確定: {current_ip}")
|
||||||
|
|
||||||
|
if status_message is None:
|
||||||
|
await send_initial_message()
|
||||||
|
else:
|
||||||
|
await update_ip_message(current_ip)
|
||||||
|
|
||||||
|
elif last_ip != current_ip:
|
||||||
|
old_ip = last_ip
|
||||||
|
last_ip = current_ip
|
||||||
|
|
||||||
|
log_ip_change(old_ip, current_ip)
|
||||||
|
|
||||||
|
await update_ip_message(current_ip, old_ip)
|
||||||
|
|
||||||
|
logging.info(f"IPアドレスの変更検出: {old_ip} -> {current_ip}")
|
||||||
|
else:
|
||||||
|
await update_ip_message(current_ip)
|
||||||
|
logging.debug(f"IPアドレスに変更なし: {current_ip}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"IP検出中に予期しないエラーが発生: {e}")
|
||||||
|
|
||||||
|
@check_ip_change.before_loop
|
||||||
|
async def before_check_ip_change():
|
||||||
|
await bot.wait_until_ready()
|
||||||
|
logging.info("BOT起動")
|
||||||
|
|
||||||
|
@check_ip_change.error
|
||||||
|
async def check_ip_change_error(error):
|
||||||
|
logging.error(f"IP検出中にエラーが発生: {error}")
|
||||||
|
if not check_ip_change.is_running():
|
||||||
|
check_ip_change.restart()
|
||||||
|
logging.info("IP検出再開")
|
||||||
|
|
||||||
|
async def send_initial_message():
|
||||||
|
global last_ip, status_message
|
||||||
|
|
||||||
|
try:
|
||||||
|
if status_message is not None:
|
||||||
|
logging.info("既にメッセージが存在するためスキップ")
|
||||||
|
return
|
||||||
|
|
||||||
|
channel = bot.get_channel(CHANNEL_ID)
|
||||||
|
if channel is None:
|
||||||
|
logging.error(f"チャンネル不明: {CHANNEL_ID}")
|
||||||
|
return
|
||||||
|
|
||||||
|
current_ip = await get_global_ip()
|
||||||
|
if current_ip is None:
|
||||||
|
logging.error("IPアドレスの取得に失敗しました")
|
||||||
|
return
|
||||||
|
|
||||||
|
last_ip = current_ip
|
||||||
|
|
||||||
|
embed = create_ip_embed(current_ip)
|
||||||
|
|
||||||
|
view = IPControlView()
|
||||||
|
|
||||||
|
status_message = await channel.send(embed=embed, view=view)
|
||||||
|
|
||||||
|
logging.info(f"メッセージを送信 Message ID: {status_message.id}")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"メッセージ送信中にエラー: {e}")
|
||||||
|
|
||||||
|
async def update_ip_message(current_ip, old_ip=None):
|
||||||
|
global status_message
|
||||||
|
|
||||||
|
try:
|
||||||
|
if status_message is None:
|
||||||
|
await send_initial_message()
|
||||||
|
return
|
||||||
|
|
||||||
|
channel = bot.get_channel(CHANNEL_ID)
|
||||||
|
if channel is None:
|
||||||
|
logging.error(f"チャンネル不明: {CHANNEL_ID}")
|
||||||
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
|
message = await channel.fetch_message(status_message.id)
|
||||||
|
except discord.NotFound:
|
||||||
|
logging.warning("ステータスメッセージ不明。新規作成開始。")
|
||||||
|
status_message = None # status_messageリセット
|
||||||
|
await send_initial_message()
|
||||||
|
return
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"メッセージ取得中にエラーが発生: {e}")
|
||||||
|
status_message = None
|
||||||
|
await send_initial_message()
|
||||||
|
return
|
||||||
|
|
||||||
|
color = discord.Color.orange() if old_ip and old_ip != current_ip else discord.Color.green()
|
||||||
|
|
||||||
|
embed = create_ip_embed(current_ip, old_ip, color)
|
||||||
|
|
||||||
|
view = IPControlView()
|
||||||
|
|
||||||
|
await message.edit(embed=embed, view=view)
|
||||||
|
|
||||||
|
if old_ip and old_ip != current_ip:
|
||||||
|
logging.info(f"IPメッセージを更新: {old_ip} -> {current_ip}")
|
||||||
|
else:
|
||||||
|
logging.debug(f"IPメッセージのタイムスタンプを更新: {current_ip}")
|
||||||
|
|
||||||
|
except discord.NotFound:
|
||||||
|
logging.warning("メッセージ不明。新規作成開始。")
|
||||||
|
status_message = None
|
||||||
|
await send_initial_message()
|
||||||
|
except discord.Forbidden:
|
||||||
|
logging.error("メッセージの編集権限がないため動作不可能")
|
||||||
|
except discord.HTTPException as e:
|
||||||
|
logging.error(f"メッセージ更新中にHTTPエラーが発生: {e}")
|
||||||
|
await asyncio.sleep(5)
|
||||||
|
try:
|
||||||
|
if status_message:
|
||||||
|
channel = bot.get_channel(CHANNEL_ID)
|
||||||
|
message = await channel.fetch_message(status_message.id)
|
||||||
|
embed = create_ip_embed(current_ip, old_ip, discord.Color.green())
|
||||||
|
view = IPControlView()
|
||||||
|
await message.edit(embed=embed, view=view)
|
||||||
|
except Exception:
|
||||||
|
status_message = None
|
||||||
|
await send_initial_message()
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"メッセージの更新中に予期しないエラーが発生: {e}")
|
||||||
|
status_message = None
|
||||||
|
await send_initial_message()
|
||||||
|
|
||||||
|
@bot.command(name="ipreset")
|
||||||
|
async def ipreset(ctx):
|
||||||
|
global status_message, initialization_complete
|
||||||
|
|
||||||
|
if not ctx.author.guild_permissions.administrator:
|
||||||
|
await ctx.send("❌ このコマンドは管理者権限が必要です", delete_after=5)
|
||||||
|
return
|
||||||
|
|
||||||
|
await ctx.message.delete()
|
||||||
|
|
||||||
|
await clear_channel_messages()
|
||||||
|
status_message = None
|
||||||
|
initialization_complete = False
|
||||||
|
|
||||||
|
initialization_complete = True
|
||||||
|
await send_initial_message()
|
||||||
|
|
||||||
|
if not check_ip_change.is_running():
|
||||||
|
check_ip_change.start()
|
||||||
|
logging.info("IP検出を開始")
|
||||||
|
|
||||||
|
await ctx.send("✅ チャンネル内を削除し、ステータスを表示しました", delete_after=5)
|
||||||
|
|
||||||
|
@bot.command(name="ipclear")
|
||||||
|
async def ipclear(ctx):
|
||||||
|
global status_message
|
||||||
|
|
||||||
|
if not ctx.author.guild_permissions.administrator:
|
||||||
|
await ctx.send("❌ このコマンドは管理者権限が必要です", delete_after=5)
|
||||||
|
return
|
||||||
|
|
||||||
|
await ctx.message.delete()
|
||||||
|
|
||||||
|
success = await clear_channel_messages()
|
||||||
|
|
||||||
|
if success:
|
||||||
|
status_message = None
|
||||||
|
|
||||||
|
await send_initial_message()
|
||||||
|
|
||||||
|
await ctx.send("✅ チャンネルをクリアしました", delete_after=5)
|
||||||
|
else:
|
||||||
|
await ctx.send("❌ チャンネルのクリアに失敗しました", delete_after=5)
|
||||||
|
|
||||||
|
@bot.command(name="ipstatus")
|
||||||
|
async def ipstatus(ctx):
|
||||||
|
await ctx.message.delete()
|
||||||
|
|
||||||
|
task_status = "実行中" if check_ip_change.is_running() else "停止中"
|
||||||
|
|
||||||
|
ip_status = f"`{last_ip}`" if last_ip else "未取得"
|
||||||
|
|
||||||
|
status_msg = await ctx.send(
|
||||||
|
f"**IPチェック状態**\n"
|
||||||
|
f"タスク: {task_status}\n"
|
||||||
|
f"現在のIP: {ip_status}\n"
|
||||||
|
f"更新間隔: {CHECK_INTERVAL}秒",
|
||||||
|
delete_after=10
|
||||||
|
)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
logging.info("BOTを起動中")
|
||||||
|
logging.info("グローバルIPの監視開始")
|
||||||
|
|
||||||
|
try:
|
||||||
|
import psutil
|
||||||
|
except ImportError:
|
||||||
|
logging.warning("psutilモジュールがインストールされていない")
|
||||||
|
logging.warning("サーバーステータス機能を使用するには、以下のコマンドでインストール:")
|
||||||
|
logging.warning("pip install psutil")
|
||||||
|
logging.warning("続行しますが、サーバーステータス機能は機能しない")
|
||||||
|
|
||||||
|
bot.run(TOKEN)
|
||||||
Loading…
Reference in New Issue
Block a user