new notifier intro update

pull/21/head
Hunter Long 2018-07-10 05:05:20 -07:00
parent 268c31418a
commit bf2ece12fe
14 changed files with 314 additions and 182 deletions

6
cli.go
View File

@ -4,8 +4,8 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/hunterlong/statup/core" "github.com/hunterlong/statup/core"
"github.com/hunterlong/statup/notifiers"
"github.com/hunterlong/statup/plugin" "github.com/hunterlong/statup/plugin"
"github.com/hunterlong/statup/types"
"github.com/hunterlong/statup/utils" "github.com/hunterlong/statup/utils"
"github.com/joho/godotenv" "github.com/joho/godotenv"
"io/ioutil" "io/ioutil"
@ -246,13 +246,13 @@ func FakeSeed(plug plugin.PluginActions) {
} }
fakeUser.Create() fakeUser.Create()
comm := &types.Communication{ comm := &notifiers.Notification{
Id: 1, Id: 1,
Method: "email", Method: "email",
} }
core.Create(comm) core.Create(comm)
comm2 := &types.Communication{ comm2 := &notifiers.Notification{
Id: 2, Id: 2,
Method: "slack", Method: "slack",
} }

View File

@ -1,37 +1,34 @@
package core package core
import ( import (
"fmt" "github.com/hunterlong/statup/notifiers"
"github.com/hunterlong/statup/notifications"
"github.com/hunterlong/statup/types"
"github.com/hunterlong/statup/utils" "github.com/hunterlong/statup/utils"
"time"
) )
func LoadDefaultCommunications() { func LoadDefaultCommunications() {
notifications.EmailComm = SelectCommunication(1) //communications.EmailComm = SelectCommunication(1)
emailer := notifications.EmailComm //emailer := communications.EmailComm
if emailer.Enabled { //if emailer.Enabled {
admin, _ := SelectUser(1) // admin, _ := SelectUser(1)
notifications.LoadEmailer(emailer) // communications.LoadEmailer(emailer)
email := &types.Email{ // email := &types.Email{
To: admin.Email, // To: admin.Email,
Subject: "Test Email", // Subject: "Test Email",
Template: "message.html", // Template: "message.html",
Data: nil, // Data: nil,
From: emailer.Var1, // From: emailer.Var1,
} // }
notifications.SendEmail(EmailBox, email) // communications.SendEmail(EmailBox, email)
go notifications.EmailRoutine() // go communications.EmailRoutine()
} //}
notifications.SlackComm = SelectCommunication(2) //communications.SlackComm = SelectCommunication(2)
slack := notifications.SlackComm //slack := communications.SlackComm
if slack.Enabled { //if slack.Enabled {
notifications.LoadSlack(slack.Host) // communications.LoadSlack(slack.Host)
msg := fmt.Sprintf("Slack loaded on your Statup Status Page!") // msg := fmt.Sprintf("Slack loaded on your Statup Status Page!")
notifications.SendSlack(msg) // communications.SendSlack(msg)
go notifications.SlackRoutine() // go communications.SlackRoutine()
} //}
} }
func LoadComms() { func LoadComms() {
@ -42,51 +39,53 @@ func LoadComms() {
} }
} }
func SelectAllCommunications() ([]*types.Communication, error) { func SelectAllCommunications() ([]*notifiers.Notification, error) {
var c []*types.Communication var c []*notifiers.Notification
col := DbSession.Collection("communication").Find() col := DbSession.Collection("communication").Find()
err := col.OrderBy("id").All(&c) err := col.OrderBy("id").All(&c)
CoreApp.Communications = c //CoreApp.Communications = c
//communications.LoadComms(c)
return c, err return c, err
} }
func Create(c *types.Communication) (int64, error) { func Create(c *notifiers.Notification) (int64, error) {
c.CreatedAt = time.Now() //c.CreatedAt = time.Now()
uuid, err := DbSession.Collection("communication").Insert(c) //uuid, err := DbSession.Collection("communication").Insert(c)
if err != nil { //if err != nil {
utils.Log(3, err) // utils.Log(3, err)
} //}
if uuid == nil { //if uuid == nil {
utils.Log(2, err) // utils.Log(2, err)
return 0, err // return 0, err
} //}
c.Id = uuid.(int64) //c.Id = uuid.(int64)
c.Routine = make(chan struct{}) //c.Routine = make(chan struct{})
if CoreApp != nil { //if CoreApp != nil {
CoreApp.Communications = append(CoreApp.Communications, c) // CoreApp.Communications = append(CoreApp.Communications, c.Communicator)
} //}
return uuid.(int64), err //return uuid.(int64), err
return 0, nil
} }
func Disable(c *types.Communication) { func Disable(c *notifiers.Notification) {
c.Enabled = false c.Enabled = false
Update(c) Update(c)
} }
func Enable(c *types.Communication) { func Enable(c *notifiers.Notification) {
c.Enabled = true c.Enabled = true
Update(c) Update(c)
} }
func Update(c *types.Communication) *types.Communication { func Update(c *notifiers.Notification) *notifiers.Notification {
col := DbSession.Collection("communication").Find("id", c.Id) col := DbSession.Collection("communication").Find("id", c.Id)
col.Update(c) col.Update(c)
SelectAllCommunications() SelectAllCommunications()
return c return c
} }
func SelectCommunication(id int64) *types.Communication { func SelectCommunication(id int64) *notifiers.Notification {
var comm *types.Communication var comm *notifiers.Notification
col := DbSession.Collection("communication").Find("id", id) col := DbSession.Collection("communication").Find("id", id)
err := col.One(&comm) err := col.One(&comm)
if err != nil { if err != nil {

View File

@ -2,6 +2,7 @@ package core
import ( import (
"github.com/GeertJohan/go.rice" "github.com/GeertJohan/go.rice"
"github.com/hunterlong/statup/notifiers"
"github.com/hunterlong/statup/plugin" "github.com/hunterlong/statup/plugin"
"github.com/hunterlong/statup/types" "github.com/hunterlong/statup/types"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -28,7 +29,7 @@ type Core struct {
Plugins []plugin.Info Plugins []plugin.Info
Repos []PluginJSON Repos []PluginJSON
AllPlugins []plugin.PluginActions AllPlugins []plugin.PluginActions
Communications []*types.Communication Communications []*notifiers.Notification
DbConnection string DbConnection string
started time.Time started time.Time
} }
@ -59,11 +60,19 @@ func NewCore() *Core {
func InitApp() { func InitApp() {
SelectCore() SelectCore()
notifiers.Collections = DbSession.Collection("communication")
SelectAllCommunications() SelectAllCommunications()
InsertDefaultComms() InsertDefaultComms()
LoadDefaultCommunications() LoadDefaultCommunications()
SelectAllServices() SelectAllServices()
CheckServices() CheckServices()
notifiers.Load()
CoreApp.Communications = notifiers.AllCommunications
go DatabaseMaintence() go DatabaseMaintence()
} }

View File

@ -3,7 +3,7 @@ package core
import ( import (
"fmt" "fmt"
"github.com/fatih/structs" "github.com/fatih/structs"
"github.com/hunterlong/statup/notifications" "github.com/hunterlong/statup/notifiers"
"github.com/hunterlong/statup/plugin" "github.com/hunterlong/statup/plugin"
"github.com/hunterlong/statup/types" "github.com/hunterlong/statup/types"
"upper.io/db.v3/lib/sqlbuilder" "upper.io/db.v3/lib/sqlbuilder"
@ -25,10 +25,10 @@ func OnFailure(s *Service, f FailureData) {
for _, p := range CoreApp.AllPlugins { for _, p := range CoreApp.AllPlugins {
p.OnFailure(structs.Map(s)) p.OnFailure(structs.Map(s))
} }
if notifications.SlackComm != nil { if notifiers.SendSlack("im failing") != nil {
onFailureSlack(s, f) onFailureSlack(s, f)
} }
if notifications.EmailComm != nil { if notifiers.EmailComm != nil {
onFailureEmail(s, f) onFailureEmail(s, f)
} }
} }
@ -36,8 +36,8 @@ func OnFailure(s *Service, f FailureData) {
func onFailureSlack(s *Service, f FailureData) { func onFailureSlack(s *Service, f FailureData) {
slack := SelectCommunication(2) slack := SelectCommunication(2)
if slack.Enabled { if slack.Enabled {
msg := fmt.Sprintf("Service %v is currently offline! Issue: %v", s.Name, f.Issue) //msg := fmt.Sprintf("Service %v is currently offline! Issue: %v", s.Name, f.Issue)
notifications.SendSlack(msg) //communications.SendSlack(msg)
} }
} }
@ -59,7 +59,7 @@ func onFailureEmail(s *Service, f FailureData) {
Data: data, Data: data,
From: email.Var1, From: email.Var1,
} }
notifications.SendEmail(EmailBox, email) notifiers.SendEmail(EmailBox, email)
} }
} }

View File

@ -2,7 +2,7 @@ package core
import ( import (
"fmt" "fmt"
"github.com/hunterlong/statup/types" "github.com/hunterlong/statup/notifiers"
"github.com/hunterlong/statup/utils" "github.com/hunterlong/statup/utils"
"os" "os"
) )
@ -10,7 +10,7 @@ import (
func InsertDefaultComms() { func InsertDefaultComms() {
emailer := SelectCommunication(1) emailer := SelectCommunication(1)
if emailer == nil { if emailer == nil {
emailer := &types.Communication{ emailer := &notifiers.Notification{
Method: "email", Method: "email",
Removable: false, Removable: false,
Enabled: false, Enabled: false,
@ -19,7 +19,7 @@ func InsertDefaultComms() {
} }
slack := SelectCommunication(2) slack := SelectCommunication(2)
if slack == nil { if slack == nil {
slack := &types.Communication{ slack := &notifiers.Notification{
Method: "slack", Method: "slack",
Removable: false, Removable: false,
Enabled: false, Enabled: false,

View File

@ -2,7 +2,7 @@ package handlers
import ( import (
"github.com/hunterlong/statup/core" "github.com/hunterlong/statup/core"
"github.com/hunterlong/statup/notifications" "github.com/hunterlong/statup/notifiers"
"github.com/hunterlong/statup/types" "github.com/hunterlong/statup/types"
"github.com/hunterlong/statup/utils" "github.com/hunterlong/statup/utils"
"net/http" "net/http"
@ -117,12 +117,12 @@ func SaveEmailSettingsHandler(w http.ResponseWriter, r *http.Request) {
Template: "message.html", Template: "message.html",
From: emailer.Var1, From: emailer.Var1,
} }
notifications.LoadEmailer(emailer) notifiers.LoadEmailer(emailer)
notifications.SendEmail(core.EmailBox, sample) notifiers.SendEmail(core.EmailBox, sample)
notifications.EmailComm = emailer notifiers.EmailComm = emailer
if emailer.Enabled { if emailer.Enabled {
utils.Log(1, "Starting Email Routine, 1 unique email per 60 seconds") utils.Log(1, "Starting Email Routine, 1 unique email per 60 seconds")
go notifications.EmailRoutine() go notifiers.EmailRoutine()
} }
http.Redirect(w, r, "/settings", http.StatusSeeOther) http.Redirect(w, r, "/settings", http.StatusSeeOther)
@ -140,7 +140,7 @@ func SaveSlackSettingsHandler(w http.ResponseWriter, r *http.Request) {
slack.Enabled = false slack.Enabled = false
if enable == "on" && slackWebhook != "" { if enable == "on" && slackWebhook != "" {
slack.Enabled = true slack.Enabled = true
go notifications.SlackRoutine() //go communications.SlackRoutine()
} }
slack.Host = slackWebhook slack.Host = slackWebhook
core.Update(slack) core.Update(slack)

29
nocmmitthis.env Normal file
View File

@ -0,0 +1,29 @@
###########################
## Database Information #
###########################
DB_CONNECTION=postgres
DB_HOST=0.0.0.0
DB_PORT=5432
DB_USER=root
DB_PASS=password123
DB_DATABASE=root
###########################
## STATUP PAGE SETTINGS #
###########################
NAME=Demo
DESCRIPTION=This is an awesome page
DOMAIN=https://domain.com
ADMIN_USER=admin
ADMIN_PASS=admin
ADMIN_EMAIL=info@admin.com
USE_CDN=true
###########################
## System Values ##
###########################
IS_DOCKER=true
IS_AWS=true
SASS=/usr/local/bin/sass
BASH_ENV=/bin/bash

View File

@ -1,61 +0,0 @@
package notifications
import (
"bytes"
"fmt"
"github.com/hunterlong/statup/types"
"github.com/hunterlong/statup/utils"
"github.com/pkg/errors"
"net/http"
"time"
)
var (
slackUrl string
sentLastMin int
slackMessages []string
SlackComm *types.Communication
)
func LoadSlack(url string) {
if url == "" {
utils.Log(1, "Slack Webhook URL is empty")
return
}
slackUrl = url
}
func SlackRoutine() {
for _, msg := range slackMessages {
utils.Log(1, fmt.Sprintf("Sending JSON to Slack Webhook: %v", msg))
client := http.Client{Timeout: 15 * time.Second}
_, err := client.Post(slackUrl, "application/json", bytes.NewBuffer([]byte(msg)))
if err != nil {
utils.Log(3, fmt.Sprintf("Issue sending Slack notification: %v", err))
}
slackMessages = removeStrArray(slackMessages, msg)
}
time.Sleep(60 * time.Second)
if SlackComm.Enabled {
SlackRoutine()
}
}
func removeStrArray(arr []string, v string) []string {
var newArray []string
for _, i := range arr {
if i != v {
newArray = append(newArray, v)
}
}
return newArray
}
func SendSlack(msg string) error {
if slackUrl == "" {
return errors.New("Slack Webhook URL has not been set in settings")
}
fullMessage := fmt.Sprintf("{\"text\":\"%v\"}", msg)
slackMessages = append(slackMessages, fullMessage)
return nil
}

View File

@ -1,4 +1,4 @@
package notifications package notifiers
import ( import (
"bytes" "bytes"
@ -15,7 +15,7 @@ import (
var ( var (
mailer *gomail.Dialer mailer *gomail.Dialer
emailQueue []*types.Email emailQueue []*types.Email
EmailComm *types.Communication EmailComm *Notification
) )
func EmailRoutine() { func EmailRoutine() {
@ -55,7 +55,7 @@ func dialSend(email *types.Email) error {
return nil return nil
} }
func LoadEmailer(mail *types.Communication) { func LoadEmailer(mail *Notification) {
utils.Log(1, fmt.Sprintf("Loading SMTP Emailer using host: %v:%v", mail.Host, mail.Port)) utils.Log(1, fmt.Sprintf("Loading SMTP Emailer using host: %v:%v", mail.Host, mail.Port))
mailer = gomail.NewDialer(mail.Host, mail.Port, mail.Username, mail.Password) mailer = gomail.NewDialer(mail.Host, mail.Port, mail.Username, mail.Password)
mailer.TLSConfig = &tls.Config{InsecureSkipVerify: true} mailer.TLSConfig = &tls.Config{InsecureSkipVerify: true}

77
notifiers/notifiers.go Normal file
View File

@ -0,0 +1,77 @@
package notifiers
import (
"github.com/hunterlong/statup/utils"
"time"
"upper.io/db.v3"
)
var (
AllCommunications []*Notification
Collections db.Collection
)
func add(c *Notification) {
AllCommunications = append(AllCommunications, c)
}
func Load() {
utils.Log(1, "Loading notifiers")
for _, comm := range AllCommunications {
comm.Init()
}
}
type Notification struct {
Id int64 `db:"id,omitempty" json:"id"`
Method string `db:"method" json:"method"`
Host string `db:"host" json:"-"`
Port int `db:"port" json:"-"`
Username string `db:"username" json:"-"`
Password string `db:"password" json:"-"`
Var1 string `db:"var1" json:"-"`
Var2 string `db:"var2" json:"-"`
ApiKey string `db:"api_key" json:"-"`
ApiSecret string `db:"api_secret" json:"-"`
Enabled bool `db:"enabled" json:"enabled"`
Limits int64 `db:"limits" json:"-"`
Removable bool `db:"removable" json:"-"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
Form []NotificationForm
Routine chan struct{}
}
type Notifier interface {
Init() error
Run() error
OnFailure() error
OnSuccess() error
}
type NotificationForm struct {
Type string
Title string
Placeholder string
}
func OnFailure() {
for _, comm := range AllCommunications {
comm.OnFailure()
}
}
func OnSuccess() {
for _, comm := range AllCommunications {
comm.OnSuccess()
}
}
func uniqueMessages(arr []string, v string) []string {
var newArray []string
for _, i := range arr {
if i != v {
newArray = append(newArray, v)
}
}
return newArray
}

96
notifiers/slack.go Normal file
View File

@ -0,0 +1,96 @@
package notifiers
import (
"bytes"
"fmt"
"github.com/hunterlong/statup/utils"
"net/http"
"time"
)
const (
SLACK_ID int64 = 2
SLACK_METHOD = "slack"
)
var (
slacker *Notification
slackMessages []string
)
// DEFINE YOUR NOTIFICATION HERE.
func init() {
slacker = &Notification{
Id: SLACK_ID,
Method: SLACK_METHOD,
Host: "https://webhooksurl.slack.com/***",
Form: []NotificationForm{{
Type: "text",
Title: "Incoming Webhook Url",
Placeholder: "Insert your Slack webhook URL here.",
}},
}
add(slacker)
}
// WHEN NOTIFIER LOADS
func (u *Notification) Init() error {
err := SendSlack("its online")
go u.Run()
return err
}
// AFTER NOTIFIER LOADS, IF ENABLED, START A QUEUE PROCESS
func (u *Notification) Run() error {
for _, msg := range slackMessages {
utils.Log(1, fmt.Sprintf("Sending JSON to Slack Webhook: %v", msg))
client := http.Client{Timeout: 15 * time.Second}
_, err := client.Post("https://hooks.slack.com/services/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", "application/json", bytes.NewBuffer([]byte(msg)))
if err != nil {
utils.Log(3, fmt.Sprintf("Issue sending Slack notification: %v", err))
}
slackMessages = uniqueMessages(slackMessages, msg)
}
time.Sleep(60 * time.Second)
if u.Enabled {
u.Run()
}
return nil
}
// CUSTOM FUNCTION FO SENDING SLACK MESSAGES
func SendSlack(msg string) error {
//if slackUrl == "" {
// return errors.New("Slack Webhook URL has not been set in settings")
//}
fullMessage := fmt.Sprintf("{\"text\":\"%v\"}", msg)
slackMessages = append(slackMessages, fullMessage)
return nil
}
// ON SERVICE FAILURE, DO YOUR OWN FUNCTIONS
func (u *Notification) OnFailure() error {
utils.Log(1, fmt.Sprintf("Notification %v is receiving a failure notification.", u.Method))
// Do failing stuff here!
return nil
}
// ON SERVICE SUCCESS, DO YOUR OWN FUNCTIONS
func (u *Notification) OnSuccess() error {
utils.Log(1, fmt.Sprintf("Notification %v is receiving a successful notification.", u.Method))
// Do checking or any successful things here
return nil
}
// ON SAVE OR UPDATE OF THE NOTIFIER FORM
func (u *Notification) OnSave() error {
utils.Log(1, fmt.Sprintf("Notification %v is receiving updated information.", u.Method))
// Do updating stuff here
return nil
}

1
notifiers/structs.go Normal file
View File

@ -0,0 +1 @@
package notifiers

View File

@ -33,10 +33,11 @@
<a class="nav-link active" id="v-pills-home-tab" data-toggle="pill" href="#v-pills-home" role="tab" aria-controls="v-pills-home" aria-selected="true">Settings</a> <a class="nav-link active" id="v-pills-home-tab" data-toggle="pill" href="#v-pills-home" role="tab" aria-controls="v-pills-home" aria-selected="true">Settings</a>
<a class="nav-link" id="v-pills-style-tab" data-toggle="pill" href="#v-pills-style" role="tab" aria-controls="v-pills-style" aria-selected="false">Theme Editor</a> <a class="nav-link" id="v-pills-style-tab" data-toggle="pill" href="#v-pills-style" role="tab" aria-controls="v-pills-style" aria-selected="false">Theme Editor</a>
<a class="nav-link" id="v-pills-email-tab" data-toggle="pill" href="#v-pills-email" role="tab" aria-controls="v-pills-email" aria-selected="true">Email Settings</a> <a class="nav-link" id="v-pills-email-tab" data-toggle="pill" href="#v-pills-email" role="tab" aria-controls="v-pills-email" aria-selected="true">Email Settings</a>
<a class="nav-link" id="v-pills-slack-tab" data-toggle="pill" href="#v-pills-slack" role="tab" aria-controls="v-pills-slack" aria-selected="true">Slack Updates</a>
{{ range .Communications }}
{{ range .Communications }}
<a class="nav-link text-capitalize" id="v-pills-{{underscore .Method}}-tab" data-toggle="pill" href="#v-pills-{{underscore .Method}}" role="tab" aria-controls="v-pills-{{underscore .Method}}" aria-selected="false">{{.Method}}</a>
{{ end }} {{ end }}
<a class="nav-link" id="v-pills-browse-tab" data-toggle="pill" href="#v-pills-browse" role="tab" aria-controls="v-pills-home" aria-selected="false">Browse Plugins</a> <a class="nav-link" id="v-pills-browse-tab" data-toggle="pill" href="#v-pills-browse" role="tab" aria-controls="v-pills-home" aria-selected="false">Browse Plugins</a>
{{ range .Plugins }} {{ range .Plugins }}
<a class="nav-link text-capitalize" id="v-pills-{{underscore .Name}}-tab" data-toggle="pill" href="#v-pills-{{underscore .Name}}" role="tab" aria-controls="v-pills-profile" aria-selected="false">{{.Name}}</a> <a class="nav-link text-capitalize" id="v-pills-{{underscore .Name}}-tab" data-toggle="pill" href="#v-pills-{{underscore .Name}}" role="tab" aria-controls="v-pills-profile" aria-selected="false">{{.Name}}</a>
@ -122,6 +123,33 @@
{{end}} {{end}}
</div> </div>
{{ range .Communications }}
<div class="tab-pane fade" id="v-pills-{{underscore .Method}}" role="tabpanel" aria-labelledby="v-pills-{{underscore .Method }}-tab">
<form method="POST" action="/settings/{{ .Method }}">
{{range .Form}}
<div class="form-group">
<label class="text-capitalize" for="{{underscore .Title}}">{{.Title}}</label>
<input type="{{.Type}}" name="{{underscore .Title}}" class="form-control" value="" id="{{underscore .Title}}" placeholder="{{.Placeholder}}">
</div>
{{end}}
<div class="form-group row">
<div class="col-sm-6">
<span class="switch">
<input type="checkbox" name="enable_{{ .Method }}" class="switch" id="switch-{{ .Method }}" {{if .Enabled}}checked{{end}}>
<label for="switch-{{ .Method }}">Enable {{ .Method }}</label>
</span>
</div>
<div class="col-sm-6">
<button type="submit" class="btn btn-primary btn-block text-capitalize">Save {{ .Method }} Settings</button>
</div>
</div>
</form>
</div>
{{ end }}
{{ with $c := index .Communications 0 }} {{ with $c := index .Communications 0 }}
<div class="tab-pane fade" id="v-pills-{{ $c.Method }}" role="tabpanel" aria-labelledby="v-pills-{{ $c.Method }}-tab"> <div class="tab-pane fade" id="v-pills-{{ $c.Method }}" role="tabpanel" aria-labelledby="v-pills-{{ $c.Method }}-tab">
@ -177,34 +205,6 @@
{{ end }} {{ end }}
{{ with $c := index .Communications 1 }}
<div class="tab-pane fade" id="v-pills-{{ $c.Method }}" role="tabpanel" aria-labelledby="v-pills-{{ $c.Method }}-tab">
<form method="POST" action="/settings/{{ $c.Method }}">
<div class="form-group">
<label for="slack_url">Slack Webhook URL</label>
<input type="text" name="slack_url" class="form-control" value="{{ $c.Host }}" id="slack_url" placeholder="https://hooks.slack.com/services/TJIIDSJIFJ/729FJSDF/hua463asda9af79">
</div>
<div class="form-group row">
<div class="col-sm-6">
<span class="switch">
<input type="checkbox" name="enable_{{ $c.Method }}" class="switch" id="switch-{{ $c.Method }}" {{if .Enabled}}checked{{end}}>
<label for="switch-{{ $c.Method }}">Enable Slack</label>
</span>
</div>
<div class="col-sm-6">
<button type="submit" class="btn btn-primary btn-block">Save Slack Settings</button>
</div>
</div>
</form>
</div>
{{ end }}
<div class="tab-pane fade" id="v-pills-browse" role="tabpanel" aria-labelledby="v-pills-browse-tab"> <div class="tab-pane fade" id="v-pills-browse" role="tabpanel" aria-labelledby="v-pills-browse-tab">
{{ range .Repos }} {{ range .Repos }}

View File

@ -40,24 +40,6 @@ type Checkin struct {
Last time.Time `json:"last"` Last time.Time `json:"last"`
} }
type Communication struct {
Id int64 `db:"id,omitempty" json:"id"`
Method string `db:"method" json:"method"`
Host string `db:"host" json:"-"`
Port int `db:"port" json:"-"`
Username string `db:"username" json:"-"`
Password string `db:"password" json:"-"`
Var1 string `db:"var1" json:"-"`
Var2 string `db:"var2" json:"-"`
ApiKey string `db:"api_key" json:"-"`
ApiSecret string `db:"api_secret" json:"-"`
Enabled bool `db:"enabled" json:"enabled"`
Limits int64 `db:"limits" json:"-"`
Removable bool `db:"removable" json:"-"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
Routine chan struct{}
}
type Email struct { type Email struct {
To string To string
Subject string Subject string