From 3bb3d9bd4f552b540ff6704b3cc3abf529024fdd Mon Sep 17 00:00:00 2001 From: DmitryZagorulko Date: Mon, 4 Jun 2018 16:48:04 +0300 Subject: [PATCH 1/4] add user struct and migrate, check activity connection, upload avatar to s3 --- config.go | 15 ++- config.yml.dist | 9 ++ database.go | 8 ++ migrations/1528208070_app.down.sql | 1 + migrations/1528208070_app.up.sql | 13 +++ models.go | 10 ++ repository.go | 11 ++ routing.go | 6 +- telegram.go | 155 +++++++++++++++++++++++++---- 9 files changed, 203 insertions(+), 25 deletions(-) create mode 100644 migrations/1528208070_app.down.sql create mode 100644 migrations/1528208070_app.up.sql diff --git a/config.go b/config.go index a7de236..7a4ede1 100644 --- a/config.go +++ b/config.go @@ -4,8 +4,8 @@ import ( "io/ioutil" "path/filepath" - logging "github.com/op/go-logging" - yaml "gopkg.in/yaml.v2" + "github.com/op/go-logging" + "gopkg.in/yaml.v2" ) // TransportConfig struct @@ -15,6 +15,17 @@ type TransportConfig struct { SentryDSN string `yaml:"sentry_dsn"` HTTPServer HTTPServerConfig `yaml:"http_server"` Debug bool `yaml:"debug"` + UpdateTime int `yaml:"update_time"` + ConfigAWS ConfigAWS `yaml:"config_aws"` +} + +// ConfigAWS struct +type ConfigAWS struct { + AccessKeyID string `yaml:"access_key_id"` + SecretAccessKey string `yaml:"secret_access_key"` + Region string `yaml:"region"` + Bucket string `yaml:"bucket"` + ContentType string `yaml:"content_type"` } // DatabaseConfig struct diff --git a/config.yml.dist b/config.yml.dist index 357105b..d0ffe8b 100644 --- a/config.yml.dist +++ b/config.yml.dist @@ -10,3 +10,12 @@ sentry_dsn: ~ log_level: 5 debug: false + +update_time: 24 + +config_aws: + access_key_id: ~ + secret_access_key: ~ + region: ~ + bucket: ~ + content_type: image/jpeg diff --git a/database.go b/database.go index a412335..bc074a6 100644 --- a/database.go +++ b/database.go @@ -35,10 +35,18 @@ func NewDb(config *TransportConfig) *Orm { setCreatedAt := func(scope *gorm.Scope) { if scope.HasColumn("CreatedAt") { scope.SetColumn("CreatedAt", time.Now()) + scope.SetColumn("UpdatedAt", time.Now()) + } + } + + setUpdatedAt := func(scope *gorm.Scope) { + if scope.HasColumn("UpdatedAt") { + scope.SetColumn("UpdatedAt", time.Now()) } } db.Callback().Create().Replace("gorm:update_time_stamp", setCreatedAt) + db.Callback().Update().Register("update_time_stamp", setUpdatedAt) return &Orm{ DB: db, diff --git a/migrations/1528208070_app.down.sql b/migrations/1528208070_app.down.sql new file mode 100644 index 0000000..66c6be7 --- /dev/null +++ b/migrations/1528208070_app.down.sql @@ -0,0 +1 @@ +drop table user_tg; \ No newline at end of file diff --git a/migrations/1528208070_app.up.sql b/migrations/1528208070_app.up.sql new file mode 100644 index 0000000..21ea3ce --- /dev/null +++ b/migrations/1528208070_app.up.sql @@ -0,0 +1,13 @@ +create table user_tg +( + id serial not null + constraint user_tg_pkey + primary key, + external_id integer not null, + user_photo varchar(255), + user_photo_id varchar(100), + created_at timestamp with time zone, + updated_at timestamp with time zone, + constraint user_tg_key unique(external_id, user_photo, user_photo_id) +); + diff --git a/models.go b/models.go index aaa5236..f576dba 100644 --- a/models.go +++ b/models.go @@ -28,5 +28,15 @@ type Bot struct { Active bool `json:"active,omitempty"` } +// UserTG model +type UserTG struct { + ID int `gorm:"primary_key"` + ExternalID int `gorm:"external_id;not null;unique"` + UserPhotoURL string `gorm:"user_photo type:varchar(255);unique"` + UserPhotoID string `gorm:"user_photo_id type:varchar(100);unique"` + CreatedAt time.Time + UpdatedAt time.Time +} + //Bots list type Bots []Bot diff --git a/repository.go b/repository.go index 2d426c3..7eb94c9 100644 --- a/repository.go +++ b/repository.go @@ -78,3 +78,14 @@ func getConnectionById(id int) *Connection { return &connection } + +func (u *UserTG) saveUser() error { + return orm.DB.Save(u).Error +} + +func getUserByExternalID(eid int) *UserTG { + user := UserTG{ExternalID: eid} + orm.DB.First(&user) + + return &user +} diff --git a/routing.go b/routing.go index 6607831..74e5b96 100644 --- a/routing.go +++ b/routing.go @@ -152,7 +152,7 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { return } - bot, err := GetBotInfo(b.Token) + bot, err := tgbotapi.NewBotAPI(b.Token) if err != nil { logger.Error(b.Token, err.Error()) http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "incorrect_token"}), http.StatusBadRequest) @@ -278,8 +278,8 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { err = b.setBotActivity() if err != nil { raven.CaptureErrorAndWait(err, nil) - logger.Error(b.ID, err.Error()) http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) + logger.Error(b.ID, err.Error()) return } @@ -530,7 +530,7 @@ func activityHandler(w http.ResponseWriter, r *http.Request) { } c := getConnection(rec.ClientId) - c.Active = rec.Activity.Active + c.Active = rec.Activity.Active && !rec.Activity.Freeze if err := c.setConnectionActivity(); err != nil { raven.CaptureErrorAndWait(err, nil) diff --git a/telegram.go b/telegram.go index e7d433b..be8dd94 100644 --- a/telegram.go +++ b/telegram.go @@ -2,11 +2,18 @@ package main import ( "encoding/json" + "errors" "io/ioutil" "net/http" "strconv" "time" + "fmt" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/credentials" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/s3/s3manager" "github.com/getsentry/raven-go" "github.com/go-telegram-bot-api/telegram-bot-api" "github.com/retailcrm/mg-transport-api-client-go/v1" @@ -17,15 +24,6 @@ func setTransportRoutes() { http.HandleFunc("/webhook/", mgWebhookHandler) } -// GetBotInfo function -func GetBotInfo(token string) (*tgbotapi.BotAPI, error) { - bot, err := tgbotapi.NewBotAPI(token) - if err != nil { - return nil, err - } - return bot, nil -} - // GetBotName function func GetBotName(bot *tgbotapi.BotAPI) string { return bot.Self.FirstName @@ -40,21 +38,15 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string return } - if b.ID == 0 { - logger.Error(token, "missing") - w.WriteHeader(http.StatusBadRequest) - return - } - - if !b.Active { - logger.Error(token, "deactivated") + if b.ID == 0 || !b.Active { + logger.Error(token, "missing or deactivated") w.WriteHeader(http.StatusBadRequest) return } c := getConnectionById(b.ConnectionID) - if c.MGURL == "" || c.MGToken == "" { - logger.Error(token, "MGURL or MGToken is empty") + if !c.Active { + logger.Error(c.ClientID, " connection deativated") w.WriteHeader(http.StatusBadRequest) return } @@ -64,8 +56,8 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string bytes, err := ioutil.ReadAll(r.Body) if err != nil { raven.CaptureErrorAndWait(err, nil) - w.WriteHeader(http.StatusInternalServerError) logger.Error(token, err) + w.WriteHeader(http.StatusInternalServerError) return } @@ -81,6 +73,44 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string return } + user := getUserByExternalID(update.Message.From.ID) + + if time.Now().After(user.UpdatedAt.Add(time.Hour*time.Duration(config.UpdateTime))) || user.ID == 0 { + + fileID, fileURL, err := getFileIDAndURL(b.Token, update.Message.From.ID) + if err != nil { + raven.CaptureErrorAndWait(err, nil) + logger.Error(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + if fileID != user.UserPhotoID && fileURL != "" { + picURL, err := UploadUserAvatar(fileURL) + if err != nil { + raven.CaptureErrorAndWait(err, nil) + logger.Error(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + user.UserPhotoID = fileID + user.UserPhotoURL = picURL + } + + if user.ExternalID == 0 { + user.ExternalID = update.Message.From.ID + } + + err = user.saveUser() + if err != nil { + raven.CaptureErrorAndWait(err, nil) + logger.Error(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + } + var client = v1.New(c.MGURL, c.MGToken) if update.Message != nil { @@ -98,6 +128,7 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string ExternalID: strconv.Itoa(update.Message.From.ID), Nickname: update.Message.From.UserName, Firstname: update.Message.From.FirstName, + Avatar: user.UserPhotoURL, Lastname: update.Message.From.LastName, Language: update.Message.From.LanguageCode, }, @@ -154,6 +185,7 @@ func mgWebhookHandler(w http.ResponseWriter, r *http.Request) { if err != nil { raven.CaptureErrorAndWait(err, nil) logger.Error(err) + w.WriteHeader(http.StatusInternalServerError) return } @@ -166,6 +198,7 @@ func mgWebhookHandler(w http.ResponseWriter, r *http.Request) { if err != nil { raven.CaptureErrorAndWait(err, nil) logger.Error(err) + w.WriteHeader(http.StatusInternalServerError) return } @@ -175,11 +208,23 @@ func mgWebhookHandler(w http.ResponseWriter, r *http.Request) { b := getBotByChannel(msg.Data.ChannelID) if b.ID == 0 { logger.Error(msg.Data.ChannelID, "missing") + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("Bot missing")) return } if !b.Active { logger.Error(msg.Data.ChannelID, "deactivated") + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("Bot deactivated")) + return + } + + c := getConnectionById(b.ConnectionID) + if !c.Active { + logger.Error(c.ClientID, " connection deativated") + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte("Connection deactivated")) return } @@ -187,6 +232,7 @@ func mgWebhookHandler(w http.ResponseWriter, r *http.Request) { if err != nil { raven.CaptureErrorAndWait(err, nil) logger.Error(err) + w.WriteHeader(http.StatusInternalServerError) return } @@ -252,3 +298,72 @@ func mgWebhookHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Message deleted")) } } + +func getFileIDAndURL(token string, userID int) (fileID, fileURL string, err error) { + bot, err := tgbotapi.NewBotAPI(token) + if err != nil { + return + } + + bot.Debug = config.Debug + + res, err := bot.GetUserProfilePhotos( + tgbotapi.UserProfilePhotosConfig{ + UserID: userID, + Limit: 1, + }, + ) + if err != nil { + return + } + + if len(res.Photos) > 0 { + fileID = res.Photos[0][len(res.Photos[0])-1].FileID + fileURL, err = bot.GetFileDirectURL(fileID) + if err != nil { + return + } + return + } + + return +} + +func UploadUserAvatar(url string) (picURLs3 string, err error) { + s3Config := &aws.Config{ + Credentials: credentials.NewStaticCredentials( + config.ConfigAWS.AccessKeyID, + config.ConfigAWS.SecretAccessKey, + ""), + Region: aws.String(config.ConfigAWS.Region), + } + + s := session.Must(session.NewSession(s3Config)) + uploader := s3manager.NewUploader(s) + + resp, err := http.Get(url) + if err != nil { + return + } + + if resp.StatusCode >= http.StatusBadRequest { + return "", errors.New(fmt.Sprintf("get: %v code: %v", url, resp.StatusCode)) + } + + defer resp.Body.Close() + + result, err := uploader.Upload(&s3manager.UploadInput{ + Bucket: aws.String(config.ConfigAWS.Bucket), + Key: aws.String(fmt.Sprintf("%v.jpg", GenerateToken())), + Body: resp.Body, + ContentType: aws.String(config.ConfigAWS.ContentType), + ACL: aws.String("public-read"), + }) + if err != nil { + return + } + + picURLs3 = result.Location + + return +} From a391a01c0fd092a56e13e27905341a5c7899730a Mon Sep 17 00:00:00 2001 From: DmitryZagorulko Date: Thu, 7 Jun 2018 15:35:27 +0300 Subject: [PATCH 2/4] change naming user struct --- config.go | 14 +++++++------- config.yml.dist | 2 +- migrations/1528208070_app.down.sql | 2 +- migrations/1528208070_app.up.sql | 3 +-- models.go | 4 ++-- repository.go | 6 +++--- telegram.go | 2 +- 7 files changed, 16 insertions(+), 17 deletions(-) diff --git a/config.go b/config.go index 7a4ede1..6b8c6af 100644 --- a/config.go +++ b/config.go @@ -10,13 +10,13 @@ import ( // TransportConfig struct type TransportConfig struct { - LogLevel logging.Level `yaml:"log_level"` - Database DatabaseConfig `yaml:"database"` - SentryDSN string `yaml:"sentry_dsn"` - HTTPServer HTTPServerConfig `yaml:"http_server"` - Debug bool `yaml:"debug"` - UpdateTime int `yaml:"update_time"` - ConfigAWS ConfigAWS `yaml:"config_aws"` + LogLevel logging.Level `yaml:"log_level"` + Database DatabaseConfig `yaml:"database"` + SentryDSN string `yaml:"sentry_dsn"` + HTTPServer HTTPServerConfig `yaml:"http_server"` + Debug bool `yaml:"debug"` + UpdateInterval int `yaml:"update_interval"` + ConfigAWS ConfigAWS `yaml:"config_aws"` } // ConfigAWS struct diff --git a/config.yml.dist b/config.yml.dist index d0ffe8b..0618529 100644 --- a/config.yml.dist +++ b/config.yml.dist @@ -11,7 +11,7 @@ log_level: 5 debug: false -update_time: 24 +update_interval: 24 config_aws: access_key_id: ~ diff --git a/migrations/1528208070_app.down.sql b/migrations/1528208070_app.down.sql index 66c6be7..7fa478c 100644 --- a/migrations/1528208070_app.down.sql +++ b/migrations/1528208070_app.down.sql @@ -1 +1 @@ -drop table user_tg; \ No newline at end of file +drop table users; diff --git a/migrations/1528208070_app.up.sql b/migrations/1528208070_app.up.sql index 21ea3ce..e9c007f 100644 --- a/migrations/1528208070_app.up.sql +++ b/migrations/1528208070_app.up.sql @@ -1,4 +1,4 @@ -create table user_tg +create table users ( id serial not null constraint user_tg_pkey @@ -10,4 +10,3 @@ create table user_tg updated_at timestamp with time zone, constraint user_tg_key unique(external_id, user_photo, user_photo_id) ); - diff --git a/models.go b/models.go index f576dba..841ba0e 100644 --- a/models.go +++ b/models.go @@ -28,8 +28,8 @@ type Bot struct { Active bool `json:"active,omitempty"` } -// UserTG model -type UserTG struct { +// Users model +type Users struct { ID int `gorm:"primary_key"` ExternalID int `gorm:"external_id;not null;unique"` UserPhotoURL string `gorm:"user_photo type:varchar(255);unique"` diff --git a/repository.go b/repository.go index 7eb94c9..615cec0 100644 --- a/repository.go +++ b/repository.go @@ -79,12 +79,12 @@ func getConnectionById(id int) *Connection { return &connection } -func (u *UserTG) saveUser() error { +func (u *Users) saveUser() error { return orm.DB.Save(u).Error } -func getUserByExternalID(eid int) *UserTG { - user := UserTG{ExternalID: eid} +func getUserByExternalID(eid int) *Users { + user := Users{ExternalID: eid} orm.DB.First(&user) return &user diff --git a/telegram.go b/telegram.go index be8dd94..83833b3 100644 --- a/telegram.go +++ b/telegram.go @@ -75,7 +75,7 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string user := getUserByExternalID(update.Message.From.ID) - if time.Now().After(user.UpdatedAt.Add(time.Hour*time.Duration(config.UpdateTime))) || user.ID == 0 { + if time.Now().After(user.UpdatedAt.Add(time.Hour*time.Duration(config.UpdateInterval))) || user.ID == 0 { fileID, fileURL, err := getFileIDAndURL(b.Token, update.Message.From.ID) if err != nil { From 9636237212d1bff5461179871c47ee3461d8db33 Mon Sep 17 00:00:00 2001 From: DmitryZagorulko Date: Fri, 8 Jun 2018 12:13:02 +0300 Subject: [PATCH 3/4] minor fixes --- config_test.yml.dist | 9 +++++++++ database.go | 20 -------------------- migrations/1528208070_app.up.sql | 6 +++--- models.go | 2 +- routing.go | 5 +++++ telegram.go | 29 +++++++++++------------------ 6 files changed, 29 insertions(+), 42 deletions(-) diff --git a/config_test.yml.dist b/config_test.yml.dist index 090e513..113781d 100644 --- a/config_test.yml.dist +++ b/config_test.yml.dist @@ -10,3 +10,12 @@ sentry_dsn: ~ log_level: 5 debug: false + +update_interval: 24 + +config_aws: + access_key_id: ~ + secret_access_key: ~ + region: ~ + bucket: ~ + content_type: image/jpeg diff --git a/database.go b/database.go index bc074a6..db2cc8c 100644 --- a/database.go +++ b/database.go @@ -25,29 +25,9 @@ func NewDb(config *TransportConfig) *Orm { db.DB().SetMaxOpenConns(config.Database.MaxOpenConnections) db.DB().SetMaxIdleConns(config.Database.MaxIdleConnections) - gorm.DefaultTableNameHandler = func(db *gorm.DB, defaultTableName string) string { - return config.Database.TablePrefix + defaultTableName - } - db.SingularTable(true) db.LogMode(config.Database.Logging) - setCreatedAt := func(scope *gorm.Scope) { - if scope.HasColumn("CreatedAt") { - scope.SetColumn("CreatedAt", time.Now()) - scope.SetColumn("UpdatedAt", time.Now()) - } - } - - setUpdatedAt := func(scope *gorm.Scope) { - if scope.HasColumn("UpdatedAt") { - scope.SetColumn("UpdatedAt", time.Now()) - } - } - - db.Callback().Create().Replace("gorm:update_time_stamp", setCreatedAt) - db.Callback().Update().Register("update_time_stamp", setUpdatedAt) - return &Orm{ DB: db, } diff --git a/migrations/1528208070_app.up.sql b/migrations/1528208070_app.up.sql index e9c007f..ebaf04d 100644 --- a/migrations/1528208070_app.up.sql +++ b/migrations/1528208070_app.up.sql @@ -1,12 +1,12 @@ create table users ( id serial not null - constraint user_tg_pkey + constraint users_pkey primary key, external_id integer not null, - user_photo varchar(255), + user_photo_url varchar(255), user_photo_id varchar(100), created_at timestamp with time zone, updated_at timestamp with time zone, - constraint user_tg_key unique(external_id, user_photo, user_photo_id) + constraint users_key unique(external_id, user_photo_url, user_photo_id) ); diff --git a/models.go b/models.go index 841ba0e..79f067f 100644 --- a/models.go +++ b/models.go @@ -32,7 +32,7 @@ type Bot struct { type Users struct { ID int `gorm:"primary_key"` ExternalID int `gorm:"external_id;not null;unique"` - UserPhotoURL string `gorm:"user_photo type:varchar(255);unique"` + UserPhotoURL string `gorm:"user_photo_url type:varchar(255);unique"` UserPhotoID string `gorm:"user_photo_id type:varchar(100);unique"` CreatedAt time.Time UpdatedAt time.Time diff --git a/routing.go b/routing.go index 74e5b96..998f690 100644 --- a/routing.go +++ b/routing.go @@ -123,6 +123,7 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { logger.Error(err.Error()) return } + defer r.Body.Close() var b Bot @@ -228,6 +229,7 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { logger.Error(err.Error()) return } + defer r.Body.Close() var b Bot @@ -329,6 +331,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } + defer r.Body.Close() var c Connection @@ -374,6 +377,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { logger.Error(err.Error()) return } + defer r.Body.Close() var c Connection @@ -512,6 +516,7 @@ func activityHandler(w http.ResponseWriter, r *http.Request) { w.Write(jsonString) return } + defer r.Body.Close() var rec v5.ActivityCallback diff --git a/telegram.go b/telegram.go index 83833b3..1846469 100644 --- a/telegram.go +++ b/telegram.go @@ -46,7 +46,7 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string c := getConnectionById(b.ConnectionID) if !c.Active { - logger.Error(c.ClientID, " connection deativated") + logger.Error(c.ClientID, "connection deativated") w.WriteHeader(http.StatusBadRequest) return } @@ -60,6 +60,7 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string w.WriteHeader(http.StatusInternalServerError) return } + defer r.Body.Close() if config.Debug { logger.Debugf("telegramWebhookHandler: %v", string(bytes)) @@ -77,7 +78,7 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string if time.Now().After(user.UpdatedAt.Add(time.Hour*time.Duration(config.UpdateInterval))) || user.ID == 0 { - fileID, fileURL, err := getFileIDAndURL(b.Token, update.Message.From.ID) + fileID, fileURL, err := GetFileIDAndURL(b.Token, update.Message.From.ID) if err != nil { raven.CaptureErrorAndWait(err, nil) logger.Error(err) @@ -188,6 +189,7 @@ func mgWebhookHandler(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) return } + defer r.Body.Close() if config.Debug { logger.Debugf("mgWebhookHandler request: %v", string(bytes)) @@ -206,23 +208,16 @@ func mgWebhookHandler(w http.ResponseWriter, r *http.Request) { cid, _ := strconv.ParseInt(msg.Data.ExternalChatID, 10, 64) b := getBotByChannel(msg.Data.ChannelID) - if b.ID == 0 { - logger.Error(msg.Data.ChannelID, "missing") + if b.ID == 0 || !b.Active { + logger.Error(msg.Data.ChannelID, "missing or deactivated") w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("Bot missing")) - return - } - - if !b.Active { - logger.Error(msg.Data.ChannelID, "deactivated") - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte("Bot deactivated")) + w.Write([]byte("missing or deactivated")) return } c := getConnectionById(b.ConnectionID) if !c.Active { - logger.Error(c.ClientID, " connection deativated") + logger.Error(c.ClientID, "connection deativated") w.WriteHeader(http.StatusBadRequest) w.Write([]byte("Connection deactivated")) return @@ -299,7 +294,8 @@ func mgWebhookHandler(w http.ResponseWriter, r *http.Request) { } } -func getFileIDAndURL(token string, userID int) (fileID, fileURL string, err error) { +//GetFileIDAndURL function +func GetFileIDAndURL(token string, userID int) (fileID, fileURL string, err error) { bot, err := tgbotapi.NewBotAPI(token) if err != nil { return @@ -320,15 +316,12 @@ func getFileIDAndURL(token string, userID int) (fileID, fileURL string, err erro if len(res.Photos) > 0 { fileID = res.Photos[0][len(res.Photos[0])-1].FileID fileURL, err = bot.GetFileDirectURL(fileID) - if err != nil { - return - } - return } return } +//UploadUserAvatar function func UploadUserAvatar(url string) (picURLs3 string, err error) { s3Config := &aws.Config{ Credentials: credentials.NewStaticCredentials( From 1fff569009b9da38f4690af021bd8cc4207acb9f Mon Sep 17 00:00:00 2001 From: DmitryZagorulko Date: Fri, 8 Jun 2018 13:57:51 +0300 Subject: [PATCH 4/4] add folder name for s3 to config --- config.go | 1 + config.yml.dist | 1 + config_test.yml.dist | 1 + migrations/1528208070_app.up.sql | 2 +- repository.go | 13 +++++++++++-- routing.go | 10 +++++----- telegram.go | 16 +++++++--------- 7 files changed, 27 insertions(+), 17 deletions(-) diff --git a/config.go b/config.go index 6b8c6af..917e0dd 100644 --- a/config.go +++ b/config.go @@ -25,6 +25,7 @@ type ConfigAWS struct { SecretAccessKey string `yaml:"secret_access_key"` Region string `yaml:"region"` Bucket string `yaml:"bucket"` + FolderName string `yaml:"folder_name"` ContentType string `yaml:"content_type"` } diff --git a/config.yml.dist b/config.yml.dist index 0618529..04b3e09 100644 --- a/config.yml.dist +++ b/config.yml.dist @@ -18,4 +18,5 @@ config_aws: secret_access_key: ~ region: ~ bucket: ~ + folder_name: ~ content_type: image/jpeg diff --git a/config_test.yml.dist b/config_test.yml.dist index 113781d..208cc8f 100644 --- a/config_test.yml.dist +++ b/config_test.yml.dist @@ -18,4 +18,5 @@ config_aws: secret_access_key: ~ region: ~ bucket: ~ + folder_name: ~ content_type: image/jpeg diff --git a/migrations/1528208070_app.up.sql b/migrations/1528208070_app.up.sql index ebaf04d..ff491f5 100644 --- a/migrations/1528208070_app.up.sql +++ b/migrations/1528208070_app.up.sql @@ -8,5 +8,5 @@ create table users user_photo_id varchar(100), created_at timestamp with time zone, updated_at timestamp with time zone, - constraint users_key unique(external_id, user_photo_url, user_photo_id) + constraint users_key unique(external_id) ); diff --git a/repository.go b/repository.go index 615cec0..24b22b6 100644 --- a/repository.go +++ b/repository.go @@ -1,6 +1,10 @@ package main -import "github.com/jinzhu/gorm" +import ( + "time" + + "github.com/jinzhu/gorm" +) func getConnection(uid string) *Connection { var connection Connection @@ -79,7 +83,7 @@ func getConnectionById(id int) *Connection { return &connection } -func (u *Users) saveUser() error { +func (u *Users) save() error { return orm.DB.Save(u).Error } @@ -89,3 +93,8 @@ func getUserByExternalID(eid int) *Users { return &user } + +//Expired method +func (u *Users) Expired(updateInterval int) bool { + return time.Now().After(u.UpdatedAt.Add(time.Hour * time.Duration(updateInterval))) +} diff --git a/routing.go b/routing.go index 998f690..cfd578e 100644 --- a/routing.go +++ b/routing.go @@ -115,6 +115,7 @@ func connectHandler(w http.ResponseWriter, r *http.Request) { } func addBotHandler(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() setLocale(r.Header.Get("Accept-Language")) body, err := ioutil.ReadAll(r.Body) if err != nil { @@ -123,7 +124,6 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { logger.Error(err.Error()) return } - defer r.Body.Close() var b Bot @@ -221,6 +221,7 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { } func activityBotHandler(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() setLocale(r.Header.Get("Accept-Language")) body, err := ioutil.ReadAll(r.Body) if err != nil { @@ -229,7 +230,6 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { logger.Error(err.Error()) return } - defer r.Body.Close() var b Bot @@ -323,6 +323,7 @@ func settingsHandler(w http.ResponseWriter, r *http.Request, uid string) { } func saveHandler(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() setLocale(r.Header.Get("Accept-Language")) body, err := ioutil.ReadAll(r.Body) @@ -331,7 +332,6 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_save"}), http.StatusInternalServerError) return } - defer r.Body.Close() var c Connection @@ -368,6 +368,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { } func createHandler(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() setLocale(r.Header.Get("Accept-Language")) body, err := ioutil.ReadAll(r.Body) @@ -377,7 +378,6 @@ func createHandler(w http.ResponseWriter, r *http.Request) { logger.Error(err.Error()) return } - defer r.Body.Close() var c Connection @@ -487,6 +487,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { } func activityHandler(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() setLocale(r.Header.Get("Accept-Language")) w.Header().Set("Content-Type", "application/json") res := Response{Success: false} @@ -516,7 +517,6 @@ func activityHandler(w http.ResponseWriter, r *http.Request) { w.Write(jsonString) return } - defer r.Body.Close() var rec v5.ActivityCallback diff --git a/telegram.go b/telegram.go index 1846469..c531c2d 100644 --- a/telegram.go +++ b/telegram.go @@ -3,13 +3,12 @@ package main import ( "encoding/json" "errors" + "fmt" "io/ioutil" "net/http" "strconv" "time" - "fmt" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" @@ -30,6 +29,7 @@ func GetBotName(bot *tgbotapi.BotAPI) string { } func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string) { + defer r.Body.Close() b, err := getBotByToken(token) if err != nil { raven.CaptureErrorAndWait(err, nil) @@ -60,7 +60,6 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string w.WriteHeader(http.StatusInternalServerError) return } - defer r.Body.Close() if config.Debug { logger.Debugf("telegramWebhookHandler: %v", string(bytes)) @@ -76,7 +75,7 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string user := getUserByExternalID(update.Message.From.ID) - if time.Now().After(user.UpdatedAt.Add(time.Hour*time.Duration(config.UpdateInterval))) || user.ID == 0 { + if user.Expired(config.UpdateInterval) || user.ID == 0 { fileID, fileURL, err := GetFileIDAndURL(b.Token, update.Message.From.ID) if err != nil { @@ -103,7 +102,7 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string user.ExternalID = update.Message.From.ID } - err = user.saveUser() + err = user.save() if err != nil { raven.CaptureErrorAndWait(err, nil) logger.Error(err) @@ -182,6 +181,7 @@ func telegramWebhookHandler(w http.ResponseWriter, r *http.Request, token string } func mgWebhookHandler(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() bytes, err := ioutil.ReadAll(r.Body) if err != nil { raven.CaptureErrorAndWait(err, nil) @@ -189,7 +189,6 @@ func mgWebhookHandler(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) return } - defer r.Body.Close() if config.Debug { logger.Debugf("mgWebhookHandler request: %v", string(bytes)) @@ -338,16 +337,15 @@ func UploadUserAvatar(url string) (picURLs3 string, err error) { if err != nil { return } + defer resp.Body.Close() if resp.StatusCode >= http.StatusBadRequest { return "", errors.New(fmt.Sprintf("get: %v code: %v", url, resp.StatusCode)) } - defer resp.Body.Close() - result, err := uploader.Upload(&s3manager.UploadInput{ Bucket: aws.String(config.ConfigAWS.Bucket), - Key: aws.String(fmt.Sprintf("%v.jpg", GenerateToken())), + Key: aws.String(fmt.Sprintf("%v/%v.jpg", config.ConfigAWS.FolderName, GenerateToken())), Body: resp.Body, ContentType: aws.String(config.ConfigAWS.ContentType), ACL: aws.String("public-read"),