Compare commits

..

No commits in common. "1acb78bb5acccb80bf7d4e3628a84abf8772cf01" and "92da19e5a8fc8974010abf2baef659f3f9ee57ae" have entirely different histories.

19 changed files with 115 additions and 234 deletions

View File

@ -61,8 +61,7 @@ type bot struct {
}
type EndPoint struct {
Name string `json:"name"`
URL string `json:"url"`
Name, URL string
}
// Variable represents a $var replacement
@ -105,7 +104,6 @@ func New(config *config.Config, connector Connector) Bot {
bot.RefreshPluginWhitelist()
http.HandleFunc("/", bot.serveRoot)
http.HandleFunc("/nav", bot.serveNav)
connector.RegisterEvent(bot.Receive)
@ -182,6 +180,10 @@ var suffixRegex *regexp.Regexp
func IsCmd(c *config.Config, message string) (bool, string) {
cmdcs := c.GetArray("CommandChar", []string{"!"})
botnick := strings.ToLower(c.Get("Nick", "bot"))
r := fmt.Sprintf(`(?i)\s*\W*\s*?%s\W*$`, botnick)
if suffixRegex == nil {
suffixRegex = regexp.MustCompile(r)
}
if botnick == "" {
log.Fatal().
Msgf(`You must run catbase -set nick -val <your bot nick>`)
@ -200,6 +202,9 @@ func IsCmd(c *config.Config, message string) (bool, string) {
if message[0] == ':' || message[0] == ',' {
message = message[1:]
}
} else if suffixRegex.MatchString(message) {
iscmd = true
message = suffixRegex.ReplaceAllString(message, "")
} else {
for _, cmdc := range cmdcs {
if strings.HasPrefix(lowerMessage, cmdc) && len(cmdc) > 0 {

View File

@ -37,8 +37,6 @@ const (
type EphemeralID string
type UnfurlLinks bool
type ImageAttachment struct {
URL string
AltTxt string

View File

@ -1,24 +1,16 @@
package bot
import (
"encoding/json"
"fmt"
"html/template"
"net/http"
"strings"
)
func (b *bot) serveRoot(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, rootIndex)
}
func (b *bot) serveNav(w http.ResponseWriter, r *http.Request) {
enc := json.NewEncoder(w)
err := enc.Encode(b.GetWebNavigation())
if err != nil {
jsonErr, _ := json.Marshal(err)
w.WriteHeader(500)
w.Write(jsonErr)
}
context := make(map[string]interface{})
context["Nav"] = b.GetWebNavigation()
t := template.Must(template.New("rootIndex").Parse(rootIndex))
t.Execute(w, context)
}
// GetWebNavigation returns a list of bootstrap-vue <b-nav-item> links
@ -59,12 +51,12 @@ var rootIndex = `
<body>
<div id="app">
<b-navbar>
<b-navbar-brand>catbase</b-navbar-brand>
<b-navbar-nav>
<b-nav-item v-for="item in nav" :href="item.url">{{ item.name }}</b-nav-item>
</b-navbar-nav>
</b-navbar>
<b-navbar>
<b-navbar-brand>catbase</b-navbar-brand>
<b-navbar-nav>
<b-nav-item v-for="item in nav" :href="item.URL">{{ "{{ item.Name }}" }}</b-nav-item>
</b-navbar-nav>
</b-navbar>
</div>
<script>
@ -72,15 +64,8 @@ var rootIndex = `
el: '#app',
data: {
err: '',
nav: [],
nav: {{ .Nav }},
},
mounted: function() {
axios.get('/nav')
.then(resp => {
this.nav = resp.data;
})
.catch(err => console.log(err))
}
})
</script>
</body>

View File

@ -281,12 +281,6 @@ func (s *SlackApp) sendMessage(channel, message string, meMessage bool, args ...
ImageURL: a.URL,
Text: a.AltTxt,
})
case bot.UnfurlLinks:
if a {
options = append(options, slack.MsgOptionEnableLinkUnfurl())
} else {
options = append(options, slack.MsgOptionDisableLinkUnfurl())
}
}
}
}

View File

@ -5,6 +5,7 @@ package admin
import (
"encoding/json"
"fmt"
"html/template"
"net/http"
"os"
"regexp"
@ -327,8 +328,10 @@ func (p *AdminPlugin) registerWeb() {
p.bot.RegisterWeb("/vars", "Variables")
}
var tpl = template.Must(template.New("factoidIndex").Parse(varIndex))
func (p *AdminPlugin) handleWeb(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, varIndex)
tpl.Execute(w, struct{ Nav []bot.EndPoint }{p.bot.GetWebNavigation()})
}
func (p *AdminPlugin) handleWebAPI(w http.ResponseWriter, r *http.Request) {

View File

@ -24,7 +24,7 @@ var varIndex = `
<b-navbar>
<b-navbar-brand>Variables</b-navbar-brand>
<b-navbar-nav>
<b-nav-item v-for="item in nav" :href="item.url" :active="item.name === 'Variables'">{{ item.name }}</b-nav-item>
<b-nav-item v-for="item in nav" :href="item.URL" :active="item.Name === 'Variables'">{{ "{{ item.Name }}" }}</b-nav-item>
</b-navbar-nav>
</b-navbar>
<b-alert
@ -32,7 +32,7 @@ var varIndex = `
variant="error"
v-if="err"
@dismissed="err = ''">
{{ err }}
{{ "{{ err }}" }}
</b-alert>
<b-container>
<b-table
@ -48,7 +48,7 @@ var varIndex = `
el: '#app',
data: {
err: '',
nav: [],
nav: {{ .Nav }},
vars: [],
sortBy: 'key',
fields: [
@ -58,11 +58,6 @@ var varIndex = `
},
mounted() {
this.getData();
axios.get('/nav')
.then(resp => {
this.nav = resp.data;
})
.catch(err => console.log(err))
},
methods: {
getData: function() {

View File

@ -5,6 +5,7 @@ package cli
import (
"encoding/json"
"fmt"
"html/template"
"net/http"
"time"
@ -90,8 +91,10 @@ func (p *CliPlugin) handleWebAPI(w http.ResponseWriter, r *http.Request) {
w.Write(data)
}
var tpl = template.Must(template.New("factoidIndex").Parse(indexHTML))
func (p *CliPlugin) handleWeb(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, indexHTML)
tpl.Execute(w, struct{ Nav []bot.EndPoint }{p.bot.GetWebNavigation()})
}
// Completing the Connector interface, but will not actually be a connector

View File

@ -24,14 +24,14 @@ var indexHTML = `
<b-navbar>
<b-navbar-brand>CLI</b-navbar-brand>
<b-navbar-nav>
<b-nav-item v-for="item in nav" :href="item.url" :active="item.name === 'CLI'">{{ item.name }}</b-nav-item>
<b-nav-item v-for="item in nav" :href="item.URL" :active="item.Name === 'CLI'">{{ "{{ item.Name }}" }}</b-nav-item>
</b-navbar-nav>
</b-navbar>
<b-alert
dismissable
variant="error"
:show="err">
{{ err }}
{{ "{{ err }}" }}
</b-alert>
<b-container>
<b-row>
@ -80,20 +80,13 @@ var indexHTML = `
el: '#app',
data: {
err: '',
nav: [],
nav: {{ .Nav }},
answer: '',
correct: 0,
textarea: [],
user: '',
input: '',
},
mounted: function() {
axios.get('/nav')
.then(resp => {
this.nav = resp.data;
})
.catch(err => console.log(err))
},
computed: {
authenticated: function() {
if (this.user !== '')

View File

@ -4,6 +4,7 @@ import (
"database/sql"
"encoding/json"
"fmt"
"html/template"
"math/rand"
"net/http"
"regexp"
@ -625,8 +626,10 @@ func (p *CounterPlugin) registerWeb() {
p.Bot.RegisterWeb("/counter", "Counter")
}
var tpl = template.Must(template.New("factoidIndex").Parse(html))
func (p *CounterPlugin) handleCounter(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, html)
tpl.Execute(w, struct{ Nav []bot.EndPoint }{p.Bot.GetWebNavigation()})
}
func (p *CounterPlugin) handleCounterAPI(w http.ResponseWriter, r *http.Request) {

View File

@ -22,14 +22,14 @@ var html = `
<b-navbar>
<b-navbar-brand>Counters</b-navbar-brand>
<b-navbar-nav>
<b-nav-item v-for="item in nav" :href="item.url" :active="item.name === 'Counter'">{{ item.name }}</b-nav-item>
<b-nav-item v-for="item in nav" :href="item.URL" :active="item.Name === 'Counter'">{{ "{{ item.Name }}" }}</b-nav-item>
</b-navbar-nav>
</b-navbar>
<b-alert
dismissable
:show="err"
variant="error">
{{ err }}
{{ "{{ err }}" }}
</b-alert>
<b-container>
<b-row>
@ -37,14 +37,14 @@ var html = `
<b-col><b-input v-model="answer"></b-col>
</b-row>
<b-row v-for="(counter, user) in counters">
{{ user }}:
{{ "{{ user }}" }}:
<b-container>
<b-row v-for="(count, thing) in counter">
<b-col offset="1">
{{ thing }}:
{{ "{{ thing }}" }}:
</b-col>
<b-col>
{{ count }}
{{ "{{ count }}" }}
</b-col>
<b-col cols="2">
<button @click="subtract(user,thing,count)">-</button>
@ -72,17 +72,12 @@ var html = `
el: '#app',
data: {
err: '',
nav: [],
nav: {{ .Nav }},
answer: '',
correct: 0,
counters: {}
},
mounted() {
axios.get('/nav')
.then(resp => {
this.nav = resp.data;
})
.catch(err => console.log(err))
axios.get('/counter/api')
.then(resp => (this.counters = convertData(resp.data)))
.catch(err => (this.err = err));

View File

@ -842,6 +842,8 @@ func (p *FactoidPlugin) serveAPI(w http.ResponseWriter, r *http.Request) {
w.Write(data)
}
var tpl = template.Must(template.New("factoidIndex").Parse(factoidIndex))
func (p *FactoidPlugin) serveQuery(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, factoidIndex)
tpl.Execute(w, struct{ Nav []bot.EndPoint }{p.Bot.GetWebNavigation()})
}

View File

@ -32,7 +32,7 @@ var factoidIndex = `
<b-navbar>
<b-navbar-brand>Factoids</b-navbar-brand>
<b-navbar-nav>
<b-nav-item v-for="item in nav" :href="item.url" :active="item.name === 'Factoid'">{{ item.name }}</b-nav-item>
<b-nav-item v-for="item in nav" :href="item.URL" :active="item.Name === 'Factoid'">{{ "{{ item.Name }}" }}</b-nav-item>
</b-navbar-nav>
</b-navbar>
<b-alert
@ -40,7 +40,7 @@ var factoidIndex = `
variant="error"
v-if="err"
@dismissed="err = ''">
{{ err }}
{{ "{{ err }}" }}
</b-alert>
<b-form @submit="runQuery">
<b-container>
@ -74,7 +74,7 @@ var factoidIndex = `
router,
data: {
err: '',
nav: [],
nav: {{ .Nav }},
query: '',
results: [],
fields: [
@ -85,11 +85,6 @@ var factoidIndex = `
]
},
mounted() {
axios.get('/nav')
.then(resp => {
this.nav = resp.data;
})
.catch(err => console.log(err))
if (this.$route.query.query) {
this.query = this.$route.query.query;
this.runQuery()

View File

@ -80,4 +80,5 @@ func (p *GitPlugin) registerWeb() {
http.HandleFunc("/git/gitea/event", p.giteaEvent)
http.HandleFunc("/git/github/event", p.githubEvent)
http.HandleFunc("/git/gitlab/event", p.gitlabEvent)
p.b.RegisterWeb("/git", "Git")
}

View File

@ -44,6 +44,6 @@ func (p *GitPlugin) giteaEvent(w http.ResponseWriter, r *http.Request) {
chs := p.c.GetArray(fmt.Sprintf("gitea.%s.%s.channels", org, repo), []string{})
for _, ch := range chs {
p.b.Send(p.b.DefaultConnector(), bot.Message, ch, msg, bot.UnfurlLinks(false))
p.b.Send(p.b.DefaultConnector(), bot.Message, ch, msg)
}
}

View File

@ -145,6 +145,6 @@ func (p *GitPlugin) githubEvent(w http.ResponseWriter, r *http.Request) {
chs := p.c.GetArray(fmt.Sprintf("github.%s.%s.channels", owner, repo), []string{})
for _, ch := range chs {
p.b.Send(p.b.DefaultConnector(), bot.Message, ch, msg, bot.UnfurlLinks(false))
p.b.Send(p.b.DefaultConnector(), bot.Message, ch, msg)
}
}

View File

@ -53,6 +53,6 @@ func (p *GitPlugin) gitlabEvent(w http.ResponseWriter, r *http.Request) {
}
chs := p.c.GetArray(fmt.Sprintf("gitlab.%s.channels", owner), []string{})
for _, ch := range chs {
p.b.Send(p.b.DefaultConnector(), bot.Message, ch, msg, bot.UnfurlLinks(false))
p.b.Send(p.b.DefaultConnector(), bot.Message, ch, msg)
}
}

View File

@ -42,7 +42,6 @@ type memeText struct {
XPerc float64 `json:"x"`
YPerc float64 `json:"y"`
Text string `json:"t"`
Caps bool `json:"c"`
}
var horizon = 24 * 7
@ -330,8 +329,8 @@ func (p *MemePlugin) findFontSize(config []memeText, w, h int, sizes []float64)
func defaultFormatConfig() []memeText {
return []memeText{
{XPerc: 0.5, YPerc: 0.05, Caps: true},
{XPerc: 0.5, YPerc: 0.95, Caps: true},
{XPerc: 0.5, YPerc: 0.05},
{XPerc: 0.5, YPerc: 0.95},
}
}
@ -396,12 +395,6 @@ func (p *MemePlugin) genMeme(meme string, bully image.Image, config []memeText)
fontLocation := p.c.Get("meme.font", "impact.ttf")
m.LoadFontFace(fontLocation, p.findFontSize(config, w, h, fontSizes))
for i, c := range config {
if c.Caps {
config[i].Text = strings.ToUpper(c.Text)
}
}
// Apply black stroke
m.SetHexColor("#000")
strokeSize := 6

View File

@ -25,7 +25,7 @@ var memeIndex = `
<b-navbar>
<b-navbar-brand>Memes</b-navbar-brand>
<b-navbar-nav>
<b-nav-item v-for="item in nav" :href="item.url" :active="item.name === 'Meme'">{{ item.name }}</b-nav-item>
<b-nav-item v-for="item in nav" :href="item.URL" :active="item.Name === 'Meme'">{{ "{{ item.Name }}" }}</b-nav-item>
</b-navbar-nav>
</b-navbar>
<b-alert
@ -33,53 +33,9 @@ var memeIndex = `
variant="error"
v-if="err"
@dismissed="err = ''">
{{ err }}
{{ "{{ err }}" }}
</b-alert>
<b-form @submit="saveConfig" v-if="editConfig">
<b-container>
<b-row>
<b-col cols="1">
Name:
</b-col>
<b-col>
{{ editConfig.name }}
</b-col>
</b-row>
<b-row>
<b-col cols="1">
Image:
</b-col>
<b-col>
<img :src="editConfig.url" :alt="editConfig.url" rounded block fluid />
</b-col>
</b-row>
<b-row>
<b-col cols="1">
URL:
</b-col>
<b-col>
<b-input placeholder="URL..." v-model="editConfig.url"></b-input>
</b-col>
</b-row>
<b-row>
<b-col cols="1">
Config:
</b-col>
<b-col>
<b-form-textarea v-model="editConfig.config" rows="10">
</b-form-textarea>
</b-col>
</b-row>
<b-row>
<b-button type="submit" variant="primary">Save</b-button>
&nbsp;
<b-button @click="rm" variant="danger">Delete</b-button>
&nbsp;
<b-button type="cancel" @click="editConfig = null" variant="secondary">Cancel</b-button>
</b-row>
</b-container>
</b-form>
<b-form @submit="addMeme" v-if="!editConfig">
<b-form @submit="addMeme">
<b-container>
<b-row>
<b-col cols="3">
@ -102,8 +58,7 @@ var memeIndex = `
:items="results"
:fields="fields">
<template v-slot:cell(config)="data">
<pre>{{data.item.config | pretty}}</pre>
<b-button @click="startEdit(data.item)">Edit</b-button>
<pre>{{ "{{data.item.config}}" }}</pre>
</template>
<template v-slot:cell(image)="data">
<b-img :src="data.item.url" rounded block fluid />
@ -116,99 +71,58 @@ var memeIndex = `
</div>
<script>
var router = new VueRouter({
mode: 'history',
routes: []
});
var app = new Vue({
el: '#app',
router,
data: {
err: '',
nav: [],
name: '',
url: '',
config: '',
results: [],
editConfig: null,
fields: [
{ key: 'name', sortable: true },
{ key: 'config' },
{ key: 'image' }
]
},
mounted() {
axios.get('/nav')
.then(resp => {
this.nav = resp.data;
})
.catch(err => console.log(err))
this.refresh();
},
filters: {
pretty: function(value) {
if (!value) {
return ""
}
return JSON.stringify(JSON.parse(value), null, 2);
}
},
methods: {
refresh: function() {
axios.get('/meme/all')
.catch(err => (this.err = err))
.then(resp => {
this.results = resp.data
})
},
addMeme: function(evt) {
if (evt) {
evt.preventDefault();
evt.stopPropagation()
}
if (this.name && this.url)
axios.post('/meme/add', {name: this.name, url: this.url, config: this.config})
.then(resp => {
this.results = resp.data;
this.name = "";
this.url = "";
this.config = "";
this.refresh();
})
.catch(err => (this.err = err));
},
startEdit: function(item) {
this.editConfig = item;
},
saveConfig: function(evt) {
if (evt) {
evt.preventDefault();
evt.stopPropagation();
}
if (this.editConfig && this.editConfig.name && this.editConfig.url) {
axios.post('/meme/add', this.editConfig)
.then(resp => {
this.results = resp.data;
this.editConfig = null;
this.refresh();
})
.catch(err => this.err = err);
}
},
rm: function(evt) {
if (evt) {
evt.preventDefault();
evt.stopPropagation();
}
axios.delete('/meme/rm', { data: this.editConfig })
.then(resp => {
this.editConfig = null;
this.refresh();
})
.catch(err => this.err = err);
}
var router = new VueRouter({
mode: 'history',
routes: []
});
var app = new Vue({
el: '#app',
router,
data: {
err: '',
nav: {{ .Nav }},
name: "",
url: "",
config: "",
results: [],
fields: [
{ key: 'name', sortable: true },
{ key: 'url', sortable: true },
{ key: 'config' },
{ key: 'image' }
]
},
mounted() {
this.refresh();
},
computed: {
},
methods: {
refresh: function() {
axios.get('/meme/all')
.catch(err => (this.err = err))
.then(resp => {
this.results = resp.data
})
},
addMeme: function(evt) {
if (evt) {
evt.preventDefault();
evt.stopPropagation()
}
})
if (this.name && this.url)
axios.post('/meme/add', {name: this.name, url: this.url, config: this.config})
.then(resp => {
this.results = resp.data;
this.name = "";
this.url = "";
this.config = "";
this.refresh();
})
.catch(err => (this.err = err));
}
}
})
</script>
</body>
</html>

View File

@ -3,6 +3,7 @@ package meme
import (
"encoding/json"
"fmt"
"html/template"
"net/http"
"net/url"
"path"
@ -46,7 +47,7 @@ func (p *MemePlugin) all(w http.ResponseWriter, r *http.Request) {
for n, u := range memes {
config, ok := configs[n]
if !ok {
b, _ := json.Marshal(defaultFormatConfig())
b, _ := json.Marshal(defaultFormatConfig)
config = string(b)
}
realURL, err := url.Parse(u)
@ -129,7 +130,8 @@ func (p *MemePlugin) addMeme(w http.ResponseWriter, r *http.Request) {
}
func (p *MemePlugin) webRoot(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, memeIndex)
var tpl = template.Must(template.New("factoidIndex").Parse(string(memeIndex)))
tpl.Execute(w, struct{ Nav []bot.EndPoint }{p.bot.GetWebNavigation()})
}
func (p *MemePlugin) img(w http.ResponseWriter, r *http.Request) {