diff --git a/bot.go b/bot.go index 7031183..8e006ce 100644 --- a/bot.go +++ b/bot.go @@ -966,7 +966,7 @@ func botGWithdraw(m *tb.Message) { p := JobPayloadGWithdraw{ MsgID64: int64(m.ID), ChatID64: m.Chat.ID, - User: m.Sender.Username, + UserID64: int64(m.Sender.ID), Status: 0, Validated: false, } diff --git a/def.go b/def.go index d051a75..1608998 100644 --- a/def.go +++ b/def.go @@ -413,7 +413,7 @@ type JobPayloadGWithdrawItem struct { type JobPayloadGWithdraw struct { MsgID64 int64 `json:"msg_id"` ChatID64 int64 `json:"chat_id"` - User string `json:"user"` + UserID64 int64 `json:"user_id"` Items []JobPayloadGWithdrawItem `json:"items"` Status int64 `json:"status"` CleanupMsg []ChatWarsMessage `json:"cleanup_msg"` diff --git a/job.go b/job.go index 1be0029..790e29d 100644 --- a/job.go +++ b/job.go @@ -133,6 +133,42 @@ func setJobTimeout(jobID64 int64, d time.Duration) error { return nil } +func setJobPayload(jobID64 int64, payload []byte) error { + var zb bytes.Buffer + + zw := zlib.NewWriter(&zb) + zw.Write(payload) + zw.Close() + zpayload := zb.Bytes() + + if len(zpayload) > 20000 { + return 0, errors.New("payload too long") + } + + stmt, err := db.Prepare(`UPDATE obj_job j SET j.payload = ? WHERE j.obj_id = ?;`) + logOnError(err, "setJobTimeout : prepare update obj_job") + if err != nil { + return err + } + defer stmt.Close() + + _, err = stmt.Exec(zpayload, jobID64) + logOnError(err, fmt.Sprintf("setJobTimeout, update obj_job(%d)", jobID64)) + if err != nil { + return err + } + + muxObjJob.Lock() + j := cacheObjJob[jobID64] + j.Payload = b + cacheObjJob[jobID64] = j + muxObjJob.Unlock() + + log.Printf("setJobPayload[%d] : %s\n", string(payload)) + + return nil +} + func setJobDone(jobID64 int64) error { stmt, err := db.Prepare(`UPDATE obj_job j SET j.is_done = 1, j.in_work = 0, j.ended = ? WHERE j.obj_id = ?;`) logOnError(err, "setJobDone : prepare update obj_job") @@ -1442,30 +1478,95 @@ func jobGWithdraw(j Job) { if j.Trigger != 0 { id, err := getObjSubTypeId(j.Trigger) logOnError(err, "jobGWithdraw : getObjSubType("+strconv.FormatInt(j.Trigger, 10)+")") - if err == nil && id == cacheObjSubType[`msg_gstock_any_ack`] { - m, err := getObjMsg(j.Trigger) - logOnError(err, "jobGWithdraw : getObjMsg") - rule, err := getMsgParsingRule(m) - logOnError(err, "jobGWithdraw : getMsgParsingRule") - cwm, err := parseSubTypeMessageGStockAnyAck(m, rule.re) - logOnError(err, "jobGWithdraw : parseSubTypeMessageGStockAnyAck") + if err == nil { + if id == cacheObjSubType[`msg_gstock_any_ack`] { + m, err := getObjMsg(j.Trigger) + logOnError(err, "jobGWithdraw : getObjMsg") + rule, err := getMsgParsingRule(m) + logOnError(err, "jobGWithdraw : getMsgParsingRule") + cwm, err := parseSubTypeMessageGStockAnyAck(m, rule.re) + logOnError(err, "jobGWithdraw : parseSubTypeMessageGStockAnyAck") - for k, req := range p.Items { - for _, disp := range cwm.Stock { - if req.Code == disp.Code { - p.Items[k].Available = disp.Quantity - p.Items[k].Name = disp.Name - log.Printf("jobGWithdraw[%d] : Found %s - %s : %d.\n", j.ID64, disp.Code, disp.Name, disp.Quantity) + for k, req := range p.Items { + for _, disp := range cwm.Stock { + if req.Code == disp.Code { + p.Items[k].Available = disp.Quantity + p.Items[k].Name = disp.Name + log.Printf("jobGWithdraw[%d] : Found %s - %s : %d.\n", j.ID64, disp.Code, disp.Name, disp.Quantity) + } } } + + p2 := JobPayloadMsgDel{ + Delay: (10 * time.Second), + ObjMsgID64: j.Trigger, + } + b2, _ := json.Marshal(p2) + createJob(cacheObjSubType[`job_msg_del`], objJobPriority, j.UserID64, 0, time.Now().UTC(), b2) } - p2 := JobPayloadMsgDel{ - Delay: (10 * time.Second), - ObjMsgID64: j.Trigger, + if id == cacheObjSubType[`msg_msg_job_gwithdraw_ack`] { + cwm, err := parseSubTypeMessageJobGWithdrawAck(m, rule.re) + logOnError(err, "jobGWithdraw : parseSubTypeMessageJobGWithdrawAck") + in, err := hex.DecodeString(cwm.Ref) + logOnError(err, "msgJobGWithdrawAck : DecodeString") + + sha256 := sha256.Sum256([]byte(cfg.Telegram.Token)) + sha128 := sha256[:aes.BlockSize] + c, err := aes.NewCipher(sha128) + + out := make([]byte, len(in)) + + c.Decrypt(out, in) + id, n := binary.Uvarint(out[:8]) + jobID64 := int64(id) + id, n = binary.Uvarint(out[8:16]) + userID64 := int64(id) + + if jobID64 == j.ID64 { + if userID64 == cwm.Msg.TGSenderUserID64 { + cmd := TGCommand{ + Type: commandReplyMsg, + Text: "You cannot validate your own withdrawl", + FromMsgID64: cwm.Msg.MsgID64, + FromChatID64: cwm.Msg.ChatID64, + } + TGCmdQueue <- cmd + p.CleanupMsg = append(p.CleanupMsg, m) + b, err := json.Marshal(p) + err = setJobPayload(j.ID64, b) + logOnError(err, "jobGWithdraw : setJobPayload") + err = rescheduleJob(j.ID64, 0, time.Unix(maxUnixTimestamp, 0).UTC()) + logOnError(err, "jobGWithdraw : rescheduleJob") + setJobCallback(j.ID64, int64(bot.Me.ID), cacheObjTypeId[`msg_job_gwithdraw_ack`]) + return + } else { + p.Validated = true + for _, d := range p.CleanupMsg { + delmsg := tb.StoredMessage{ + MessageID: fmt.Sprintf("%d", d.MsgID64), + ChatID: d.ChatID64, + } + err = bot.Delete(delmsg) + logOnError(err, "jobGWithdraw : Delete") + } + p.CleanupMsg = []ChatWarsMessage{} + delmsg := tb.StoredMessage{ + MessageID: fmt.Sprintf("%d", cwm.Msg.MsgID64), + ChatID: cwm.Msg.ChatID64, + } + err = bot.Delete(delmsg) + logOnError(err, "jobGWithdraw : Delete") + } + } else { + err = rescheduleJob(j.ID64, 0, time.Unix(maxUnixTimestamp, 0).UTC()) + logOnError(err, "jobGWithdraw : rescheduleJob") + setJobCallback(j.ID64, int64(bot.Me.ID), cacheObjTypeId[`msg_job_gwithdraw_ack`]) + return + } + + return } - b2, _ := json.Marshal(p2) - createJob(cacheObjSubType[`job_msg_del`], objJobPriority, j.UserID64, 0, time.Now().UTC(), b2) } } @@ -1581,6 +1682,7 @@ func jobGWithdraw(j Job) { b, _ := json.Marshal(p) id, err := createJob(cacheObjSubType[`job_gwithdraw`], objJobPriority, j.UserID64, 0, time.Unix(maxUnixTimestamp, 0).UTC(), b) logOnError(err, "jobGWithdraw : createJob") + setJobCallback(id, int64(bot.Me.ID), cacheObjTypeId[`msg_job_gwithdraw_ack`]) sha256 := sha256.Sum256([]byte(cfg.Telegram.Token)) sha128 := sha256[:aes.BlockSize] @@ -1590,7 +1692,7 @@ func jobGWithdraw(j Job) { buf := make([]byte, 8) binary.LittleEndian.PutUint64(buf, uint64(id)) in = append(in, buf...) - binary.LittleEndian.PutUint64(buf, uint64(j.UserID64)) + binary.LittleEndian.PutUint64(buf, uint64(p.UserID64)) in = append(in, buf...) out := make([]byte, len(in)) @@ -1605,7 +1707,10 @@ func jobGWithdraw(j Job) { b, err = json.Marshal(p) log.Printf("jobGWithdraw[%d] : %s\n", string(b)) - msg := fmt.Sprintf("Click to validate @%s's withdrawal of%s\n/withdraw_%s", p.User, stock, string(ref)) + u, err := bot.ChatByID(fmt.Sprintf("%d", p.UserID64)) + logOnError(err, "jobGWithdraw : ChatByID") + + msg := fmt.Sprintf("Click to validate @%s's withdrawal of%s\n/withdraw_%s", u.Username, stock, string(ref)) cmd := TGCommand{ Type: commandReplyMsg, @@ -1633,27 +1738,6 @@ func jobGWithdraw(j Job) { return } -func msgJobGWithdrawAck(cwm *ChatWarsMessageJobGWithdrawAck) error { - in, err := hex.DecodeString(cwm.Ref) - logOnError(err, "msgJobGWithdrawAck : DecodeString") - if err != nil { - return err - } - - sha256 := sha256.Sum256([]byte(cfg.Telegram.Token)) - sha128 := sha256[:aes.BlockSize] - c, err := aes.NewCipher(sha128) - - out := make([]byte, len(in)) - - c.Decrypt(out, in) - ref := hex.EncodeToString(out) - log.Printf("msgJobGWithdrawAck : out string : %s.\n", ref) - - return nil - -} - func jobSetDef(j Job) { var p JobPayloadSetDef err := setJobStart(j.ID64) diff --git a/workers.go b/workers.go index 8e0f41a..8b2f023 100644 --- a/workers.go +++ b/workers.go @@ -506,10 +506,8 @@ func SQLIdentifyMsgWorker(id int, objIds <-chan int64) { err = setClientIdle(m.TGUserID64, m.Date) logOnError(err, "SQLIdentifyMsgWorker["+strconv.Itoa(id)+"] : setClientIdle") case cacheObjSubType[`msg_job_gwithdraw_ack`]: - cwm, err := parseSubTypeMessageJobGWithdrawAck(m, rule.re) + _, err := parseSubTypeMessageJobGWithdrawAck(m, rule.re) logOnError(err, "SQLIdentifyMsgWorker["+strconv.Itoa(id)+"] : Parsing cacheObjSubType[`msg_quest_res`]") - err = msgJobGWithdrawAck(cwm) - logOnError(err, "SQLIdentifyMsgWorker["+strconv.Itoa(id)+"] : msgJobGWithdrawAck") default: //log.Printf("SQLIdentifyMsgWorker["+strconv.Itoa(id)+"] : Unknwon message type in rule %d : %d (%d)\n%s\n", msgParsingRules[i].ID, msgParsingRules[i].MsgTypeID64, objId, m.Text) } @@ -523,6 +521,15 @@ func SQLIdentifyMsgWorker(id int, objIds <-chan int64) { mc1[rule.MsgTypeID64] = nil } } + if mc1, mok1 := callbacks[int64(bot.Me.ID)]; mok1 { + if mc2, mok2 := mc1[rule.MsgTypeID64]; mok2 { + for j := range mc2 { + err := rescheduleJob(mc2[j], m.ObjID64, time.Now().UTC()) + logOnError(err, "SQLIdentifyMsgWorker["+strconv.Itoa(id)+"] : callbacks triggering") + } + mc1[rule.MsgTypeID64] = nil + } + } muxCallbacks.Unlock() } }