Skip to content

Commit eff733f

Browse files
committed
refactor(autobuy): use numeric quota and refine tracking to prevent unintended purchases
1 parent 66f538a commit eff733f

File tree

2 files changed

+73
-31
lines changed

2 files changed

+73
-31
lines changed

bot/autobuy.go

Lines changed: 59 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212

1313
"telkomsel-bot/otp"
1414
"telkomsel-bot/telkomsel"
15-
"telkomsel-bot/util"
1615
)
1716

1817
func (h *Handler) cbShowAutoMonitor(b *gotgbot.Bot, chatID, msgID, userID int64) {
@@ -66,7 +65,7 @@ func (h *Handler) cbSetAutoThreshold(b *gotgbot.Bot, chatID, msgID, userID int64
6665
}
6766

6867
h.editMsg(b, chatID, msgID, "⏳ Mengambil rekomendasi paket...", nil)
69-
68+
7069
apiCtx := context.Background()
7170
offers, _ := h.api.GetRecommendedOffers(apiCtx, session)
7271

@@ -225,8 +224,8 @@ func (h *Handler) runAutoBuyMonitor(ctx context.Context, b *gotgbot.Bot, chatID,
225224
needsBuy := false
226225
var matchedOrderID string
227226

227+
var trackedItem *telkomsel.QuotaItem
228228
if session.AutoBuyOrderID != "" {
229-
var trackedItem *telkomsel.QuotaItem
230229
for _, group := range quota.Groups {
231230
for _, item := range group.Items {
232231
if item.OrderID == session.AutoBuyOrderID {
@@ -240,41 +239,76 @@ func (h *Handler) runAutoBuyMonitor(ctx context.Context, b *gotgbot.Bot, chatID,
240239
break
241240
}
242241
}
242+
}
243243

244-
if trackedItem == nil {
245-
log.Printf("[AutoBuy] Tracked OrderID %s not found for user %d. Assuming depleted.", session.AutoBuyOrderID, userID)
244+
if trackedItem != nil {
245+
log.Printf("[AutoBuy] Tracked OrderID %s found for user %d: %.2f MB remaining", session.AutoBuyOrderID, userID, trackedItem.RemainingValue)
246+
if trackedItem.RemainingValue <= float64(session.AutoBuyThreshold) {
247+
log.Printf("[AutoBuy] Tracked quota (%.2f MB) <= threshold (%d MB) for user %d", trackedItem.RemainingValue, session.AutoBuyThreshold, userID)
246248
needsBuy = true
247-
} else {
248-
log.Printf("[AutoBuy] Tracked OrderID %s found for user %d: %s remaining", session.AutoBuyOrderID, userID, trackedItem.Remaining)
249-
if util.ParseQuotaToMB(trackedItem.Remaining) <= float64(session.AutoBuyThreshold) {
250-
needsBuy = true
251-
}
252249
}
253250
} else {
251+
if session.AutoBuyOrderID != "" {
252+
log.Printf("[AutoBuy] Tracked OrderID %s not found for user %d. Falling back to class tracking.", session.AutoBuyOrderID, userID)
253+
session.AutoBuyOrderID = ""
254+
}
255+
254256
var totalTargetQuota float64
255257
hasTargetGroup := false
256-
258+
257259
targetClass := "Internet"
258260
if session.AutoBuyPackage == "ilmupedia" || offerID == "" {
259261
targetClass = "ENTERTAINMENT"
260262
}
261263

262264
for _, group := range quota.Groups {
263-
if strings.EqualFold(group.Class, targetClass) {
264-
for _, item := range group.Items {
265-
if targetClass == "ENTERTAINMENT" && !strings.Contains(strings.ToLower(item.Name), "belajar") {
265+
isGroupTarget := strings.EqualFold(group.Class, targetClass)
266+
if !isGroupTarget && targetClass == "Internet" && strings.Contains(strings.ToLower(group.Class), "internet") {
267+
isGroupTarget = true
268+
}
269+
270+
for _, item := range group.Items {
271+
if targetClass == "ENTERTAINMENT" {
272+
if !strings.EqualFold(group.Class, "ENTERTAINMENT") {
273+
continue
274+
}
275+
if !strings.Contains(strings.ToLower(item.Name), "belajar") {
266276
continue
267277
}
268-
hasTargetGroup = true
269-
totalTargetQuota += util.ParseQuotaToMB(item.Remaining)
270-
if item.OrderID != "" {
271-
matchedOrderID = item.OrderID
278+
} else {
279+
isItemTarget := isGroupTarget || strings.Contains(strings.ToLower(item.Name), "internet") || strings.Contains(strings.ToLower(item.Name), "flash")
280+
if !isItemTarget {
281+
continue
282+
}
283+
}
284+
285+
hasTargetGroup = true
286+
totalTargetQuota += item.RemainingValue
287+
if item.OrderID != "" {
288+
matchedOrderID = item.OrderID
289+
}
290+
}
291+
}
292+
293+
if !hasTargetGroup && targetClass == "Internet" {
294+
for _, group := range quota.Groups {
295+
if strings.EqualFold(group.Class, "ENTERTAINMENT") {
296+
for _, item := range group.Items {
297+
hasTargetGroup = true
298+
totalTargetQuota += item.RemainingValue
272299
}
273300
}
274301
}
302+
if hasTargetGroup {
303+
log.Printf("[AutoBuy] User %d has 0 Internet quota but has %.2f MB Entertainment quota. Falling back to tracking Entertainment.", userID, totalTargetQuota)
304+
}
275305
}
276306

277-
if !hasTargetGroup || totalTargetQuota <= float64(session.AutoBuyThreshold) {
307+
if !hasTargetGroup {
308+
log.Printf("[AutoBuy] No target quota (%s) found for user %d. Assuming depleted.", targetClass, userID)
309+
needsBuy = true
310+
} else if totalTargetQuota <= float64(session.AutoBuyThreshold) {
311+
log.Printf("[AutoBuy] Total target quota (%.2f MB) <= threshold (%d MB) for user %d", totalTargetQuota, session.AutoBuyThreshold, userID)
278312
needsBuy = true
279313
} else {
280314
if matchedOrderID != "" {
@@ -285,13 +319,18 @@ func (h *Handler) runAutoBuyMonitor(ctx context.Context, b *gotgbot.Bot, chatID,
285319
}
286320
}
287321

322+
// Commenting out airtime expiry trigger since it causes unintended quota purchases
323+
// when user only wants to monitor quota limit.
324+
/*
288325
_, expiry, balErr := h.api.GetBalance(apiCtx, session)
289326
if balErr == nil && expiry != "" {
290327
expiryTime, parseErr := time.Parse("2006-01-02", expiry)
291328
if parseErr == nil && time.Now().After(expiryTime) {
292-
needsBuy = true
329+
log.Printf("[AutoBuy] Airtime expired (%s) for user %d, triggering purchase", expiry, userID)
330+
// needsBuy = true -> disabled specifically so threshold works
293331
}
294332
}
333+
*/
295334

296335
if !needsBuy {
297336
log.Printf("[AutoBuy] Quota OK for user %d, skipping purchase", userID)

telkomsel/quota.go

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import (
1111
type BonusItem struct {
1212
Name string `json:"name"`
1313
BucketDesc string `json:"bucketdescription"`
14-
RemainingQuota string `json:"remainingquota"`
15-
ExpiryDate string `json:"expirydate"`
16-
OrderID string `json:"order_id"`
14+
RemainingQuota string `json:"remainingquota"`
15+
RemainingQuotaValue float64 `json:"remainingquotaValue"`
16+
ExpiryDate string `json:"expirydate"`
17+
OrderID string `json:"order_id"`
1718
}
1819

1920
type BonusGroup struct {
@@ -38,10 +39,11 @@ type QuotaGroup struct {
3839
}
3940

4041
type QuotaItem struct {
41-
Name string
42-
Remaining string
43-
Expiry string
44-
OrderID string
42+
Name string
43+
Remaining string
44+
RemainingValue float64
45+
Expiry string
46+
OrderID string
4547
}
4648

4749
func (c *Client) CheckQuota(ctx context.Context, session *model.Session) (*QuotaInfo, error) {
@@ -77,10 +79,11 @@ func (c *Client) CheckQuota(ctx context.Context, session *model.Session) (*Quota
7779
name = item.BucketDesc
7880
}
7981
group.Items = append(group.Items, QuotaItem{
80-
Name: name,
81-
Remaining: item.RemainingQuota,
82-
Expiry: item.ExpiryDate,
83-
OrderID: item.OrderID,
82+
Name: name,
83+
Remaining: item.RemainingQuota,
84+
RemainingValue: item.RemainingQuotaValue,
85+
Expiry: item.ExpiryDate,
86+
OrderID: item.OrderID,
8487
})
8588
}
8689
info.Groups = append(info.Groups, group)

0 commit comments

Comments
 (0)