Skip to content

Commit

Permalink
fix: add Sanitize HTML in inline query responses (#1)
Browse files Browse the repository at this point in the history
* fix 

* Update README.md
  • Loading branch information
AshokShau authored Sep 24, 2024
1 parent f984cfc commit cdff7c4
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 15 deletions.
7 changes: 4 additions & 3 deletions .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ This project is licensed under the MIT License—see the [LICENSE](/LICENSE) fil
[![Telegram](https://img.shields.io/badge/Telegram-Chat-blue.svg)](https://t.me/AshokShau)
## Thanks
- [Ashok Shau](https://github.com/AshokShau) for the project.
- [PaulSonOfLars](https://github.com/PaulSonOfLars) for the [GoTgBot](https://github.com/PaulSonOfLars/gotgbot) library and [Api](https://github.com/PaulSonOfLars/telegram-bot-api-spec/raw/main/api.json).
## Acknowledgments
- **[Ashok Shau](https://github.com/AshokShau)**: For creating and maintaining this [project](https://github.com/AshokShau/BotApiDocs), which provides a solid foundation for building Telegram bots.
- **[PaulSonOfLars](https://github.com/PaulSonOfLars)**: For the invaluable [GoTgBot](https://github.com/PaulSonOfLars/gotgbot) library, which simplifies Telegram bot development in Go, and for the [API specification](https://github.com/PaulSonOfLars/telegram-bot-api-spec/raw/main/api.json) that serves as a reference for bot methods and types.
38 changes: 26 additions & 12 deletions Telegram/modules/inline.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"log"
"math/rand"
"net/http"
"regexp"
"strconv"
"strings"
"sync"
Expand All @@ -15,6 +16,8 @@ import (
"github.com/PaulSonOfLars/gotgbot/v2/ext"
)

const maxMessageLength = 4096 // Telegram's maximum message length

// apiCache is a global cache for storing API methods and types.
var apiCache struct {
sync.RWMutex
Expand Down Expand Up @@ -56,10 +59,6 @@ func fetchAPI() error {
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
}

var apiDocs struct {
Methods map[string]Method `json:"methods"`
Types map[string]Type `json:"types"`
Expand Down Expand Up @@ -128,7 +127,7 @@ func sendEmptyQueryResponse(bot *gotgbot.Bot, ctx *ext.Context) error {
IsPersonal: true,
CacheTime: 5,
Button: &gotgbot.InlineQueryResultsButton{
Text: "Type '<your_query>' to search!",
Text: "Type 'your_query' to search!",
StartParameter: "start",
},
})
Expand Down Expand Up @@ -169,35 +168,43 @@ func sendNoResultsResponse(bot *gotgbot.Bot, ctx *ext.Context, query string) err
func buildMethodMessage(method Method) string {
var msgBuilder strings.Builder
msgBuilder.WriteString(fmt.Sprintf("<b>%s</b>\n", method.Name))
msgBuilder.WriteString(fmt.Sprintf("Description: %s\n\n", strings.Join(method.Description, ", ")))
msgBuilder.WriteString(fmt.Sprintf("Description: %s\n\n", sanitizeHTML(strings.Join(method.Description, ", "))))
msgBuilder.WriteString("<b>Returns:</b> " + strings.Join(method.Returns, ", ") + "\n")

if len(method.Fields) > 0 {
msgBuilder.WriteString("<b>Fields:</b>\n")
for _, field := range method.Fields {
msgBuilder.WriteString(fmt.Sprintf("<code>%s</code> (<b>%s</b>) - Required: <code>%t</code>\n", field.Name, strings.Join(field.Types, ", "), field.Required))
msgBuilder.WriteString(field.Description + "\n\n")
msgBuilder.WriteString(sanitizeHTML(field.Description) + "\n\n")
}
}

return msgBuilder.String()
message := msgBuilder.String()
if len(message) > maxMessageLength {
return fmt.Sprintf("See full documentation: %s", method.Href)
}
return message
}

// buildTypeMessage builds a message string for a given API type.
func buildTypeMessage(typ Type) string {
var msgBuilder strings.Builder
msgBuilder.WriteString(fmt.Sprintf("<b>%s</b>\n", typ.Name))
msgBuilder.WriteString(fmt.Sprintf("Description: %s\n\n", strings.Join(typ.Description, ", ")))
msgBuilder.WriteString(fmt.Sprintf("Description: %s\n\n", sanitizeHTML(strings.Join(typ.Description, ", "))))

if len(typ.Fields) > 0 {
msgBuilder.WriteString("<b>Fields:</b>\n")
for _, field := range typ.Fields {
msgBuilder.WriteString(fmt.Sprintf("<code>%s</code> (<b>%s</b>) - Required: <code>%t</code>\n", field.Name, strings.Join(field.Types, ", "), field.Required))
msgBuilder.WriteString(field.Description + "\n\n")
msgBuilder.WriteString(sanitizeHTML(field.Description) + "\n\n")
}
}

return msgBuilder.String()
message := msgBuilder.String()
if len(message) > maxMessageLength {
return fmt.Sprintf("See full documentation: %s", typ.Href)
}
return message
}

// createInlineResult creates an inline query result for a given API method or type.
Expand Down Expand Up @@ -225,7 +232,7 @@ func createInlineResult(title, url, message, methodUrl string) gotgbot.InlineQue
func noResultsArticle(query string) gotgbot.InlineQueryResult {
ok := "botapi"
return gotgbot.InlineQueryResultArticle{
Id: "no_results",
Id: strconv.Itoa(rand.Intn(100000)),
Title: "No Results Found!",
InputMessageContent: gotgbot.InputTextMessageContent{
MessageText: fmt.Sprintf("<i>👋 Sorry, I couldn't find any results for '%s'. Try searching with a different keyword!</i>", query),
Expand All @@ -239,3 +246,10 @@ func noResultsArticle(query string) gotgbot.InlineQueryResult {
},
}
}

// sanitizeHTML removes unsupported HTML tags from the message
func sanitizeHTML(input string) string {
// This regex matches any HTML tags that are not supported
re := regexp.MustCompile(`<[^>]*>`)
return re.ReplaceAllString(input, "")
}

0 comments on commit cdff7c4

Please sign in to comment.