fix old comments

This commit is contained in:
lyx0 2024-02-28 11:53:39 +01:00
parent 9377bcf897
commit 78dff0e347
40 changed files with 151 additions and 242 deletions

View file

@ -7,9 +7,9 @@ import (
"github.com/lyx0/nourybot/pkg/ivr" "github.com/lyx0/nourybot/pkg/ivr"
) )
// AddChannel takes in a channel name, then calls GetIdByLogin for the // AddChannel calls ivr.IDByUsername with the provided login and tries to insert
// channels ID and inserts both the name and id value into the database. // the Twitch login and userID into the database. If there is no error thrown the
// If there is no error thrown the TwitchClient joins the channel afterwards. // TwitchClient joins the channel afterwards.
func (app *application) AddChannel(login string, message twitch.PrivateMessage) { func (app *application) AddChannel(login string, message twitch.PrivateMessage) {
userID := ivr.IDByUsername(login) userID := ivr.IDByUsername(login)
@ -27,7 +27,6 @@ func (app *application) AddChannel(login string, message twitch.PrivateMessage)
} }
// GetAllChannels() queries the database and lists all channels. // GetAllChannels() queries the database and lists all channels.
// Only used for debug/information purposes.
func (app *application) GetAllChannels() { func (app *application) GetAllChannels() {
channel, err := app.Models.Channels.GetAll() channel, err := app.Models.Channels.GetAll()
if err != nil { if err != nil {

View file

@ -10,8 +10,8 @@ import (
"github.com/lyx0/nourybot/internal/data" "github.com/lyx0/nourybot/internal/data"
) )
// AddCommand splits a message into two parts and passes on the // AddCommand splits a message into two parts and passes on the name and text
// name and text to the database handler. // to the database handler.
func (app *application) AddCommand(name string, message twitch.PrivateMessage) { func (app *application) AddCommand(name string, message twitch.PrivateMessage) {
// snipLength is the length we need to "snip" off of the start of `message`. // snipLength is the length we need to "snip" off of the start of `message`.
// `()add command` = +12 // `()add command` = +12
@ -21,13 +21,12 @@ func (app *application) AddCommand(name string, message twitch.PrivateMessage) {
snipLength := 15 snipLength := 15
// Split the twitch message at `snipLength` plus length of the name of the // Split the twitch message at `snipLength` plus length of the name of the
// command that we want to add. // command that we want to add. The part of the message we are left over with
// The part of the message we are left over with is then passed on to the database // is then passed on to the database handlers as the `text` part of the command.
// handlers as the `text` part of the command.
// //
// e.g. `()addcommand CoolSponsors Check out CoolSponsor.com they are the coolest sponsors! // e.g. ()addcommand CoolSponsors Check out CoolSponsor.com they are the coolest sponsors!
// | <- snipLength + name -> | <--- command text with however many characters ---> | // | <- snipLength + name -> | <--- command text with however many characters ---> |
// | <----- 14 + 12 ------> | // | <----- 15 + 12 ------> |
text := message.Message[snipLength+len(name) : len(message.Message)] text := message.Message[snipLength+len(name) : len(message.Message)]
command := &data.Command{ command := &data.Command{
Name: name, Name: name,
@ -50,12 +49,11 @@ func (app *application) AddCommand(name string, message twitch.PrivateMessage) {
} }
} }
// GetCommand queries the database for a name. If an entry exists it checks // GetCommand queries the database for a command with the provided name. If an entry exists
// if the Command.Level is 0, if it is the command.Text value is returned. // it checks if the Command.Level is 0, if it is the command.Text value is returned.
// //
// If the Command.Level is not 0 it queries the database for the level of the // If the Command.Level is not 0 it queries the database for the level of the user who sent
// user who sent the message. If the users level is equal or higher // the message. If the users level is equal or higher the command.Text field is returned.
// the command.Text field is returned.
func (app *application) GetCommand(target, commandName string, userLevel int) (string, error) { func (app *application) GetCommand(target, commandName string, userLevel int) (string, error) {
app.Log.Infow("command", app.Log.Infow("command",
"target", target, "target", target,
@ -75,22 +73,17 @@ func (app *application) GetCommand(target, commandName string, userLevel int) (s
} else if userLevel >= command.Level { } else if userLevel >= command.Level {
// Userlevel is sufficient so return the command.Text // Userlevel is sufficient so return the command.Text
return command.Text, nil return command.Text, nil
// If the command has no level set just return the text.
// Otherwise check if the level is high enough.
} }
// Userlevel was not enough so return an empty string and error. // Userlevel was not enough so return an empty string and error.
return "", ErrUserInsufficientLevel return "", ErrUserInsufficientLevel
} }
// GetCommand queries the database for a name. If an entry exists it checks // GetCommandDescription queries the database for a command with the provided name in the channel.
// if the Command.Level is 0, if it is the command.Text value is returned. // If a command exist it then checks if the Command.Level is 0, if it is the command.Text value is returned.
// //
// If the Command.Level is not 0 it queries the database for the level of the // If the Command.Level is not 0 it queries the database for the level of the user who sent
// user who sent the message. If the users level is equal or higher // the message. If the users level is equal or higher the command.Text field is returned.
// the command.Text field is returned.
func (app *application) GetCommandDescription(name, channel, username string) (string, error) { func (app *application) GetCommandDescription(name, channel, username string) (string, error) {
// Fetch the command from the database if it exists.
command, err := app.Models.Commands.Get(name, channel) command, err := app.Models.Commands.Get(name, channel)
if err != nil { if err != nil {
// It probably did not exist // It probably did not exist
@ -102,8 +95,7 @@ func (app *application) GetCommandDescription(name, channel, username string) (s
if command.Level == 0 { if command.Level == 0 {
return command.Description, nil return command.Description, nil
} else { } else {
// Get the user from the database to check if the userlevel is equal // Get the user from the database to check if the userlevel is sufficient.
// or higher than the command.Level.
user, err := app.Models.Users.Get(username) user, err := app.Models.Users.Get(username)
if err != nil { if err != nil {
return "", err return "", err
@ -118,8 +110,8 @@ func (app *application) GetCommandDescription(name, channel, username string) (s
return "", ErrUserInsufficientLevel return "", ErrUserInsufficientLevel
} }
// EditCommandLevel takes in a name and level string and updates the entry with name // EditCommandLevel checks if a command with the provided name exists in the database. If it does it
// to the supplied level value. // changes the level of the command with the supplied value.
func (app *application) EditCommandLevel(name, lvl string, message twitch.PrivateMessage) { func (app *application) EditCommandLevel(name, lvl string, message twitch.PrivateMessage) {
level, err := strconv.Atoi(lvl) level, err := strconv.Atoi(lvl)
if err != nil { if err != nil {
@ -141,10 +133,9 @@ func (app *application) EditCommandLevel(name, lvl string, message twitch.Privat
} }
} }
// DebugCommand checks if a command with the provided name exists in the database // DebugCommand checks if a command with the provided name exists in the database and if it
// and outputs information about it in the chat. // does it creates a new paste with the commands information.
func (app *application) DebugCommand(name string, message twitch.PrivateMessage) { func (app *application) DebugCommand(name string, message twitch.PrivateMessage) {
// Query the database for a command with the provided name
cmd, err := app.Models.Commands.Get(name, message.Channel) cmd, err := app.Models.Commands.Get(name, message.Channel)
if err != nil { if err != nil {
reply := fmt.Sprintf("Something went wrong FeelsBadMan %s", err) reply := fmt.Sprintf("Something went wrong FeelsBadMan %s", err)
@ -160,7 +151,6 @@ func (app *application) DebugCommand(name string, message twitch.PrivateMessage)
cmd.Description, cmd.Description,
) )
//app.Send(message.Channel, reply)
resp, err := app.uploadPaste(reply) resp, err := app.uploadPaste(reply)
if err != nil { if err != nil {
app.Log.Errorln("Could not upload paste:", err) app.Log.Errorln("Could not upload paste:", err)
@ -168,7 +158,6 @@ func (app *application) DebugCommand(name string, message twitch.PrivateMessage)
return return
} }
app.Send(message.Channel, resp, message) app.Send(message.Channel, resp, message)
//app.SendEmail(fmt.Sprintf("DEBUG for command %s", name), reply)
return return
} }
} }
@ -205,7 +194,7 @@ func (app *application) EditCommandHelp(name string, message twitch.PrivateMessa
} }
} }
// DeleteCommand takes in a name value and deletes the command from the database if it exists. // DeleteCommand takes in a name of a command and deletes the command from the database if it exists.
func (app *application) DeleteCommand(name string, message twitch.PrivateMessage) { func (app *application) DeleteCommand(name string, message twitch.PrivateMessage) {
err := app.Models.Commands.Delete(name, message.Channel) err := app.Models.Commands.Delete(name, message.Channel)
if err != nil { if err != nil {
@ -218,6 +207,7 @@ func (app *application) DeleteCommand(name string, message twitch.PrivateMessage
app.Send(message.Channel, reply, message) app.Send(message.Channel, reply, message)
} }
// LogCommand is called when a command is called and logs information about it in the database.
func (app *application) LogCommand(msg twitch.PrivateMessage, commandName string, userLevel int) { func (app *application) LogCommand(msg twitch.PrivateMessage, commandName string, userLevel int) {
twitchLogin := msg.User.Name twitchLogin := msg.User.Name
twitchID := msg.User.ID twitchID := msg.User.ID
@ -229,8 +219,7 @@ func (app *application) LogCommand(msg twitch.PrivateMessage, commandName string
go app.Models.CommandsLogs.Insert(twitchLogin, twitchID, twitchChannel, twitchMessage, commandName, userLevel, identifier, rawMsg) go app.Models.CommandsLogs.Insert(twitchLogin, twitchID, twitchChannel, twitchMessage, commandName, userLevel, identifier, rawMsg)
} }
// InitialTimers is called on startup and queries the database for a list of // ListCommands queries the databse for all commands, and then creates a new paste with them.
// timers and then adds each onto the scheduler.
func (app *application) ListCommands() string { func (app *application) ListCommands() string {
command, err := app.Models.Commands.GetAll() command, err := app.Models.Commands.GetAll()
if err != nil { if err != nil {
@ -277,8 +266,8 @@ func (app *application) ListCommands() string {
return reply return reply
} }
// InitialTimers is called on startup and queries the database for a list of // ListChannelCommands queries the databse for all commands in a specified twitch channel
// timers and then adds each onto the scheduler. // and then creates a new paste with them.
func (app *application) ListChannelCommands(channel string) string { func (app *application) ListChannelCommands(channel string) string {
channelUrl := fmt.Sprintf("https://bot.noury.li/commands/%s", channel) channelUrl := fmt.Sprintf("https://bot.noury.li/commands/%s", channel)
commandUrl := "https://bot.noury.li/commands" commandUrl := "https://bot.noury.li/commands"

View file

@ -37,6 +37,8 @@ func (app *application) NewDownload(destination, target, link string, msg twitch
} }
} }
// ConvertAndSave downloads a given video link with yt-dlp, then tries to convert it
// to mp4 with ffmpeg and afterwards serves the video from /public/uploads
func (app *application) ConvertAndSave(fName, link string, msg twitch.PrivateMessage) { func (app *application) ConvertAndSave(fName, link string, msg twitch.PrivateMessage) {
goutubedl.Path = "yt-dlp" goutubedl.Path = "yt-dlp"
uuid_og := uuid.NewString() uuid_og := uuid.NewString()
@ -64,10 +66,8 @@ func (app *application) ConvertAndSave(fName, link string, msg twitch.PrivateMes
app.Send(msg.Channel, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err), msg) app.Send(msg.Channel, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err), msg)
return return
} }
//app.Send(target, "Downloaded.", msg)
fileName := fmt.Sprintf("/public/uploads/%s.%s", uuid_og, rExt) fileName := fmt.Sprintf("/public/uploads/%s.%s", uuid_og, rExt)
f, err := os.Create(fileName) f, err := os.Create(fileName)
//app.Send(target, fmt.Sprintf("Filename: %s", fileName), msg)
if err != nil { if err != nil {
app.Log.Errorln(err) app.Log.Errorln(err)
app.Send(msg.Channel, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err), msg) app.Send(msg.Channel, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err), msg)
@ -100,6 +100,8 @@ func (app *application) ConvertAndSave(fName, link string, msg twitch.PrivateMes
app.Send(msg.Channel, fmt.Sprintf("https://bot.noury.li/uploads/%s.mp4", fName), msg) app.Send(msg.Channel, fmt.Sprintf("https://bot.noury.li/uploads/%s.mp4", fName), msg)
} }
// ConvertAndSave downloads a given video link with yt-dlp, then tries to convert it
// to mp4 with ffmpeg and afterwards passes the result to NewUpload with yaf.li as destination.
func (app *application) ConvertToMP4(link string, msg twitch.PrivateMessage) { func (app *application) ConvertToMP4(link string, msg twitch.PrivateMessage) {
fName := "in" fName := "in"
goutubedl.Path = "yt-dlp" goutubedl.Path = "yt-dlp"
@ -129,10 +131,8 @@ func (app *application) ConvertToMP4(link string, msg twitch.PrivateMessage) {
app.Send(msg.Channel, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err), msg) app.Send(msg.Channel, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err), msg)
return return
} }
//app.Send(target, "Downloaded.", msg)
fileName := fmt.Sprintf("/public/uploads/%s.%s", uuid_og, rExt) fileName := fmt.Sprintf("/public/uploads/%s.%s", uuid_og, rExt)
f, err := os.Create(fileName) f, err := os.Create(fileName)
//app.Send(target, fmt.Sprintf("Filename: %s", fileName), msg)
if err != nil { if err != nil {
app.Log.Errorln(err) app.Log.Errorln(err)
app.Send(msg.Channel, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err), msg) app.Send(msg.Channel, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err), msg)
@ -165,6 +165,8 @@ func (app *application) ConvertToMP4(link string, msg twitch.PrivateMessage) {
go app.NewUpload("yaf", out, msg.Channel, uuid_new, msg) go app.NewUpload("yaf", out, msg.Channel, uuid_new, msg)
} }
// YafDownload downloads a given link with yt-dlp and then passes the result on to the NewUpload function
// with yaf.li as destination.
func (app *application) YafDownload(target, link, identifier string, msg twitch.PrivateMessage) { func (app *application) YafDownload(target, link, identifier string, msg twitch.PrivateMessage) {
goutubedl.Path = "yt-dlp" goutubedl.Path = "yt-dlp"
@ -191,10 +193,8 @@ func (app *application) YafDownload(target, link, identifier string, msg twitch.
app.Send(target, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err), msg) app.Send(target, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err), msg)
return return
} }
//app.Send(target, "Downloaded.", msg)
fileName := fmt.Sprintf("/public/uploads/%s.%s", identifier, rExt) fileName := fmt.Sprintf("/public/uploads/%s.%s", identifier, rExt)
f, err := os.Create(fileName) f, err := os.Create(fileName)
//app.Send(target, fmt.Sprintf("Filename: %s", fileName), msg)
if err != nil { if err != nil {
app.Log.Errorln(err) app.Log.Errorln(err)
@ -210,14 +210,12 @@ func (app *application) YafDownload(target, link, identifier string, msg twitch.
downloadResult.Close() downloadResult.Close()
f.Close() f.Close()
// duration := 5 * time.Second
// dl.twitchClient.Say(target, "ResidentSleeper ..")
// time.Sleep(duration)
go app.NewUpload("yaf", fileName, target, identifier, msg) go app.NewUpload("yaf", fileName, target, identifier, msg)
} }
// KappaDownload downloads a given link with yt-dlp and then passes the result on to the NewUpload function
// with kappa.lol as destination.
func (app *application) KappaDownload(target, link, identifier string, msg twitch.PrivateMessage) { func (app *application) KappaDownload(target, link, identifier string, msg twitch.PrivateMessage) {
goutubedl.Path = "yt-dlp" goutubedl.Path = "yt-dlp"
@ -263,14 +261,12 @@ func (app *application) KappaDownload(target, link, identifier string, msg twitc
downloadResult.Close() downloadResult.Close()
f.Close() f.Close()
// duration := 5 * time.Second
// dl.twitchClient.Say(target, "ResidentSleeper ..")
// time.Sleep(duration)
go app.NewUpload("kappa", fileName, target, identifier, msg) go app.NewUpload("kappa", fileName, target, identifier, msg)
} }
// GoFileDownload downloads a given link with yt-dlp and then passes the result to the NewUpload function
// with gofile.io as destination.
func (app *application) GofileDownload(target, link, identifier string, msg twitch.PrivateMessage) { func (app *application) GofileDownload(target, link, identifier string, msg twitch.PrivateMessage) {
goutubedl.Path = "yt-dlp" goutubedl.Path = "yt-dlp"
@ -324,6 +320,8 @@ func (app *application) GofileDownload(target, link, identifier string, msg twit
go app.NewUpload("gofile", fileName, target, identifier, msg) go app.NewUpload("gofile", fileName, target, identifier, msg)
} }
// CatboxDownload downloads a given link with yt-dlp and then passes the result to NewUpload function
// with catbox.moe as destination.
func (app *application) CatboxDownload(target, link, identifier string, msg twitch.PrivateMessage) { func (app *application) CatboxDownload(target, link, identifier string, msg twitch.PrivateMessage) {
goutubedl.Path = "yt-dlp" goutubedl.Path = "yt-dlp"
var fileName string var fileName string
@ -348,10 +346,8 @@ func (app *application) CatboxDownload(target, link, identifier string, msg twit
app.Send(target, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err), msg) app.Send(target, fmt.Sprintf("Something went wrong FeelsBadMan: %q", err), msg)
return return
} }
//app.Send(target, "Downloaded.", msg)
fileName = fmt.Sprintf("/public/uploads/%s.%s", identifier, rExt) fileName = fmt.Sprintf("/public/uploads/%s.%s", identifier, rExt)
f, err := os.Create(fileName) f, err := os.Create(fileName)
//app.Send(target, fmt.Sprintf("Filename: %s", fileName), msg)
if err != nil { if err != nil {
app.Log.Errorln(err) app.Log.Errorln(err)

View file

@ -8,7 +8,8 @@ import (
"gopkg.in/gomail.v2" "gopkg.in/gomail.v2"
) )
// Thanks to Twitch moving whispers again I just use email now. // SendEmail sends an email to the email address configured in the .env file
// with the supplied body.
func (app *application) SendEmail(subject, body string) { func (app *application) SendEmail(subject, body string) {
err := godotenv.Load() err := godotenv.Load()
if err != nil { if err != nil {

View file

@ -17,16 +17,6 @@ const (
) )
func (app *application) createLiveSubscription(target, channel string) string { func (app *application) createLiveSubscription(target, channel string) string {
// client, err := helix.NewClient(&helix.Options{
// ClientID: app.Config.twitchClientId,
// AppAccessToken: app.HelixClient.GetAppAccessToken(),
// })
// if err != nil {
// app.Log.Errorw("Error creating new helix client",
// "err", err,
// )
// }
uid := ivr.IDByUsername(channel) uid := ivr.IDByUsername(channel)
if uid == "xd" { if uid == "xd" {
return fmt.Sprintf("Could not find user with name %v", channel) return fmt.Sprintf("Could not find user with name %v", channel)
@ -56,22 +46,12 @@ func (app *application) createLiveSubscription(target, channel string) string {
} }
func (app *application) deleteLiveSubscription(target, channel string) string { func (app *application) deleteLiveSubscription(target, channel string) string {
client, err := helix.NewClient(&helix.Options{
ClientID: app.Config.twitchClientId,
AppAccessToken: app.HelixClient.GetAppAccessToken(),
})
if err != nil {
app.Log.Errorw("Error creating new helix client",
"err", err,
)
}
uid := ivr.IDByUsername(channel) uid := ivr.IDByUsername(channel)
if uid == "xd" { if uid == "xd" {
return fmt.Sprintf("Could not find user with name %v", channel) return fmt.Sprintf("Could not find user with name %v", channel)
} }
resp, err := client.GetEventSubSubscriptions(&helix.EventSubSubscriptionsParams{ resp, err := app.HelixClient.GetEventSubSubscriptions(&helix.EventSubSubscriptionsParams{
UserID: uid, UserID: uid,
}) })
if err != nil { if err != nil {
@ -103,7 +83,7 @@ func (app *application) deleteLiveSubscription(target, channel string) string {
//eventSubID := resp.Data.EventSubSubscriptions[0].ID //eventSubID := resp.Data.EventSubSubscriptions[0].ID
//app.SendNoContext("nouryxd", eventSubID) //app.SendNoContext("nouryxd", eventSubID)
resp2, err := client.RemoveEventSubSubscription(eventSubID) resp2, err := app.HelixClient.RemoveEventSubSubscription(eventSubID)
if err != nil { if err != nil {
app.Log.Errorw("Error getting EventSub subscriptions", app.Log.Errorw("Error getting EventSub subscriptions",
"resp", resp, "resp", resp,
@ -121,16 +101,6 @@ func (app *application) deleteLiveSubscription(target, channel string) string {
} }
func (app *application) createOfflineSubscription(target, channel string) string { func (app *application) createOfflineSubscription(target, channel string) string {
// client, err := helix.NewClient(&helix.Options{
// ClientID: app.Config.twitchClientId,
// AppAccessToken: app.HelixClient.GetAppAccessToken(),
// })
// if err != nil {
// app.Log.Errorw("Error creating new helix client",
// "err", err,
// )
// }
uid := ivr.IDByUsername(channel) uid := ivr.IDByUsername(channel)
if uid == "xd" { if uid == "xd" {
return fmt.Sprintf("Could not find user with name %v", channel) return fmt.Sprintf("Could not find user with name %v", channel)
@ -160,22 +130,12 @@ func (app *application) createOfflineSubscription(target, channel string) string
} }
func (app *application) deleteOfflineSubscription(target, channel string) string { func (app *application) deleteOfflineSubscription(target, channel string) string {
client, err := helix.NewClient(&helix.Options{
ClientID: app.Config.twitchClientId,
AppAccessToken: app.HelixClient.GetAppAccessToken(),
})
if err != nil {
app.Log.Errorw("Error creating new helix client",
"err", err,
)
}
uid := ivr.IDByUsername(channel) uid := ivr.IDByUsername(channel)
if uid == "xd" { if uid == "xd" {
return fmt.Sprintf("Could not find user with name %v", channel) return fmt.Sprintf("Could not find user with name %v", channel)
} }
resp, err := client.GetEventSubSubscriptions(&helix.EventSubSubscriptionsParams{ resp, err := app.HelixClient.GetEventSubSubscriptions(&helix.EventSubSubscriptionsParams{
UserID: uid, UserID: uid,
}) })
if err != nil { if err != nil {
@ -207,7 +167,7 @@ func (app *application) deleteOfflineSubscription(target, channel string) string
//eventSubID = resp.Data.EventSubSubscriptions[0].ID //eventSubID = resp.Data.EventSubSubscriptions[0].ID
//app.SendNoContext("nouryxd", eventSubID) //app.SendNoContext("nouryxd", eventSubID)
resp2, err := client.RemoveEventSubSubscription(eventSubID) resp2, err := app.HelixClient.RemoveEventSubSubscription(eventSubID)
if err != nil { if err != nil {
app.Log.Errorw("Error getting EventSub subscriptions", app.Log.Errorw("Error getting EventSub subscriptions",
"resp", resp, "resp", resp,

View file

@ -50,9 +50,6 @@ type application struct {
// Rdb *redis.Client // Rdb *redis.Client
} }
// main() only calls the run function so that we can go around the limitation
// that main() cannot return anything, like int for error codes in c for example.
// https://grafana.com/blog/2024/02/09/how-i-write-http-services-in-go-after-13-years/
func main() { func main() {
ctx := context.Background() ctx := context.Background()
ctx, cancel := signal.NotifyContext(ctx, os.Interrupt) ctx, cancel := signal.NotifyContext(ctx, os.Interrupt)
@ -65,8 +62,7 @@ func main() {
func run(ctx context.Context, w io.Writer, args []string) error { func run(ctx context.Context, w io.Writer, args []string) error {
var cfg config var cfg config
// Initialize a new sugared logger that we'll pass on
// down through the application.
logger := zap.NewExample() logger := zap.NewExample()
defer func() { defer func() {
if err := logger.Sync(); err != nil { if err := logger.Sync(); err != nil {
@ -156,13 +152,6 @@ func run(ctx context.Context, w io.Writer, args []string) error {
// Received a PrivateMessage (normal chat message). // Received a PrivateMessage (normal chat message).
app.TwitchClient.OnPrivateMessage(func(message twitch.PrivateMessage) { 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,
// )
// roomId is the Twitch UserID of the channel the message originated from. // roomId is the Twitch UserID of the channel the message originated from.
// If there is no roomId something went really wrong. // If there is no roomId something went really wrong.
roomId := message.Tags["room-id"] roomId := message.Tags["room-id"]

View file

@ -14,6 +14,7 @@ type latestFullResult struct {
Results int `json:"results"` Results int `json:"results"`
Data []latestSingleResult `json:"data"` Data []latestSingleResult `json:"data"`
} }
type latestSingleResult struct { type latestSingleResult struct {
ID string `json:"id"` ID string `json:"id"`
PreTime string `json:"pretime"` PreTime string `json:"pretime"`

View file

@ -10,6 +10,7 @@ import (
"net/http" "net/http"
"os" "os"
"sort" "sort"
"time"
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
"github.com/lyx0/nourybot/internal/data" "github.com/lyx0/nourybot/internal/data"
@ -77,6 +78,9 @@ func (app *application) eventsubFollow(w http.ResponseWriter, r *http.Request, _
w.WriteHeader(200) w.WriteHeader(200)
w.Write([]byte("ok")) w.Write([]byte("ok"))
// Sleep for 5 seconds before checking querying game and title as they might not be updated.
time.Sleep(time.Duration(5) * time.Second)
game := ivr.GameByUsername(liveEvent.BroadcasterUserLogin) game := ivr.GameByUsername(liveEvent.BroadcasterUserLogin)
title := ivr.TitleByUsername(liveEvent.BroadcasterUserLogin) title := ivr.TitleByUsername(liveEvent.BroadcasterUserLogin)
@ -114,8 +118,6 @@ func (app *application) timersRoute(w http.ResponseWriter, r *http.Request, _ ht
app.Log.Errorw("Error trying to retrieve all timer for a channel from database", err) app.Log.Errorw("Error trying to retrieve all timer for a channel from database", err)
return return
} }
// The slice of timers is only used to log them at
// the start so it looks a bit nicer.
// Iterate over all timers and then add them onto the scheduler. // Iterate over all timers and then add them onto the scheduler.
for i, v := range timerData { for i, v := range timerData {
@ -164,8 +166,6 @@ func (app *application) channelTimersRoute(w http.ResponseWriter, r *http.Reques
app.Log.Errorw("Error trying to retrieve all timer for a channel from database", err) app.Log.Errorw("Error trying to retrieve all timer for a channel from database", err)
return return
} }
// The slice of timers is only used to log them at
// the start so it looks a bit nicer.
// Iterate over all timers and then add them onto the scheduler. // Iterate over all timers and then add them onto the scheduler.
for i, v := range timerData { for i, v := range timerData {
@ -206,11 +206,8 @@ func (app *application) commandsRoute(w http.ResponseWriter, r *http.Request, _
return return
} }
// The slice of timers is only used to log them at
// the start so it looks a bit nicer.
var cs []string var cs []string
// Iterate over all timers and then add them onto the scheduler.
for i, v := range helpText { for i, v := range helpText {
// idk why this works but it does so no touchy touchy. // idk why this works but it does so no touchy touchy.
// https://github.com/robfig/cron/issues/420#issuecomment-940949195 // https://github.com/robfig/cron/issues/420#issuecomment-940949195

View file

@ -12,16 +12,14 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
) )
// banphraseResponse is the data we receive back from // banphraseResponse is the data we receive back from the banphrase API
// the banphrase API
type banphraseResponse struct { type banphraseResponse struct {
Banned bool `json:"banned"` Banned bool `json:"banned"`
InputMessage string `json:"input_message"` InputMessage string `json:"input_message"`
BanphraseData banphraseData `json:"banphrase_data"` BanphraseData banphraseData `json:"banphrase_data"`
} }
// banphraseData contains details about why a message // banphraseData contains details about why a message was banphrased.
// was banphrased.
type banphraseData struct { type banphraseData struct {
Id int `json:"id"` Id int `json:"id"`
Name string `json:"name"` Name string `json:"name"`
@ -83,8 +81,7 @@ func (app *application) checkMessage(text string) (bool, string) {
return true, "Banphrase API couldn't be reached monkaS" return true, "Banphrase API couldn't be reached monkaS"
} }
// Send is used to send twitch replies and contains the necessary // SendNoContext is used to send twitch replies without the full twitch.PrivateMessage context to be logged.
// safeguards and logic for that.
func (app *application) SendNoContext(target, message string) { func (app *application) SendNoContext(target, message string) {
// Message we are trying to send is empty. // Message we are trying to send is empty.
if len(message) == 0 { if len(message) == 0 {
@ -141,8 +138,8 @@ func (app *application) SendNoContext(target, message string) {
} }
} }
// Send is used to send twitch replies and contains the necessary // Send is used to send twitch replies and contains the necessary safeguards and logic for that.
// safeguards and logic for that. // Send also logs the twitch.PrivateMessage contents into the database.
func (app *application) Send(target, message string, msgContext twitch.PrivateMessage) { func (app *application) Send(target, message string, msgContext twitch.PrivateMessage) {
// Message we are trying to send is empty. // Message we are trying to send is empty.
if len(message) == 0 { if len(message) == 0 {
@ -200,8 +197,7 @@ func (app *application) Send(target, message string, msgContext twitch.PrivateMe
} }
} }
// Send is used to send twitch replies and contains the necessary // SendNoBanphrase does not check the banphrase before sending a twitch mesage.
// safeguards and logic for that.
func (app *application) SendNoBanphrase(target, message string) { func (app *application) SendNoBanphrase(target, message string) {
// Message we are trying to send is empty. // Message we are trying to send is empty.
if len(message) == 0 { if len(message) == 0 {

View file

@ -52,9 +52,8 @@ func (app *application) AddTimer(name, repeat string, message twitch.PrivateMess
Repeat: repeat, Repeat: repeat,
} }
// Check if the time string we got is valid, this is important // Check if the time string we got is valid, this is important because the Scheduler
// because the Scheduler panics instead of erroring out if an invalid // panics instead of erroring out if an invalid time format string is supplied.
// time format string is supplied.
if validateTimeFormat { if validateTimeFormat {
timer := &data.Timer{ timer := &data.Timer{
Name: name, Name: name,
@ -70,19 +69,14 @@ func (app *application) AddTimer(name, repeat string, message twitch.PrivateMess
"timer", timer, "timer", timer,
"error", err, "error", err,
) )
reply := fmt.Sprintln("Something went wrong FeelsBadMan") reply := fmt.Sprintln("Something went wrong FeelsBadMan")
app.Send(message.Channel, reply, message) app.Send(message.Channel, reply, message)
return return
} else { } else {
// cronName is the internal, unique tag/name for the timer.
// A timer named "sponsor" in channel "forsen" will be named "forsensponsor"
app.Scheduler.AddFunc(fmt.Sprintf("@every %s", repeat), func() { app.newPrivateMessageTimer(message.Channel, text) }, id) app.Scheduler.AddFunc(fmt.Sprintf("@every %s", repeat), func() { app.newPrivateMessageTimer(message.Channel, text) }, id)
app.Log.Infow("Added new timer", app.Log.Infow("Added new timer",
"timer", timer, "timer", timer,
) )
reply := fmt.Sprintf("Successfully added timer %s repeating every %s", name, repeat) reply := fmt.Sprintf("Successfully added timer %s repeating every %s", name, repeat)
app.Send(message.Channel, reply, message) app.Send(message.Channel, reply, message)
return return
@ -102,8 +96,6 @@ func (app *application) AddTimer(name, repeat string, message twitch.PrivateMess
// with the same name. It is technically not editing the timer. // with the same name. It is technically not editing the timer.
func (app *application) EditTimer(name, repeat string, message twitch.PrivateMessage) { func (app *application) EditTimer(name, repeat string, message twitch.PrivateMessage) {
// Check if a timer with that name is in the database. // Check if a timer with that name is in the database.
app.Log.Info(name)
old, err := app.Models.Timers.Get(name) old, err := app.Models.Timers.Get(name)
if err != nil { if err != nil {
app.Log.Errorw("Could not get timer", app.Log.Errorw("Could not get timer",
@ -115,9 +107,7 @@ func (app *application) EditTimer(name, repeat string, message twitch.PrivateMes
return return
} }
// -----------------------
// Delete the old timer // Delete the old timer
// -----------------------
identifier := old.Identifier identifier := old.Identifier
app.Scheduler.RemoveJob(identifier) app.Scheduler.RemoveJob(identifier)
@ -134,21 +124,8 @@ func (app *application) EditTimer(name, repeat string, message twitch.PrivateMes
return return
} }
// -----------------------
// Add the new timer // Add the new timer
// -----------------------
//cmdParams := strings.SplitN(message.Message, " ", 500)
// prefixLength is the length of `()editcommand` plus +2 (for the space and zero based)
prefix := "()edit timer" prefix := "()edit timer"
prefixLength := len("()add timer")
nameLength := len(name)
repeatLength := len(repeat)
app.Log.Infow("Lengths",
"prefix", prefixLength,
"name", nameLength,
"repeat", repeatLength,
"sum", prefixLength+nameLength+repeatLength,
)
// Split the message into the parts we need. // Split the message into the parts we need.
// //
@ -156,8 +133,8 @@ func (app *application) EditTimer(name, repeat string, message twitch.PrivateMes
// parts: | prefix | |name | |repeat | <----------- text -------------> | // parts: | prefix | |name | |repeat | <----------- text -------------> |
text := message.Message[3+len(prefix)+len(name)+len(repeat) : len(message.Message)] text := message.Message[3+len(prefix)+len(name)+len(repeat) : len(message.Message)]
// validateTimeFormat will be true if the repeat parameter is in // validateTimeFormat will be true if the repeat parameter is in the format
// the format of either 30m, 10h, or 10h30m. // of either 30m, 10h, or 10h30m.
validateTimeFormat, err := regexp.MatchString(`^(\d{1,2}[h])$|^(\d+[m])$|^(\d+[s])$|((\d{1,2}[h])((([0]?|[1-5]{1})[0-9])[m]))$`, repeat) validateTimeFormat, err := regexp.MatchString(`^(\d{1,2}[h])$|^(\d+[m])$|^(\d+[s])$|((\d{1,2}[h])((([0]?|[1-5]{1})[0-9])[m]))$`, repeat)
if err != nil { if err != nil {
app.Log.Errorw("Received malformed time format in timer", app.Log.Errorw("Received malformed time format in timer",
@ -176,9 +153,8 @@ func (app *application) EditTimer(name, repeat string, message twitch.PrivateMes
Repeat: repeat, Repeat: repeat,
} }
// Check if the time string we got is valid, this is important // Check if the time string we got is valid, this is important because the
// because the Scheduler panics instead of erroring out if an invalid // Scheduler panics instead of erroring out if an invalid time format string is supplied.
// time format string is supplied.
if validateTimeFormat { if validateTimeFormat {
timer := &data.Timer{ timer := &data.Timer{
Name: name, Name: name,
@ -194,13 +170,10 @@ func (app *application) EditTimer(name, repeat string, message twitch.PrivateMes
"timer", timer, "timer", timer,
"error", err, "error", err,
) )
reply := fmt.Sprintln("Something went wrong FeelsBadMan") reply := fmt.Sprintln("Something went wrong FeelsBadMan")
app.Send(message.Channel, reply, message) app.Send(message.Channel, reply, message)
return return
} else { // this is a bit scuffed. The else here is the end of a successful call. } else { // this is a bit scuffed. The else here is the end of a successful call.
// cronName is the internal, unique tag/name for the timer.
// A timer named "sponsor" in channel "forsen" will be named "forsensponsor"
app.Scheduler.AddFunc(fmt.Sprintf("@every %s", repeat), func() { app.newPrivateMessageTimer(message.Channel, text) }, id) app.Scheduler.AddFunc(fmt.Sprintf("@every %s", repeat), func() { app.newPrivateMessageTimer(message.Channel, text) }, id)
app.Log.Infow("Updated a timer", app.Log.Infow("Updated a timer",
@ -225,8 +198,7 @@ func (app *application) EditTimer(name, repeat string, message twitch.PrivateMes
} }
} }
// InitialTimers is called on startup and queries the database for a list of // ListTimers queries the database for all timers and uploads the contents as a paste.
// timers and then adds each onto the scheduler.
func (app *application) ListTimers() string { func (app *application) ListTimers() string {
timer, err := app.Models.Timers.GetAll() timer, err := app.Models.Timers.GetAll()
if err != nil { if err != nil {
@ -257,11 +229,7 @@ func (app *application) ListTimers() string {
"\n\n", "\n\n",
v.ID, v.Name, v.Identifier, v.Text, v.Channel, v.Repeat, v.ID, v.Name, v.Identifier, v.Text, v.Channel, v.Repeat,
) )
// Add new value to the slice
ts = append(ts, t) ts = append(ts, t)
//app.Scheduler.AddFunc(repeating, func() { app.newPrivateMessageTimer(v.Channel, v.Text) }, cronName)
} }
reply, err := app.uploadPaste(strings.Join(ts, "")) reply, err := app.uploadPaste(strings.Join(ts, ""))
@ -282,8 +250,6 @@ func (app *application) InitialTimers() {
return return
} }
// The slice of timers is only used to log them at
// the start so it looks a bit nicer.
var ts []*data.Timer var ts []*data.Timer
// Iterate over all timers and then add them onto the scheduler. // Iterate over all timers and then add them onto the scheduler.
@ -311,15 +277,14 @@ func (app *application) InitialTimers() {
) )
} }
// newPrivateMessageTimer is a helper function to set timers // newPrivateMessageTimer is a helper function to set timers which trigger
// which trigger into sending a twitch PrivateMessage. // into sending a twitch PrivateMessage.
func (app *application) newPrivateMessageTimer(channel, text string) { func (app *application) newPrivateMessageTimer(channel, text string) {
app.SendNoContext(channel, text) app.SendNoContext(channel, text)
} }
// DeleteTimer takes in the name of a timer and tries to delete the timer from the database. // DeleteTimer takes in the name of a timer and tries to delete the timer from the database.
func (app *application) DeleteTimer(name string, message twitch.PrivateMessage) { func (app *application) DeleteTimer(name string, message twitch.PrivateMessage) {
identifier, err := app.Models.Timers.GetIdentifier(name) identifier, err := app.Models.Timers.GetIdentifier(name)
if err != nil { if err != nil {
app.Log.Errorw("Error retrieving identifier rom database", app.Log.Errorw("Error retrieving identifier rom database",
@ -354,6 +319,7 @@ func (app *application) DeleteTimer(name string, message twitch.PrivateMessage)
app.Send(message.Channel, reply, message) app.Send(message.Channel, reply, message)
} }
// DebugChannelTimers queries the database for all timers in channel and uploads the contents as a paste.
func (app *application) DebugChannelTimers(channel string) string { func (app *application) DebugChannelTimers(channel string) string {
timer, err := app.Models.Timers.GetChannelTimer(channel) timer, err := app.Models.Timers.GetChannelTimer(channel)
if err != nil { if err != nil {
@ -396,6 +362,8 @@ func (app *application) DebugChannelTimers(channel string) string {
return reply return reply
} }
// ListchannelTimer queries the database for all timers in channel and uploads the contents as a paste.
func (app *application) ListChannelTimer(channel string) string { func (app *application) ListChannelTimer(channel string) string {
timer, err := app.Models.Timers.GetChannelTimer(channel) timer, err := app.Models.Timers.GetChannelTimer(channel)
if err != nil { if err != nil {
@ -403,8 +371,6 @@ func (app *application) ListChannelTimer(channel string) string {
return "" return ""
} }
// The slice of timers is only used to log them at
// the start so it looks a bit nicer.
var ts []string var ts []string
// Iterate over all timers and then add them onto the scheduler. // Iterate over all timers and then add them onto the scheduler.
@ -423,7 +389,6 @@ func (app *application) ListChannelTimer(channel string) string {
v.Name, v.Text, v.Repeat, v.Name, v.Text, v.Repeat,
) )
// Add new value to the slice
ts = append(ts, t) ts = append(ts, t)
} }

View file

@ -44,6 +44,7 @@ func (app *application) NewUpload(destination, fileName, target, identifier stri
} }
} }
// CatboxUpload uplodas the given file to catbox.moe.
func (app *application) CatboxUpload(target, fileName, identifier string, msg twitch.PrivateMessage) { func (app *application) CatboxUpload(target, fileName, identifier string, msg twitch.PrivateMessage) {
defer os.Remove(fileName) defer os.Remove(fileName)
file, err := os.Open(fileName) file, err := os.Open(fileName)
@ -54,10 +55,6 @@ func (app *application) CatboxUpload(target, fileName, identifier string, msg tw
defer file.Close() defer file.Close()
app.Send(target, "Uploading to catbox.moe... dankCircle", msg) app.Send(target, "Uploading to catbox.moe... dankCircle", msg)
// if size := helper.FileSize(fileName); size > 209715200 {
// return "", fmt.Errorf("file too large, size: %d MB", size/1024/1024)
// }
r, w := io.Pipe() r, w := io.Pipe()
m := multipart.NewWriter(w) m := multipart.NewWriter(w)
@ -112,6 +109,7 @@ func (app *application) CatboxUpload(target, fileName, identifier string, msg tw
app.Send(target, reply, msg) app.Send(target, reply, msg)
} }
// GetGofileServer queries to gofile api for the server name to upload to
func (app *application) GetGofileServer() string { func (app *application) GetGofileServer() string {
type gofileData struct { type gofileData struct {
Server string `json:"server"` Server string `json:"server"`
@ -139,6 +137,7 @@ func (app *application) GetGofileServer() string {
return uploadServer return uploadServer
} }
// GofileUpload uplodas the given file to gofile.io.
func (app *application) GofileUpload(target, path, identifier string, msg twitch.PrivateMessage) { func (app *application) GofileUpload(target, path, identifier string, msg twitch.PrivateMessage) {
defer os.Remove(path) defer os.Remove(path)
app.Send(target, "Uploading to gofile.io... dankCircle", msg) app.Send(target, "Uploading to gofile.io... dankCircle", msg)
@ -231,6 +230,7 @@ func (app *application) GofileUpload(target, path, identifier string, msg twitch
app.Send(target, reply, msg) app.Send(target, reply, msg)
} }
// KappaUpload uplodas the given file to kappa.lol.
func (app *application) KappaUpload(target, path, identifier string, msg twitch.PrivateMessage) { func (app *application) KappaUpload(target, path, identifier string, msg twitch.PrivateMessage) {
defer os.Remove(path) defer os.Remove(path)
app.Send(target, "Uploading to kappa.lol... dankCircle", msg) app.Send(target, "Uploading to kappa.lol... dankCircle", msg)
@ -319,6 +319,7 @@ func (app *application) KappaUpload(target, path, identifier string, msg twitch.
app.Send(target, reply, msg) app.Send(target, reply, msg)
} }
// YafUpload uplodas the given file to yaf.li.
func (app *application) YafUpload(target, path, identifier string, msg twitch.PrivateMessage) { func (app *application) YafUpload(target, path, identifier string, msg twitch.PrivateMessage) {
defer os.Remove(path) defer os.Remove(path)
app.Send(target, "Uploading to yaf.li... dankCircle", msg) app.Send(target, "Uploading to yaf.li... dankCircle", msg)
@ -395,6 +396,7 @@ func (app *application) YafUpload(target, path, identifier string, msg twitch.Pr
app.Send(target, reply, msg) app.Send(target, reply, msg)
} }
// YafUploadString uplodas text to yaf.li.
func (app *application) YafUploadString(text string) string { func (app *application) YafUploadString(text string) string {
path := uuid.NewString() path := uuid.NewString()
app.Log.Info(path) app.Log.Info(path)

View file

@ -9,8 +9,8 @@ import (
"github.com/lyx0/nourybot/pkg/owm" "github.com/lyx0/nourybot/pkg/owm"
) )
// AddUser calls GetIdByLogin to get the twitch id of the login name and then adds // InitUser is called on each command usage and checks if the user that sent the command
// the login name, twitch id and supplied level to the database. // is already in the database. If he isn't then add the user to the database.
func (app *application) InitUser(login, twitchId string) { func (app *application) InitUser(login, twitchId string) {
_, err := app.Models.Users.Check(twitchId) _, err := app.Models.Users.Check(twitchId)
//app.Log.Error(err) //app.Log.Error(err)
@ -21,8 +21,7 @@ func (app *application) InitUser(login, twitchId string) {
} }
} }
// DebugUser queries the database for a login name, if that name exists it returns the fields // DebugUser queries the database for a login name, if that name exists it creates a new paste
// and outputs them to twitch chat and a twitch whisper.
func (app *application) DebugUser(login string, message twitch.PrivateMessage) { func (app *application) DebugUser(login string, message twitch.PrivateMessage) {
user, err := app.Models.Users.Get(login) user, err := app.Models.Users.Get(login)
@ -47,7 +46,6 @@ func (app *application) DebugUser(login string, message twitch.PrivateMessage) {
return return
} }
app.Send(message.Channel, resp, message) app.Send(message.Channel, resp, message)
// app.SendEmail(subject, body)
return return
} }
} }
@ -93,10 +91,6 @@ func (app *application) EditUserLevel(login, lvl string, message twitch.PrivateM
// SetUserLocation sets new location for the user // SetUserLocation sets new location for the user
func (app *application) SetUserLocation(message twitch.PrivateMessage) { func (app *application) SetUserLocation(message twitch.PrivateMessage) {
// snipLength is the length we need to "snip" off of the start of `message`. // snipLength is the length we need to "snip" off of the start of `message`.
// `()set location` = +13
// trailing space = +1
// zero-based = +1
// = 16
snipLength := 15 snipLength := 15
// Split the twitch message at `snipLength` plus length of the name of the // Split the twitch message at `snipLength` plus length of the name of the
@ -134,6 +128,7 @@ func (app *application) SetUserLastFM(lastfmUser string, message twitch.PrivateM
} }
} }
// GetUserLevel returns the level a user has in the database.
func (app *application) GetUserLevel(msg twitch.PrivateMessage) int { func (app *application) GetUserLevel(msg twitch.PrivateMessage) int {
var dbUserLevel int var dbUserLevel int
var twitchUserLevel int var twitchUserLevel int
@ -160,6 +155,10 @@ func (app *application) GetUserLevel(msg twitch.PrivateMessage) int {
} }
} }
// UserCheckWeather checks if a user is in the database and if he has a location
// provided. If both is true it calls owm.Weather with the location and replies
// with the result.
// If no location was provided the response will instruct the user how to set a location.
func (app *application) UserCheckWeather(message twitch.PrivateMessage) { func (app *application) UserCheckWeather(message twitch.PrivateMessage) {
target := message.Channel target := message.Channel
twitchLogin := message.User.Name twitchLogin := message.User.Name
@ -180,6 +179,10 @@ func (app *application) UserCheckWeather(message twitch.PrivateMessage) {
app.Send(target, reply, message) app.Send(target, reply, message)
} }
// UserCheckWeather checks if a user is in the database and if he has a lastfm
// username provided. If both is true it calls lastfm.LastFmUserRecent with the username
// and replies with the result.
// If no lastfm username was provided the response will instruct the user how to set a lastfm username.
func (app *application) UserCheckLastFM(message twitch.PrivateMessage) string { func (app *application) UserCheckLastFM(message twitch.PrivateMessage) string {
twitchLogin := message.User.Name twitchLogin := message.User.Name
target := message.Channel target := message.Channel

View file

@ -48,7 +48,7 @@ func (c ChannelModel) Get(login string) (*Channel, error) {
return &channel, nil return &channel, nil
} }
// Insert takes in a channel struct and inserts it into the database. // Insert takes in a twitch login name and a twitch id and inserts them into the database.
func (c ChannelModel) Insert(login, id string) error { func (c ChannelModel) Insert(login, id string) error {
query := ` query := `
INSERT INTO channels(login, twitchid) INSERT INTO channels(login, twitchid)
@ -79,7 +79,7 @@ func (c ChannelModel) Insert(login, id string) error {
return nil return nil
} }
// GetAll() returns a pointer to a slice of all channels (`[]*Channel`) in the database. // GetAll returns all channels in the database.
func (c ChannelModel) GetAll() ([]*Channel, error) { func (c ChannelModel) GetAll() ([]*Channel, error) {
query := ` query := `
SELECT id, added_at, login, twitchid SELECT id, added_at, login, twitchid
@ -97,11 +97,8 @@ func (c ChannelModel) GetAll() ([]*Channel, error) {
return nil, err return nil, err
} }
// Need to defer a call to rows.Close() to ensure the resultset
// is closed before GetAll() returns.
defer rows.Close() defer rows.Close()
// Initialize an empty slice to hold the data.
channels := []*Channel{} channels := []*Channel{}
// Iterate over the resultset. // Iterate over the resultset.
@ -132,7 +129,7 @@ func (c ChannelModel) GetAll() ([]*Channel, error) {
return channels, nil return channels, nil
} }
// GetJoinable() returns a slice of channel names (Channel.Login) in the database. // GetJoinable returns a slice of channels in the database.
func (c ChannelModel) GetJoinable() ([]string, error) { func (c ChannelModel) GetJoinable() ([]string, error) {
query := ` query := `
SELECT login SELECT login
@ -150,11 +147,8 @@ func (c ChannelModel) GetJoinable() ([]string, error) {
return nil, err return nil, err
} }
// Need to defer a call to rows.Close() to ensure the resultset
// is closed before GetAll() returns.
defer rows.Close() defer rows.Close()
// Initialize an empty slice to hold the data.
channels := []string{} channels := []string{}
// Iterate over the resultset. // Iterate over the resultset.
@ -182,8 +176,7 @@ func (c ChannelModel) GetJoinable() ([]string, error) {
return channels, nil return channels, nil
} }
// Delete takes in a login name and queries the database and if there is an // Delete deletes the channel with the given login name string in the database.
// entry with that login name deletes the entry.
func (c ChannelModel) Delete(login string) error { func (c ChannelModel) Delete(login string) error {
// Prepare the statement. // Prepare the statement.
query := ` query := `

View file

@ -20,7 +20,7 @@ type CommandModel struct {
DB *sql.DB DB *sql.DB
} }
// Get tries to find a command in the database with the provided name. // Get tries to find a command in the database with the provided name and channel.
func (c CommandModel) Get(name, channel string) (*Command, error) { func (c CommandModel) Get(name, channel string) (*Command, error) {
query := ` query := `
SELECT * SELECT *
@ -50,14 +50,13 @@ func (c CommandModel) Get(name, channel string) (*Command, error) {
return &command, nil return &command, nil
} }
// GetAll() returns a pointer to a slice of all channels (`[]*Channel`) in the database. // GetAll returns a slice of all channels in the database.
func (c CommandModel) GetAll() ([]*Command, error) { func (c CommandModel) GetAll() ([]*Command, error) {
query := ` query := `
SELECT * SELECT *
FROM commands FROM commands
ORDER BY id` ORDER BY id`
// Create a context with 3 seconds timeout.
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel() defer cancel()
@ -68,11 +67,8 @@ func (c CommandModel) GetAll() ([]*Command, error) {
return nil, err return nil, err
} }
// Need to defer a call to rows.Close() to ensure the resultset
// is closed before GetAll() returns.
defer rows.Close() defer rows.Close()
// Initialize an empty slice to hold the data.
commands := []*Command{} commands := []*Command{}
// Iterate over the resultset. // Iterate over the resultset.
@ -105,7 +101,7 @@ func (c CommandModel) GetAll() ([]*Command, error) {
return commands, nil return commands, nil
} }
// GetAll() returns a pointer to a slice of all channels (`[]*Channel`) in the database. // GetAll returns a slice of all channels in the database.
func (c CommandModel) GetAllChannel(channel string) ([]*Command, error) { func (c CommandModel) GetAllChannel(channel string) ([]*Command, error) {
query := ` query := `
SELECT id, name, channel, text, level, description SELECT id, name, channel, text, level, description
@ -113,7 +109,6 @@ func (c CommandModel) GetAllChannel(channel string) ([]*Command, error) {
WHERE channel = $1 WHERE channel = $1
ORDER BY name` ORDER BY name`
// Create a context with 3 seconds timeout.
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel() defer cancel()
@ -124,8 +119,6 @@ func (c CommandModel) GetAllChannel(channel string) ([]*Command, error) {
return nil, err return nil, err
} }
// Need to defer a call to rows.Close() to ensure the resultset
// is closed before GetAll() returns.
defer rows.Close() defer rows.Close()
// Initialize an empty slice to hold the data. // Initialize an empty slice to hold the data.
@ -193,6 +186,7 @@ func (c CommandModel) Insert(command *Command) error {
return nil return nil
} }
// Update updates a command with the new supplied values.
func (c CommandModel) Update(command *Command) error { func (c CommandModel) Update(command *Command) error {
query := ` query := `
UPDATE commands UPDATE commands
@ -220,7 +214,7 @@ func (c CommandModel) Update(command *Command) error {
} }
// SetLevel queries the database for an entry with the provided name, // SetLevel queries the database for an entry with the provided name,
// if there is one it updates the entrys level with the provided level. // if there is one it updates the entries level with the newly provided level.
func (c CommandModel) SetLevel(name, channel string, level int) error { func (c CommandModel) SetLevel(name, channel string, level int) error {
query := ` query := `
UPDATE commands UPDATE commands

View file

@ -20,7 +20,7 @@ type CommandsLogModel struct {
DB *sql.DB DB *sql.DB
} }
// Get tries to find a command in the database with the provided name. // Insert inserts the supplied values into the database commands_logs
func (c CommandsLogModel) Insert(twitchLogin, twitchId, twitchChannel, twitchMessage, commandName string, uLvl int, identifier, rawMsg string) { func (c CommandsLogModel) Insert(twitchLogin, twitchId, twitchChannel, twitchMessage, commandName string, uLvl int, identifier, rawMsg string) {
query := ` query := `
INSERT into commands_logs(twitch_login, twitch_id, twitch_channel, twitch_message, command_name, user_level, identifier, raw_message) INSERT into commands_logs(twitch_login, twitch_id, twitch_channel, twitch_message, command_name, user_level, identifier, raw_message)

View file

@ -20,7 +20,7 @@ type SentMessagesLogModel struct {
DB *sql.DB DB *sql.DB
} }
// Get tries to find a command in the database with the provided name. // Insert adds the supplied values to the database sent_messages_logs.
func (s SentMessagesLogModel) Insert(twitchChannel, twitchMessage, ctxCommandName, ctxUser, ctxUserID, ctxMsg, identifier, ctxRaw string) { func (s SentMessagesLogModel) Insert(twitchChannel, twitchMessage, ctxCommandName, ctxUser, ctxUserID, ctxMsg, identifier, ctxRaw string) {
query := ` query := `
INSERT into sent_messages_logs(twitch_channel, twitch_message, context_command_name, context_username, context_user_id, context_message, identifier, context_raw) INSERT into sent_messages_logs(twitch_channel, twitch_message, context_command_name, context_username, context_user_id, context_message, identifier, context_raw)

View file

@ -20,6 +20,7 @@ type TimerModel struct {
DB *sql.DB DB *sql.DB
} }
// Get tries to find a timer with the supplied name.
func (t TimerModel) Get(name string) (*Timer, error) { func (t TimerModel) Get(name string) (*Timer, error) {
query := ` query := `
SELECT id, name, identifier, text, channel, repeat SELECT id, name, identifier, text, channel, repeat
@ -49,6 +50,7 @@ func (t TimerModel) Get(name string) (*Timer, error) {
return &timer, nil return &timer, nil
} }
// GetIdentifier returns the internal identifier for a supplied timer name.
func (t TimerModel) GetIdentifier(name string) (string, error) { func (t TimerModel) GetIdentifier(name string) (string, error) {
query := ` query := `
SELECT id, name, identifier, text, channel, repeat SELECT id, name, identifier, text, channel, repeat
@ -78,7 +80,7 @@ func (t TimerModel) GetIdentifier(name string) (string, error) {
return timer.Identifier, nil return timer.Identifier, nil
} }
// Insert adds a command into the database. // Insert adds a new timer into the database.
func (t TimerModel) Insert(timer *Timer) error { func (t TimerModel) Insert(timer *Timer) error {
query := ` query := `
INSERT into timers(name, identifier, text, channel, repeat) INSERT into timers(name, identifier, text, channel, repeat)
@ -105,14 +107,13 @@ func (t TimerModel) Insert(timer *Timer) error {
return nil return nil
} }
// GetAll() returns a pointer to a slice of all channels (`[]*Channel`) in the database. // GetAll returns a pointer to a slice of all timers in the database.
func (t TimerModel) GetAll() ([]*Timer, error) { func (t TimerModel) GetAll() ([]*Timer, error) {
query := ` query := `
SELECT id, name, identifier, text, channel, repeat SELECT id, name, identifier, text, channel, repeat
FROM timers FROM timers
ORDER BY id` ORDER BY id`
// Create a context with 3 seconds timeout.
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel() defer cancel()
@ -123,11 +124,8 @@ func (t TimerModel) GetAll() ([]*Timer, error) {
return nil, err return nil, err
} }
// Need to defer a call to rows.Close() to ensure the resultset
// is closed before GetAll() returns.
defer rows.Close() defer rows.Close()
// Initialize an empty slice to hold the data.
timers := []*Timer{} timers := []*Timer{}
// Iterate over the resultset. // Iterate over the resultset.
@ -160,7 +158,7 @@ func (t TimerModel) GetAll() ([]*Timer, error) {
return timers, nil return timers, nil
} }
// GetAll() returns a pointer to a slice of all channels (`[]*Channel`) in the database. // GetChanneltimer returns a pointer to a slice of all timers of a given channel in the database.
func (t TimerModel) GetChannelTimer(channel string) ([]*Timer, error) { func (t TimerModel) GetChannelTimer(channel string) ([]*Timer, error) {
query := ` query := `
SELECT id, name, identifier, text, channel, repeat SELECT id, name, identifier, text, channel, repeat
@ -168,7 +166,6 @@ func (t TimerModel) GetChannelTimer(channel string) ([]*Timer, error) {
WHERE channel = $1 WHERE channel = $1
ORDER BY name` ORDER BY name`
// Create a context with 3 seconds timeout.
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel() defer cancel()
@ -179,11 +176,8 @@ func (t TimerModel) GetChannelTimer(channel string) ([]*Timer, error) {
return nil, err return nil, err
} }
// Need to defer a call to rows.Close() to ensure the resultset
// is closed before GetAll() returns.
defer rows.Close() defer rows.Close()
// Initialize an empty slice to hold the data.
timers := []*Timer{} timers := []*Timer{}
// Iterate over the resultset. // Iterate over the resultset.
@ -248,7 +242,7 @@ func (t TimerModel) Update(timer *Timer) error {
} }
// Delete takes in a command name and queries the database for an entry with // Delete takes in a command name and queries the database for an entry with
// the same name and tries to delete that entry. // the name and tries to delete that entry.
func (t TimerModel) Delete(identifier string) error { func (t TimerModel) Delete(identifier string) error {
// Prepare the statement. // Prepare the statement.
query := ` query := `

View file

@ -23,7 +23,7 @@ type UploadModel struct {
DB *sql.DB DB *sql.DB
} }
// Insert takes in a channel struct and inserts it into the database. // Insert logs the supplied valeus to the uploads database.
func (u UploadModel) Insert(twitchLogin, twitchID, twitchChannel, twitchMessage, filehoster, downloadURL, identifier string) { func (u UploadModel) Insert(twitchLogin, twitchID, twitchChannel, twitchMessage, filehoster, downloadURL, identifier string) {
query := ` query := `
INSERT INTO uploads(twitchlogin, twitchid, twitchchannel, twitchmessage, filehoster, downloadurl, uploadurl, identifier) INSERT INTO uploads(twitchlogin, twitchid, twitchchannel, twitchmessage, filehoster, downloadurl, uploadurl, identifier)
@ -59,6 +59,7 @@ func (u UploadModel) Insert(twitchLogin, twitchID, twitchChannel, twitchMessage,
} }
} }
// UpdateUploadURL updates the url for a given upload identifier.
func (u UploadModel) UpdateUploadURL(identifier, uploadURL string) { func (u UploadModel) UpdateUploadURL(identifier, uploadURL string) {
var id string var id string
query := ` query := `

View file

@ -51,7 +51,7 @@ func (u UserModel) Insert(login, twitchId string) error {
return nil return nil
} }
// SetLocation searches the database for a record with the provided login value // SetLocation queries the database for a record with the provided login value
// and if that exists sets the location to the supplied // and if that exists sets the location to the supplied
func (u UserModel) SetLocation(twitchId, location string) error { func (u UserModel) SetLocation(twitchId, location string) error {
query := ` query := `
@ -78,8 +78,8 @@ func (u UserModel) SetLocation(twitchId, location string) error {
return nil return nil
} }
// SetLocation searches the database for a record with the provided login value // GetLocation queries the database for a record with the provided login value
// and if that exists sets the location to the supplied // and if that exists returns the location value.
func (u UserModel) GetLocation(twitchId string) (string, error) { func (u UserModel) GetLocation(twitchId string) (string, error) {
query := ` query := `
SELECT location SELECT location
@ -104,8 +104,8 @@ func (u UserModel) GetLocation(twitchId string) (string, error) {
return user.Location, nil return user.Location, nil
} }
// SetLocation searches the database for a record with the provided login value // SetLastFM queries the database for a record with the provided login value
// and if that exists sets the location to the supplied // and if that exists sets the lastfm value to the supplied value.
func (u UserModel) SetLastFM(login, lastfmUser string) error { func (u UserModel) SetLastFM(login, lastfmUser string) error {
query := ` query := `
UPDATE users UPDATE users
@ -131,8 +131,8 @@ func (u UserModel) SetLastFM(login, lastfmUser string) error {
return nil return nil
} }
// SetLocation searches the database for a record with the provided login value // GetLastFM queries the database for a record with the provided login value
// and if that exists sets the location to the supplied // and if that exists returns the lastfm username.
func (u UserModel) GetLastFM(login string) (string, error) { func (u UserModel) GetLastFM(login string) (string, error) {
query := ` query := `
SELECT lastfm_username SELECT lastfm_username
@ -157,8 +157,8 @@ func (u UserModel) GetLastFM(login string) (string, error) {
return user.LastFMUsername, nil return user.LastFMUsername, nil
} }
// SetLocation searches the database for a record with the provided login value // SetLocation queries the database for a record with the provided twitch id
// and if that exists sets the location to the supplied // and if that exists returns the level specified in the database for the user.
func (u UserModel) GetLevel(twitchId string) (int, error) { func (u UserModel) GetLevel(twitchId string) (int, error) {
query := ` query := `
SELECT level SELECT level
@ -184,14 +184,13 @@ func (u UserModel) GetLevel(twitchId string) (int, error) {
} }
// Setlevel searches the database for a record with the provided login value // Setlevel searches the database for a record with the provided login value
// and if that exists sets the level to the supplied level value. // and if that exists sets the level to the newly supplied level value.
func (u UserModel) SetLevel(login string, level int) error { func (u UserModel) SetLevel(login string, level int) error {
query := ` query := `
UPDATE users UPDATE users
SET level = $2 SET level = $2
WHERE login = $1` WHERE login = $1`
// err := u.DB.QueryRow(query, args...).Scan(&user)
result, err := u.DB.Exec(query, login, level) result, err := u.DB.Exec(query, login, level)
if err != nil { if err != nil {
return err return err
@ -242,7 +241,7 @@ func (u UserModel) Get(login string) (*User, error) {
return &user, nil return &user, nil
} }
// Check checks the database for a record with the given login name. // Check checks for a record with the given login name.
func (u UserModel) Check(twitchId string) (*User, error) { func (u UserModel) Check(twitchId string) (*User, error) {
query := ` query := `
SELECT id, login SELECT id, login

View file

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
) )
// Bttv returns a search string to a specified betterttv search query.
func Bttv(query string) string { func Bttv(query string) string {
reply := fmt.Sprintf("https://betterttv.com/emotes/shared/search?query=%s", query) reply := fmt.Sprintf("https://betterttv.com/emotes/shared/search?query=%s", query)

View file

@ -4,6 +4,7 @@ import (
"github.com/lyx0/nourybot/pkg/common" "github.com/lyx0/nourybot/pkg/common"
) )
// Coinflip returns either "Heads!" or "Tails!"
func Coinflip() string { func Coinflip() string {
flip := common.GenerateRandomNumber(2) flip := common.GenerateRandomNumber(2)
var reply string var reply string

View file

@ -6,6 +6,8 @@ import (
"net/http" "net/http"
) )
// Currency queries the decapi.me api for the current exchange rate for
// two given currencies.
func Currency(currAmount, currFrom, currTo string) (string, error) { func Currency(currAmount, currFrom, currTo string) (string, error) {
basePath := "https://decapi.me/misc/currency/" basePath := "https://decapi.me/misc/currency/"
from := fmt.Sprintf("?from=%s", currFrom) from := fmt.Sprintf("?from=%s", currFrom)

View file

@ -5,6 +5,7 @@ import (
"net/url" "net/url"
) )
// DuckDuckGo returns the search url for a given query.
func DuckDuckGo(query string) string { func DuckDuckGo(query string) string {
query = url.QueryEscape(query) query = url.QueryEscape(query)
reply := fmt.Sprintf("https://duckduckgo.com/?va=n&hps=1&q=%s", query) reply := fmt.Sprintf("https://duckduckgo.com/?va=n&hps=1&q=%s", query)

View file

@ -2,9 +2,9 @@ package commands
import "fmt" import "fmt"
// Ffz returns the search url for a given query.
func Ffz(query string) string { func Ffz(query string) string {
reply := fmt.Sprintf("https://www.frankerfacez.com/emoticons/?q=%s&sort=count-desc&days=0", query) reply := fmt.Sprintf("https://www.frankerfacez.com/emoticons/?q=%s&sort=count-desc&days=0", query)
return reply return reply
} }

View file

@ -5,6 +5,7 @@ import (
"net/url" "net/url"
) )
// Godocs returns the search link for a given query.
func Godocs(query string) string { func Godocs(query string) string {
query = url.QueryEscape(query) query = url.QueryEscape(query)
reply := fmt.Sprintf("https://godocs.io/?q=%s", query) reply := fmt.Sprintf("https://godocs.io/?q=%s", query)

View file

@ -5,6 +5,7 @@ import (
"net/url" "net/url"
) )
// Google returns the search link for a given query.
func Google(query string) string { func Google(query string) string {
query = url.QueryEscape(query) query = url.QueryEscape(query)
reply := fmt.Sprintf("https://www.google.com/search?q=%s", query) reply := fmt.Sprintf("https://www.google.com/search?q=%s", query)

View file

@ -5,6 +5,7 @@ import (
"net/url" "net/url"
) )
// OSRS returns the search link for a given query.
func OSRS(query string) string { func OSRS(query string) string {
query = url.QueryEscape(query) query = url.QueryEscape(query)
reply := fmt.Sprintf("https://oldschool.runescape.wiki/?search=%s", query) reply := fmt.Sprintf("https://oldschool.runescape.wiki/?search=%s", query)

View file

@ -75,6 +75,8 @@ var cm = map[string]string{
"M": "М", "M": "М",
} }
// Phonetic replaces the characters in a given message with the characters on a
// russian phonetic keyboard.
func Phonetic(message string) (string, error) { func Phonetic(message string) (string, error) {
var ts string var ts string

View file

@ -7,6 +7,7 @@ import (
"github.com/lyx0/nourybot/pkg/humanize" "github.com/lyx0/nourybot/pkg/humanize"
) )
// Ping returns information about the bot.
func Ping(env string) string { func Ping(env string) string {
botUptime := humanize.Time(common.GetUptime()) botUptime := humanize.Time(common.GetUptime())
commandsUsed := common.GetCommandsUsed() commandsUsed := common.GetCommandsUsed()

View file

@ -6,6 +6,8 @@ import (
"github.com/lyx0/nourybot/pkg/common" "github.com/lyx0/nourybot/pkg/common"
) )
// Preview returns a link to an almost live image of a given twitch stream
// if the channel is currently live.
func Preview(channel string) string { func Preview(channel string) string {
imageHeight := common.GenerateRandomNumberRange(1040, 1080) imageHeight := common.GenerateRandomNumberRange(1040, 1080)
imageWidth := common.GenerateRandomNumberRange(1890, 1920) imageWidth := common.GenerateRandomNumberRange(1890, 1920)

View file

@ -2,9 +2,9 @@ package commands
import "fmt" import "fmt"
// SevenTV returns a search link to a given query.
func SevenTV(query string) string { func SevenTV(query string) string {
reply := fmt.Sprintf("https://7tv.app/emotes?page=1&query=%s", query) reply := fmt.Sprintf("https://7tv.app/emotes?page=1&query=%s", query)
return reply return reply
} }

View file

@ -7,6 +7,8 @@ import (
"net/url" "net/url"
) )
// WolframAlphaQuery queries the WolframAlpha api with the supplied query and replies
// with the result.
func WolframAlphaQuery(query, appid string) string { func WolframAlphaQuery(query, appid string) string {
escaped := url.QueryEscape(query) escaped := url.QueryEscape(query)
url := fmt.Sprintf("http://api.wolframalpha.com/v1/result?appid=%s&i=%s", appid, escaped) url := fmt.Sprintf("http://api.wolframalpha.com/v1/result?appid=%s&i=%s", appid, escaped)

View file

@ -15,6 +15,7 @@ type xkcdResponse struct {
Img string `json:"img"` Img string `json:"img"`
} }
// Xkcd queries the xkcd api and returns latest xkcd comic.
func Xkcd() (string, error) { func Xkcd() (string, error) {
response, err := http.Get("https://xkcd.com/info.0.json") response, err := http.Get("https://xkcd.com/info.0.json")
if err != nil { if err != nil {
@ -34,8 +35,9 @@ func Xkcd() (string, error) {
return reply, nil return reply, nil
} }
// RandomXkcd queries the xkcd api and returns a random xkcd comic.
func RandomXkcd() (string, error) { func RandomXkcd() (string, error) {
comicNum := fmt.Sprint(common.GenerateRandomNumber(2772)) comicNum := fmt.Sprint(common.GenerateRandomNumber(2899))
response, err := http.Get(fmt.Sprint("http://xkcd.com/" + comicNum + "/info.0.json")) response, err := http.Get(fmt.Sprint("http://xkcd.com/" + comicNum + "/info.0.json"))
if err != nil { if err != nil {

View file

@ -5,6 +5,7 @@ import (
"net/url" "net/url"
) )
// Youtube returns a search link to a given query.
func Youtube(query string) string { func Youtube(query string) string {
query = url.QueryEscape(query) query = url.QueryEscape(query)
reply := fmt.Sprintf("https://www.youtube.com/results?search_query=%s", query) reply := fmt.Sprintf("https://www.youtube.com/results?search_query=%s", query)

View file

@ -14,4 +14,3 @@ func CommandUsed() {
func GetCommandsUsed() int { func GetCommandsUsed() int {
return tempCommands return tempCommands
} }

View file

@ -6,10 +6,12 @@ var (
uptime time.Time uptime time.Time
) )
// StartTime adds the current time to the uptime variable.
func StartTime() { func StartTime() {
uptime = time.Now() uptime = time.Now()
} }
// GetUptime returns the time from the uptime variable.
func GetUptime() time.Time { func GetUptime() time.Time {
return uptime return uptime
} }

View file

@ -11,6 +11,8 @@ import (
"runtime/debug" "runtime/debug"
) )
// GetVersion returns the current git commit hash.
// If the version is modified the hash ends in "-dirty"
func GetVersion() string { func GetVersion() string {
var revision string var revision string
var modified bool var modified bool
@ -40,6 +42,8 @@ func GetVersion() string {
return revision return revision
} }
// GetVersion returns the current git commit hash.
// This function does not add the "-dirty" string at the end of the hash.
func GetVersionPure() string { func GetVersionPure() string {
var revision string var revision string
var modified bool var modified bool

View file

@ -6,6 +6,7 @@ import (
humanize "github.com/dustin/go-humanize" humanize "github.com/dustin/go-humanize"
) )
// Time returns the humanized time for a supplied time value.
func Time(t time.Time) string { func Time(t time.Time) string {
return humanize.Time(t) return humanize.Time(t)
} }

View file

@ -20,6 +20,7 @@ type ivrGame struct {
DisplayName string `json:"displayName"` DisplayName string `json:"displayName"`
} }
// TitleByUsername returns the current title of a supplied twitch channel.
func TitleByUsername(login string) string { func TitleByUsername(login string) string {
baseUrl := "https://api.ivr.fi/v2/twitch/user?login=" baseUrl := "https://api.ivr.fi/v2/twitch/user?login="
@ -39,6 +40,7 @@ func TitleByUsername(login string) string {
return responseList[0].Stream.Title return responseList[0].Stream.Title
} }
// GameByUsername returns the current game of a supplied twitch channel.
func GameByUsername(login string) string { func GameByUsername(login string) string {
baseUrl := "https://api.ivr.fi/v2/twitch/user?login=" baseUrl := "https://api.ivr.fi/v2/twitch/user?login="
@ -58,6 +60,8 @@ func GameByUsername(login string) string {
return responseList[0].Stream.Game.DisplayName return responseList[0].Stream.Game.DisplayName
} }
// IDByUsernameReply returns the twitch user id of a supplied
// twitch username in the format of "username=id"
func IDByUsernameReply(username string) string { func IDByUsernameReply(username string) string {
baseUrl := "https://api.ivr.fi/v2/twitch/user?login=" baseUrl := "https://api.ivr.fi/v2/twitch/user?login="
@ -76,6 +80,7 @@ func IDByUsernameReply(username string) string {
return reply return reply
} }
// IDByUsername returns the twitch user id for a given twitch username.
func IDByUsername(username string) string { func IDByUsername(username string) string {
baseUrl := "https://api.ivr.fi/v2/twitch/user?login=" baseUrl := "https://api.ivr.fi/v2/twitch/user?login="

View file

@ -9,6 +9,7 @@ import (
"go.uber.org/zap" "go.uber.org/zap"
) )
// LastFmUserRecent returns the recently played track for a given lastfm username.
func LastFmUserRecent(target, user string) string { func LastFmUserRecent(target, user string) string {
sugar := zap.NewExample().Sugar() sugar := zap.NewExample().Sugar()