pull/10/head
hunterlong 2018-06-22 17:10:37 -07:00
parent dbb73f7651
commit 8d8f25ea23
18 changed files with 300 additions and 58 deletions

4
api.go
View File

@ -20,13 +20,13 @@ func ApiCheckinHandler(w http.ResponseWriter, r *http.Request) {
func ApiServiceHandler(w http.ResponseWriter, r *http.Request) { func ApiServiceHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
service, _ := SelectService(StringInt(vars["id"])) service := SelectService(StringInt(vars["id"]))
json.NewEncoder(w).Encode(service) json.NewEncoder(w).Encode(service)
} }
func ApiServiceUpdateHandler(w http.ResponseWriter, r *http.Request) { func ApiServiceUpdateHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
service, _ := SelectService(StringInt(vars["id"])) service := SelectService(StringInt(vars["id"]))
var s Service var s Service
decoder := json.NewDecoder(r.Body) decoder := json.NewDecoder(r.Body)

53
comms/emailer.go Normal file
View File

@ -0,0 +1,53 @@
package comms
import (
"bytes"
"crypto/tls"
"fmt"
"gopkg.in/gomail.v2"
"html/template"
"log"
"os"
)
var (
mailer *gomail.Dialer
)
func NewMailer() {
mailer = gomail.NewDialer(os.Getenv("HOST"), 587, os.Getenv("USER"), os.Getenv("PASS"))
mailer.TLSConfig = &tls.Config{InsecureSkipVerify: true}
source := EmailTemplate("comms/templates/error.html", "this is coooool")
fmt.Println("source: ", source)
}
func EmailTemplate(tmpl string, data interface{}) string {
t := template.New("error.html")
var err error
t, err = t.ParseFiles(tmpl)
if err != nil {
panic(err)
}
var tpl bytes.Buffer
if err := t.Execute(&tpl, data); err != nil {
log.Println(err)
}
result := tpl.String()
return result
}
func SendEmail(to, subject, body string) {
m := gomail.NewMessage()
m.SetHeader("From", "info@email.com")
m.SetHeader("To", to)
m.SetHeader("Subject", subject)
m.SetBody("text/html", body)
if err := mailer.DialAndSend(m); err != nil {
fmt.Println(err)
}
}

View File

@ -0,0 +1,15 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
</head>
<body>
<p>
<strong>Hello {{.}}</strong>
</p>
</body>
</html>

80
communication.go Normal file
View File

@ -0,0 +1,80 @@
package main
import "time"
var (
Communications []*Communication
)
type Communication struct {
Id int64 `db:"id,omitempty" json:"id"`
Method string `db:"method" json:"method"`
Host string `db:"host" json:"host"`
Port int64 `db:"port" json:"port"`
User string `db:"user" json:"user"`
Password string `db:"password" json:"-"`
Var1 string `db:"var1" json:"var1"`
Var2 string `db:"var2" json:"var2"`
ApiKey string `db:"api_key" json:"api_key"`
ApiSecret string `db:"api_secret" json:"api_secret"`
Enabled bool `db:"enabled" json:"enabled"`
Limits int64 `db:"limits" json:"limits"`
Removable bool `db:"removable" json:"removable"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
}
func OnCommunicate() {
for _, c := range Communications {
if c.Enabled {
c.Run()
}
}
}
func (c *Communication) Run() {
}
func SelectAllCommunications() ([]*Communication, error) {
var c []*Communication
col := dbSession.Collection("communication").Find()
err := col.All(&c)
Communications = c
return c, err
}
func (c *Communication) Create() (int64, error) {
c.CreatedAt = time.Now()
uuid, err := dbSession.Collection("communication").Insert(c)
if uuid == nil {
return 0, err
}
c.Id = uuid.(int64)
Communications = append(Communications, c)
return uuid.(int64), err
}
func (c *Communication) Disable() {
c.Enabled = false
c.Update()
}
func (c *Communication) Enable() {
c.Enabled = true
c.Update()
}
func (c *Communication) Update() *Communication {
col := dbSession.Collection("communication").Find("id", c.Id)
col.Update(c)
return c
}
func SelectCommunication(id int64) *Communication {
for _, c := range Communications {
if c.Id == id {
return c
}
}
return nil
}

View File

@ -13,6 +13,7 @@ type Core struct {
ApiSecret string `db:"api_secret"` ApiSecret string `db:"api_secret"`
Style string `db:"style"` Style string `db:"style"`
Footer string `db:"footer"` Footer string `db:"footer"`
Domain string `db:"domain"`
Version string `db:"version"` Version string `db:"version"`
Plugins []plugin.Info Plugins []plugin.Info
Repos []PluginJSON Repos []PluginJSON

View File

@ -27,11 +27,11 @@ func (s *Service) CreateFailure(data FailureData) (int64, error) {
return uuid.(int64), err return uuid.(int64), err
} }
func (s *Service) SelectAllFailures() ([]*Failure, error) { func (s *Service) SelectAllFailures() []*Failure {
var fails []*Failure var fails []*Failure
col := dbSession.Collection("failures").Find("service", s.Id).OrderBy("-id") col := dbSession.Collection("failures").Find("service", s.Id).OrderBy("-id")
err := col.All(&fails) col.All(&fails)
return fails, err return fails
} }
func (u *Service) DeleteFailures() { func (u *Service) DeleteFailures() {

View File

@ -116,8 +116,8 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="service_url" class="col-sm-12 col-form-label">Application Endpoint (URL)</label> <label for="service_url" class="col-sm-4 col-form-label">Application Endpoint (URL)</label>
<div class="col-12"> <div class="col-sm-8">
<input type="text" name="domain" class="form-control" id="service_url" value="{{.Domain}}" placeholder="https://google.com"> <input type="text" name="domain" class="form-control" id="service_url" value="{{.Domain}}" placeholder="https://google.com">
</div> </div>
</div> </div>
@ -194,20 +194,10 @@
label: 'Response Time (Milliseconds)', label: 'Response Time (Milliseconds)',
data: {{js .GraphData}}, data: {{js .GraphData}},
backgroundColor: [ backgroundColor: [
'rgba(255, 99, 132, 0.2)', 'rgba(47, 206, 30, 0.92)'
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
], ],
borderColor: [ borderColor: [
'rgba(255,99,132,1)', 'rgb(47, 171, 34)'
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
], ],
borderWidth: 1 borderWidth: 1
}] }]

View File

@ -64,8 +64,8 @@
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="service_url" class="col-sm-12 col-form-label">Application Endpoint (URL)</label> <label for="service_url" class="col-sm-4 col-form-label">Application Endpoint (URL)</label>
<div class="col-12"> <div class="col-sm-8">
<input type="text" name="domain" class="form-control" id="service_url" placeholder="https://google.com"> <input type="text" name="domain" class="form-control" id="service_url" placeholder="https://google.com">
</div> </div>
</div> </div>

View File

@ -6,6 +6,7 @@ import (
"github.com/GeertJohan/go.rice" "github.com/GeertJohan/go.rice"
"github.com/go-yaml/yaml" "github.com/go-yaml/yaml"
"github.com/gorilla/sessions" "github.com/gorilla/sessions"
"github.com/hunterlong/statup/comms"
"github.com/hunterlong/statup/plugin" "github.com/hunterlong/statup/plugin"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"io" "io"
@ -124,6 +125,9 @@ func DownloadFile(filepath string, url string) error {
func main() { func main() {
var err error var err error
fmt.Printf("Starting Statup v%v\n", VERSION) fmt.Printf("Starting Statup v%v\n", VERSION)
comms.NewMailer()
RenderBoxes() RenderBoxes()
configs, err = LoadConfig() configs, err = LoadConfig()
if err != nil { if err != nil {

View File

@ -140,8 +140,8 @@ func TestUser_Create(t *testing.T) {
} }
func TestOneService_Check(t *testing.T) { func TestOneService_Check(t *testing.T) {
service, err := SelectService(1) service := SelectService(1)
assert.Nil(t, err) assert.NotNil(t, service)
assert.Equal(t, "Google", service.Name) assert.Equal(t, "Google", service.Name)
} }
@ -161,32 +161,30 @@ func TestService_Create(t *testing.T) {
} }
func TestService_Check(t *testing.T) { func TestService_Check(t *testing.T) {
service, err := SelectService(2) service := SelectService(2)
assert.Nil(t, err) assert.NotNil(t, service)
assert.Equal(t, "Statup.io", service.Name) assert.Equal(t, "Statup.io", service.Name)
out := service.Check() out := service.Check()
assert.Equal(t, true, out.Online) assert.Equal(t, true, out.Online)
} }
func TestService_AvgTime(t *testing.T) { func TestService_AvgTime(t *testing.T) {
service, err := SelectService(1) service := SelectService(1)
assert.Nil(t, err) assert.NotNil(t, service)
avg := service.AvgUptime() avg := service.AvgUptime()
assert.Nil(t, err)
assert.Equal(t, "100", avg) assert.Equal(t, "100", avg)
} }
func TestService_Online24(t *testing.T) { func TestService_Online24(t *testing.T) {
service, err := SelectService(1) service := SelectService(1)
assert.Nil(t, err) assert.NotNil(t, service)
online := service.Online24() online := service.Online24()
assert.Nil(t, err)
assert.Equal(t, float32(100), online) assert.Equal(t, float32(100), online)
} }
func TestService_GraphData(t *testing.T) { func TestService_GraphData(t *testing.T) {
service, err := SelectService(1) service := SelectService(1)
assert.Nil(t, err) assert.NotNil(t, service)
data := service.GraphData() data := service.GraphData()
assert.NotEmpty(t, data) assert.NotEmpty(t, data)
} }
@ -207,22 +205,22 @@ func TestBadService_Create(t *testing.T) {
} }
func TestBadService_Check(t *testing.T) { func TestBadService_Check(t *testing.T) {
service, err := SelectService(4) service := SelectService(4)
assert.Nil(t, err) assert.NotNil(t, service)
assert.Equal(t, "Github Failing Check", service.Name) assert.Equal(t, "Github Failing Check", service.Name)
} }
func TestService_Hits(t *testing.T) { func TestService_Hits(t *testing.T) {
service, err := SelectService(1) service := SelectService(1)
assert.Nil(t, err) assert.NotNil(t, service)
hits, err := service.Hits() hits, err := service.Hits()
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 20, len(hits)) assert.Equal(t, 20, len(hits))
} }
func TestService_LimitedHits(t *testing.T) { func TestService_LimitedHits(t *testing.T) {
service, err := SelectService(1) service := SelectService(1)
assert.Nil(t, err) assert.NotNil(t, service)
hits, err := service.LimitedHits() hits, err := service.LimitedHits()
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, 20, len(hits)) assert.Equal(t, 20, len(hits))

View File

@ -23,6 +23,7 @@ type Service struct {
Interval int `db:"check_interval" json:"check_interval"` Interval int `db:"check_interval" json:"check_interval"`
Type string `db:"check_type" json:"type"` Type string `db:"check_type" json:"type"`
Method string `db:"method" json:"method"` Method string `db:"method" json:"method"`
PostData string `db:"post_data" json:"post_data"`
Port int `db:"port" json:"port"` Port int `db:"port" json:"port"`
CreatedAt time.Time `db:"created_at" json:"created_at"` CreatedAt time.Time `db:"created_at" json:"created_at"`
Online bool `json:"online"` Online bool `json:"online"`
@ -30,30 +31,34 @@ type Service struct {
Online24Hours float32 `json:"24_hours_online"` Online24Hours float32 `json:"24_hours_online"`
AvgResponse string `json:"avg_response"` AvgResponse string `json:"avg_response"`
TotalUptime string `json:"uptime"` TotalUptime string `json:"uptime"`
OrderId int64 `json:"order_id"`
Failures []*Failure `json:"failures"` Failures []*Failure `json:"failures"`
Checkins []*Checkin `json:"checkins"` Checkins []*Checkin `json:"checkins"`
runRoutine bool
} }
func serviceCol() db.Collection { func serviceCol() db.Collection {
return dbSession.Collection("services") return dbSession.Collection("services")
} }
func SelectService(id int64) (*Service, error) { func SelectService(id int64) *Service {
var service *Service for _, s := range services {
res := serviceCol().Find("id", id) if s.Id == id {
err := res.One(&service) return s
service.Checkins = service.SelectAllCheckins() }
return service, err }
return nil
} }
func SelectAllServices() ([]*Service, error) { func SelectAllServices() ([]*Service, error) {
var services []*Service var srvcs []*Service
col := serviceCol().Find() col := serviceCol().Find()
err := col.All(&services) err := col.All(&srvcs)
for _, s := range services { for _, s := range srvcs {
s.Checkins = s.SelectAllCheckins() s.Checkins = s.SelectAllCheckins()
s.Failures = s.SelectAllFailures()
} }
return services, err return srvcs, err
} }
func (s *Service) AvgTime() float64 { func (s *Service) AvgTime() float64 {
@ -132,9 +137,21 @@ func (s *Service) AvgUptime() string {
return s.TotalUptime return s.TotalUptime
} }
func (u *Service) RemoveArray() []*Service {
var srvcs []*Service
for _, s := range services {
if s.Id != u.Id {
srvcs = append(srvcs, s)
}
}
services = srvcs
return srvcs
}
func (u *Service) Delete() error { func (u *Service) Delete() error {
res := serviceCol().Find("id", u.Id) res := serviceCol().Find("id", u.Id)
err := res.Delete() err := res.Delete()
u.RemoveArray()
OnDeletedService(u) OnDeletedService(u)
return err return err
} }
@ -151,6 +168,7 @@ func (u *Service) Create() (int64, error) {
} }
u.Id = uuid.(int64) u.Id = uuid.(int64)
services = append(services, u) services = append(services, u)
go u.CheckQueue()
OnNewService(u) OnNewService(u)
return uuid.(int64), err return uuid.(int64), err
} }

View File

@ -26,6 +26,10 @@ type DbConfig struct {
} }
func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) { func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
if core.ApiKey != "" {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
r.ParseForm() r.ParseForm()
dbHost := r.PostForm.Get("db_host") dbHost := r.PostForm.Get("db_host")
dbUser := r.PostForm.Get("db_user") dbUser := r.PostForm.Get("db_user")
@ -77,9 +81,12 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
admin := &User{ admin := &User{
Username: config.Username, Username: config.Username,
Password: config.Password, Password: config.Password,
Admin: true,
} }
admin.Create() admin.Create()
InsertDefaultComms()
if sample == "on" { if sample == "on" {
go LoadSampleData() go LoadSampleData()
} }
@ -89,6 +96,15 @@ func ProcessSetupHandler(w http.ResponseWriter, r *http.Request) {
mainProcess() mainProcess()
} }
func InsertDefaultComms() {
emailer := &Communication{
Method: "email",
Removable: false,
Enabled: false,
}
emailer.Create()
}
func DeleteConfig() { func DeleteConfig() {
err := os.Remove("./config.yml") err := os.Remove("./config.yml")
if err != nil { if err != nil {
@ -145,6 +161,7 @@ func (c *DbConfig) Save() error {
NewSHA1Hash(10), NewSHA1Hash(10),
"", "",
"", "",
"",
VERSION, VERSION,
[]plugin.Info{}, []plugin.Info{},
[]PluginJSON{}, []PluginJSON{},

View File

@ -3,4 +3,5 @@ DROP table hits;
DROP table failures; DROP table failures;
DROP table users; DROP table users;
DROP table checkins; DROP table checkins;
DROP table services; DROP table services;
DROP table communication;

View File

@ -6,6 +6,7 @@ CREATE TABLE core (
api_secret VARCHAR(50), api_secret VARCHAR(50),
style text, style text,
footer text, footer text,
domain text,
version VARCHAR(50) version VARCHAR(50)
); );
CREATE TABLE users ( CREATE TABLE users (
@ -15,6 +16,7 @@ CREATE TABLE users (
email text, email text,
api_key VARCHAR(50), api_key VARCHAR(50),
api_secret VARCHAR(50), api_secret VARCHAR(50),
admin bool,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX (id) INDEX (id)
); );
@ -28,6 +30,8 @@ CREATE TABLE services (
expected text, expected text,
expected_status INT(6), expected_status INT(6),
check_interval int(11), check_interval int(11),
post_data text,
order_id integer,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX (id) INDEX (id)
); );
@ -55,4 +59,20 @@ CREATE TABLE checkins (
created_at TIMESTAMP, created_at TIMESTAMP,
INDEX (id, service), INDEX (id, service),
FOREIGN KEY (service) REFERENCES services(id) FOREIGN KEY (service) REFERENCES services(id)
);
CREATE TABLE communication (
id SERIAL PRIMARY KEY,
method text,
host text,
port integer,
user text,
password text,
var1 text,
var2 text,
api_key text,
api_secret text,
enabled boolean,
removable boolean,
limits integer,
created_at TIMESTAMP
); );

View File

@ -6,6 +6,7 @@ CREATE TABLE core (
api_secret text, api_secret text,
style text, style text,
footer text, footer text,
domain text,
version text version text
); );
@ -16,6 +17,7 @@ CREATE TABLE users (
email text, email text,
api_key text, api_key text,
api_secret text, api_secret text,
admin bool,
created_at TIMESTAMP created_at TIMESTAMP
); );
@ -29,6 +31,8 @@ CREATE TABLE services (
expected text, expected text,
expected_status integer, expected_status integer,
check_interval integer, check_interval integer,
post_data text,
order_id integer,
created_at TIMESTAMP created_at TIMESTAMP
); );
@ -55,6 +59,23 @@ CREATE TABLE checkins (
created_at TIMESTAMP created_at TIMESTAMP
); );
CREATE TABLE communication (
id SERIAL PRIMARY KEY,
method text,
host text,
port integer,
user text,
password text,
var1 text,
var2 text,
api_key text,
api_secret text,
enabled boolean,
removable boolean,
limits integer,
created_at TIMESTAMP
);
CREATE INDEX idx_hits ON hits(service); CREATE INDEX idx_hits ON hits(service);
CREATE INDEX idx_failures ON failures(service); CREATE INDEX idx_failures ON failures(service);

View File

@ -6,6 +6,7 @@ CREATE TABLE core (
api_secret text, api_secret text,
style text, style text,
footer text, footer text,
domain text,
version text version text
); );
@ -16,6 +17,7 @@ CREATE TABLE users (
email text, email text,
api_key text, api_key text,
api_secret text, api_secret text,
admin bool,
created_at TIMESTAMP created_at TIMESTAMP
); );
@ -29,6 +31,8 @@ CREATE TABLE services (
expected text, expected text,
expected_status integer, expected_status integer,
check_interval integer, check_interval integer,
post_data text,
order_id integer,
created_at TIMESTAMP created_at TIMESTAMP
); );
@ -54,6 +58,24 @@ CREATE TABLE checkins (
created_at TIMESTAMP created_at TIMESTAMP
); );
CREATE TABLE communication (
id SERIAL PRIMARY KEY,
method text,
host text,
port integer,
user text,
password text,
var1 text,
var2 text,
api_key text,
api_secret text,
enabled boolean,
removable boolean,
limits integer,
created_at TIMESTAMP
);
CREATE INDEX idx_hits ON hits(service); CREATE INDEX idx_hits ON hits(service);
CREATE INDEX idx_failures ON failures(service); CREATE INDEX idx_failures ON failures(service);
CREATE INDEX idx_checkins ON checkins(service); CREATE INDEX idx_checkins ON checkins(service);

View File

@ -12,6 +12,7 @@ type User struct {
Email string `db:"email" json:"-"` Email string `db:"email" json:"-"`
ApiKey string `db:"api_key" json:"api_key"` ApiKey string `db:"api_key" json:"api_key"`
ApiSecret string `db:"api_secret" json:"-"` ApiSecret string `db:"api_secret" json:"-"`
Admin bool `db:"admin" json:"admin"`
CreatedAt time.Time `db:"created_at" json:"created_at"` CreatedAt time.Time `db:"created_at" json:"created_at"`
} }

17
web.go
View File

@ -48,7 +48,6 @@ func Router() *mux.Router {
r.Handle("/plugins/download/{name}", http.HandlerFunc(PluginsDownloadHandler)) r.Handle("/plugins/download/{name}", http.HandlerFunc(PluginsDownloadHandler))
r.Handle("/plugins/{name}/save", http.HandlerFunc(PluginSavedHandler)).Methods("POST") r.Handle("/plugins/{name}/save", http.HandlerFunc(PluginSavedHandler)).Methods("POST")
r.Handle("/help", http.HandlerFunc(HelpHandler)) r.Handle("/help", http.HandlerFunc(HelpHandler))
r.Handle("/api", http.HandlerFunc(ApiIndexHandler)) r.Handle("/api", http.HandlerFunc(ApiIndexHandler))
r.Handle("/api/checkin/{api}", http.HandlerFunc(ApiCheckinHandler)) r.Handle("/api/checkin/{api}", http.HandlerFunc(ApiCheckinHandler))
r.Handle("/api/services", http.HandlerFunc(ApiAllServicesHandler)) r.Handle("/api/services", http.HandlerFunc(ApiAllServicesHandler))
@ -151,6 +150,10 @@ func CreateServiceHandler(w http.ResponseWriter, r *http.Request) {
} }
func SetupHandler(w http.ResponseWriter, r *http.Request) { func SetupHandler(w http.ResponseWriter, r *http.Request) {
if core.ApiKey != "" {
http.Redirect(w, r, "/", http.StatusSeeOther)
return
}
ExecuteResponse(w, r, "setup.html", nil) ExecuteResponse(w, r, "setup.html", nil)
} }
@ -209,10 +212,8 @@ func ServicesDeleteHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
vars := mux.Vars(r) vars := mux.Vars(r)
service, _ := SelectService(StringInt(vars["id"])) service := SelectService(StringInt(vars["id"]))
service.Delete() service.Delete()
services, _ = SelectAllServices()
http.Redirect(w, r, "/services", http.StatusSeeOther) http.Redirect(w, r, "/services", http.StatusSeeOther)
} }
@ -223,7 +224,7 @@ func ServicesDeleteFailuresHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
vars := mux.Vars(r) vars := mux.Vars(r)
service, _ := SelectService(StringInt(vars["id"])) service := SelectService(StringInt(vars["id"]))
service.DeleteFailures() service.DeleteFailures()
services, _ = SelectAllServices() services, _ = SelectAllServices()
@ -345,7 +346,7 @@ func CheckinCreateUpdateHandler(w http.ResponseWriter, r *http.Request) {
} }
vars := mux.Vars(r) vars := mux.Vars(r)
interval := StringInt(r.PostForm.Get("interval")) interval := StringInt(r.PostForm.Get("interval"))
service, _ := SelectService(StringInt(vars["id"])) service := SelectService(StringInt(vars["id"]))
checkin := &Checkin{ checkin := &Checkin{
Service: service.Id, Service: service.Id,
Interval: interval, Interval: interval,
@ -365,7 +366,7 @@ func ServicesUpdateHandler(w http.ResponseWriter, r *http.Request) {
func ServicesBadgeHandler(w http.ResponseWriter, r *http.Request) { func ServicesBadgeHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
service, _ := SelectService(StringInt(vars["id"])) service := SelectService(StringInt(vars["id"]))
var badge []byte var badge []byte
if service.Online { if service.Online {
@ -388,7 +389,7 @@ func ServicesViewHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
vars := mux.Vars(r) vars := mux.Vars(r)
service, _ := SelectService(StringInt(vars["id"])) service := SelectService(StringInt(vars["id"]))
ExecuteResponse(w, r, "service.html", service) ExecuteResponse(w, r, "service.html", service)
} }