|
|
package userbot |
|
|
|
|
|
import ( |
|
|
"context" |
|
|
"fmt" |
|
|
"gitea.russia9.dev/russia9/muskrat/storage" |
|
|
"gitea.russia9.dev/russia9/muskrat/types" |
|
|
"github.com/go-co-op/gocron" |
|
|
"github.com/gotd/td/session" |
|
|
"github.com/gotd/td/telegram" |
|
|
"github.com/gotd/td/telegram/message" |
|
|
"github.com/gotd/td/tg" |
|
|
"github.com/rs/zerolog/log" |
|
|
"math/rand" |
|
|
"os" |
|
|
"regexp" |
|
|
"strconv" |
|
|
"strings" |
|
|
"time" |
|
|
) |
|
|
|
|
|
type Userbot struct { |
|
|
Account *types.Account |
|
|
Client *telegram.Client |
|
|
Sender *message.Sender |
|
|
SW *message.RequestBuilder |
|
|
Closed bool |
|
|
Scheduler *gocron.Scheduler |
|
|
} |
|
|
|
|
|
var Userbots map[int64]*Userbot |
|
|
|
|
|
func (b *Userbot) Start(ctx context.Context) error { |
|
|
// Session |
|
|
st := session.StorageMemory{} |
|
|
err := st.StoreSession(ctx, b.Account.Session) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
|
|
|
// Dispatcher |
|
|
dp := tg.NewUpdateDispatcher() |
|
|
dp.OnNewChannelMessage(func(c context.Context, e tg.Entities, u *tg.UpdateNewChannelMessage) error { |
|
|
m, ok := u.Message.(*tg.Message) |
|
|
if !ok { |
|
|
return nil |
|
|
} |
|
|
|
|
|
from, ok := m.FromID.(*tg.PeerUser) |
|
|
if !ok { |
|
|
return nil |
|
|
} |
|
|
|
|
|
peer, ok := m.PeerID.(*tg.PeerChannel) |
|
|
if !ok { |
|
|
return nil |
|
|
} |
|
|
|
|
|
reportChatID := int64(0) |
|
|
pinChatID := int64(0) |
|
|
if len(strconv.FormatInt(b.Account.ReportChat, 10)) > 4 { |
|
|
reportChatID, _ = strconv.ParseInt(strconv.FormatInt(b.Account.ReportChat, 10)[4:], 10, 64) |
|
|
} |
|
|
if len(strconv.FormatInt(b.Account.PinChat, 10)) > 4 { |
|
|
pinChatID, _ = strconv.ParseInt(strconv.FormatInt(b.Account.PinChat, 10)[4:], 10, 64) |
|
|
} |
|
|
|
|
|
if (peer.ChannelID == b.Account.PinChat || peer.ChannelID == pinChatID) && b.Account.Pin && rand.Intn(100) <= b.Account.PinChance { |
|
|
if from.UserID == 376592453 { // Pin |
|
|
rand.Seed(time.Now().UnixNano()) |
|
|
time.Sleep(time.Duration(rand.Float64()*b.Account.PinDelay) * time.Minute) |
|
|
|
|
|
r := regexp.MustCompile("(⚔В атаку на |🛡Все в защиту - )([^a-zA-Z]+)") |
|
|
|
|
|
if !r.MatchString(m.Message) { |
|
|
return nil |
|
|
} |
|
|
|
|
|
_, err = b.SW.Text(context.Background(), r.FindAllStringSubmatch(m.Message, -1)[0][2]) |
|
|
if err != nil { |
|
|
fmt.Println(err) |
|
|
} |
|
|
|
|
|
markup, ok := m.ReplyMarkup.(*tg.ReplyInlineMarkup) |
|
|
if !ok { |
|
|
return nil |
|
|
} |
|
|
|
|
|
callback, ok := markup.Rows[0].Buttons[0].(*tg.KeyboardButtonCallback) |
|
|
if !ok { |
|
|
return nil |
|
|
} |
|
|
|
|
|
_, err = b.Client.API().MessagesGetBotCallbackAnswer(context.Background(), &tg.MessagesGetBotCallbackAnswerRequest{ |
|
|
Peer: &tg.InputPeerChannel{ChannelID: peer.ChannelID, AccessHash: e.Channels[peer.ChannelID].AccessHash}, |
|
|
MsgID: m.ID, |
|
|
Data: callback.Data, |
|
|
}) |
|
|
if err != nil { |
|
|
fmt.Println(err, "pin", string(callback.Data)) |
|
|
} |
|
|
|
|
|
_, err = b.Client.API().ChannelsReadHistory(context.Background(), &tg.ChannelsReadHistoryRequest{ |
|
|
Channel: &tg.InputChannelFromMessage{ |
|
|
Peer: &tg.InputPeerChannel{ChannelID: peer.ChannelID, AccessHash: e.Channels[peer.ChannelID].AccessHash}, |
|
|
MsgID: m.ID, |
|
|
ChannelID: peer.ChannelID, |
|
|
}, |
|
|
MaxID: m.ID, |
|
|
}) |
|
|
if err != nil { |
|
|
fmt.Println(err) |
|
|
} |
|
|
} |
|
|
|
|
|
if from.UserID == 1714476897 || from.UserID == 1806724130 || from.UserID == 613165445 || from.UserID == 739073438 || from.UserID == 629902813 { |
|
|
rand.Seed(time.Now().UnixNano()) |
|
|
time.Sleep(time.Duration(rand.Float64()*b.Account.PinDelay) * time.Minute) |
|
|
|
|
|
markup, ok := m.ReplyMarkup.(*tg.ReplyInlineMarkup) |
|
|
if !ok { |
|
|
return nil |
|
|
} |
|
|
|
|
|
callback, ok := markup.Rows[0].Buttons[0].(*tg.KeyboardButtonCallback) |
|
|
if !ok { |
|
|
return nil |
|
|
} |
|
|
|
|
|
_, err = b.Client.API().MessagesGetBotCallbackAnswer(context.Background(), &tg.MessagesGetBotCallbackAnswerRequest{ |
|
|
Peer: &tg.InputPeerChannel{ChannelID: peer.ChannelID, AccessHash: e.Channels[peer.ChannelID].AccessHash}, |
|
|
MsgID: m.ID, |
|
|
Data: callback.Data, |
|
|
}) |
|
|
if err != nil { |
|
|
fmt.Println(err) |
|
|
} |
|
|
|
|
|
_, err = b.Client.API().ChannelsReadHistory(context.Background(), &tg.ChannelsReadHistoryRequest{ |
|
|
Channel: &tg.InputChannelFromMessage{ |
|
|
Peer: &tg.InputPeerChannel{ChannelID: peer.ChannelID, AccessHash: e.Channels[peer.ChannelID].AccessHash}, |
|
|
MsgID: m.ID, |
|
|
ChannelID: peer.ChannelID, |
|
|
}, |
|
|
MaxID: m.ID, |
|
|
}) |
|
|
if err != nil { |
|
|
fmt.Println(err) |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
if peer.ChannelID == 1109615116 { // Main Chat |
|
|
if from.UserID == 376592453 { // Informator |
|
|
if strings.HasPrefix(m.Message, "⚔️В любом мире есть противники. 🐮Быки и 🐻Медведи") { // Shark |
|
|
if b.Account.Shark { |
|
|
rand.Seed(time.Now().UnixNano()) |
|
|
time.Sleep(time.Duration(rand.Float64()*b.Account.SharkDelay+2) * time.Minute) |
|
|
|
|
|
markup, ok := m.ReplyMarkup.(*tg.ReplyInlineMarkup) |
|
|
if !ok { |
|
|
return nil |
|
|
} |
|
|
|
|
|
button := 0 |
|
|
if b.Account.SharkTeam { |
|
|
button = 1 |
|
|
} |
|
|
|
|
|
callback, ok := markup.Rows[0].Buttons[button].(*tg.KeyboardButtonCallback) |
|
|
if !ok { |
|
|
return nil |
|
|
} |
|
|
|
|
|
_, err = b.Client.API().MessagesGetBotCallbackAnswer(context.Background(), &tg.MessagesGetBotCallbackAnswerRequest{ |
|
|
Peer: &tg.InputPeerChannel{ChannelID: peer.ChannelID, AccessHash: e.Channels[peer.ChannelID].AccessHash}, |
|
|
MsgID: m.ID, |
|
|
Data: callback.Data, |
|
|
}) |
|
|
if err != nil { |
|
|
fmt.Println(err) |
|
|
} |
|
|
|
|
|
_, err = b.Client.API().ChannelsReadHistory(context.Background(), &tg.ChannelsReadHistoryRequest{ |
|
|
Channel: &tg.InputChannelFromMessage{ |
|
|
Peer: &tg.InputPeerChannel{ChannelID: peer.ChannelID, AccessHash: e.Channels[peer.ChannelID].AccessHash}, |
|
|
MsgID: m.ID, |
|
|
ChannelID: peer.ChannelID, |
|
|
}, |
|
|
MaxID: m.ID, |
|
|
}) |
|
|
if err != nil { |
|
|
fmt.Println(err) |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
if peer.ChannelID == b.Account.ReportChat || peer.ChannelID == reportChatID { // Update access hash |
|
|
if b.Account.ReportChatAccessHash != e.Channels[peer.ChannelID].AccessHash { |
|
|
b.Account.ReportChatAccessHash = e.Channels[peer.ChannelID].AccessHash |
|
|
storage.DB.Save(b.Account) |
|
|
} |
|
|
} |
|
|
|
|
|
return nil |
|
|
}) |
|
|
|
|
|
dp.OnNewMessage(func(c context.Context, e tg.Entities, u *tg.UpdateNewMessage) error { |
|
|
m, ok := u.Message.(*tg.Message) |
|
|
if !ok { |
|
|
return nil |
|
|
} |
|
|
|
|
|
peer, ok := m.PeerID.(*tg.PeerUser) |
|
|
if !ok { |
|
|
return nil |
|
|
} |
|
|
|
|
|
if peer.UserID == 227859379 { // StartupWarsBot |
|
|
rand.Seed(time.Now().UnixNano()) |
|
|
time.Sleep(time.Duration(rand.Float64()*5+2) * time.Second) |
|
|
|
|
|
if regexp.MustCompile("🎚(\\d+)").MatchString(m.Message) { // Update Profile |
|
|
self, err := b.Client.Self(context.Background()) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
|
|
|
b.Account.Name = self.FirstName + " " + self.LastName |
|
|
b.Account.Level, err = strconv.Atoi(regexp.MustCompile("🎚(\\d+)").FindAllStringSubmatch(m.Message, -1)[0][1]) |
|
|
b.Account.Corp = regexp.MustCompile("\\((.)[^)]+\\)").FindAllStringSubmatch(m.Message, -1)[0][1] |
|
|
|
|
|
storage.DB.Save(b.Account) |
|
|
} |
|
|
|
|
|
if _, ok = m.Media.(*tg.MessageMediaDocument); (ok || strings.HasPrefix(m.Message, "Ты достиг нового уровня.")) && b.Account.Levelup { // Levelup |
|
|
_, err = b.SW.Text(context.Background(), "/levelup") |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
|
|
|
rand.Seed(time.Now().UnixNano()) |
|
|
time.Sleep(time.Duration(rand.Float64()*5) * time.Second) |
|
|
|
|
|
if b.Account.LevelupSkill { |
|
|
_, err = b.SW.Text(context.Background(), "+1 🔨Практика") |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
|
|
|
rand.Seed(time.Now().UnixNano()) |
|
|
time.Sleep(time.Duration(rand.Float64()*5+5) * time.Second) |
|
|
|
|
|
_, err = b.SW.Text(context.Background(), "+1 🐿Хитрость") |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
} else { |
|
|
_, err = b.SW.Text(context.Background(), "+1 🎓Теория") |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
|
|
|
rand.Seed(time.Now().UnixNano()) |
|
|
time.Sleep(time.Duration(rand.Float64()*5+5) * time.Second) |
|
|
|
|
|
_, err = b.SW.Text(context.Background(), "+1 🐢Мудрость") |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
if b.Account.Eat { // Eat |
|
|
if regexp.MustCompile("🔋Выносливость на нуле").MatchString(m.Message) { |
|
|
_, err = b.SW.Text(context.Background(), "/to_eat") |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
} |
|
|
|
|
|
if regexp.MustCompile("🔋Выносливость: (\\d{1,3})%").MatchString(m.Message) && !strings.HasPrefix(m.Message, "🍴Меню") { |
|
|
data := regexp.MustCompile("🔋Выносливость: (\\d{1,3})%").FindAllStringSubmatch(m.Message, -1) |
|
|
if len(data[0]) >= 2 { |
|
|
stamina, err := strconv.Atoi(data[0][1]) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
|
|
|
if b.Account.Eat200 { |
|
|
if stamina < 200 { |
|
|
_, err = b.SW.Text(context.Background(), "/to_eat") |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
} |
|
|
} else { |
|
|
if stamina < 100 { |
|
|
_, err = b.SW.Text(context.Background(), "/to_eat") |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
if strings.HasPrefix(m.Message, "🍴Меню") { |
|
|
data := regexp.MustCompile("🔋Выносливость: (\\d{1,3})%").FindAllStringSubmatch(m.Message, -1) |
|
|
if len(data[0]) >= 2 { |
|
|
stamina, err := strconv.Atoi(data[0][1]) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
|
|
|
if b.Account.Eat200 { |
|
|
if stamina < 200 { |
|
|
_, err = b.SW.Text(context.Background(), b.Account.EatCommand) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
} |
|
|
} else { |
|
|
if stamina < 100 { |
|
|
_, err = b.SW.Text(context.Background(), b.Account.EatCommand) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
if strings.Contains(m.Message, "Твои результаты в битве") && b.Account.Report { // Forward Report |
|
|
rand.Seed(time.Now().UnixNano()) |
|
|
_, err = b.Client.API().MessagesForwardMessages(context.Background(), &tg.MessagesForwardMessagesRequest{ |
|
|
FromPeer: &tg.InputPeerUser{UserID: 227859379}, |
|
|
ID: []int{m.ID}, |
|
|
ToPeer: &tg.InputPeerChannel{ChannelID: b.Account.ReportChat, AccessHash: b.Account.ReportChatAccessHash}, |
|
|
RandomID: []int64{rand.Int63()}, |
|
|
}) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
} |
|
|
|
|
|
if strings.Contains(m.Message, "Опа, тебя начал грабить") && b.Account.Sleep { |
|
|
markup, ok := m.ReplyMarkup.(*tg.ReplyInlineMarkup) |
|
|
if !ok { |
|
|
return nil |
|
|
} |
|
|
|
|
|
callback, ok := markup.Rows[0].Buttons[0].(*tg.KeyboardButtonCallback) |
|
|
if !ok { |
|
|
return nil |
|
|
} |
|
|
|
|
|
_, err = b.Client.API().MessagesGetBotCallbackAnswer(context.Background(), &tg.MessagesGetBotCallbackAnswerRequest{ |
|
|
Peer: &tg.InputPeerUser{UserID: peer.UserID, AccessHash: e.Users[peer.UserID].AccessHash}, |
|
|
MsgID: m.ID, |
|
|
Data: callback.Data, |
|
|
}) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
} |
|
|
|
|
|
if strings.Contains(m.Message, b.Account.MotivationCommand) && b.Account.MotivationCommand != "" && b.Account.MotivationKD && b.Account.Motivation { |
|
|
builder := b.Sender.Resolve("@StartupWarsBot") |
|
|
if builder != nil { |
|
|
_, err := builder.Text(context.Background(), b.Account.MotivationCommand) |
|
|
if err != nil { |
|
|
log.Error().Err(err) |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
// TODO: Sleep |
|
|
// TODO: Mobs |
|
|
} |
|
|
|
|
|
return nil |
|
|
}) |
|
|
|
|
|
// Telegram Client |
|
|
appID, err := strconv.Atoi(os.Getenv("TELEGRAM_APP_ID")) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
|
|
|
b.Client = telegram.NewClient(appID, os.Getenv("TELEGRAM_APP_HASH"), telegram.Options{ |
|
|
SessionStorage: &st, |
|
|
UpdateHandler: &dp, |
|
|
}) |
|
|
|
|
|
go func() { |
|
|
err = b.Client.Run(context.Background(), func(c context.Context) error { |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
|
|
|
// Create Sender |
|
|
b.Sender = message.NewSender(b.Client.API()) |
|
|
b.SW = b.Sender.Resolve("@StartupWarsBot") |
|
|
if b.SW == nil { |
|
|
fmt.Println("no startupwars") |
|
|
return err |
|
|
} |
|
|
|
|
|
_, err = b.SW.Text(context.Background(), "/compact") |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
|
|
|
// Scheduler |
|
|
location, err := time.LoadLocation("Europe/Moscow") |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
|
|
|
b.Scheduler = gocron.NewScheduler(location) |
|
|
|
|
|
_, err = b.Scheduler.Every(30).Minutes().Do(MotivationTask(b)) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
_, err = b.Scheduler.Cron("45 9-21/3 * * *").Do(EatTask(b)) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
_, err = b.Scheduler.Cron("15 10-22/3 * * *").Do(EatTask(b)) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
_, err = b.Scheduler.Cron("1 10-22/3 * * *").Do(ReportTask(b)) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
_, err = b.Scheduler.Cron("0 1 * * *").Do(ProfileTask(b)) |
|
|
if err != nil { |
|
|
return err |
|
|
} |
|
|
|
|
|
b.Scheduler.StartAsync() |
|
|
|
|
|
for !b.Closed { |
|
|
time.Sleep(time.Second) |
|
|
} |
|
|
return nil |
|
|
}) |
|
|
if err != nil { |
|
|
fmt.Println(err) |
|
|
} |
|
|
}() |
|
|
|
|
|
return nil |
|
|
} |
|
|
|
|
|
func (b *Userbot) Stop() error { |
|
|
b.Closed = true |
|
|
if b.Scheduler != nil { |
|
|
b.Scheduler.Stop() |
|
|
} |
|
|
return nil |
|
|
}
|
|
|
|