Geophysics_class / core /callbacks.py
cwadayi's picture
Upload 8 files
57b8366 verified
raw
history blame
3.59 kB
# core/callbacks.py
import io
import contextlib
import traceback
from datetime import datetime
import pytz
from core.visits import get_current_visit_count
from core.notifications import send_line_notification_in_background
from config.data import KNOWLEDGE_BASE
def execute_user_code(code_string, source_lab):
"""Executes user-provided code in a restricted environment and sends a notification."""
string_io = io.StringIO()
status = "✅ 成功"
error_info = ""
fig = None
try:
with contextlib.redirect_stdout(string_io):
local_scope = {}
# Pre-import necessary libraries for the user's code
exec("import matplotlib.pyplot as plt; import numpy as np; import cartopy.crs as ccrs; import cartopy.feature as cfeature; from matplotlib.ticker import FixedFormatter", local_scope)
exec(code_string, local_scope)
console_output = string_io.getvalue()
fig = local_scope.get('fig')
if fig is None:
status = "⚠️ 警告"
error_info = "程式碼執行完畢,但未找到 'fig' 物件。"
return None, f"{error_info}\nPrint 輸出:\n{console_output}"
success_message = f"✅ 程式碼執行成功!\n\n--- Console Output ---\n{console_output}"
return fig, success_message
except Exception:
status = "❌ 失敗"
error_info = traceback.format_exc()
final_message = f"❌ 程式碼執行失敗!\n\n--- Error Traceback ---\n{error_info}"
return None, final_message
finally:
# This block will always run, regardless of success or failure
tz = pytz.timezone('Asia/Taipei')
current_time = datetime.now(tz).strftime('%H:%M:%S')
visit_count = get_current_visit_count()
notification_text = (
f"🔬 程式碼實驗室互動!\n\n"
f"時間: {current_time}\n"
f"實驗室: {source_lab}\n"
f"執行狀態: {status}\n"
f"總載入數: {visit_count}"
)
if status == "❌ 失敗":
# Add specific error type to notification for quick debugging
error_type = error_info.strip().split('\n')[-1]
notification_text += f"\n錯誤類型: {error_type}"
send_line_notification_in_background(notification_text)
def ai_chatbot_with_kb(message, history):
"""Handles chatbot interaction, queries the knowledge base, and sends a notification."""
# Send notification in the background
tz = pytz.timezone('Asia/Taipei')
current_time = datetime.now(tz).strftime('%H:%M:%S')
visit_count = get_current_visit_count()
notification_text = (
f"🤖 AI 助教被提問!\n\n"
f"時間: {current_time}\n"
f"使用者問題:\n「{message}」\n\n"
f"總載入數: {visit_count}"
)
send_line_notification_in_background(notification_text)
# Perform knowledge base lookup
user_message = message.lower().strip()
for item in KNOWLEDGE_BASE:
for keyword in item['keywords']:
if keyword in user_message:
return item['answer']
# Default response if no keyword is matched
return "這個問題很有趣,不過我的知識庫目前還沒有收錄相關的答案。您可以試著問我關於**課程評分、Anaconda安裝、Colab與Codespaces的差別、什麼是API,或者期末專題的靈感**等問題!"