RITlug/teleirc

View on GitHub
internal/handlers/telegram/handler.go

Summary

Maintainability
A
0 mins
Test Coverage
D
69%
package telegram

import (
    "fmt"
    "strconv"
    "strings"

    tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
)

/*
Handler specifies a function that handles a Telegram update.
In this case, we take a Telegram client and update object,
where the specific Handler will "handle" the given event.
*/
type Handler = func(tg *Client, u tgbotapi.Update)

/*
updateHandler takes in a Telegram Update channel, and determines
which handler to fire off
*/
func updateHandler(tg *Client, updates tgbotapi.UpdatesChannel) {
    for u := range updates {
        switch {
        case u.Message == nil:
            tg.logger.LogError("Missing message data")
            continue
        case u.Message.NewChatMembers != nil:
            tg.logger.LogDebug("joinHandler triggered")
            joinHandler(tg, u.Message.NewChatMembers)
        case u.Message.LeftChatMember != nil:
            tg.logger.LogDebug("partHandler triggered")
            partHandler(tg, u.Message.LeftChatMember)
        case u.Message.Text != "":
            tg.logger.LogDebug("messageHandler triggered")
            messageHandler(tg, u)
        case u.Message.Sticker != nil:
            tg.logger.LogDebug("stickerHandler triggered")
            stickerHandler(tg, u)
        case u.Message.Document != nil:
            tg.logger.LogDebug("documentHandler triggered")
            documentHandler(tg, u.Message)
        case u.Message.Photo != nil:
            tg.logger.LogDebug("photoHandler triggered")
            photoHandler(tg, u)
        case u.Message.Location != nil:
            tg.logger.LogDebug("locationHandler triggered")
            locationHandler(tg, u.Message)
        default:
            tg.logger.LogWarning("Triggered, but message type is currently unsupported")
            tg.logger.LogWarning("Unhandled Update:", u)
            continue
        }
    }
}

/*
messageHandler handles the Message Telegram Object, which formats the
Telegram update into a simple string for IRC.
*/
func messageHandler(tg *Client, u tgbotapi.Update) {
    username := GetUsername(tg.IRCSettings.ShowZWSP, u.Message.From)
    formatted := ""

    if tg.IRCSettings.NoForwardPrefix != "" && strings.HasPrefix(u.Message.Text, tg.IRCSettings.NoForwardPrefix) {
        return
    }

    // Don't forward messages to IRC that didn't come from the
    // chat we're bridging
    if u.Message.Chat.ID != tg.Settings.ChatID {
        return
    }

    // Telegram user replied to a message
    if u.Message.ReplyToMessage != nil {
        replyHandler(tg, u)
        return
    }

    formatted = fmt.Sprintf("%s%s%s %s",
        tg.Settings.Prefix,
        username,
        tg.Settings.Suffix,
        // Trim unexpected trailing whitespace
        strings.Trim(u.Message.Text, " "))

    tg.sendToIrc(formatted)
}

/*
replyHandler handles when users reply to a Telegram message
*/
func replyHandler(tg *Client, u tgbotapi.Update) {
    replyText := strings.Trim(u.Message.ReplyToMessage.Text, " ")
    username := GetUsername(tg.IRCSettings.ShowZWSP, u.Message.From)
    replyUser := GetUsername(tg.IRCSettings.ShowZWSP, u.Message.ReplyToMessage.From)

    // Only show a portion of the reply text
    if replyTextAsRunes := []rune(replyText); len(replyTextAsRunes) > tg.Settings.ReplyLength {
        replyText = string(replyTextAsRunes[:tg.Settings.ReplyLength]) + "…"
    }

    formatted := fmt.Sprintf("%s%s%s %sRe %s: %s%s %s",
        tg.Settings.Prefix,
        username,
        tg.Settings.Suffix,
        tg.Settings.ReplyPrefix,
        replyUser,
        replyText,
        tg.Settings.ReplySuffix,
        u.Message.Text)

    tg.sendToIrc(formatted)
}

/*
joinHandler handles when users join the Telegram group
*/
func joinHandler(tg *Client, users *[]tgbotapi.User) {
    if tg.IRCSettings.ShowJoinMessage {
        for _, user := range *users {
            user := user
            username := GetFullUsername(tg.IRCSettings.ShowZWSP, &user)
            formatted := username + " has joined the Telegram Group!"
            tg.sendToIrc(formatted)
        }
    }
}

/*
partHandler handles when users leave the Telegram group
*/
func partHandler(tg *Client, user *tgbotapi.User) {
    if tg.IRCSettings.ShowLeaveMessage {
        username := GetFullUsername(tg.IRCSettings.ShowZWSP, user)
        formatted := username + " has left the Telegram Group!"

        tg.sendToIrc(formatted)
    }
}

/*
stickerHandler handles the Message.Sticker Telegram Object, which formats the
Telegram message into its base Emoji unicode character.
*/
func stickerHandler(tg *Client, u tgbotapi.Update) {
    username := GetUsername(tg.IRCSettings.ShowZWSP, u.Message.From)
    formatted := fmt.Sprintf("%s%s%s %s",
        tg.Settings.Prefix,
        username,
        tg.Settings.Suffix,
        u.Message.Sticker.Emoji)
    tg.sendToIrc(formatted)
}

/*
photoHandler handles the Message.Photo Telegram object. Only acknowledges Photo
exists, and sends notification to IRC
*/
func photoHandler(tg *Client, u tgbotapi.Update) {
    link := uploadImage(tg, u)
    username := GetUsername(tg.IRCSettings.ShowZWSP, u.Message.From)
    caption := u.Message.Caption
    if caption == "" {
        caption = "No caption provided."
    }
    formatted := "'" + caption + "' uploaded by " + username + ": " + link

    tg.sendToIrc(formatted)
}

/*
documentHandler receives a document object from Telegram, and sends
a notification to IRC.
*/
func documentHandler(tg *Client, u *tgbotapi.Message) {
    username := GetUsername(tg.IRCSettings.ShowZWSP, u.From)
    formatted := username + " shared a file"
    if u.Document.MimeType != "" {
        formatted += " (" + u.Document.MimeType + ")"
    }

    if u.Caption != "" {
        formatted += " on Telegram with caption: " + "'" + u.Caption + "'."
    } else if u.Document.FileName != "" {
        formatted += " on Telegram with title: " + "'" + u.Document.FileName + "'."
    }

    tg.sendToIrc(formatted)
}

/*
locationHandler receivers a location object from Telegram, and sends
a notification to IRC.
*/
func locationHandler(tg *Client, u *tgbotapi.Message) {
    if !tg.IRCSettings.ShowLocationMessage {
        return
    }

    username := GetUsername(tg.IRCSettings.ShowZWSP, u.From)
    formatted := username + " shared their location: ("

    // f means do not use an exponent.
    // -1 means use the smallest number of digits needed so parseFloat will return f exactly.
    // 64 to represent a standard 64 bit floating point number.
    formatted += strconv.FormatFloat(u.Location.Latitude, 'f', -1, 64)
    formatted += ", "
    formatted += strconv.FormatFloat(u.Location.Longitude, 'f', -1, 64)
    formatted += ")."

    tg.sendToIrc(formatted)
}