-
Notifications
You must be signed in to change notification settings - Fork 31
Expand file tree
/
Copy pathcallback_queue_handler.py
More file actions
118 lines (103 loc) · 5.47 KB
/
Copy pathcallback_queue_handler.py
File metadata and controls
118 lines (103 loc) · 5.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# ==========================================================
# FILE: callback_queue_handler.py
# ==========================================================
# 🚨 MODIFIED: [V-REV LIFO 지층 제어 전담 도메인] 큐 장부 조작 로직 분리
# 🚨 MODIFIED: [Case 08, 14, 25, 26 절대 헌법 준수] 동기식 파일 스캔(os.path.exists) 배제 및 html.escape 쉴드 전역 결속 완료
# ==========================================================
import logging
import asyncio
import html
from telegram import Update
from telegram.ext import ContextTypes
class CallbackQueueHandler:
def __init__(self, config, queue_ledger, sync_engine, view):
self.cfg = config
self.queue_ledger = queue_ledger
self.sync_engine = sync_engine
self.view = view
async def handle(self, update: Update, context: ContextTypes.DEFAULT_TYPE, controller, action: str, sub: str, data: list):
query = update.callback_query
chat_id = update.effective_chat.id
if action == "QUEUE":
try:
await query.answer()
except Exception:
pass
if sub == "VIEW":
ticker = data[2] if len(data) > 2 else ""
if getattr(self, 'queue_ledger', None) and ticker:
q_data = await asyncio.to_thread(self.queue_ledger.get_queue, ticker) or []
else:
q_data = []
msg, markup = self.view.get_queue_management_menu(ticker, q_data)
try:
await query.edit_message_text(msg, reply_markup=markup, parse_mode='HTML')
except Exception:
pass
elif action == "DEL_REQ":
try:
await query.answer()
except Exception:
pass
ticker = sub
target_date = ":".join(data[2:])
if getattr(self, 'queue_ledger', None):
q_data = await asyncio.to_thread(self.queue_ledger.get_queue, ticker) or []
else:
q_data = []
qty, price = 0, 0.0
for item in q_data:
if isinstance(item, dict) and item.get('date') == target_date:
qty = int(float(str(item.get('qty') or 0).replace(',', '')))
price = float(str(item.get('price') or 0.0).replace(',', ''))
break
msg, markup = self.view.get_queue_action_confirm_menu(ticker, target_date, qty, price)
try:
await query.edit_message_text(msg, reply_markup=markup, parse_mode='HTML')
except Exception:
pass
elif action in ["DEL_Q", "EDIT_Q"]:
ticker = sub
target_date = ":".join(data[2:])
try:
if action == "DEL_Q":
if getattr(self, 'queue_ledger', None):
await asyncio.to_thread(self.queue_ledger.delete_lot, ticker, target_date)
try:
await query.answer("✅ 지층 삭제 완료. KIS 원장과 동기화합니다.", show_alert=False)
except Exception:
pass
if ticker not in self.sync_engine.sync_locks:
self.sync_engine.sync_locks[ticker] = asyncio.Lock()
if not self.sync_engine.sync_locks[ticker].locked():
await self.sync_engine.process_auto_sync(ticker, chat_id, context, silent_ledger=True)
final_q = await asyncio.to_thread(self.queue_ledger.get_queue, ticker) if getattr(self, 'queue_ledger', None) else []
final_q = final_q or []
msg, markup = self.view.get_queue_management_menu(ticker, final_q)
try:
await query.edit_message_text(msg, reply_markup=markup, parse_mode='HTML')
except Exception:
pass
elif action == "EDIT_Q":
try:
await query.answer("✏️ 수정 모드 진입", show_alert=False)
except Exception:
pass
short_date = html.escape(str(target_date)[:10]) if len(str(target_date)) >= 10 else html.escape(str(target_date))
safe_ticker = html.escape(str(ticker))
controller.user_states[chat_id] = f"EDITQ_{ticker}_{target_date}"
prompt = f"✏️ <b>[{safe_ticker} 지층 수정 모드]</b>\n"
prompt += f"선택하신 <b>[{short_date}]</b> 지층을 재설정합니다.\n\n"
prompt += "새로운 <b>[수량]</b>과 <b>[평단가]</b>를 띄어쓰기로 입력하세요.\n"
prompt += "(예: <code>229 52.16</code>)\n\n"
prompt += "<i>(입력을 취소하려면 숫자 이외의 문자를 보내주세요)</i>"
try:
await query.edit_message_text(prompt, parse_mode='HTML')
except Exception:
pass
except Exception as e:
safe_err = html.escape(str(e))
try:
await query.answer(f"❌ 처리 중 에러 발생: {safe_err}", show_alert=True)
except Exception:
pass