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.
183 lines
4.8 KiB
183 lines
4.8 KiB
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 |
|
}
|
|
|