This repository has been archived by the owner on Feb 12, 2023. It is now read-only.
/
bot.go
133 lines (120 loc) · 4.91 KB
/
bot.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package cmd
import (
"context"
"crypto/x509"
"encoding/pem"
"os"
"time"
"github.com/dimboknv/tg-stand-with-ukraine/app/bot"
"github.com/dimboknv/tg-stand-with-ukraine/app/hub"
"github.com/dimboknv/tg-stand-with-ukraine/app/reporter"
"github.com/dimboknv/tg-stand-with-ukraine/app/store"
"github.com/jessevdk/go-flags"
"github.com/pkg/errors"
"go.uber.org/zap"
)
type Hub struct {
AppHash string `long:"app_hash" env:"APP_HASH" description:"Telegram API app hash" required:"true"`
PublicKey flags.Filename `long:"pk" env:"PUBLIC_KEY" description:"Telegram API public key" required:"true"`
DeviceModel string `long:"device" env:"DEVICE" description:"Telegram API device model" default:"Dmitry Nev"`
DCOption struct {
IPAddress string `long:"ip" env:"IP" description:"DC ip address" required:"true"`
ID int `long:"id" env:"ID" description:"DC id" default:"2"`
Port int `long:"port" env:"PORT" description:"DC port" default:"443"`
} `group:"dc" namespace:"dc" env-namespace:"DC"`
ClientTTL time.Duration `long:"client_ttl" env:"CLIENT_TTL" description:"A telegram API client TTL" default:"3m"`
AppID int `long:"app_id" env:"APP_ID" description:"Telegram API app id" required:"true"`
}
type Reporter struct {
Message string `long:"msg" env:"MESSAGE" description:"A report message" default:"The channel undermines the integrity of the Ukrainian state. Spreading fake news, misleading people. There are a lot of posts with threats against Ukrainians and Ukrainian soldiers. Block him ASAP"` // nolint
Interval time.Duration `long:"interval" env:"INTERVAL" description:"Interval between sending reports" default:"40m"`
IntervalMaxReports int `long:"max_reps" env:"INTERVAL_MAX_REPORTS" default:"25" description:"Max number of sent reports from a telegram client"` // nolint
}
type BotCmd struct {
Reporter `group:"reporter" namespace:"reporter" env-namespace:"REPORTER"`
Token string `long:"token" env:"TOKEN" description:"Bot token" required:"true"`
DB string `long:"db" env:"DB" description:"Database filepath" required:"true" default:"bbolt.db"`
CommonOpts
Admins []string `short:"a" long:"admin" env:"ADMIN" env-delim:"," description:"Bot admin telegram usernames" required:"true"`
Pattern string `long:"pattern" env:"PATTERN" description:"Bot server handler pattern" default:"/"`
CertFile flags.Filename `long:"cert" env:"CERT_FILE" description:"Bot server tls cert file"`
KeyFile flags.Filename `long:"key" env:"KEY_FILE" description:"Bot server tls key file"`
WebhookURL string `long:"webhook_url" env:"WEBHOOK_URL" description:"Bot server webhook url"`
Address string `long:"address" env:"ADDRESS" description:"Bot server bind address" default:"0.0.0.0:443"`
Hub `group:"hub" namespace:"hub" env-namespace:"HUB"`
}
// Execute gets statements list for specified merchant, entry point for "statements" command
func (cmd *BotCmd) Execute(_ []string) error {
cmd.Logger.Info("\"bot\" command started")
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
defer cancel()
cmd.waitSigterm(ctx)
}()
content, err := os.ReadFile(string(cmd.PublicKey))
if err != nil {
return errors.Wrapf(err, "can`t read %q file", string(cmd.PublicKey))
}
block, _ := pem.Decode(content)
publicKey, err := x509.ParsePKCS1PublicKey(block.Bytes)
if err != nil {
return errors.Wrap(err, "can`t parse public publicKey")
}
db, err := store.NewBoltStore(cmd.DB)
if err != nil {
return errors.Wrap(err, "can`t create bolt store")
}
defer func() {
if closeErr := db.Close(); err != nil {
cmd.Logger.Warn("fail to close database", zap.Error(closeErr))
}
}()
h := hub.NewHub(hub.Opts{
Context: ctx,
ClientTTL: cmd.ClientTTL,
DB: db,
Logger: cmd.Logger.Named("hub"),
PublicKey: publicKey,
DeviceModel: cmd.DeviceModel,
AppVersion: cmd.CommonOpts.BuildInfo.Version,
AppHash: cmd.AppHash,
DCOption: struct {
IPAddress string
ID int
Port int
}{
IPAddress: cmd.DCOption.IPAddress,
ID: cmd.DCOption.ID,
Port: cmd.DCOption.Port,
},
AppID: cmd.AppID,
})
rep := reporter.New(reporter.Opts{
DB: db,
Hub: h,
Logger: cmd.Logger.Named("rep"),
Message: cmd.Message,
Interval: cmd.Interval,
IntervalMaxReports: cmd.IntervalMaxReports,
})
b, err := bot.New(bot.Opts{
DB: db,
Logger: cmd.Logger.Named("bot"),
Hub: h,
Reporter: rep,
Token: cmd.Token,
CertFile: string(cmd.CertFile),
KeyFile: string(cmd.KeyFile),
WebhookURL: cmd.WebhookURL,
Pattern: cmd.Pattern,
Address: cmd.Address,
Admins: cmd.Admins,
Debug: cmd.Debug,
})
if err != nil {
return errors.Wrap(err, "can`t create bot")
}
defer cmd.Logger.Info("\"bot\" command is terminated")
return b.Run(ctx)
}