- Remove CAS, as it no longer works for us - Remove other checks - Implement 15 minute greet timeout check - Fix chat logos - Ditch thirdparty logger, use stdlib log facility wrapper for logging
120 lines
2.9 KiB
Go
120 lines
2.9 KiB
Go
package moon
|
|
|
|
import (
|
|
"bunny-bot/internal/elog"
|
|
"bunny-bot/internal/mylog"
|
|
|
|
"github.com/NicoNex/echotron/v3"
|
|
)
|
|
|
|
// retractGreetings deletes the greetings we sent to a member who has just been
|
|
// banned for never answering them, so the room is not left asking a question of
|
|
// someone who no longer has access.
|
|
//
|
|
// Ids <= 0 mean "no greeting was ever sent for that join" and are skipped
|
|
// silently. A deletion Telegram refuses is logged and the pass continues: the
|
|
// greeting is not worth abandoning the rest over, and a failed retraction never
|
|
// changes the ban that has already landed.
|
|
func retractGreetings(chat *echotron.Chat, user *echotron.User, greetingIDs []int) retractOutcome {
|
|
retracted, failed := 0, 0
|
|
|
|
for _, id := range greetingIDs {
|
|
if id <= 0 {
|
|
continue
|
|
}
|
|
|
|
if _, err := Tg.DeleteMessage(chat.ID, id); err != nil {
|
|
failed++
|
|
|
|
reportRetractFailure(chat, user, id, err)
|
|
|
|
continue
|
|
}
|
|
|
|
retracted++
|
|
|
|
elog.LogGreetingRetracted(chat, user, id)
|
|
}
|
|
|
|
return retractOutcomeFor(retracted, failed)
|
|
}
|
|
|
|
// reportRetractFailure logs a refused deletion. It is a WARN rather than an ERROR
|
|
// because the ban it followed already succeeded and nothing depends on the
|
|
// greeting being gone.
|
|
func reportRetractFailure(chat *echotron.Chat, user *echotron.User, id int, err error) {
|
|
mylog.Warnf(
|
|
"Left an unanswered greeting in place: cannot delete message %d in chat %d for user %d: %s",
|
|
id,
|
|
chat.ID,
|
|
userIDOf(user),
|
|
err,
|
|
)
|
|
}
|
|
|
|
// retractAskedGreetings takes down the questions this member was asked and never
|
|
// answered. One id per recorded join, so a member who joined twice had two
|
|
// greetings and both go.
|
|
func retractAskedGreetings(refs []joinRef) {
|
|
ids := make([]int, 0, len(refs))
|
|
for _, ref := range refs {
|
|
ids = append(ids, ref.greetingID)
|
|
}
|
|
|
|
chat, user := refs[0].chat, refs[0].user
|
|
|
|
switch retractGreetings(&chat, user, ids) {
|
|
case greetingRetracted:
|
|
mylog.Debugf(
|
|
"Deleted %d unanswered greeting(s) asked of user %d in chat %d",
|
|
countNamedGreetings(ids),
|
|
user.ID,
|
|
chat.ID,
|
|
)
|
|
case greetingRetractFailed:
|
|
mylog.Warnf(
|
|
"Banned user %d in chat %d, but could not delete every greeting we asked them",
|
|
user.ID,
|
|
chat.ID,
|
|
)
|
|
case nothingToRetract:
|
|
}
|
|
}
|
|
|
|
// countNamedGreetings counts the ids that actually named a message; the rest
|
|
// mean no greeting was ever delivered.
|
|
func countNamedGreetings(ids []int) int {
|
|
n := 0
|
|
|
|
for _, id := range ids {
|
|
if id > 0 {
|
|
n++
|
|
}
|
|
}
|
|
|
|
return n
|
|
}
|
|
|
|
// retractOutcomeFor collapses the two counts into the single value callers act on.
|
|
func retractOutcomeFor(retracted int, failed int) retractOutcome {
|
|
switch {
|
|
case retracted > 0 && failed == 0:
|
|
return greetingRetracted
|
|
case failed > 0:
|
|
return greetingRetractFailed
|
|
default:
|
|
return nothingToRetract
|
|
}
|
|
}
|
|
|
|
// userIDOf names a user in a log line without dereferencing a possibly nil one.
|
|
func userIDOf(user *echotron.User) int64 {
|
|
if user == nil {
|
|
return 0
|
|
}
|
|
|
|
return user.ID
|
|
}
|
|
|
|
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */
|