-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathmain.go
183 lines (150 loc) · 4.42 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package main
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"strings"
"time"
"github.com/charmbracelet/lipgloss"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)
// AppConfig holds the application configuration.
type AppConfig struct {
BotKey string `mapstructure:"bot_key"`
UserID int64 `mapstructure:"user_id"`
Filepath string // This will be set by a flag, not by viper directly.
Server bool // Flag to run in server mode
}
func initConfig() *AppConfig {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
viper.AddConfigPath("$HOME/.config/telegrammer")
viper.AddConfigPath(".")
viper.AutomaticEnv()
viper.SetEnvPrefix("TELEGRAMMER")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
if err := viper.ReadInConfig(); err != nil {
log.Printf("Warning: Error reading config file, %s", err)
}
var config AppConfig
if err := viper.Unmarshal(&config); err != nil {
log.Fatalf("Unable to decode into struct, %v", err)
}
return &config
}
func main() {
config := initConfig()
// Setup flags and override config if flags are provided.
pflag.StringVarP(&config.Filepath, "file", "f", "", "Filepath to file")
pflag.BoolVar(&config.Server, "server", false, "Run in server mode to listen for new messages")
pflag.Parse()
if config.Server {
runServerMode(config)
return
}
messageText := ""
// Get text from stdin and start messageText with it
stdin, err := readStdin()
if stdin != "" && err == nil {
messageText += stdin
}
messageText += pflag.Arg(0) // Get the first non-flag command-line argument.
bot, err := tgbotapi.NewBotAPI(config.BotKey)
if err != nil {
log.Fatalf("Failed to create bot: %v", err)
}
if err := sendMessage(bot, config.UserID, messageText, config.Filepath); err != nil {
log.Fatalf("Failed to send message: %v", err)
}
notifySuccess()
}
func runServerMode(config *AppConfig) {
bot, err := tgbotapi.NewBotAPI(config.BotKey)
if err != nil {
log.Fatalf("Failed to create bot: %v", err)
}
// Delete the existing webhook
_, err = bot.RemoveWebhook()
if err != nil {
log.Fatalf("Failed to remove webhook: %v", err)
}
// Wait a bit to ensure webhook is fully deleted
time.Sleep(time.Second * 1)
u := tgbotapi.NewUpdate(0)
u.Timeout = 60
updates, err := bot.GetUpdatesChan(u)
if err != nil {
log.Fatalf("Failed to get updates channel: %v", err)
}
for update := range updates {
if update.Message != nil {
displayDebugData(update)
os.Exit(0)
}
}
}
func displayDebugData(update tgbotapi.Update) {
// Check if the update contains a message
if update.Message == nil {
log.Println("Received update does not contain a message.")
return
}
// Marshal the message part of the update to JSON for readability
messageData, err := json.MarshalIndent(update.Message, "", " ")
if err != nil {
log.Printf("Error marshalling message data: %v", err)
return
}
// Create a Lipgloss style for the message data display
messageStyle := lipgloss.NewStyle().
Border(lipgloss.NormalBorder()).
Padding(1, 2).
Margin(1).
BorderForeground(lipgloss.Color("63"))
// Render the message data with the style and print it
fmt.Println(messageStyle.Render(string(messageData)))
}
func sendMessage(bot *tgbotapi.BotAPI, userID int64, messageText, filepath string) error {
if filepath != "" {
return sendDocument(bot, userID, messageText, filepath)
}
return sendTextMessage(bot, userID, messageText)
}
func sendDocument(bot *tgbotapi.BotAPI, userID int64, messageText, filepath string) error {
fileBytes, err := ioutil.ReadFile(filepath)
if err != nil {
return fmt.Errorf("error reading file: %w", err)
}
fileUpload := tgbotapi.FileBytes{Name: filepath, Bytes: fileBytes}
msg := tgbotapi.NewDocumentUpload(userID, fileUpload)
msg.Caption = messageText
_, err = bot.Send(msg)
return err
}
func sendTextMessage(bot *tgbotapi.BotAPI, userID int64, messageText string) error {
msg := tgbotapi.NewMessage(userID, messageText)
_, err := bot.Send(msg)
return err
}
func notifySuccess() {
style := lipgloss.NewStyle().Foreground(lipgloss.Color("205"))
fmt.Println(style.Render("Message sent!"))
}
func readStdin() (string, error) {
stat, _ := os.Stdin.Stat()
if (stat.Mode() & os.ModeCharDevice) == 0 {
// Data is being piped to stdin
stdin, err := io.ReadAll(os.Stdin)
if err != nil {
return "", err
}
return string(stdin), nil
}
// No data piped, return empty string
return "", nil
}