pull/429/head
hunterlong 2020-03-11 21:58:56 -07:00
parent bbf8073315
commit 6958f41997
41 changed files with 243 additions and 162 deletions

View File

@ -1,13 +1,13 @@
package main package main
import ( import (
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/checkins" "github.com/statping/statping/types/checkins"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/groups" "github.com/statping/statping/types/groups"
"github.com/statping/statping/types/hits" "github.com/statping/statping/types/hits"
"github.com/statping/statping/types/incidents" "github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/messages" "github.com/statping/statping/types/messages"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/types/users" "github.com/statping/statping/types/users"
) )
@ -18,5 +18,5 @@ var (
) )
func init() { func init() {
DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}} DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifiers.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
} }

View File

@ -19,11 +19,13 @@
"@sentry/integrations": "^5.13.2", "@sentry/integrations": "^5.13.2",
"apexcharts": "^3.15.0", "apexcharts": "^3.15.0",
"axios": "^0.19.1", "axios": "^0.19.1",
"bootstrap": "^4.4.1",
"bootstrap-vue": "^2.6.1",
"codemirror-colorpicker": "^1.9.66", "codemirror-colorpicker": "^1.9.66",
"core-js": "^3.4.4", "core-js": "^3.4.4",
"date-fns": "^2.9.0", "date-fns": "^2.9.0",
"querystring": "^0.2.0", "querystring": "^0.2.0",
"vue": "^2.6.10", "vue": "^2.6.11",
"vue-apexcharts": "^1.5.2", "vue-apexcharts": "^1.5.2",
"vue-codemirror": "^4.0.6", "vue-codemirror": "^4.0.6",
"vue-flatpickr-component": "^8.1.5", "vue-flatpickr-component": "^8.1.5",

View File

@ -18,7 +18,7 @@
{{if USING_ASSETS}} {{if USING_ASSETS}}
<link href="css/vendor.css" rel="stylesheet"> <link href="css/vendor.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet"> <link href="css/style.css" rel="stylesheet">
<link rel="stylesheet" href="css/base.css"> <link href="css/base.css" rel="stylesheet">
{{else}} {{else}}
<% _.each(htmlWebpackPlugin.tags.headTags, function(headTag) { %> <% _.each(htmlWebpackPlugin.tags.headTags, function(headTag) { %>
<%= headTag %> <% }) %> <%= headTag %> <% }) %>

View File

@ -53,7 +53,5 @@
<style lang="scss"> <style lang="scss">
@import "./assets/css/bootstrap.min.css"; @import "./assets/css/bootstrap.min.css";
@import "./assets/scss/variables"; @import "./assets/scss/main";
@import "./assets/scss/base";
@import "./assets/scss/mobile";
</style> </style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 574 KiB

View File

@ -1,6 +1,3 @@
@import 'variables';
HTML,BODY { HTML,BODY {
background-color: $background-color; background-color: $background-color;
} }
@ -32,7 +29,7 @@ HTML,BODY {
} }
.service-chart { .service-chart {
bottom: -15px; bottom: -16px;
position: relative; position: relative;
} }
@ -668,4 +665,4 @@ HTML,BODY {
opacity: 0; opacity: 0;
} }
@import 'mobile'; @import 'mobile';

View File

@ -0,0 +1,3 @@
@import 'variables';
@import 'base';
@import 'mobile';

View File

@ -1,5 +1,3 @@
@import 'variables';
@media (max-width: 767px) { @media (max-width: 767px) {
HTML,BODY { HTML,BODY {

View File

@ -12,7 +12,7 @@ $service-title-size: 1.8rem;
$service-stats-color: #4f4f4f; $service-stats-color: #4f4f4f;
$service-description-color: #fff; $service-description-color: #fff;
$service-stats-size: 2.3rem; $service-stats-size: 2.3rem;
$service-card-height: 490px; $service-card-height: 480px !important;
/* Button Colors */ /* Button Colors */
$success-color: #47d337; $success-color: #47d337;

View File

@ -43,9 +43,9 @@
</div> </div>
<div class="col-md-4 col-6 float-right"> <div class="col-md-4 col-6 float-right">
<router-link :to="serviceLink(service)" class="d-none btn btn-sm float-right dyn-dark btn-block text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}"> <router-link :to="serviceLink(service)" class="d-none btn btn-sm float-right dyn-dark text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}">
View Service</router-link> View Service</router-link>
<button @click="expanded = !expanded" class="btn btn-sm float-right dyn-dark btn-block text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}">View Service</button> <button @click="expanded = !expanded" class="btn btn-sm float-right dyn-dark text-white" :class="{'bg-success': service.online, 'bg-danger': !service.online}">View Service</button>
</div> </div>
<div v-if="expanded" class="row"> <div v-if="expanded" class="row">

View File

@ -12,7 +12,7 @@
<div v-for="(form, index) in notifier.form" v-bind:key="index" class="form-group"> <div v-for="(form, index) in notifier.form" v-bind:key="index" class="form-group">
<label class="text-capitalize">{{form.title}}</label> <label class="text-capitalize">{{form.title}}</label>
<input v-if="form.type === 'text' || 'number' || 'password'" v-model="notifier[form.field]" :type="form.type" class="form-control" :placeholder="form.placeholder" > <input v-if="form.type === 'text' || 'number' || 'password'" v-model="notifier[form.field.toLowerCase()]" :type="form.type" class="form-control" :placeholder="form.placeholder" >
<small class="form-text text-muted" v-html="form.small_text"></small> <small class="form-text text-muted" v-html="form.small_text"></small>
</div> </div>
@ -53,6 +53,7 @@
<span class="d-block small text-center mt-5 mb-5"> <span class="d-block small text-center mt-5 mb-5">
<span class="text-capitalize">{{notifier.title}}</span> Notifier created by <a :href="notifier.author_url" target="_blank">{{notifier.author}}</a> <span class="text-capitalize">{{notifier.title}}</span> Notifier created by <a :href="notifier.author_url" target="_blank">{{notifier.author}}</a>
</span> </span>
</form> </form>
</template> </template>
@ -73,6 +74,7 @@ export default {
error: null, error: null,
saved: false, saved: false,
ok: false, ok: false,
form: {},
} }
}, },
mounted() { mounted() {
@ -81,14 +83,14 @@ export default {
methods: { methods: {
async saveNotifier() { async saveNotifier() {
this.loading = true this.loading = true
let form = {} this.form.enabled = this.notifier.enabled
this.form.limits = parseInt(this.notifier.limits)
this.form.method = this.notifier.method
this.notifier.form.forEach((f) => { this.notifier.form.forEach((f) => {
form[f.field] = this.notifier[f.field] let field = f.field.toLowerCase()
this.form[field] = this.notifier[field]
}); });
form.enabled = this.notifier.enabled await Api.notifier_save(this.form)
form.limits = parseInt(this.notifier.limits)
form.method = this.notifier.method
await Api.notifier_save(form)
const notifiers = await Api.notifiers() const notifiers = await Api.notifiers()
await this.$store.commit('setNotifiers', notifiers) await this.$store.commit('setNotifiers', notifiers)
this.saved = true this.saved = true

View File

@ -227,6 +227,8 @@
delete s.last_success delete s.last_success
delete s.latency delete s.latency
delete s.online_24_hours delete s.online_24_hours
s.check_interval = parseInt(s.check_interval)
if (s.id) { if (s.id) {
await this.updateService(s) await this.updateService(s)
} else { } else {

View File

@ -76,6 +76,13 @@ const routes = [
const router = new VueRouter({ const router = new VueRouter({
mode: 'history', mode: 'history',
scrollBehavior (to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { x: 0, y: 0 }
}
},
routes routes
}) })

View File

@ -1040,6 +1040,15 @@
"@nodelib/fs.scandir" "2.1.3" "@nodelib/fs.scandir" "2.1.3"
fastq "^1.6.0" fastq "^1.6.0"
"@nuxt/opencollective@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@nuxt/opencollective/-/opencollective-0.3.0.tgz#11d8944dcf2d526e31660bb69570be03f8fb72b7"
integrity sha512-Vf09BxCdj1iT2IRqVwX5snaY2WCTkvM0O4cWWSO1ThCFuc4if0Q/nNwAgCxRU0FeYHJ7DdyMUNSdswCLKlVqeg==
dependencies:
chalk "^2.4.2"
consola "^2.10.1"
node-fetch "^2.6.0"
"@sentry/browser@^5.13.2": "@sentry/browser@^5.13.2":
version "5.13.2" version "5.13.2"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.13.2.tgz#fcca630c8c80447ba8392803d4e4450fd2231b92" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.13.2.tgz#fcca630c8c80447ba8392803d4e4450fd2231b92"
@ -2165,6 +2174,22 @@ boolbase@^1.0.0, boolbase@~1.0.0:
resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
bootstrap-vue@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/bootstrap-vue/-/bootstrap-vue-2.6.1.tgz#ee96e2e4d277a9044b378e925ef703b2bd9d27c4"
integrity sha512-eOL06T2sjOREUiyN1IZCFYANKrb+tqRqe1pgwjXjbjYa3oclYT6E99v/O12W0Eq9i7+0rQiy+wFOSkFL2yvnng==
dependencies:
"@nuxt/opencollective" "^0.3.0"
bootstrap ">=4.4.1 <5.0.0"
popper.js "^1.16.1"
portal-vue "^2.1.7"
vue-functional-data-merge "^3.1.0"
"bootstrap@>=4.4.1 <5.0.0", bootstrap@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.4.1.tgz#8582960eea0c5cd2bede84d8b0baf3789c3e8b01"
integrity sha512-tbx5cHubwE6e2ZG7nqM3g/FZ5PQEDMWmMGNrCUBVRPHXTJaH7CBDdsLeu3eCh3B1tzAxTnAbtmrzvWEvT2NNEA==
brace-expansion@^1.1.7: brace-expansion@^1.1.7:
version "1.1.11" version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@ -2954,6 +2979,11 @@ connect-history-api-fallback@^1.3.0, connect-history-api-fallback@^1.6.0:
resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"
integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==
consola@^2.10.1:
version "2.11.3"
resolved "https://registry.yarnpkg.com/consola/-/consola-2.11.3.tgz#f7315836224c143ac5094b47fd4c816c2cd1560e"
integrity sha512-aoW0YIIAmeftGR8GSpw6CGQluNdkWMWh3yEFjH/hmynTYnMtibXszii3lxCXmk8YxJtI3FAK5aTiquA5VH68Gw==
console-browserify@^1.1.0: console-browserify@^1.1.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336"
@ -6904,6 +6934,11 @@ node-environment-flags@1.0.6:
object.getownpropertydescriptors "^2.0.3" object.getownpropertydescriptors "^2.0.3"
semver "^5.7.0" semver "^5.7.0"
node-fetch@^2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd"
integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==
node-forge@0.9.0: node-forge@0.9.0:
version "0.9.0" version "0.9.0"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"
@ -7701,6 +7736,16 @@ pnp-webpack-plugin@^1.6.0:
dependencies: dependencies:
ts-pnp "^1.1.6" ts-pnp "^1.1.6"
popper.js@^1.16.1:
version "1.16.1"
resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b"
integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==
portal-vue@^2.1.7:
version "2.1.7"
resolved "https://registry.yarnpkg.com/portal-vue/-/portal-vue-2.1.7.tgz#ea08069b25b640ca08a5b86f67c612f15f4e4ad4"
integrity sha512-+yCno2oB3xA7irTt0EU5Ezw22L2J51uKAacE/6hMPMoO/mx3h4rXFkkBkT4GFsMDv/vEe8TNKC3ujJJ0PTwb6g==
portfinder@^1.0.25, portfinder@^1.0.9: portfinder@^1.0.25, portfinder@^1.0.9:
version "1.0.25" version "1.0.25"
resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca"
@ -10138,6 +10183,11 @@ vue-flatpickr-component@^8.1.5:
dependencies: dependencies:
flatpickr "^4.6.1" flatpickr "^4.6.1"
vue-functional-data-merge@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/vue-functional-data-merge/-/vue-functional-data-merge-3.1.0.tgz#08a7797583b7f35680587f8a1d51d729aa1dc657"
integrity sha512-leT4kdJVQyeZNY1kmnS1xiUlQ9z1B/kdBFCILIjYYQDqZgLqCLa0UhjSSeRX6c3mUe6U5qYeM8LrEqkHJ1B4LA==
vue-hot-reload-api@^2.3.0: vue-hot-reload-api@^2.3.0:
version "2.3.4" version "2.3.4"
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2" resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"
@ -10203,7 +10253,7 @@ vue-template-es2015-compiler@^1.9.0:
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
vue@^2.6.10: vue@^2.6.11:
version "2.6.11" version "2.6.11"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.11.tgz#76594d877d4b12234406e84e35275c6d514125c5" resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.11.tgz#76594d877d4b12234406e84e35275c6d514125c5"
integrity sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ== integrity sha512-VfPwgcGABbGAue9+sfrD4PuwFar7gPb1yl1UK1MwXoQPAw0BKSqWfoYCT/ThFrdEVWoI51dBuyCoiNU9bZDZxQ==

View File

@ -19,12 +19,12 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/checkins" "github.com/statping/statping/types/checkins"
"github.com/statping/statping/types/core" "github.com/statping/statping/types/core"
"github.com/statping/statping/types/groups" "github.com/statping/statping/types/groups"
"github.com/statping/statping/types/incidents" "github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/messages" "github.com/statping/statping/types/messages"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/types/users" "github.com/statping/statping/types/users"
@ -143,7 +143,7 @@ func sendJsonAction(obj interface{}, method string, w http.ResponseWriter, r *ht
case *services.Service: case *services.Service:
objName = "service" objName = "service"
objId = v.Id objId = v.Id
case *notifications.Notification: case *notifiers.Notification:
objName = "notifier" objName = "notifier"
objId = v.Id objId = v.Id
case *core.Core: case *core.Core:

View File

@ -19,21 +19,24 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/statping/statping/types/core" "github.com/statping/statping/notifiers"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"net/http" "net/http"
) )
func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) { func apiNotifiersHandler(w http.ResponseWriter, r *http.Request) {
all := notifications.All() var notifs []notifiers.Notifier
returnJson(all, w, r) all := notifiers.All()
for _, v := range all {
notifs = append(notifs, v)
}
returnJson(notifs, w, r)
} }
func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) { func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
notifier, err := notifications.Find(vars["notifier"]) notifier, err := notifiers.Find(vars["notifier"])
if err != nil { if err != nil {
sendErrorJson(err, w, r) sendErrorJson(err, w, r)
return return
@ -43,26 +46,24 @@ func apiNotifierGetHandler(w http.ResponseWriter, r *http.Request) {
func apiNotifierUpdateHandler(w http.ResponseWriter, r *http.Request) { func apiNotifierUpdateHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r) vars := mux.Vars(r)
notifer, err := notifications.Find(vars["notifier"]) notifer, err := notifiers.Find(vars["notifier"])
if err != nil { if err != nil {
sendErrorJson(err, w, r) sendErrorJson(err, w, r)
return return
} }
n := notifer.Select()
decoder := json.NewDecoder(r.Body) decoder := json.NewDecoder(r.Body)
err = decoder.Decode(&n) err = decoder.Decode(&notifer)
if err != nil { if err != nil {
sendErrorJson(err, w, r) sendErrorJson(err, w, r)
return return
} }
err = n.Update() err = notifer.Update()
if err != nil { if err != nil {
sendErrorJson(err, w, r) sendErrorJson(err, w, r)
return return
} }
notifications.OnSave(n.Method) //notifications.OnSave(notifer.Method)
sendJsonAction(notifer, "update", w, r) sendJsonAction(notifer, "update", w, r)
} }
@ -82,14 +83,14 @@ func testNotificationHandler(w http.ResponseWriter, r *http.Request) {
apiSecret := form.Get("api_secret") apiSecret := form.Get("api_secret")
limits := int(utils.ToInt(form.Get("limits"))) limits := int(utils.ToInt(form.Get("limits")))
notifier, err := notifications.Find(method) notifier, err := notifiers.Find(method)
if err != nil { if err != nil {
log.Errorln(fmt.Sprintf("issue saving notifier %v: %v", method, err)) log.Errorln(fmt.Sprintf("issue saving notifier %v: %v", method, err))
ExecuteResponse(w, r, "settings.gohtml", core.App, "settings") sendErrorJson(err, w, r)
return return
} }
n := notifier.Select() n := notifier
if host != "" { if host != "" {
n.Host = host n.Host = host

View File

@ -17,8 +17,8 @@ package handlers
import ( import (
"fmt" "fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"net/http" "net/http"
@ -104,7 +104,7 @@ func prometheusHandler(w http.ResponseWriter, r *http.Request) {
} }
for _, n := range notifications.All() { for _, n := range notifiers.All() {
notif := n.Select() notif := n.Select()
PrometheusComment(fmt.Sprintf("Notifier %s:", notif.Method)) PrometheusComment(fmt.Sprintf("Notifier %s:", notif.Method))
enabled := 0 enabled := 0

View File

@ -1,4 +1,4 @@
package notifications package notifiers
import ( import (
"errors" "errors"
@ -11,14 +11,14 @@ func SetDB(database database.Database) {
db = database.Model(&Notification{}) db = database.Model(&Notification{})
} }
func Append(n Notifier) { func appendList(n Notifier) {
allNotifiers = append(allNotifiers, n) allNotifiers = append(allNotifiers, n)
} }
func Find(name string) (*Notification, error) { func Find(name string) (*Notification, error) {
for _, n := range allNotifiers { for _, n := range allNotifiers {
notif := n.Select() notif := n.(*Notification)
if notif.Name() == name || notif.Method == name { if notif.Method == name {
return notif, nil return notif, nil
} }
} }
@ -30,12 +30,13 @@ func All() []Notifier {
} }
func (n *Notification) Create() error { func (n *Notification) Create() error {
var notif Notification q := db.Where("method = ?", n.Method).Find(n)
if db.Where("method = ?", n.Method).Find(&notif).RecordNotFound() { if q.RecordNotFound() {
Append(n) if err := db.Create(n).Error(); err != nil {
return db.Create(n).Error() return err
}
} }
Append(n) appendList(n)
return nil return nil
} }
@ -44,7 +45,7 @@ func (n *Notification) Update() error {
if n.Enabled.Bool { if n.Enabled.Bool {
n.Close() n.Close()
n.Start() n.Start()
go Queue(Notifier(n)) go Queue(n)
} else { } else {
n.Close() n.Close()
} }

View File

@ -13,7 +13,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifications package notifiers
import ( import (
"fmt" "fmt"
@ -27,9 +27,9 @@ import (
func OnSave(method string) { func OnSave(method string) {
for _, comm := range allNotifiers { for _, comm := range allNotifiers {
if utils.IsType(comm, new(Notifier)) { if utils.IsType(comm, new(Notifier)) {
notifier := comm.(Notifier) notifier := comm.Select()
if notifier.Select().Method == method { if notifier.Method == method {
notifier.OnSave() comm.OnSave()
} }
} }
} }
@ -55,7 +55,7 @@ func OnFailure(s *services.Service, f *failures.Failure) {
sendMessages: sendMessages:
for _, comm := range allNotifiers { for _, comm := range allNotifiers {
if utils.IsType(comm, new(BasicEvents)) && isEnabled(comm) && (s.Online || inLimits(comm)) { if utils.IsType(comm, new(BasicEvents)) && isEnabled(comm) && (s.Online || inLimits(comm)) {
notifier := comm.(Notifier).Select() notifier := comm.(*Notification)
log. log.
WithField("trigger", "OnFailure"). WithField("trigger", "OnFailure").
WithFields(utils.ToFields(notifier, s)).Debugln(fmt.Sprintf("Sending [OnFailure] '%v' notification for service %v", notifier.Method, s.Name)) WithFields(utils.ToFields(notifier, s)).Debugln(fmt.Sprintf("Sending [OnFailure] '%v' notification for service %v", notifier.Method, s.Name))
@ -78,7 +78,7 @@ func OnSuccess(s *services.Service) {
for _, comm := range allNotifiers { for _, comm := range allNotifiers {
if utils.IsType(comm, new(BasicEvents)) && isEnabled(comm) && (!s.Online || inLimits(comm)) { if utils.IsType(comm, new(BasicEvents)) && isEnabled(comm) && (!s.Online || inLimits(comm)) {
notifier := comm.(Notifier).Select() notifier := comm.(*Notification)
log. log.
WithField("trigger", "OnSuccess"). WithField("trigger", "OnSuccess").
WithFields(utils.ToFields(notifier, s)).Debugln(fmt.Sprintf("Sending [OnSuccess] '%v' notification for service %v", notifier.Method, s.Name)) WithFields(utils.ToFields(notifier, s)).Debugln(fmt.Sprintf("Sending [OnSuccess] '%v' notification for service %v", notifier.Method, s.Name))

View File

@ -117,4 +117,4 @@
// see more details and examples of how to build your own notifier. // see more details and examples of how to build your own notifier.
// //
// More info on: https://github.com/statping/statping/wiki/Notifiers // More info on: https://github.com/statping/statping/wiki/Notifiers
package notifications package _interface

View File

@ -13,7 +13,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifications package notifiers
import ( import (
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"

View File

@ -1,4 +1,4 @@
package notifications package notifiers
import ( import (
"fmt" "fmt"

View File

@ -1,4 +1,4 @@
package notifications package notifiers
import ( import (
"github.com/statping/statping/database" "github.com/statping/statping/database"

View File

@ -3,7 +3,9 @@ package notifiers
import ( import (
"fmt" "fmt"
"github.com/google/martian/log" "github.com/google/martian/log"
"github.com/statping/statping/types/notifications" "github.com/statping/statping/notifiers/senders"
"github.com/statping/statping/types/failures"
"github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"strings" "strings"
) )
@ -12,7 +14,24 @@ var (
allowedVars = []string{"host", "username", "password", "port", "api_key", "api_secret", "var1", "var2"} allowedVars = []string{"host", "username", "password", "port", "api_key", "api_secret", "var1", "var2"}
) )
func checkNotifierForm(n *notifications.Notification) error { func SendEvent(data ...interface{}) {
d1 := data[0]
service, ok := d1.(*services.Service)
if !ok {
return
}
d2 := data[1]
if d2 == nil {
OnSuccess(service)
}
fail, ok := d2.(*failures.Failure)
if !ok {
return
}
OnFailure(service, fail)
}
func checkNotifierForm(n *Notification) error {
for _, f := range n.Form { for _, f := range n.Form {
contains := contains(f.DbField, allowedVars) contains := contains(f.DbField, allowedVars)
if !contains { if !contains {
@ -32,7 +51,7 @@ func contains(s string, arr []string) bool {
} }
// AddNotifier accept a Notifier interface to be added into the array // AddNotifier accept a Notifier interface to be added into the array
func AddNotifiers(notifiers ...notifications.Notifier) error { func AddNotifiers(notifiers ...Notifier) error {
log.Infof("Initiating %d Notifiers\n", len(notifiers)) log.Infof("Initiating %d Notifiers\n", len(notifiers))
for _, n := range notifiers { for _, n := range notifiers {
@ -49,12 +68,10 @@ func AddNotifiers(notifiers ...notifications.Notifier) error {
return err return err
} }
notifications.Append(notif)
if notif.Enabled.Bool { if notif.Enabled.Bool {
notif.Close() notif.Close()
notif.Start() notif.Start()
go notifications.Queue(notif) go Queue(notif)
} }
} }
@ -63,14 +80,14 @@ func AddNotifiers(notifiers ...notifications.Notifier) error {
// startAllNotifiers will start the go routine for each loaded notifier // startAllNotifiers will start the go routine for each loaded notifier
func startAllNotifiers() { func startAllNotifiers() {
for _, notify := range notifications.All() { for _, notify := range All() {
n := notify.Select() n := notify.Select()
log.Infof("Initiating %s Notifier\n", n.Method) log.Infof("Initiating %s Notifier\n", n.Method)
if utils.IsType(notify, new(notifications.Notifier)) { if utils.IsType(notify, new(Notifier)) {
if n.Enabled.Bool { if n.Enabled.Bool {
n.Close() n.Close()
n.Start() n.Start()
go notifications.Queue(notify) go Queue(notify)
} }
} }
} }
@ -78,14 +95,14 @@ func startAllNotifiers() {
func Migrate() error { func Migrate() error {
return AddNotifiers( return AddNotifiers(
Command, senders.Command,
Discorder, senders.Discorder,
Emailer, senders.Emailer,
LineNotify, senders.LineNotify,
Mobile, senders.Mobile,
Slacker, senders.Slacker,
Telegram, senders.Telegram,
Twilio, senders.Twilio,
Webhook, senders.Webhook,
) )
} }

View File

@ -13,25 +13,25 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers package senders
import ( import (
"fmt" "fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"strings" "strings"
"time" "time"
) )
var _ notifications.Notifier = (*commandLine)(nil) var _ notifiers.Notifier = (*commandLine)(nil)
type commandLine struct { type commandLine struct {
*notifications.Notification *notifiers.Notification
} }
var Command = &commandLine{&notifications.Notification{ var Command = &commandLine{&notifiers.Notification{
Method: "command", Method: "command",
Title: "Shell Command", Title: "Shell Command",
Description: "Shell Command allows you to run a customized shell/bash Command on the local machine it's running on.", Description: "Shell Command allows you to run a customized shell/bash Command on the local machine it's running on.",
@ -40,7 +40,7 @@ var Command = &commandLine{&notifications.Notification{
Delay: time.Duration(1 * time.Second), Delay: time.Duration(1 * time.Second),
Icon: "fas fa-terminal", Icon: "fas fa-terminal",
Host: "/bin/bash", Host: "/bin/bash",
Form: []notifications.NotificationForm{{ Form: []notifiers.NotificationForm{{
Type: "text", Type: "text",
Title: "Shell or Bash", Title: "Shell or Bash",
Placeholder: "/bin/bash", Placeholder: "/bin/bash",
@ -66,7 +66,7 @@ func runCommand(app string, cmd ...string) (string, string, error) {
return outStr, errStr, err return outStr, errStr, err
} }
func (u *commandLine) Select() *notifications.Notification { func (u *commandLine) Select() *notifiers.Notification {
return u.Notification return u.Notification
} }

View File

@ -13,28 +13,28 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers package senders
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"strings" "strings"
"time" "time"
) )
var _ notifications.Notifier = (*discord)(nil) var _ notifiers.Notifier = (*discord)(nil)
type discord struct { type discord struct {
*notifications.Notification *notifiers.Notification
} }
var Discorder = &discord{&notifications.Notification{ var Discorder = &discord{&notifiers.Notification{
Method: "discord", Method: "discord",
Title: "discord", Title: "discord",
Description: "Send notifications to your discord channel using discord webhooks. Insert your discord channel Webhook URL to receive notifications. Based on the <a href=\"https://discordapp.com/developers/docs/resources/Webhook\">discord webhooker API</a>.", Description: "Send notifications to your discord channel using discord webhooks. Insert your discord channel Webhook URL to receive notifications. Based on the <a href=\"https://discordapp.com/developers/docs/resources/Webhook\">discord webhooker API</a>.",
@ -43,7 +43,7 @@ var Discorder = &discord{&notifications.Notification{
Delay: time.Duration(5 * time.Second), Delay: time.Duration(5 * time.Second),
Host: "https://discordapp.com/api/webhooks/****/*****", Host: "https://discordapp.com/api/webhooks/****/*****",
Icon: "fab fa-discord", Icon: "fab fa-discord",
Form: []notifications.NotificationForm{{ Form: []notifiers.NotificationForm{{
Type: "text", Type: "text",
Title: "discord webhooker URL", Title: "discord webhooker URL",
Placeholder: "Insert your Webhook URL here", Placeholder: "Insert your Webhook URL here",
@ -58,7 +58,7 @@ func (u *discord) Send(msg interface{}) error {
return err return err
} }
func (u *discord) Select() *notifications.Notification { func (u *discord) Select() *notifiers.Notification {
return u.Notification return u.Notification
} }

View File

@ -13,15 +13,15 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers package senders
import ( import (
"bytes" "bytes"
"crypto/tls" "crypto/tls"
"fmt" "fmt"
"github.com/go-mail/mail" "github.com/go-mail/mail"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
@ -29,7 +29,7 @@ import (
"time" "time"
) )
var _ notifications.Notifier = (*email)(nil) var _ notifiers.Notifier = (*email)(nil)
const ( const (
mainEmailTemplate = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> mainEmailTemplate = `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
@ -112,17 +112,17 @@ var (
) )
type email struct { type email struct {
*notifications.Notification *notifiers.Notification
} }
var Emailer = &email{&notifications.Notification{ var Emailer = &email{&notifiers.Notification{
Method: "email", Method: "email",
Title: "email", Title: "email",
Description: "Send emails via SMTP when services are online or offline.", Description: "Send emails via SMTP when services are online or offline.",
Author: "Hunter Long", Author: "Hunter Long",
AuthorUrl: "https://github.com/hunterlong", AuthorUrl: "https://github.com/hunterlong",
Icon: "far fa-envelope", Icon: "far fa-envelope",
Form: []notifications.NotificationForm{{ Form: []notifiers.NotificationForm{{
Type: "text", Type: "text",
Title: "SMTP Host", Title: "SMTP Host",
Placeholder: "Insert your SMTP Host here.", Placeholder: "Insert your SMTP Host here.",
@ -211,7 +211,7 @@ func (u *email) OnSuccess(s *services.Service) {
} }
} }
func (u *email) Select() *notifications.Notification { func (u *email) Select() *notifiers.Notification {
return u.Notification return u.Notification
} }

View File

@ -13,12 +13,12 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers package senders
import ( import (
"fmt" "fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"net/url" "net/url"
@ -26,24 +26,24 @@ import (
"time" "time"
) )
var _ notifications.Notifier = (*lineNotifier)(nil) var _ notifiers.Notifier = (*lineNotifier)(nil)
const ( const (
lineNotifyMethod = "line_notify" lineNotifyMethod = "line_notify"
) )
type lineNotifier struct { type lineNotifier struct {
*notifications.Notification *notifiers.Notification
} }
var LineNotify = &lineNotifier{&notifications.Notification{ var LineNotify = &lineNotifier{&notifiers.Notification{
Method: lineNotifyMethod, Method: lineNotifyMethod,
Title: "LINE Notify", Title: "LINE Notify",
Description: "LINE Notify will send notifications to your LINE Notify account when services are offline or online. Based on the <a href=\"https://notify-bot.line.me/doc/en/\">LINE Notify API</a>.", Description: "LINE Notify will send notifications to your LINE Notify account when services are offline or online. Based on the <a href=\"https://notify-bot.line.me/doc/en/\">LINE Notify API</a>.",
Author: "Kanin Peanviriyakulkit", Author: "Kanin Peanviriyakulkit",
AuthorUrl: "https://github.com/dogrocker", AuthorUrl: "https://github.com/dogrocker",
Icon: "far fa-bell", Icon: "far fa-bell",
Form: []notifications.NotificationForm{{ Form: []notifiers.NotificationForm{{
Type: "text", Type: "text",
Title: "Access Token", Title: "Access Token",
Placeholder: "Insert your Line Notify Access Token here.", Placeholder: "Insert your Line Notify Access Token here.",
@ -61,7 +61,7 @@ func (u *lineNotifier) Send(msg interface{}) error {
return err return err
} }
func (u *lineNotifier) Select() *notifications.Notification { func (u *lineNotifier) Select() *notifiers.Notification {
return u.Notification return u.Notification
} }

View File

@ -13,28 +13,28 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers package senders
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"time" "time"
) )
var _ notifications.Notifier = (*mobilePush)(nil) var _ notifiers.Notifier = (*mobilePush)(nil)
const mobileIdentifier = "com.statping" const mobileIdentifier = "com.statping"
type mobilePush struct { type mobilePush struct {
*notifications.Notification *notifiers.Notification
} }
var Mobile = &mobilePush{&notifications.Notification{ var Mobile = &mobilePush{&notifiers.Notification{
Method: "mobile", Method: "mobile",
Title: "Mobile Notifications", Title: "Mobile Notifications",
Description: `Receive push notifications on your Mobile device using the Statping App. You can scan the Authentication QR Code found in Settings to get the Mobile app setup in seconds. Description: `Receive push notifications on your Mobile device using the Statping App. You can scan the Authentication QR Code found in Settings to get the Mobile app setup in seconds.
@ -43,7 +43,7 @@ var Mobile = &mobilePush{&notifications.Notification{
AuthorUrl: "https://github.com/hunterlong", AuthorUrl: "https://github.com/hunterlong",
Delay: time.Duration(5 * time.Second), Delay: time.Duration(5 * time.Second),
Icon: "fas fa-mobile-alt", Icon: "fas fa-mobile-alt",
Form: []notifications.NotificationForm{{ Form: []notifiers.NotificationForm{{
Type: "text", Type: "text",
Title: "Device Identifiers", Title: "Device Identifiers",
Placeholder: "A list of your Mobile device push notification ID's.", Placeholder: "A list of your Mobile device push notification ID's.",
@ -58,7 +58,7 @@ var Mobile = &mobilePush{&notifications.Notification{
}}}, }}},
} }
func (u *mobilePush) Select() *notifications.Notification { func (u *mobilePush) Select() *notifiers.Notification {
return u.Notification return u.Notification
} }

View File

@ -13,14 +13,14 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers package senders
import ( import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"strings" "strings"
@ -28,7 +28,7 @@ import (
"time" "time"
) )
var _ notifications.Notifier = (*slack)(nil) var _ notifiers.Notifier = (*slack)(nil)
const ( const (
slackMethod = "slack" slackMethod = "slack"
@ -38,10 +38,10 @@ const (
) )
type slack struct { type slack struct {
*notifications.Notification *notifiers.Notification
} }
var Slacker = &slack{&notifications.Notification{ var Slacker = &slack{&notifiers.Notification{
Method: slackMethod, Method: slackMethod,
Title: "slack", Title: "slack",
Description: "Send notifications to your slack channel when a service is offline. Insert your Incoming webhooker URL for your channel to receive notifications. Based on the <a href=\"https://api.slack.com/incoming-webhooks\">slack API</a>.", Description: "Send notifications to your slack channel when a service is offline. Insert your Incoming webhooker URL for your channel to receive notifications. Based on the <a href=\"https://api.slack.com/incoming-webhooks\">slack API</a>.",
@ -50,7 +50,7 @@ var Slacker = &slack{&notifications.Notification{
Delay: time.Duration(10 * time.Second), Delay: time.Duration(10 * time.Second),
Host: "https://webhooksurl.slack.com/***", Host: "https://webhooksurl.slack.com/***",
Icon: "fab fa-slack", Icon: "fab fa-slack",
Form: []notifications.NotificationForm{{ Form: []notifiers.NotificationForm{{
Type: "text", Type: "text",
Title: "Incoming webhooker Url", Title: "Incoming webhooker Url",
Placeholder: "Insert your slack Webhook URL here.", Placeholder: "Insert your slack Webhook URL here.",
@ -85,7 +85,7 @@ func (u *slack) Send(msg interface{}) error {
return err return err
} }
func (u *slack) Select() *notifications.Notification { func (u *slack) Select() *notifiers.Notification {
return u.Notification return u.Notification
} }

View File

@ -13,14 +13,14 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers package senders
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"net/url" "net/url"
@ -28,13 +28,13 @@ import (
"time" "time"
) )
var _ notifications.Notifier = (*telegram)(nil) var _ notifiers.Notifier = (*telegram)(nil)
type telegram struct { type telegram struct {
*notifications.Notification *notifiers.Notification
} }
var Telegram = &telegram{&notifications.Notification{ var Telegram = &telegram{&notifiers.Notification{
Method: "telegram", Method: "telegram",
Title: "Telegram", Title: "Telegram",
Description: "Receive notifications on your Telegram channel when a service has an issue. You must get a Telegram API token from the /botfather. Review the <a target=\"_blank\" href=\"http://techthoughts.info/how-to-create-a-telegram-bot-and-send-messages-via-api\">Telegram API Tutorial</a> to learn how to generate a new API Token.", Description: "Receive notifications on your Telegram channel when a service has an issue. You must get a Telegram API token from the /botfather. Review the <a target=\"_blank\" href=\"http://techthoughts.info/how-to-create-a-telegram-bot-and-send-messages-via-api\">Telegram API Tutorial</a> to learn how to generate a new API Token.",
@ -42,7 +42,7 @@ var Telegram = &telegram{&notifications.Notification{
AuthorUrl: "https://github.com/hunterlong", AuthorUrl: "https://github.com/hunterlong",
Icon: "fab fa-telegram-plane", Icon: "fab fa-telegram-plane",
Delay: time.Duration(5 * time.Second), Delay: time.Duration(5 * time.Second),
Form: []notifications.NotificationForm{{ Form: []notifiers.NotificationForm{{
Type: "text", Type: "text",
Title: "Telegram API Token", Title: "Telegram API Token",
Placeholder: "383810182:EEx829dtCeufeQYXG7CUdiQopqdmmxBPO7-s", Placeholder: "383810182:EEx829dtCeufeQYXG7CUdiQopqdmmxBPO7-s",
@ -59,7 +59,7 @@ var Telegram = &telegram{&notifications.Notification{
}}}, }}},
} }
func (u *telegram) Select() *notifications.Notification { func (u *telegram) Select() *notifiers.Notification {
return u.Notification return u.Notification
} }

View File

@ -13,14 +13,14 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers package senders
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"net/url" "net/url"
@ -28,13 +28,13 @@ import (
"time" "time"
) )
var _ notifications.Notifier = (*twilio)(nil) var _ notifiers.Notifier = (*twilio)(nil)
type twilio struct { type twilio struct {
*notifications.Notification *notifiers.Notification
} }
var Twilio = &twilio{&notifications.Notification{ var Twilio = &twilio{&notifiers.Notification{
Method: "twilio", Method: "twilio",
Title: "Twilio", Title: "Twilio",
Description: "Receive SMS text messages directly to your cellphone when a service is offline. You can use a Twilio test account with limits. This notifier uses the <a href=\"https://www.twilio.com/docs/usage/api\">Twilio API</a>.", Description: "Receive SMS text messages directly to your cellphone when a service is offline. You can use a Twilio test account with limits. This notifier uses the <a href=\"https://www.twilio.com/docs/usage/api\">Twilio API</a>.",
@ -42,7 +42,7 @@ var Twilio = &twilio{&notifications.Notification{
AuthorUrl: "https://github.com/hunterlong", AuthorUrl: "https://github.com/hunterlong",
Icon: "far fa-comment-alt", Icon: "far fa-comment-alt",
Delay: time.Duration(10 * time.Second), Delay: time.Duration(10 * time.Second),
Form: []notifications.NotificationForm{{ Form: []notifiers.NotificationForm{{
Type: "text", Type: "text",
Title: "Account SID", Title: "Account SID",
Placeholder: "Insert your Twilio Account SID", Placeholder: "Insert your Twilio Account SID",
@ -69,7 +69,7 @@ var Twilio = &twilio{&notifications.Notification{
}}}, }}},
} }
func (u *twilio) Select() *notifications.Notification { func (u *twilio) Select() *notifiers.Notification {
return u.Notification return u.Notification
} }

View File

@ -13,13 +13,13 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers package senders
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"io/ioutil" "io/ioutil"
@ -28,17 +28,17 @@ import (
"time" "time"
) )
var _ notifications.Notifier = (*webhooker)(nil) var _ notifiers.Notifier = (*webhooker)(nil)
const ( const (
webhookMethod = "webhook" webhookMethod = "webhook"
) )
type webhooker struct { type webhooker struct {
*notifications.Notification *notifiers.Notification
} }
var Webhook = &webhooker{&notifications.Notification{ var Webhook = &webhooker{&notifiers.Notification{
Method: webhookMethod, Method: webhookMethod,
Title: "HTTP webhooker", Title: "HTTP webhooker",
Description: "Send a custom HTTP request to a specific URL with your own body, headers, and parameters.", Description: "Send a custom HTTP request to a specific URL with your own body, headers, and parameters.",
@ -46,7 +46,7 @@ var Webhook = &webhooker{&notifications.Notification{
AuthorUrl: "https://github.com/hunterlong", AuthorUrl: "https://github.com/hunterlong",
Icon: "fas fa-code-branch", Icon: "fas fa-code-branch",
Delay: time.Duration(1 * time.Second), Delay: time.Duration(1 * time.Second),
Form: []notifications.NotificationForm{{ Form: []notifiers.NotificationForm{{
Type: "text", Type: "text",
Title: "HTTP Endpoint", Title: "HTTP Endpoint",
Placeholder: "http://webhookurl.com/JW2MCP4SKQP", Placeholder: "http://webhookurl.com/JW2MCP4SKQP",
@ -90,7 +90,7 @@ func (w *webhooker) Send(msg interface{}) error {
return err return err
} }
func (w *webhooker) Select() *notifications.Notification { func (w *webhooker) Select() *notifiers.Notification {
return w.Notification return w.Notification
} }
@ -132,7 +132,7 @@ func (w *webhooker) sendHttpWebhook(body string) (*http.Response, error) {
} }
func (w *webhooker) OnTest() error { func (w *webhooker) OnTest() error {
body := replaceBodyText(w.Var2, notifications.ExampleService, nil) body := replaceBodyText(w.Var2, notifiers.ExampleService, nil)
resp, err := w.sendHttpWebhook(body) resp, err := w.sendHttpWebhook(body)
if err != nil { if err != nil {
return err return err

View File

@ -13,7 +13,7 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifications package notifiers
import ( import (
"encoding/json" "encoding/json"
@ -173,7 +173,7 @@ func SelectNotifier(method string) (*Notification, Notifier, error) {
// Queue is the FIFO go routine to send notifications when objects are triggered // Queue is the FIFO go routine to send notifications when objects are triggered
func Queue(notifer Notifier) { func Queue(notifer Notifier) {
n := notifer.Select() n := notifer.(*Notification)
rateLimit := n.Delay rateLimit := n.Delay
CheckNotifier: CheckNotifier:
@ -182,6 +182,8 @@ CheckNotifier:
case <-n.Running: case <-n.Running:
break CheckNotifier break CheckNotifier
case <-time.After(rateLimit): case <-time.After(rateLimit):
n := notifer.(*Notification)
fmt.Printf("checking %s %d\n", n.Method, len(n.Queue))
if len(n.Queue) > 0 { if len(n.Queue) > 0 {
ok, _ := n.WithinLimits() ok, _ := n.WithinLimits()
if ok { if ok {

View File

@ -5,6 +5,7 @@ import (
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/statping/statping/database" "github.com/statping/statping/database"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/checkins" "github.com/statping/statping/types/checkins"
"github.com/statping/statping/types/core" "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
@ -12,7 +13,6 @@ import (
"github.com/statping/statping/types/hits" "github.com/statping/statping/types/hits"
"github.com/statping/statping/types/incidents" "github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/messages" "github.com/statping/statping/types/messages"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/null" "github.com/statping/statping/types/null"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/types/users" "github.com/statping/statping/types/users"
@ -100,7 +100,7 @@ func initModels(db database.Database) {
hits.SetDB(db) hits.SetDB(db)
failures.SetDB(db) failures.SetDB(db)
checkins.SetDB(db) checkins.SetDB(db)
notifications.SetDB(db) notifiers.SetDB(db)
incidents.SetDB(db) incidents.SetDB(db)
users.SetDB(db) users.SetDB(db)
messages.SetDB(db) messages.SetDB(db)

View File

@ -2,6 +2,7 @@ package configs
import ( import (
"github.com/statping/statping/database" "github.com/statping/statping/database"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/checkins" "github.com/statping/statping/types/checkins"
"github.com/statping/statping/types/core" "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
@ -9,7 +10,6 @@ import (
"github.com/statping/statping/types/hits" "github.com/statping/statping/types/hits"
"github.com/statping/statping/types/incidents" "github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/messages" "github.com/statping/statping/types/messages"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/types/users" "github.com/statping/statping/types/users"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
@ -73,7 +73,7 @@ func (d *DbConfig) Delete() error {
// DropDatabase will DROP each table Statping created // DropDatabase will DROP each table Statping created
func (d *DbConfig) DropDatabase() error { func (d *DbConfig) DropDatabase() error {
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}} var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifiers.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
log.Infoln("Dropping Database Tables...") log.Infoln("Dropping Database Tables...")
for _, t := range DbModels { for _, t := range DbModels {
if err := d.Db.DropTableIfExists(t); err != nil { if err := d.Db.DropTableIfExists(t); err != nil {
@ -92,7 +92,7 @@ func (d *DbConfig) Close() {
func (d *DbConfig) CreateDatabase() error { func (d *DbConfig) CreateDatabase() error {
var err error var err error
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}} var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifiers.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
log.Infoln("Creating Database Tables...") log.Infoln("Creating Database Tables...")
for _, table := range DbModels { for _, table := range DbModels {

View File

@ -5,6 +5,7 @@ import (
_ "github.com/jinzhu/gorm/dialects/mysql" _ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/postgres" _ "github.com/jinzhu/gorm/dialects/postgres"
_ "github.com/jinzhu/gorm/dialects/sqlite" _ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/checkins" "github.com/statping/statping/types/checkins"
"github.com/statping/statping/types/core" "github.com/statping/statping/types/core"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
@ -12,7 +13,6 @@ import (
"github.com/statping/statping/types/hits" "github.com/statping/statping/types/hits"
"github.com/statping/statping/types/incidents" "github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/messages" "github.com/statping/statping/types/messages"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/types/users" "github.com/statping/statping/types/users"
) )
@ -52,7 +52,7 @@ func (c *DbConfig) DatabaseChanges() error {
//If this function has an issue, it will ROLLBACK to the previous state. //If this function has an issue, it will ROLLBACK to the previous state.
func (c *DbConfig) MigrateDatabase() error { func (c *DbConfig) MigrateDatabase() error {
var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifications.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}} var DbModels = []interface{}{&services.Service{}, &users.User{}, &hits.Hit{}, &failures.Failure{}, &messages.Message{}, &groups.Group{}, &checkins.Checkin{}, &checkins.CheckinHit{}, &notifiers.Notification{}, &incidents.Incident{}, &incidents.IncidentUpdate{}}
log.Infoln("Migrating Database Tables...") log.Infoln("Migrating Database Tables...")
tx := c.Db.Begin() tx := c.Db.Begin()

View File

@ -118,6 +118,5 @@ func (s *Service) DeleteCheckins() error {
//} //}
func (s *Service) AfterFind() error { func (s *Service) AfterFind() error {
s.UpdateStats()
return nil return nil
} }

View File

@ -38,7 +38,7 @@ func humanMicro(val int64) string {
if val < 10000 { if val < 10000 {
return fmt.Sprintf("%d μs", val) return fmt.Sprintf("%d μs", val)
} }
return fmt.Sprintf("%0.0f ms", float64(val)*0.001) return fmt.Sprintf("%d ms", float64(val)*0.001)
} }
// IsRunning returns true if the service go routine is running // IsRunning returns true if the service go routine is running

View File

@ -3,6 +3,7 @@ package services
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"github.com/statping/statping/notifiers"
"github.com/statping/statping/types/failures" "github.com/statping/statping/types/failures"
"github.com/statping/statping/types/hits" "github.com/statping/statping/types/hits"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
@ -39,6 +40,7 @@ CheckLoop:
break CheckLoop break CheckLoop
case <-time.After(s.SleepDuration): case <-time.After(s.SleepDuration):
s.CheckService(record) s.CheckService(record)
s.UpdateStats()
s.Checkpoint = s.Checkpoint.Add(s.Duration()) s.Checkpoint = s.Checkpoint.Add(s.Duration())
sleep := s.Checkpoint.Sub(time.Now()) sleep := s.Checkpoint.Sub(time.Now())
if !s.Online { if !s.Online {
@ -238,26 +240,26 @@ func recordSuccess(s *Service) {
log.Error(err) log.Error(err)
} }
log.WithFields(utils.ToFields(hit, s)).Infoln( log.WithFields(utils.ToFields(hit, s)).Infoln(
fmt.Sprintf("Service #%d '%v' Successful Response: %s | Lookup in: %s | Online: %v | Interval: %d seconds", s.Id, s.Name, humanMicro(hit.Latency), humanMicro(hit.PingTime), s.Online, s.Interval)) fmt.Sprintf("Service #%d '%v' Successful Response: %s | Lookup in: %v | Online: %v | Interval: %d seconds", s.Id, s.Name, humanMicro(hit.Latency), humanMicro(hit.PingTime), s.Online, s.Interval))
s.LastLookupTime = hit.PingTime s.LastLookupTime = hit.PingTime
s.LastLatency = hit.Latency s.LastLatency = hit.Latency
//notifier.OnSuccess(s) notifiers.OnSuccess(s)
s.SuccessNotified = true s.SuccessNotified = true
} }
// recordFailure will create a new 'Failure' record in the database for a offline service // recordFailure will create a new 'Failure' record in the database for a offline service
func recordFailure(s *Service, issue string) { func recordFailure(s *Service, issue string) {
s.LastOffline = time.Now().UTC() s.LastOffline = utils.Now()
fail := &failures.Failure{ fail := &failures.Failure{
Service: s.Id, Service: s.Id,
Issue: issue, Issue: issue,
PingTime: s.PingTime, PingTime: s.PingTime,
CreatedAt: time.Now().UTC(), CreatedAt: utils.Now(),
ErrorCode: s.LastStatusCode, ErrorCode: s.LastStatusCode,
} }
log.WithFields(utils.ToFields(fail, s)). log.WithFields(utils.ToFields(fail, s)).
Warnln(fmt.Sprintf("Service %v Failing: %v | Lookup in: %0.2f ms", s.Name, issue, fail.PingTime*1000)) Warnln(fmt.Sprintf("Service %v Failing: %v | Lookup in: %v", s.Name, issue, humanMicro(fail.PingTime)))
if err := fail.Create(); err != nil { if err := fail.Create(); err != nil {
log.Error(err) log.Error(err)
@ -265,7 +267,7 @@ func recordFailure(s *Service, issue string) {
s.Online = false s.Online = false
s.SuccessNotified = false s.SuccessNotified = false
s.DownText = s.DowntimeText() s.DownText = s.DowntimeText()
//notifier.OnFailure(s, fail) notifiers.OnFailure(s, fail)
} }
// Check will run checkHttp for HTTP services and checkTcp for TCP services // Check will run checkHttp for HTTP services and checkTcp for TCP services