diff --git a/cmd/nourybot/command.go b/cmd/nourybot/command.go index e99edba..544b9a9 100644 --- a/cmd/nourybot/command.go +++ b/cmd/nourybot/command.go @@ -70,7 +70,7 @@ func (app *application) GetCommand(target, commandName string, userLevel int) (s // Cannot use app.Send() here since the command is a ascii pasta and will be // timed out, thus not passing the banphrase check app.Send() does before actually // sending the message. - app.TwitchClient.Say(target, command.Text) + app.SendNoBanphrase(target, command.Text) return "", nil } else { diff --git a/cmd/nourybot/main.go b/cmd/nourybot/main.go index d0a20ae..a3e0808 100644 --- a/cmd/nourybot/main.go +++ b/cmd/nourybot/main.go @@ -24,6 +24,7 @@ type config struct { twitchOauth string twitchClientId string twitchClientSecret string + twitchID string commandPrefix string db struct { dsn string @@ -74,6 +75,7 @@ func main() { cfg.twitchClientId = os.Getenv("TWITCH_CLIENT_ID") cfg.twitchClientSecret = os.Getenv("TWITCH_CLIENT_SECRET") cfg.commandPrefix = os.Getenv("TWITCH_COMMAND_PREFIX") + cfg.twitchID = os.Getenv("TWITCH_ID") tc := twitch.NewClient(cfg.twitchUsername, cfg.twitchOauth) switch envFlag { @@ -133,12 +135,12 @@ func main() { // Received a PrivateMessage (normal chat message). app.TwitchClient.OnPrivateMessage(func(message twitch.PrivateMessage) { - // sugar.Infow("New Twitch PrivateMessage", - // "message.Channel", message.Channel, - // "message.User.DisplayName", message.User.DisplayName, - // "message.User.ID", message.User.ID, - // "message.Message", message.Message, - // ) + sugar.Infow("New Twitch PrivateMessage", + "message.Channel", message.Channel, + "message.User.DisplayName", message.User.DisplayName, + "message.User.ID", message.User.ID, + "message.Message", message.Message, + ) // roomId is the Twitch UserID of the channel the message originated from. // If there is no roomId something went really wrong. diff --git a/cmd/nourybot/send.go b/cmd/nourybot/send.go index 1ff31c9..fe7943c 100644 --- a/cmd/nourybot/send.go +++ b/cmd/nourybot/send.go @@ -6,6 +6,8 @@ import ( "fmt" "io" "net/http" + + "github.com/google/uuid" ) // banphraseResponse is the data we receive back from @@ -84,6 +86,9 @@ func (app *application) Send(target, message string) { return } + identifier := uuid.NewString() + go app.Models.SentMessagesLogs.Insert(target, message, identifier) + // Since messages starting with `.` or `/` are used for special actions // (ban, whisper, timeout) and so on, we place an emote infront of it so // the actions wouldn't execute. `!` and `$` are common bot prefixes so we @@ -111,7 +116,7 @@ func (app *application) Send(target, message string) { return } else { // Message was fine. - app.TwitchClient.Say(target, message) + go app.TwitchClient.Say(target, message) return } } else { @@ -127,6 +132,30 @@ func (app *application) Send(target, message string) { } } +// Send is used to send twitch replies and contains the necessary +// safeguards and logic for that. +func (app *application) SendNoBanphrase(target, message string) { + // Message we are trying to send is empty. + if len(message) == 0 { + return + } + + identifier := uuid.NewString() + go app.Models.SentMessagesLogs.Insert(target, message, identifier) + + // Since messages starting with `.` or `/` are used for special actions + // (ban, whisper, timeout) and so on, we place an emote infront of it so + // the actions wouldn't execute. `!` and `$` are common bot prefixes so we + // don't allow them either. + if message[0] == '.' || message[0] == '/' || message[0] == '!' || message[0] == '$' { + message = ":tf: " + message + } + + // check the message for bad words before we say it + // Message was fine. + go app.TwitchClient.Say(target, message) +} + // SendNoLimit does not check for the maximum message size. // Used in sending commands from the database since the command has to have // been gotten in there somehow. So it fits. Still checks for banphrases. @@ -148,7 +177,7 @@ func (app *application) SendNoLimit(target, message string) { messageBanned, banReason := app.checkMessage(message) if messageBanned { // Bad message, replace message and log it. - app.TwitchClient.Say(target, "[BANPHRASED] monkaS") + go app.TwitchClient.Say(target, "[BANPHRASED] monkaS") app.Log.Infow("banned message detected", "target channel", target, "message", message, @@ -164,7 +193,9 @@ func (app *application) SendNoLimit(target, message string) { // https://discuss.dev.twitch.tv/t/missing-client-side-message-length-check/21316 // TODO: Make it so it splits at a space instead and not in the middle of a word. // Message was fine. - app.TwitchClient.Say(target, message) + identifier := uuid.NewString() + go app.Models.SentMessagesLogs.Insert(target, message, identifier) + go app.TwitchClient.Say(target, message) return } } diff --git a/internal/data/models.go b/internal/data/models.go index 8cb72c7..63bdffe 100644 --- a/internal/data/models.go +++ b/internal/data/models.go @@ -60,15 +60,19 @@ type Models struct { CommandsLogs interface { Insert(twitchLogin, twitchId, twitchChannel, twitchMessage, commandName string, uLvl int, identifier, rawMsg string) } + SentMessagesLogs interface { + Insert(twitchChannel, twitchMessage, identifier string) + } } func NewModels(db *sql.DB) Models { return Models{ - Channels: ChannelModel{DB: db}, - Users: UserModel{DB: db}, - Commands: CommandModel{DB: db}, - Timers: TimerModel{DB: db}, - Uploads: UploadModel{DB: db}, - CommandsLogs: CommandsLogModel{DB: db}, + Channels: ChannelModel{DB: db}, + Users: UserModel{DB: db}, + Commands: CommandModel{DB: db}, + Timers: TimerModel{DB: db}, + Uploads: UploadModel{DB: db}, + CommandsLogs: CommandsLogModel{DB: db}, + SentMessagesLogs: SentMessagesLogModel{DB: db}, } } diff --git a/internal/data/sent_messages_logs.go b/internal/data/sent_messages_logs.go new file mode 100644 index 0000000..efe844a --- /dev/null +++ b/internal/data/sent_messages_logs.go @@ -0,0 +1,41 @@ +package data + +import ( + "database/sql" +) + +type SentMessagesLog struct { + ID int `json:"id"` + TwitchChannel string `json:"twitch_channel,omitempty"` + TwitchMessage string `json:"twitch_message,omitempty"` + Identifier string `json:"identifier,omitempty"` +} + +type SentMessagesLogModel struct { + DB *sql.DB +} + +// Get tries to find a command in the database with the provided name. +func (s SentMessagesLogModel) Insert(twitchChannel, twitchMessage, identifier string) { + query := ` + INSERT into sent_messages_logs(twitch_channel, twitch_message, identifier) + VALUES ($1, $2, $3) + RETURNING id; + ` + + args := []interface{}{twitchChannel, twitchMessage, identifier} + + result, err := s.DB.Exec(query, args...) + if err != nil { + return + } + + rowsAffected, err := result.RowsAffected() + if err != nil { + return + } + + if rowsAffected == 0 { + return + } +} diff --git a/internal/data/uploads.go b/internal/data/uploads.go index db71ccd..115edea 100644 --- a/internal/data/uploads.go +++ b/internal/data/uploads.go @@ -57,8 +57,6 @@ func (u UploadModel) Insert(twitchLogin, twitchID, twitchChannel, twitchMessage, if rowsAffected == 0 { return } - - return } func (u UploadModel) UpdateUploadURL(identifier, uploadURL string) { diff --git a/migrations/000007_create_sent_messages_logs_table.down.sql b/migrations/000007_create_sent_messages_logs_table.down.sql new file mode 100644 index 0000000..e0861b5 --- /dev/null +++ b/migrations/000007_create_sent_messages_logs_table.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS sent_messages_logs; diff --git a/migrations/000007_create_sent_messages_logs_table.up.sql b/migrations/000007_create_sent_messages_logs_table.up.sql new file mode 100644 index 0000000..afe0aa7 --- /dev/null +++ b/migrations/000007_create_sent_messages_logs_table.up.sql @@ -0,0 +1,10 @@ +CREATE TABLE IF NOT EXISTS sent_messages_logs ( + id bigserial PRIMARY KEY, + added_at timestamp(0) with time zone NOT NULL DEFAULT NOW(), + twitch_channel text NOT NULL, + twitch_message text NOT NULL, + identifier text NOT NULL +); + +INSERT INTO sent_messages_logs (added_at,twitch_channel,twitch_message,identifier) VALUES + (NOW(),'nourybot','Weather for Vilnius, LT: Feels like: 9.3°C. Currently 10.85°C with a high of 12.07°C and a low of 10.49°C, humidity: 50%, wind: 2.57m/s.','04fbd9c0-47da-466f-b966-44d1d04de11c');