2023-03-11 08:35:23 +00:00
package main
2023-03-11 09:00:25 +00:00
import (
"errors"
"fmt"
"io/ioutil"
"log"
2023-03-11 12:38:01 +00:00
"net/http"
2023-03-11 09:00:25 +00:00
"os"
2023-03-11 10:17:30 +00:00
"strconv"
2023-03-11 09:00:25 +00:00
"strings"
2023-03-18 07:35:05 +00:00
"valera/calories"
2023-03-11 09:00:25 +00:00
"valera/commands"
2023-03-11 10:17:30 +00:00
"valera/db"
2023-03-18 07:35:05 +00:00
tgbot "github.com/go-telegram-bot-api/telegram-bot-api"
"github.com/umputun/go-flags"
2023-03-11 09:00:25 +00:00
)
2023-03-11 08:35:23 +00:00
2023-03-12 19:54:19 +00:00
var (
workoutTypes = [ ] string {
"Отжимания" ,
"Пресс" ,
2023-03-14 19:09:08 +00:00
"Подтягивания" ,
2023-03-12 19:54:19 +00:00
}
)
2023-03-11 08:37:46 +00:00
const (
2023-03-14 19:09:08 +00:00
version = "v1.5.0"
2023-03-11 08:37:46 +00:00
)
2023-03-11 09:00:25 +00:00
type Opts struct {
Token string ` short:"t" long:"token" description:"Telegram api token" `
Name string ` short:"n" long:"name" description:"Telegram bot name" default:"@body_weight_loss_bot" `
}
var opts Opts
2023-03-12 19:38:48 +00:00
func readFile ( filename string ) ( string , error ) {
b , err := ioutil . ReadFile ( filename )
2023-03-11 09:00:25 +00:00
if err != nil {
return "" , err
}
str := string ( b )
return str , nil
}
2023-03-11 08:35:23 +00:00
func main ( ) {
2023-03-11 09:00:25 +00:00
run ( )
}
func run ( ) {
p := flags . NewParser ( & opts , flags . PrintErrors | flags . PassDoubleDash | flags . HelpFlag )
p . SubcommandsOptional = true
if _ , err := p . Parse ( ) ; err != nil {
if err . ( * flags . Error ) . Type != flags . ErrHelp {
log . Println ( errors . New ( "[ERROR] cli error: " + err . Error ( ) ) )
}
os . Exit ( 2 )
}
if opts . Token == "" {
2023-03-12 19:38:48 +00:00
token , err := readFile ( "token.txt" )
2023-03-11 09:00:25 +00:00
if err != nil {
panic ( err )
}
opts . Token = strings . ReplaceAll ( token , "\n" , "" )
}
fmt . Println ( opts . Token )
bot , err := tgbot . NewBotAPI ( opts . Token )
if err != nil {
panic ( err )
}
2023-03-12 19:38:48 +00:00
mongoURL , err := readFile ( "mongo_url.txt" )
if err != nil {
panic ( err )
}
mongoURL = strings . ReplaceAll ( mongoURL , "\n" , "" )
fmt . Println ( mongoURL )
dbName , err := readFile ( "db_name.txt" )
if err != nil {
panic ( err )
}
dbName = strings . ReplaceAll ( dbName , "\n" , "" )
fmt . Println ( dbName )
2023-03-14 19:09:08 +00:00
dataBase , err := db . NewDB (
2023-03-12 19:38:48 +00:00
mongoURL ,
dbName ,
)
2023-03-14 19:09:08 +00:00
if err != nil {
panic ( err )
}
2023-03-12 19:38:48 +00:00
2023-03-11 09:00:25 +00:00
u := tgbot . NewUpdate ( 0 )
u . Timeout = 60
updates , err := bot . GetUpdatesChan ( u )
if err != nil {
panic ( err )
}
2023-03-11 12:38:01 +00:00
go func ( ) {
http . HandleFunc ( "/go" , func ( w http . ResponseWriter , r * http . Request ) {
2023-03-12 19:38:48 +00:00
chats , err := dataBase . GetAllChats ( )
2023-03-11 12:38:01 +00:00
if err != nil {
w . Header ( ) . Add ( "Content-Type" , "application/json" )
w . WriteHeader ( http . StatusInternalServerError )
_ , _ = fmt . Fprintf ( w , ` { "result":"error"} ` )
return
}
for _ , chatID := range chats {
2023-03-12 19:38:48 +00:00
sendGoToChat ( bot , dataBase , chatID )
2023-03-11 12:38:01 +00:00
}
w . Header ( ) . Add ( "Content-Type" , "application/json" )
w . WriteHeader ( http . StatusOK )
_ , _ = fmt . Fprintf ( w , ` { "result":"ok"} ` )
} )
2023-03-11 17:40:37 +00:00
http . HandleFunc ( "/stat" , func ( w http . ResponseWriter , r * http . Request ) {
2023-03-12 19:38:48 +00:00
chats , err := dataBase . GetAllChats ( )
2023-03-11 17:40:37 +00:00
if err != nil {
fmt . Println ( err )
w . Header ( ) . Add ( "Content-Type" , "application/json" )
w . WriteHeader ( http . StatusInternalServerError )
_ , _ = fmt . Fprintf ( w , ` { "result":"error"} ` )
return
}
for _ , chatID := range chats {
2023-03-13 18:49:54 +00:00
if err := sendStatToChat ( bot , dataBase , chatID , "Напоминаю:\n- Cе г о дня больше не жрем!\n\n" , true ) ; err != nil {
2023-03-11 17:40:37 +00:00
fmt . Println ( err )
w . Header ( ) . Add ( "Content-Type" , "application/json" )
w . WriteHeader ( http . StatusInternalServerError )
_ , _ = fmt . Fprintf ( w , ` { "result":"error"} ` )
return
}
}
w . Header ( ) . Add ( "Content-Type" , "application/json" )
w . WriteHeader ( http . StatusOK )
_ , _ = fmt . Fprintf ( w , ` { "result":"ok"} ` )
} )
2023-03-11 12:38:01 +00:00
port := ":10002"
log . Println ( "Server is start up! port" , port )
log . Fatal ( http . ListenAndServe ( port , nil ) )
} ( )
2023-03-11 09:00:25 +00:00
log . Println ( "Run" , opts . Name )
for update := range updates {
if update . Message == nil {
continue
}
text := update . Message . Text
chatID := update . Message . Chat . ID
2023-03-11 11:30:12 +00:00
username := update . Message . From . UserName
2023-03-11 10:30:38 +00:00
2023-03-12 19:38:48 +00:00
userInfoDTO , err := dataBase . GetChatInfo ( chatID )
2023-03-11 10:30:38 +00:00
if err != nil {
log . Println ( err )
continue
}
2023-03-12 19:54:19 +00:00
isWorkout := false
for _ , workoutType := range workoutTypes {
if userInfoDTO . GetStatus ( ) == db . UserState ( workoutType ) {
count , err := strconv . Atoi ( text )
if err != nil {
log . Println ( err )
continue
}
if err := dataBase . AddWorkout ( chatID , db . NewWorkout ( workoutType , count , username ) ) ; err != nil {
log . Println ( err )
continue
}
msgText := fmt . Sprintf ( "Отлично, %s, записал." , text )
if count <= 0 {
msgText = "Плохо, хочешь быть толстым и не красивым?"
}
_ , _ = bot . Send ( tgbot . NewMessage ( chatID , msgText ) )
if err := dataBase . SetStatusToChat ( chatID , db . UserStateNone ) ; err != nil {
log . Println ( err )
}
isWorkout = true
break
}
}
if isWorkout {
continue
}
2023-03-12 06:53:50 +00:00
switch userInfoDTO . GetStatus ( ) {
case db . UserStateGo :
2023-03-12 19:54:19 +00:00
if err := dataBase . SetStatusToChat ( chatID , db . UserState ( text ) ) ; err != nil {
2023-03-11 11:30:12 +00:00
log . Println ( err )
2023-03-11 10:17:30 +00:00
}
2023-03-12 19:54:19 +00:00
msg := tgbot . NewMessage ( chatID , fmt . Sprintf ( "%s, отпишись сколько раз ты выполнил упражнение" , text ) )
2023-03-12 07:02:54 +00:00
msg . ReplyMarkup = tgbot . NewRemoveKeyboard ( false )
2023-03-11 10:17:30 +00:00
_ , _ = bot . Send ( msg )
2023-03-11 09:34:31 +00:00
continue
2023-03-12 06:53:50 +00:00
case db . UserStateEat :
2023-03-18 07:35:05 +00:00
count , err := calories . CalcCalories ( text )
2023-03-12 06:53:50 +00:00
if err != nil {
log . Println ( err )
continue
}
2023-03-12 19:38:48 +00:00
if err := dataBase . AddCalories ( chatID , db . NewCalories ( count , username ) ) ; err != nil {
2023-03-12 06:53:50 +00:00
log . Println ( err )
continue
}
if count <= 0 {
_ , _ = bot . Send ( tgbot . NewMessage ( chatID , "В с е фигня, давай по новой" ) )
continue
}
2023-03-13 18:15:11 +00:00
_ , _ = bot . Send ( tgbot . NewMessage ( chatID , fmt . Sprintf ( "Калории, фу, %d, записал." , count ) ) )
2023-03-12 19:38:48 +00:00
if err := dataBase . SetStatusToChat ( chatID , db . UserStateNone ) ; err != nil {
2023-03-12 06:53:50 +00:00
log . Println ( err )
}
continue
2023-03-11 09:34:31 +00:00
}
2023-03-11 09:00:25 +00:00
command := commands . Command ( strings . Replace ( text , opts . Name , "" , 1 ) )
switch command {
case commands . Start :
_ , _ = bot . Send ( tgbot . NewMessage ( chatID , fmt . Sprintf ( "Здорова, я Валера (%s), твой тренер (%d)." , version , chatID ) ) )
2023-03-12 19:38:48 +00:00
if err := dataBase . SetStatusToChat ( chatID , db . UserStateNone ) ; err != nil {
2023-03-11 11:30:12 +00:00
log . Println ( err )
}
2023-03-11 09:00:25 +00:00
case commands . Help :
2023-03-14 19:09:08 +00:00
_ , _ = bot . Send ( tgbot . NewMessage ( chatID , "Вот что я умею:\n\n1) Предлагать размяться\n - несколько видов упражнений 6 раз в день\n2) Показывать статистику за день\n3) Считать калории\n - введи одно число, я запишу калории\n - введи 2 числа через пробел одно количество грамм другое количество калорий в 100 граммах (порядок не важен), я посчитаю\n - введи название того что ты съел, я посчитаю (если знаю)" ) )
2023-03-11 09:00:25 +00:00
case commands . Ping :
_ , _ = bot . Send ( tgbot . NewMessage ( chatID , "pong" ) )
2023-03-11 09:34:31 +00:00
case commands . Go :
2023-03-12 19:38:48 +00:00
sendGoToChat ( bot , dataBase , chatID )
2023-03-11 11:30:12 +00:00
case commands . Stat :
2023-03-13 18:49:54 +00:00
if err := sendStatToChat ( bot , dataBase , chatID , "" , false ) ; err != nil {
2023-03-11 17:40:37 +00:00
fmt . Println ( err )
2023-03-11 11:30:12 +00:00
continue
}
2023-03-12 06:53:50 +00:00
case commands . Eat :
if _ , err := bot . Send ( tgbot . NewMessage ( chatID , "Вижу ты поел, отпишись сколько калорий было" ) ) ; err == nil {
2023-03-12 19:38:48 +00:00
if err := dataBase . SetStatusToChat ( chatID , db . UserStateEat ) ; err != nil {
2023-03-12 06:53:50 +00:00
log . Println ( err )
}
}
2023-03-11 09:00:25 +00:00
}
}
2023-03-11 08:35:23 +00:00
}
2023-03-11 12:38:01 +00:00
2023-03-12 19:38:48 +00:00
func sendGoToChat ( bot * tgbot . BotAPI , dataBase * db . DB , chatID int64 ) {
2023-03-12 19:54:19 +00:00
msg := tgbot . NewMessage ( chatID , "Давай немного разомнемся, выбирай:" )
2023-03-14 19:09:08 +00:00
rows := make ( [ ] [ ] tgbot . KeyboardButton , 0 , len ( workoutTypes ) )
2023-03-12 19:54:19 +00:00
for _ , workoutType := range workoutTypes {
2023-03-14 19:09:08 +00:00
rows = append ( rows , tgbot . NewKeyboardButtonRow ( tgbot . NewKeyboardButton ( workoutType ) ) )
2023-03-12 19:54:19 +00:00
}
2023-03-14 19:09:08 +00:00
msg . ReplyMarkup = tgbot . NewReplyKeyboard ( rows ... )
2023-03-11 12:38:01 +00:00
if _ , err := bot . Send ( msg ) ; err == nil {
2023-03-12 19:38:48 +00:00
if err := dataBase . SetStatusToChat ( chatID , db . UserStateGo ) ; err != nil {
2023-03-11 12:38:01 +00:00
log . Println ( err )
}
}
}
2023-03-11 17:40:37 +00:00
2023-03-13 18:49:54 +00:00
func sendStatToChat ( bot * tgbot . BotAPI , dataBase * db . DB , chatID int64 , prefix string , cron bool ) error {
stat , err := dataBase . GetStat ( chatID , cron )
2023-03-11 17:40:37 +00:00
if err != nil {
return err
}
msgText := prefix + "Результаты за сегодня:\n"
for k , v := range stat {
msgText += fmt . Sprintf ( "- %s: %d\n" , k , v )
}
_ , _ = bot . Send ( tgbot . NewMessage ( chatID , msgText ) )
return nil
}