You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
4.8 KiB
184 lines
4.8 KiB
3 years ago
|
package message
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"strconv"
|
||
|
"time"
|
||
|
|
||
|
"github.com/go-faster/errors"
|
||
|
|
||
|
"github.com/gotd/td/internal/crypto"
|
||
|
"github.com/gotd/td/telegram/message/entity"
|
||
|
"github.com/gotd/td/telegram/message/styling"
|
||
|
"github.com/gotd/td/tg"
|
||
|
)
|
||
|
|
||
|
type pollAnswerBuilder struct {
|
||
|
input *tg.InputMediaPoll
|
||
|
}
|
||
|
|
||
|
// PollAnswerOption is an option to create poll answer.
|
||
|
type PollAnswerOption func(p *pollAnswerBuilder)
|
||
|
|
||
|
// RawPollAnswer creates new raw poll answer option.
|
||
|
func RawPollAnswer(poll tg.PollAnswer) PollAnswerOption {
|
||
|
return func(p *pollAnswerBuilder) {
|
||
|
p.input.Poll.Answers = append(p.input.Poll.Answers, poll)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// PollAnswer creates new plain poll answer option.
|
||
|
func PollAnswer(text string) PollAnswerOption {
|
||
|
return func(p *pollAnswerBuilder) {
|
||
|
i := len(p.input.Poll.Answers)
|
||
|
p.input.Poll.Answers = append(p.input.Poll.Answers, tg.PollAnswer{
|
||
|
Text: text,
|
||
|
Option: []byte(text + strconv.Itoa(i)),
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// CorrectPollAnswer creates new correct poll answer option.
|
||
|
func CorrectPollAnswer(text string) PollAnswerOption {
|
||
|
return func(p *pollAnswerBuilder) {
|
||
|
p.input.Poll.Quiz = true
|
||
|
i := len(p.input.Poll.Answers)
|
||
|
option := []byte(text + strconv.Itoa(i))
|
||
|
p.input.Poll.Answers = append(p.input.Poll.Answers, tg.PollAnswer{
|
||
|
Text: text,
|
||
|
Option: option,
|
||
|
})
|
||
|
p.input.CorrectAnswers = append(p.input.CorrectAnswers, option)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// PollBuilder is a Poll media option.
|
||
|
type PollBuilder struct {
|
||
|
input tg.InputMediaPoll
|
||
|
answers []PollAnswerOption
|
||
|
opts []StyledTextOption
|
||
|
}
|
||
|
|
||
|
// PollID return poll ID. If poll was not sent, will be zero.
|
||
|
// It useful to close polls.
|
||
|
func (p *PollBuilder) PollID() int64 {
|
||
|
return p.input.Poll.ID
|
||
|
}
|
||
|
|
||
|
// Close sets flag that the poll is closed and doesn't accept any more answers.
|
||
|
func (p *PollBuilder) Close() *PollBuilder {
|
||
|
p.input.Poll.Closed = true
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
// PublicVoters sets flag that votes are publicly visible to all users (non-anonymous poll).
|
||
|
func (p *PollBuilder) PublicVoters(publicVoters bool) *PollBuilder {
|
||
|
p.input.Poll.PublicVoters = publicVoters
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
// MultipleChoice sets flag that multiple options can be chosen as answer.
|
||
|
func (p *PollBuilder) MultipleChoice(multipleChoice bool) *PollBuilder {
|
||
|
p.input.Poll.MultipleChoice = multipleChoice
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
// CloseDate sets point in time (Unix timestamp) when the poll will be automatically closed.
|
||
|
// Must be at least 5 and no more than 600 seconds in the future.
|
||
|
func (p *PollBuilder) CloseDate(d time.Time) *PollBuilder {
|
||
|
return p.CloseDateTS(int(d.Unix()))
|
||
|
}
|
||
|
|
||
|
// CloseDateTS sets point in time (Unix timestamp) when the poll will be automatically closed.
|
||
|
// Must be at least 5 and no more than 600 seconds in the future.
|
||
|
func (p *PollBuilder) CloseDateTS(ts int) *PollBuilder {
|
||
|
p.input.Poll.ClosePeriod = 0
|
||
|
p.input.Poll.CloseDate = ts
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
// ClosePeriod sets amount of time in seconds the poll will be active after creation, 5-600 seconds.
|
||
|
func (p *PollBuilder) ClosePeriod(d time.Duration) *PollBuilder {
|
||
|
return p.ClosePeriodSeconds(int(d.Seconds()))
|
||
|
}
|
||
|
|
||
|
// ClosePeriodSeconds sets amount of time in seconds the poll will be active after creation, 5-600.
|
||
|
func (p *PollBuilder) ClosePeriodSeconds(s int) *PollBuilder {
|
||
|
p.input.Poll.ClosePeriod = s
|
||
|
p.input.Poll.CloseDate = 0
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
// Explanation sets explanation message.
|
||
|
func (p *PollBuilder) Explanation(msg string) *PollBuilder {
|
||
|
p.input.Solution = msg
|
||
|
p.input.SolutionEntities = nil
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
// StyledExplanation sets styled explanation message.
|
||
|
func (p *PollBuilder) StyledExplanation(texts ...StyledTextOption) *PollBuilder {
|
||
|
p.opts = texts
|
||
|
return p
|
||
|
}
|
||
|
|
||
|
func (p *PollBuilder) apply(ctx context.Context, b *multiMediaBuilder) error {
|
||
|
if p.input.Poll.ID == 0 {
|
||
|
id, err := crypto.RandInt64(b.sender.rand)
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "generate id")
|
||
|
}
|
||
|
|
||
|
p.input.Poll.ID = id
|
||
|
}
|
||
|
|
||
|
if len(p.opts) > 0 {
|
||
|
tb := entity.Builder{}
|
||
|
if err := styling.Perform(&tb, p.opts...); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
p.input.Solution, p.input.SolutionEntities = tb.Complete()
|
||
|
}
|
||
|
|
||
|
pb := pollAnswerBuilder{input: &p.input}
|
||
|
for _, opt := range p.answers {
|
||
|
opt(&pb)
|
||
|
}
|
||
|
|
||
|
return Media(&p.input).apply(ctx, b)
|
||
|
}
|
||
|
|
||
|
// Poll adds poll attachment.
|
||
|
func Poll(question string, a, b PollAnswerOption, answers ...PollAnswerOption) *PollBuilder {
|
||
|
return &PollBuilder{
|
||
|
input: tg.InputMediaPoll{
|
||
|
Poll: tg.Poll{
|
||
|
Question: question,
|
||
|
},
|
||
|
},
|
||
|
answers: append([]PollAnswerOption{a, b}, answers...),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// PollVote votes in a poll.
|
||
|
func (b *RequestBuilder) PollVote(
|
||
|
ctx context.Context, msgID int,
|
||
|
answer []byte, answers ...[]byte,
|
||
|
) (tg.UpdatesClass, error) {
|
||
|
p, err := b.peer(ctx)
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrap(err, "peer")
|
||
|
}
|
||
|
|
||
|
upd, err := b.sender.sendVote(ctx, &tg.MessagesSendVoteRequest{
|
||
|
Peer: p,
|
||
|
MsgID: msgID,
|
||
|
Options: append([][]byte{answer}, answers...),
|
||
|
})
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrap(err, "start bot")
|
||
|
}
|
||
|
|
||
|
return upd, nil
|
||
|
}
|