+// post sends event to the chat. A reply goes as rich messages of its Markdown,
+// split with splitRich. Every other event goes as plain text, split with
+// splitMessage.
+func (b *telegramBot) post(ctx context.Context, event Event) {
+ if event.Kind != "reply" {
+ for _, text := range splitMessage(botText(event), messageUnits) {
+ b.deliver(ctx, botPart{
+ text: text,
+ })
+ }
+
+ return
+ }
+
+ for _, markdown := range splitRich(event.Text, richMessageBytes) {
+ b.deliverRich(ctx, markdown)
+ }
+}
+
+// deliverRich sends markdown to the chat as a rich message. When the Bot API
+// refuses it with HTTP 400 or 404, the message was not sent, so deliverRich
+// sends the same Markdown once with message entities, and the reply is not
+// lost and does not repeat. It tries again after each failure that a later try
+// can fix, until ctx ends. It drops the message after any other failure.
+func (b *telegramBot) deliverRich(ctx context.Context, markdown string) {
+ wait := b.minWait
+ for {
+ err := b.api.SendRichMessage(ctx, b.owner, markdown)
+ if err == nil || ctx.Err() != nil {
+ return
+ }
+
+ if rejected(err) {
+ b.logger.Printf("rich message refused, the reply goes with entities: %v", err)
+ for _, part := range replyParts(markdown) {
+ b.deliver(ctx, part)
+ }
+
+ return
+ }
+
+ retry, asked := retryable(err)
+ if !retry {
+ b.logger.Printf("message dropped: %v", err)
+ return
+ }
+
+ wait = b.pause(ctx, err, wait, asked)
+ }
+}
+