11import database
22from ai_brain import get_json_data_from_text
3+ import time
4+
5+ # Dictionary untuk menyimpan timestamp pemrosesan AI terakhir per user (Rate Limiting)
6+ last_ai_calls = {}
7+ RATE_LIMIT_COOLDOWN = 10 # detik
38
49def register_handlers (bot ):
510 # Gunakan lambda yang menangkap semua teks, tapi pastikan bukan command
@@ -20,44 +25,85 @@ def handle_text(message):
2025 # Show typing status while processing
2126 bot .send_chat_action (message .chat .id , 'typing' )
2227
28+ # --- RATE LIMITING CHECK ---
29+ now = time .time ()
30+ if user_id in last_ai_calls :
31+ elapsed = now - last_ai_calls [user_id ]
32+ if elapsed < RATE_LIMIT_COOLDOWN :
33+ remaining = int (RATE_LIMIT_COOLDOWN - elapsed )
34+ bot .reply_to (message , f"⚠️ *Terlalu cepat!* Mohon tunggu { remaining } detik lagi sebelum mencatat transaksi baru... 🙏" , parse_mode = 'Markdown' )
35+ return
36+
37+ # Update timestamp pemrosesan terakhir
38+ last_ai_calls [user_id ] = now
39+
2340 # Process text with AI
24- data = get_json_data_from_text (text )
41+ results = get_json_data_from_text (text )
2542
26- if data .get ("error" ):
43+ # Jika hasil bukan list (misal {"error": true}), handle error
44+ if isinstance (results , dict ) and results .get ("error" ):
2745 bot .reply_to (message , "❌ Maaf, saya tidak menangkap adanya transaksi keuangan. Pastikan formatnya jelas (contoh: 'beli makan 20rb' atau 'gajian 4 juta')." )
2846 return
2947
30- tipe = data .get ("tipe" , "" ).lower ()
31- item = data .get ("item" , "" )
32- nominal = float (data .get ("nominal" , 0 ))
33- kategori = data .get ("kategori" , "" )
48+ success_count = 0
49+ summary_lines = []
3450
35- # Save to database based on type
3651 try :
37- # Sekarang hanya fokus pada pemasukan, pengeluaran, dan investasi
38- if tipe in ["pemasukan" , "pengeluaran" , "investasi" ]:
39- last_id = database .insert_transaction (user_id , tipe , item , nominal , kategori )
52+ for data in results :
53+ tipe = data .get ("tipe" , "" ).lower ()
54+ item = data .get ("item" , "" )
55+ nominal = float (data .get ("nominal" , 0 ))
56+ kategori = data .get ("kategori" , "" )
4057
41- if tipe == "pemasukan" :
42- icon = "🟢"
43- elif tipe == "investasi" :
44- icon = "🔵"
45- else :
46- icon = "🔴"
47-
48- reply = (
49- f"{ icon } *Berhasil dicatat!*\n \n "
50- f"🔹 *Tipe:* { tipe .capitalize ()} \n "
51- f"🔹 *Item:* { item } \n "
52- f"🔹 *Nominal:* Rp { nominal :,.0f} \n "
53- f"🔹 *Kategori:* { kategori .replace ('_' , ' ' ).capitalize ()} \n \n "
54- f"🆔 *ID:* `T-{ last_id } `"
55- )
58+ # Save to database based on type
59+ try :
60+ if tipe == "saldo" :
61+ # Reconcile balance
62+ current_balance = database .get_user_balance (user_id )
63+ diff = nominal - current_balance
64+
65+ if diff == 0 :
66+ summary_lines .append (f"💰 *Saldo:* Sudah sesuai di angka Rp { nominal :,.0f} " )
67+ success_count += 1
68+ continue
69+
70+ # Determine if reconciliation is income or expense
71+ rec_tipe = "pemasukan" if diff > 0 else "pengeluaran"
72+ rec_nominal = abs (diff )
73+ rec_item = "Penyesuaian Saldo"
74+
75+ last_id = database .insert_transaction (user_id , rec_tipe , rec_item , rec_nominal , "lainnya" )
76+
77+ icon = "💰"
78+ summary_lines .append (
79+ f"{ icon } *Saldo disesuaikan:* Rp { current_balance :,.0f} ➔ Rp { nominal :,.0f} (`T-{ last_id } `)"
80+ )
81+ success_count += 1
82+
83+ elif tipe in ["pemasukan" , "pengeluaran" , "investasi" ]:
84+ last_id = database .insert_transaction (user_id , tipe , item , nominal , kategori )
85+
86+ if tipe == "pemasukan" :
87+ icon = "🟢"
88+ elif tipe == "investasi" :
89+ icon = "🔵"
90+ else :
91+ icon = "🔴"
92+
93+ summary_lines .append (
94+ f"{ icon } *{ tipe .capitalize ()} :* { item } — Rp { nominal :,.0f} (`T-{ last_id } `)"
95+ )
96+ success_count += 1
97+ except Exception as e :
98+ print (f"Error inserting transaction: { e } " )
99+
100+ if success_count > 0 :
101+ reply = "✅ *Berhasil mencatat " + (f"{ success_count } transaksi" if success_count > 1 else "transaksi" ) + ":*\n \n "
102+ reply += "\n " .join (summary_lines )
56103 bot .reply_to (message , reply , parse_mode = 'Markdown' )
57-
58104 else :
59- bot .reply_to (message , "❌ Tipe data tidak dikenali dari hasil AI . Pastikan AI mengembalikan format yang benar." )
60-
105+ bot .reply_to (message , "❌ Gagal mencatat transaksi . Pastikan format pesan sudah benar." )
106+
61107 except Exception as e :
62108 print (f"Error in handle_text: { e } " )
63109 bot .reply_to (message , "❌ Terjadi kesalahan sistem saat memproses permintaan Anda. Silakan coba lagi nanti." )
0 commit comments