Multi-channel support and deployment for webserver.
Signed-off-by: Martyn Ranyard <m@rtyn.berlin>
This commit is contained in:
parent
deb12318b6
commit
a9dc6db0a4
|
@ -10,4 +10,6 @@ FROM scratch
|
|||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
|
||||
COPY --from=builder /go/src/git.martyn.berlin/martyn/karaokards /app/
|
||||
COPY strings.json /app/strings.json
|
||||
COPY web/ /app/web/
|
||||
WORKDIR /app
|
||||
CMD ["/app/karaokards"]
|
|
@ -21,9 +21,9 @@ const PSTFormat = "Jan 2 15:04:05 PST"
|
|||
|
||||
// Regex for parsing PRIVMSG strings.
|
||||
//
|
||||
// First matched group is the user's name and the second matched group is the content of the
|
||||
// First matched group is the user's name, second is the channel? and the third matched group is the content of the
|
||||
// user's message.
|
||||
var MsgRegex *regexp.Regexp = regexp.MustCompile(`^:(\w+)!\w+@\w+\.tmi\.twitch\.tv (PRIVMSG) #\w+(?: :(.*))?$`)
|
||||
var MsgRegex *regexp.Regexp = regexp.MustCompile(`^:(\w+)!\w+@\w+\.tmi\.twitch\.tv (PRIVMSG) #(\w+)(?: :(.*))?$`)
|
||||
|
||||
// Regex for parsing user commands, from already parsed PRIVMSG strings.
|
||||
//
|
||||
|
@ -38,6 +38,9 @@ type OAuthCred struct {
|
|||
|
||||
// The developer application client ID. Used for API calls to Twitch.
|
||||
ClientID string `json:"client_id,omitempty"`
|
||||
|
||||
// List of Channels to join
|
||||
Channels []string `json:"channels,omitempty"`
|
||||
}
|
||||
|
||||
type KardBot struct {
|
||||
|
@ -111,10 +114,11 @@ func (bb *KardBot) HandleChat() error {
|
|||
if nil != matches {
|
||||
userName := matches[1]
|
||||
msgType := matches[2]
|
||||
channel := matches[3]
|
||||
|
||||
switch msgType {
|
||||
case "PRIVMSG":
|
||||
msg := matches[3]
|
||||
msg := matches[4]
|
||||
rgb.GPrintf("[%s] %s: %s\n", TimeStamp(), userName, msg)
|
||||
|
||||
// parse commands from user message
|
||||
|
@ -124,9 +128,9 @@ func (bb *KardBot) HandleChat() error {
|
|||
|
||||
switch cmd {
|
||||
case "card":
|
||||
rgb.CPrintf("[%s] Card asked for!\n", TimeStamp())
|
||||
rgb.CPrintf("[%s] Card asked for by %s on %s' channel!\n", TimeStamp(), userName, channel)
|
||||
|
||||
bb.Say("Your prompt is : " + bb.Prompts[rand.Intn(len(bb.Prompts))])
|
||||
bb.Say("Your prompt is : "+bb.Prompts[rand.Intn(len(bb.Prompts))], channel)
|
||||
}
|
||||
|
||||
// channel-owner specific commands
|
||||
|
@ -147,6 +151,7 @@ func (bb *KardBot) HandleChat() error {
|
|||
}
|
||||
default:
|
||||
// do nothing
|
||||
rgb.YPrintf("[%s] unknown IRC message : %s\n", TimeStamp(), line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -154,14 +159,24 @@ func (bb *KardBot) HandleChat() error {
|
|||
}
|
||||
}
|
||||
|
||||
// Makes the bot join its pre-specified channel.
|
||||
func (bb *KardBot) JoinChannel() {
|
||||
rgb.YPrintf("[%s] Joining #%s...\n", TimeStamp(), bb.Channel)
|
||||
// Login to the IRC server
|
||||
func (bb *KardBot) Login() {
|
||||
rgb.YPrintf("[%s] Logging into #%s...\n", TimeStamp(), bb.Channel)
|
||||
bb.conn.Write([]byte("PASS " + bb.Credentials.Password + "\r\n"))
|
||||
bb.conn.Write([]byte("NICK " + bb.Name + "\r\n"))
|
||||
bb.conn.Write([]byte("JOIN #" + bb.Channel + "\r\n"))
|
||||
}
|
||||
|
||||
rgb.YPrintf("[%s] Joined #%s as @%s!\n", TimeStamp(), bb.Channel, bb.Name)
|
||||
// Makes the bot join its pre-specified channel.
|
||||
func (bb *KardBot) JoinChannel(channels ...string) {
|
||||
if len(channels) == 0 {
|
||||
channels = append(channels, bb.Channel)
|
||||
}
|
||||
|
||||
for _, channel := range channels {
|
||||
rgb.YPrintf("[%s] Joining #%s...\n", TimeStamp(), channel)
|
||||
bb.conn.Write([]byte("JOIN #" + channel + "\r\n"))
|
||||
rgb.YPrintf("[%s] Joined #%s as @%s!\n", TimeStamp(), channel, bb.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// Reads from the private credentials file and stores the data in the bot's Credentials field.
|
||||
|
@ -185,7 +200,7 @@ func (bb *KardBot) ReadCredentials() error {
|
|||
}
|
||||
|
||||
// Makes the bot send a message to the chat channel.
|
||||
func (bb *KardBot) Say(msg string) error {
|
||||
func (bb *KardBot) Say(msg string, channels ...string) error {
|
||||
if "" == msg {
|
||||
return errors.New("BasicBot.Say: msg was empty.")
|
||||
}
|
||||
|
@ -195,9 +210,17 @@ func (bb *KardBot) Say(msg string) error {
|
|||
return errors.New("BasicBot.Say: msg exceeded 512 bytes")
|
||||
}
|
||||
|
||||
_, err := bb.conn.Write([]byte(fmt.Sprintf("PRIVMSG #%s :%s\r\n", bb.Channel, msg)))
|
||||
if nil != err {
|
||||
return err
|
||||
if len(channels) == 0 {
|
||||
channels = append(channels, bb.Channel)
|
||||
}
|
||||
|
||||
rgb.YPrintf("[%s] sending %s to channels %v as @%s!\n", TimeStamp(), msg, channels, bb.Name)
|
||||
for _, channel := range channels {
|
||||
_, err := bb.conn.Write([]byte(fmt.Sprintf("PRIVMSG #%s :%s\r\n", channel, msg)))
|
||||
rgb.YPrintf("[%s] PRIVMSG #%s :%s\r\n", TimeStamp(), channel, msg)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -215,7 +238,12 @@ func (bb *KardBot) Start() {
|
|||
|
||||
for {
|
||||
bb.Connect()
|
||||
bb.JoinChannel()
|
||||
bb.Login()
|
||||
if len(bb.Credentials.Channels) > 0 {
|
||||
bb.JoinChannel(bb.Credentials.Channels...)
|
||||
} else {
|
||||
bb.JoinChannel()
|
||||
}
|
||||
err = bb.HandleChat()
|
||||
if nil != err {
|
||||
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package webserver
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
|
||||
irc "git.martyn.berlin/martyn/karaokards/internal/irc"
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/sessions"
|
||||
|
||||
"fmt"
|
||||
"html/template"
|
||||
|
@ -15,7 +17,7 @@ import (
|
|||
|
||||
//var store = sessions.NewCookieStore(os.Getenv("SESSION_KEY"))
|
||||
|
||||
var store = sessions.NewCookieStore([]byte("GO_SESS"))
|
||||
var ircBot irc.KardBot
|
||||
|
||||
func HealthHandler(response http.ResponseWriter, request *http.Request) {
|
||||
response.Header().Add("Content-type", "text/plain")
|
||||
|
@ -42,8 +44,10 @@ func RootHandler(response http.ResponseWriter, request *http.Request) {
|
|||
func TemplateHandler(response http.ResponseWriter, request *http.Request) {
|
||||
response.Header().Add("X-Template-File", "web"+request.URL.Path)
|
||||
type TemplateData struct {
|
||||
Prompt string
|
||||
AvailCount int
|
||||
Prompt string
|
||||
AvailCount int
|
||||
ChannelCount int
|
||||
MessageCount int
|
||||
}
|
||||
// tmpl, err := template.New("html"+request.URL.Path).Funcs(template.FuncMap{
|
||||
// "ToUpper": strings.ToUpper,
|
||||
|
@ -68,7 +72,7 @@ func TemplateHandler(response http.ResponseWriter, request *http.Request) {
|
|||
// NotFoundHandler(response, request)
|
||||
// return
|
||||
}
|
||||
var td = TemplateData{"Hello", 1}
|
||||
var td = TemplateData{ircBot.Prompts[rand.Intn(len(ircBot.Prompts))], len(ircBot.Prompts), len(ircBot.Credentials.Channels), 0}
|
||||
err = tmpl.Execute(response, td)
|
||||
if err != nil {
|
||||
http.Error(response, err.Error(), http.StatusInternalServerError)
|
||||
|
@ -76,7 +80,8 @@ func TemplateHandler(response http.ResponseWriter, request *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
func HandleHTTP() {
|
||||
func HandleHTTP(passedIrcBot irc.KardBot) {
|
||||
ircBot = passedIrcBot
|
||||
r := mux.NewRouter()
|
||||
loggedRouter := handlers.LoggingHandler(os.Stdout, r)
|
||||
r.NotFoundHandler = http.HandlerFunc(NotFoundHandler)
|
||||
|
|
2
main.go
2
main.go
|
@ -86,7 +86,7 @@ func main() {
|
|||
}
|
||||
go func() {
|
||||
rgb.YPrintf("[%s] Starting webserver on port %s\n", irc.TimeStamp(), "5353")
|
||||
webserver.HandleHTTP()
|
||||
webserver.HandleHTTP(myBot)
|
||||
}()
|
||||
myBot.Start()
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="Templates files for the workshop">
|
||||
<meta name="description" content="Karaokards">
|
||||
<meta name="author" content="Martyn Ranyard">
|
||||
<title>The k8s zoo</title>
|
||||
<title>The great unknown!</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
|
||||
|
@ -47,7 +47,6 @@
|
|||
a{
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body class="text-center">
|
||||
|
@ -64,8 +63,7 @@
|
|||
<h1 class="cover-heading">Ooops!</h1>
|
||||
<p>It seems you've gone somewhere you shouldn't! 404 NOT FOUND!</p>
|
||||
<p/>
|
||||
<p>This can happen if you enter the spotify id wrong and search, go back and check it!</p>
|
||||
<p class="lead">Spotify IDs look like this : 37i9dQZF1DX4UtSsGT1Sbe - 22 characters and can be got by clicking share and "Copy (Playlist|Album) Link".</p>
|
||||
<p>I'm not quite sure how you got here to be honest, if it was via a link on the site, let me know via twitch DM, if it was from someone else, let them know.</p>
|
||||
<p>Shameless self-promotion : Follow me on twitch - <a href="https://www.twitch.tv/iMartynOnTwitch">iMartynOnTwitch</a>, oddly enough, I do a lot of twitchsings!</p>
|
||||
</main>
|
||||
<footer class="mastfoot mt-auto">
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
<div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column">
|
||||
<header class="masthead mb-auto">
|
||||
<div class="inner">
|
||||
<h3 class="masthead-brand">k8s-zoo</h3>
|
||||
<h3 class="masthead-brand">Karaokards</h3>
|
||||
<nav class="nav nav-masthead justify-content-center">
|
||||
<a class="nav-link active" href="/">Home</a>
|
||||
</nav>
|
||||
|
@ -63,7 +63,7 @@
|
|||
<main role="main" class="inner cover">
|
||||
<h1 class="cover-heading">Karaokards!!!</h1>
|
||||
<p>Random prompt for you : {{.Prompt}}</p>
|
||||
<p>There are a total of {{.AvailCount}} prompts available.</p>
|
||||
<p>There are a total of {{.AvailCount}} prompts available. This bot is hanging out in {{.ChannelCount}} channels and has served {{.MessageCount}} prompts via twitch chat!</p>
|
||||
</main>
|
||||
<footer class="mastfoot mt-auto">
|
||||
<div class="inner">
|
||||
|
|
Loading…
Reference in New Issue