// mautrix-telegram - A Matrix-Telegram puppeting bridge. // Copyright (C) 2024 Sumner Evans // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . package telegramfmt import ( "fmt" "strings" "unicode/utf16" ) func (m Mention) Format(message string) string { if m.Username != "" { return fmt.Sprintf(`@%s`, m.MXID.URI().MatrixToURL(), m.Username) } return fmt.Sprintf(`%s`, m.MXID.URI().MatrixToURL(), m.Name) } func (s Style) Format(message string) string { switch s.Type { case StyleBold: return fmt.Sprintf("%s", message) case StyleItalic: return fmt.Sprintf("%s", message) case StyleSpoiler: return fmt.Sprintf("%s", message) case StyleStrikethrough: return fmt.Sprintf("%s", message) case StyleCode: if strings.ContainsRune(message, '\n') { // This is somewhat incorrect, as it won't allow inline text before/after a multiline monospace-formatted string. return fmt.Sprintf("
%s
", message) } return fmt.Sprintf("%s", message) case StyleUnderline: return fmt.Sprintf("%s", message) case StyleBlockquote: return fmt.Sprintf("
%s
", message) case StylePre: if s.Language != "" { return fmt.Sprintf(`
%s
`, s.Language, message) } return fmt.Sprintf("
%s
", message) case StyleEmail: return fmt.Sprintf(`%s`, message, message) case StyleTextURL, StyleURL: return fmt.Sprintf(`%s`, s.URL, message) case StyleCustomEmoji: if s.EmojiInfo.Emoji != "" { return s.EmojiInfo.Emoji } else if s.EmojiInfo.EmojiURI != "" { return fmt.Sprintf( `%s`, s.EmojiInfo.EmojiURI, message, message, ) } return message case StyleBotCommand, StyleHashtag, StyleCashtag, StylePhone: return fmt.Sprintf(`%s`, message) default: return message } } type UTF16String []uint16 func NewUTF16String(s string) UTF16String { return utf16.Encode([]rune(s)) } func (u UTF16String) String() string { return string(utf16.Decode(u)) } func (lrt *LinkedRangeTree) Format(message UTF16String, ctx formatContext) string { if lrt == nil || lrt.Node == nil { return ctx.TextToHTML(message.String()) } head := message[:lrt.Node.Start] headStr := ctx.TextToHTML(head.String()) inner := message[lrt.Node.Start:lrt.Node.End()] tail := message[lrt.Node.End():] ourCtx := ctx if lrt.Node.Value.IsCode() { ourCtx.IsInCodeblock = true } childMessage := lrt.Child.Format(inner, ourCtx) formattedChildMessage := lrt.Node.Value.Format(childMessage) siblingMessage := lrt.Sibling.Format(tail, ctx) return headStr + formattedChildMessage + siblingMessage }