ボタン操作ができるように、タイムアウト機能の実装、スラッシュコマンド対応への準備
This commit is contained in:
parent
f7b6caca30
commit
b908ce17ed
1 changed files with 230 additions and 2 deletions
232
dislocker.py
232
dislocker.py
|
@ -1,13 +1,17 @@
|
||||||
import json
|
import json
|
||||||
import discord
|
import discord
|
||||||
|
from discord import Interaction, TextStyle, app_commands
|
||||||
|
from discord.ui import TextInput, View, Modal
|
||||||
import os
|
import os
|
||||||
import psycopg2
|
import psycopg2
|
||||||
from psycopg2 import sql
|
from psycopg2 import sql
|
||||||
import hashlib
|
import hashlib
|
||||||
import string
|
import string
|
||||||
import random
|
import random
|
||||||
from datetime import datetime
|
from datetime import datetime, timedelta
|
||||||
from openpyxl import Workbook
|
from openpyxl import Workbook
|
||||||
|
import threading
|
||||||
|
import time
|
||||||
|
|
||||||
class DL():
|
class DL():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -70,7 +74,10 @@ class DL():
|
||||||
print(find_pc_list_table)
|
print(find_pc_list_table)
|
||||||
if find_pc_list_table[0][0] == False:
|
if find_pc_list_table[0][0] == False:
|
||||||
cursor.execute("CREATE TABLE pc_list (pc_number INTEGER NOT NULL, using_user_id INTEGER, password_hash VARCHAR(32), PRIMARY KEY (pc_number), FOREIGN KEY (using_user_id) REFERENCES club_member(id))")
|
cursor.execute("CREATE TABLE pc_list (pc_number INTEGER NOT NULL, using_user_id INTEGER, password_hash VARCHAR(32), PRIMARY KEY (pc_number), FOREIGN KEY (using_user_id) REFERENCES club_member(id))")
|
||||||
self.db.commit
|
for i in range(10):
|
||||||
|
print(i)
|
||||||
|
cursor.execute("INSERT INTO pc_list (pc_number) VALUES (%s)", (i + 1,))
|
||||||
|
self.db.commit()
|
||||||
|
|
||||||
cursor.execute("SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'pc_usage_history')")
|
cursor.execute("SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_schema = 'public' AND table_name = 'pc_usage_history')")
|
||||||
find_pc_usage_history_table = cursor.fetchall()
|
find_pc_usage_history_table = cursor.fetchall()
|
||||||
|
@ -91,6 +98,7 @@ class DL():
|
||||||
|
|
||||||
|
|
||||||
class Bot(discord.Client):
|
class Bot(discord.Client):
|
||||||
|
|
||||||
def password_generate(self, length):
|
def password_generate(self, length):
|
||||||
numbers = string.digits # (1)
|
numbers = string.digits # (1)
|
||||||
password = ''.join(random.choice(numbers) for _ in range(length)) # (2)
|
password = ''.join(random.choice(numbers) for _ in range(length)) # (2)
|
||||||
|
@ -370,10 +378,37 @@ class Bot(discord.Client):
|
||||||
finally:
|
finally:
|
||||||
cursor.close()
|
cursor.close()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
async def timeout_notify(self, **kwargs):
|
||||||
|
try:
|
||||||
|
pc_number = kwargs["pc_number"]
|
||||||
|
discord_display_name = kwargs["discord_display_name"]
|
||||||
|
|
||||||
|
await self.get_channel(dislocker.server_config["bot"]["log_channel_id"]).send(f':negative_squared_cross_mark: {discord_display_name} さんのPC {pc_number} の使用登録はタイムアウトにより解除されました。')
|
||||||
|
result = {"result": "ok"}
|
||||||
|
|
||||||
|
except Exception as error:
|
||||||
|
print("自動停止処理中にエラーが発生しました。\nエラー内容")
|
||||||
|
print(str(error.__class__.__name__))
|
||||||
|
print(str(error.args))
|
||||||
|
print(str(error))
|
||||||
|
result = {"result": "error"}
|
||||||
|
|
||||||
|
finally:
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
async def on_ready(self):
|
async def on_ready(self):
|
||||||
print("DiscordのBotが起動しました。")
|
print("DiscordのBotが起動しました。")
|
||||||
|
|
||||||
|
async def on_interaction(self, interaction:discord.Interaction):
|
||||||
|
try:
|
||||||
|
if interaction.data["component_type"] == 2:
|
||||||
|
await self.on_button(interaction)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
async def on_message(self, message):
|
async def on_message(self, message):
|
||||||
if message.author.bot:
|
if message.author.bot:
|
||||||
pass
|
pass
|
||||||
|
@ -490,6 +525,29 @@ class Bot(discord.Client):
|
||||||
else:
|
else:
|
||||||
await message.channel.send("# :warning: PCを登録できませんでした。\n構文が間違っています。\n-# /pcregister PC番号")
|
await message.channel.send("# :warning: PCを登録できませんでした。\n構文が間違っています。\n-# /pcregister PC番号")
|
||||||
|
|
||||||
|
elif msg_split[0] == "/registerbutton":
|
||||||
|
pc_button_view = View(timeout=None)
|
||||||
|
for i in range(1, 11):
|
||||||
|
pc_register_button = discord.ui.Button(style=discord.ButtonStyle.primary, label=f"{i}", custom_id=f"pcregister_{i}")
|
||||||
|
pc_button_view.add_item(pc_register_button)
|
||||||
|
|
||||||
|
await self.get_channel(dislocker.server_config["bot"]["config_public_channel_id"]).send(f'# :index_pointing_at_the_viewer: 使いたいPCの番号を選んでください!', view=pc_button_view)
|
||||||
|
|
||||||
|
elif msg_split[0] == "/stopbutton":
|
||||||
|
stop_button_view = View(timeout=None)
|
||||||
|
stop_button = discord.ui.Button(style=discord.ButtonStyle.danger, label="PCの使用を停止", custom_id="stop")
|
||||||
|
stop_button_view.add_item(stop_button)
|
||||||
|
|
||||||
|
await self.get_channel(dislocker.server_config["bot"]["config_public_channel_id"]).send(f'# :index_pointing_at_the_viewer: 使用を停止しますか?', view=stop_button_view)
|
||||||
|
|
||||||
|
elif msg_split[0] == "/userbutton":
|
||||||
|
user_register_button_view = View(timeout=None)
|
||||||
|
user_register_button = discord.ui.Button(style=discord.ButtonStyle.green, label="ユーザー登録", custom_id="user_register")
|
||||||
|
user_register_button_view.add_item(user_register_button)
|
||||||
|
|
||||||
|
await self.get_channel(dislocker.server_config["bot"]["config_public_channel_id"]).send(f'# :index_pointing_at_the_viewer: ユーザー登録はお済ですか?', view=user_register_button_view)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
elif message.channel.id == dislocker.server_config["bot"]["config_public_channel_id"]:
|
elif message.channel.id == dislocker.server_config["bot"]["config_public_channel_id"]:
|
||||||
msg_split = message.content.split()
|
msg_split = message.content.split()
|
||||||
|
@ -507,6 +565,174 @@ class Bot(discord.Client):
|
||||||
else:
|
else:
|
||||||
await message.channel.send("# :skull_crossbones: 登録できませんでした。\n\n-# もしかして...\n-# 手動でメンバーを登録したいですか?\n-# もしそうなら、このチャンネルにはその権限がありません。\n-# そのチャンネルに移動してから、もう一度試してみてください!")
|
await message.channel.send("# :skull_crossbones: 登録できませんでした。\n\n-# もしかして...\n-# 手動でメンバーを登録したいですか?\n-# もしそうなら、このチャンネルにはその権限がありません。\n-# そのチャンネルに移動してから、もう一度試してみてください!")
|
||||||
|
|
||||||
|
async def on_button(self, interaction: Interaction):
|
||||||
|
custom_id = interaction.data["custom_id"]
|
||||||
|
custom_id_split = custom_id.split("_")
|
||||||
|
print(custom_id, custom_id_split[0])
|
||||||
|
|
||||||
|
if custom_id_split[0] == "pcregister":
|
||||||
|
device_register_view = View(timeout=15)
|
||||||
|
pc_number = custom_id_split[1]
|
||||||
|
print(custom_id_split)
|
||||||
|
for i in range(1, 20):
|
||||||
|
device_register_button = discord.ui.Button(style=discord.ButtonStyle.primary, label=f"{i}", custom_id=f"deviceregister_{str(pc_number)}_{i}")
|
||||||
|
device_register_view.add_item(device_register_button)
|
||||||
|
|
||||||
|
await interaction.response.send_message(f"# :keyboard: デバイス番号を選んでください!\n>>> # PC番号 | {str(pc_number)}", view=device_register_view, ephemeral=True)
|
||||||
|
|
||||||
|
elif custom_id_split[0] == "deviceregister":
|
||||||
|
pc_number = custom_id_split[1]
|
||||||
|
device_number = custom_id_split[2]
|
||||||
|
reason_register_view = View(timeout=15)
|
||||||
|
reason_button = discord.ui.Button(style=discord.ButtonStyle.primary, label="使用目的を入力する", custom_id=f"reasonregister_{str(pc_number)}_{str(device_number)}")
|
||||||
|
reason_register_view.add_item(reason_button)
|
||||||
|
|
||||||
|
await interaction.response.send_message(f"# :regional_indicator_q: 使用目的を書いてください!\n>>> # PC番号 | {str(pc_number)}\n# デバイス番号 | {str(device_number)}", view=reason_register_view, ephemeral=True)
|
||||||
|
|
||||||
|
elif custom_id_split[0] == "reasonregister":
|
||||||
|
pc_number = custom_id_split[1]
|
||||||
|
device_number = custom_id_split[2]
|
||||||
|
reason_input_form = Reason(title="Dislocker | 登録", pc_number=str(pc_number), device_number=str(device_number))
|
||||||
|
await interaction.response.send_modal(reason_input_form)
|
||||||
|
|
||||||
|
elif custom_id_split[0] == "stop":
|
||||||
|
print("STOP running")
|
||||||
|
pc_stop = self.stop(user_id=interaction.user.id)
|
||||||
|
print(pc_stop)
|
||||||
|
stop_view = View(timeout=15)
|
||||||
|
if pc_stop["result"] == "unused":
|
||||||
|
await interaction.response.send_message("# :shaking_face: 使用されていないようです...", ephemeral=True)
|
||||||
|
elif pc_stop["result"] == "ok":
|
||||||
|
await interaction.response.send_message(f":white_check_mark: PC番号 {pc_stop["pc_number"]} の使用が終了されました。", ephemeral=True)
|
||||||
|
await self.get_channel(dislocker.server_config["bot"]["log_channel_id"]).send(f':negative_squared_cross_mark: {pc_stop["name"]} さんがPC {pc_stop["pc_number"]} の使用を終了しました。')
|
||||||
|
else:
|
||||||
|
await interaction.response.send_message("# :skull_crossbones: 停止できませんでした。\n内部エラーが発生しています。", ephemeral=True)
|
||||||
|
|
||||||
|
elif custom_id_split[0] == "user" and custom_id_split[1] == "register":
|
||||||
|
print("User Register RUnning")
|
||||||
|
user_register = self.user_register(name=interaction.user.display_name, discord_user_name=interaction.user.name, discord_user_id=interaction.user.id)
|
||||||
|
if user_register["result"] == "ok":
|
||||||
|
await interaction.response.send_message(f"# :white_check_mark: ユーザー情報が登録されました。\n>>> ユーザー名:{interaction.user.display_name}", ephemeral=True)
|
||||||
|
elif user_register["result"] == "already_exists":
|
||||||
|
await interaction.response.send_message("# :no_entry: 登録できませんでした。\nもう登録されている可能性があります。", ephemeral=True)
|
||||||
|
else:
|
||||||
|
await interaction.response.send_message("# :no_entry: 登録できませんでした。\n内部エラーが発生しています。", ephemeral=True)
|
||||||
|
|
||||||
|
class Monitor():
|
||||||
|
def __init__(self) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def start(self, **kwargs):
|
||||||
|
self.serach_time = kwargs["search_time"]
|
||||||
|
self.allowable_time = kwargs["allowable_time"]
|
||||||
|
serach_thread = threading.Thread(target=self.search)
|
||||||
|
serach_thread.start()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def search(self):
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
cursor = dislocker.db.cursor()
|
||||||
|
cursor.execute("SELECT * FROM pc_list WHERE password_hash IS NOT NULL")
|
||||||
|
pc_list = cursor.fetchall()
|
||||||
|
print(pc_list)
|
||||||
|
print(len(pc_list))
|
||||||
|
if pc_list:
|
||||||
|
if len(pc_list) == 1:
|
||||||
|
user_id = pc_list[0][1]
|
||||||
|
cursor.execute("SELECT * FROM pc_usage_history WHERE member_id= %s AND end_use_time IS NULL ORDER BY id DESC LIMIT 1", (user_id,))
|
||||||
|
pc_usage = cursor.fetchall()
|
||||||
|
print(pc_usage)
|
||||||
|
start_time = pc_usage[0][4]
|
||||||
|
print(start_time)
|
||||||
|
print(type(start_time))
|
||||||
|
current_time = datetime.now()
|
||||||
|
time_difference = current_time - start_time
|
||||||
|
if time_difference >= timedelta(seconds=self.allowable_time):
|
||||||
|
cursor.execute("SELECT * FROM club_member WHERE id = %s", (user_id,))
|
||||||
|
user_info = cursor.fetchall()
|
||||||
|
stop = bot.stop(user_id=user_info[0][3])
|
||||||
|
|
||||||
|
bot.timeout_notify(pc_number=pc_list[0][0], discord_display_name=user_info[0][1])
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
|
elif len(pc_list) >= 2:
|
||||||
|
for i in pc_list:
|
||||||
|
print(i)
|
||||||
|
user_id = i[1]
|
||||||
|
cursor.execute("SELECT * FROM pc_usage_history WHERE member_id= %s AND end_use_time IS NULL ORDER BY id DESC LIMIT 1", (user_id,))
|
||||||
|
pc_usage = cursor.fetchall()
|
||||||
|
print(pc_usage)
|
||||||
|
start_time = pc_usage[0][4]
|
||||||
|
print(start_time)
|
||||||
|
print(type(start_time))
|
||||||
|
current_time = datetime.now()
|
||||||
|
time_difference = current_time - start_time
|
||||||
|
if time_difference >= timedelta(seconds=self.allowable_time):
|
||||||
|
cursor.execute("SELECT * FROM club_member WHERE id = %s", (user_id,))
|
||||||
|
user_info = cursor.fetchall()
|
||||||
|
stop = bot.stop(user_id=user_info[0][3])
|
||||||
|
|
||||||
|
bot.timeout_notify(pc_number=i[0], discord_display_name=user_info[0][1])
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
else:
|
||||||
|
result = {"result": "NONE"}
|
||||||
|
else:
|
||||||
|
result = {"result": "NONE"}
|
||||||
|
|
||||||
|
cursor.close()
|
||||||
|
|
||||||
|
print(result["result"])
|
||||||
|
time.sleep(self.serach_time)
|
||||||
|
|
||||||
|
except Exception as error:
|
||||||
|
print("自動停止処理中にエラーが発生しました。\nエラー内容")
|
||||||
|
print(str(error.__class__.__name__))
|
||||||
|
print(str(error.args))
|
||||||
|
print(str(error))
|
||||||
|
result = {"result": "error"}
|
||||||
|
dislocker.db.rollback()
|
||||||
|
|
||||||
|
finally:
|
||||||
|
cursor.close()
|
||||||
|
print(result["result"])
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Reason(Modal):
|
||||||
|
def __init__(self, title: str, pc_number: str, device_number: str, timeout=15) -> None:
|
||||||
|
super().__init__(title=title, timeout=timeout)
|
||||||
|
print(pc_number)
|
||||||
|
print(device_number)
|
||||||
|
self.reason_input_form = TextInput(label="使用目的を入力してください", style=TextStyle.short, custom_id=f"register_{pc_number}_{device_number}")
|
||||||
|
self.add_item(self.reason_input_form)
|
||||||
|
|
||||||
|
async def on_submit(self, interaction: Interaction) -> None:
|
||||||
|
custom_id = interaction.data["components"][0]["components"][0]["custom_id"]
|
||||||
|
print(custom_id)
|
||||||
|
custom_id_split = custom_id.split("_")
|
||||||
|
pc_number = custom_id_split[1]
|
||||||
|
device_number = custom_id_split[2]
|
||||||
|
register = bot.register(user_id=interaction.user.id, name=interaction.user.name, display_name=interaction.user.display_name, pc_number=pc_number, device_number=device_number, detail=self.reason_input_form.value)
|
||||||
|
print(register["result"])
|
||||||
|
|
||||||
|
if register["result"] == "ok":
|
||||||
|
await interaction.response.send_message(f":white_check_mark: 使用が開始されました。\n>>> # パスワード | {register["password"]}\n## PC番号 | {pc_number}\n## デバイス番号 | {device_number}\n## 使用目的 | {self.reason_input_form.value}", ephemeral=True)
|
||||||
|
await bot.get_channel(dislocker.server_config["bot"]["log_channel_id"]).send(f':white_check_mark: {register["name"]} さんがPC {pc_number} の使用を開始しました。')
|
||||||
|
elif register["result"] == "pc_already_in_use_by_you":
|
||||||
|
await interaction.response.send_message(f"# :exploding_head: あなたはPCをもう使用されているようです。\n使用状態を解除するには 終了ボタン で使用終了をお知らせください。\n>>> # PC番号 | {register["pc_number"]}\n# デバイス番号 | {register["device_number"]}\n# 使用開始時刻 | {register["start_time"]}\n# 使用目的 | {register["detail"]}", ephemeral=True)
|
||||||
|
elif register["result"] == "pc_already_in_use_by_other":
|
||||||
|
await interaction.response.send_message(f"# :man_gesturing_no: そのPCは他のメンバーによって使用されています。\n別のPC番号を指定して、再度お試しください。", ephemeral=True)
|
||||||
|
elif register["result"] == "user_data_not_found":
|
||||||
|
await interaction.response.send_message("# :dizzy_face: ユーザーとして登録されていないようです。\n最初にサーバーで登録を行ってください。", ephemeral=True)
|
||||||
|
else:
|
||||||
|
await interaction.response.send_message("# :skull_crossbones: 登録できませんでした。\n内部エラーが発生しています。", ephemeral=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dislocker = DL()
|
dislocker = DL()
|
||||||
if dislocker.init_result == "ok":
|
if dislocker.init_result == "ok":
|
||||||
|
@ -514,6 +740,8 @@ if dislocker.init_result == "ok":
|
||||||
intents = discord.Intents.default()
|
intents = discord.Intents.default()
|
||||||
intents.message_content = True
|
intents.message_content = True
|
||||||
bot = Bot(intents=intents)
|
bot = Bot(intents=intents)
|
||||||
|
monitor = Monitor()
|
||||||
|
monitor.start(search_time=10, allowable_time=30)
|
||||||
bot.run(dislocker.server_config['bot']['token'])
|
bot.run(dislocker.server_config['bot']['token'])
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
Loading…
Reference in a new issue