UI updates - Teleram notifier

pull/116/head
Hunter Long 2018-12-09 21:43:15 -08:00
parent fcae7f2667
commit cffa814e8c
10 changed files with 288 additions and 15 deletions

View File

@ -34,23 +34,23 @@ var command = &commandLine{&notifier.Notification{
AuthorUrl: "https://github.com/hunterlong",
Delay: time.Duration(1 * time.Second),
Icon: "fas fa-terminal",
Host: "sh",
Host: "/bin/bash",
Form: []notifier.NotificationForm{{
Type: "text",
Title: "Shell or Bash",
Placeholder: "sh",
Placeholder: "/bin/bash",
DbField: "host",
SmallText: "You can use 'sh', 'bash' or even an absolute path for an application",
SmallText: "You can use '/bin/sh', '/bin/bash' or even an absolute path for an application",
}, {
Type: "text",
Title: "Command to Run on OnSuccess",
Placeholder: "ping google.com",
Placeholder: "curl google.com",
DbField: "var1",
SmallText: "This command will run everytime a service is receiving a Successful event.",
}, {
Type: "text",
Title: "Command to Run on OnFailure",
Placeholder: "ping offline.com",
Placeholder: "curl offline.com",
DbField: "var2",
SmallText: "This command will run everytime a service is receiving a Failing event.",
}}},

View File

@ -33,7 +33,7 @@ var mobile = &mobilePush{&notifier.Notification{
Method: "mobile",
Title: "Mobile Notifications",
Description: `Receive push notifications on your Android or iPhone devices using the Statping App. You can scan the Authentication QR Code found in Settings to get the mobile app setup in seconds.
<p align="center"><a href="https://play.google.com/store/apps/details?id=com.statping"><img src="https://img.cjx.io/google-play.svg"></a> <a href="https://testflight.apple.com/join/TuBIj25Q"><img src="https://img.cjx.io/app-store-badge.svg"></a></p>`,
<p align="center"><a href="https://play.google.com/store/apps/details?id=com.statping"><img src="https://img.cjx.io/google-play.svg"></a> <a href="https://testflight.apple.com/join/teFUckJm"><img src="https://img.cjx.io/app-store-badge.svg"></a></p>`,
Author: "Hunter Long",
AuthorUrl: "https://github.com/hunterlong",
Delay: time.Duration(5 * time.Second),

165
notifiers/telegram.go Normal file
View File

@ -0,0 +1,165 @@
// Statup
// Copyright (C) 2018. Hunter Long and the project contributors
// Written by Hunter Long <info@socialeck.com> and the project contributors
//
// https://github.com/hunterlong/statup
//
// The licenses for most software and other practical works are designed
// to take away your freedom to share and change the works. By contrast,
// the GNU General Public License is intended to guarantee your freedom to
// share and change all versions of a program--to make sure it remains free
// software for all its users.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers
import (
"encoding/json"
"errors"
"fmt"
"github.com/hunterlong/statping/core/notifier"
"github.com/hunterlong/statping/types"
"github.com/hunterlong/statping/utils"
"net/url"
"strings"
"time"
)
type telegram struct {
*notifier.Notification
}
var telegramNotifier = &telegram{&notifier.Notification{
Method: "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.",
Author: "Hunter Long",
AuthorUrl: "https://github.com/hunterlong",
Icon: "fab fa-telegram-plane",
Delay: time.Duration(5 * time.Second),
Form: []notifier.NotificationForm{{
Type: "text",
Title: "Telegram API Token",
Placeholder: "383810182:EEx829dtCeufeQYXG7CUdiQopqdmmxBPO7-s",
SmallText: "Enter the API Token given to you from the /botfather chat.",
DbField: "api_secret",
Required: true,
}, {
Type: "text",
Title: "Channel or User ID",
Placeholder: "789325392",
SmallText: "Insert your Telegram Channel ID or User ID here.",
DbField: "Var1",
Required: true,
}}},
}
// DEFINE YOUR NOTIFICATION HERE.
func init() {
err := notifier.AddNotifier(telegramNotifier)
if err != nil {
panic(err)
}
}
func (u *telegram) Select() *notifier.Notification {
return u.Notification
}
// Send will send a HTTP Post to the Telegram API. It accepts type: string
func (u *telegram) Send(msg interface{}) error {
message := msg.(string)
apiEndpoint := fmt.Sprintf("https://api.telegram.org/bot%v/sendMessage", u.ApiSecret)
v := url.Values{}
v.Set("chat_id", u.Var1)
v.Set("text", message)
rb := *strings.NewReader(v.Encode())
contents, _, err := utils.HttpRequest(apiEndpoint, "GET", "application/x-www-form-urlencoded", nil, &rb, time.Duration(10*time.Second))
success, _ := telegramSuccess(contents)
if !success {
errorOut := telegramError(contents)
out := fmt.Sprintf("Error code %v - %v", errorOut.ErrorCode, errorOut.Description)
return errors.New(out)
}
return err
}
// OnFailure will trigger failing service
func (u *telegram) OnFailure(s *types.Service, f *types.Failure) {
msg := fmt.Sprintf("Your service '%v' is currently offline!", s.Name)
u.AddQueue(s.Id, msg)
u.Online = false
}
// OnSuccess will trigger successful service
func (u *telegram) OnSuccess(s *types.Service) {
if !u.Online {
u.ResetUniqueQueue(s.Id)
msg := fmt.Sprintf("Your service '%v' is back online!", s.Name)
u.AddQueue(s.Id, msg)
}
u.Online = true
}
// OnSave triggers when this notifier has been saved
func (u *telegram) OnSave() error {
utils.Log(1, fmt.Sprintf("Notification %v is receiving updated information.", u.Method))
// Do updating stuff here
return nil
}
// OnTest will test the Twilio SMS messaging
func (u *telegram) OnTest() error {
msg := fmt.Sprintf("Testing the Twilio SMS Notifier on your Statup server")
return u.Send(msg)
}
func telegramSuccess(res []byte) (bool, telegramResponse) {
var obj telegramResponse
json.Unmarshal(res, &obj)
if obj.Ok {
return true, obj
}
return false, obj
}
func telegramError(res []byte) telegramErrorObj {
var obj telegramErrorObj
json.Unmarshal(res, &obj)
return obj
}
type telegramErrorObj struct {
Ok bool `json:"ok"`
ErrorCode int `json:"error_code"`
Description string `json:"description"`
}
type telegramResponse struct {
Ok bool `json:"ok"`
Result struct {
MessageID int `json:"message_id"`
From struct {
ID int `json:"id"`
IsBot bool `json:"is_bot"`
FirstName string `json:"first_name"`
Username string `json:"username"`
} `json:"from"`
Chat struct {
ID int `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Username string `json:"username"`
Type string `json:"type"`
} `json:"chat"`
Date int `json:"date"`
Text string `json:"text"`
} `json:"result"`
}

108
notifiers/telegram_test.go Normal file
View File

@ -0,0 +1,108 @@
// Statup
// Copyright (C) 2018. Hunter Long and the project contributors
// Written by Hunter Long <info@socialeck.com> and the project contributors
//
// https://github.com/hunterlong/statup
//
// The licenses for most software and other practical works are designed
// to take away your freedom to share and change the works. By contrast,
// the GNU General Public License is intended to guarantee your freedom to
// share and change all versions of a program--to make sure it remains free
// software for all its users.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
package notifiers
import (
"github.com/hunterlong/statping/core/notifier"
"github.com/stretchr/testify/assert"
"os"
"testing"
"time"
)
var (
telegramToken string
telegramChannel string
telegramMessage = "The Telegram notifier on Statping has been tested!"
)
func init() {
telegramToken = os.Getenv("TELEGRAM_TOKEN")
telegramChannel = os.Getenv("TELEGRAM_CHANNEL")
telegramNotifier.ApiSecret = telegramToken
telegramNotifier.Var1 = telegramChannel
}
func TestTelegramNotifier(t *testing.T) {
t.Parallel()
if telegramToken == "" || telegramChannel == "" {
t.Log("Telegram notifier testing skipped, missing TELEGRAM_TOKEN and TELEGRAM_CHANNEL environment variable")
t.SkipNow()
}
currentCount = CountNotifiers()
t.Run("Load Telegram", func(t *testing.T) {
telegramNotifier.ApiSecret = telegramToken
telegramNotifier.Var1 = telegramChannel
telegramNotifier.Delay = time.Duration(1 * time.Second)
err := notifier.AddNotifier(telegramNotifier)
assert.Nil(t, err)
assert.Equal(t, "Hunter Long", telegramNotifier.Author)
assert.Equal(t, telegramToken, telegramNotifier.ApiSecret)
assert.Equal(t, telegramChannel, telegramNotifier.Var1)
})
t.Run("Load Telegram Notifier", func(t *testing.T) {
notifier.Load()
})
t.Run("Telegram Within Limits", func(t *testing.T) {
ok, err := telegramNotifier.WithinLimits()
assert.Nil(t, err)
assert.True(t, ok)
})
t.Run("Telegram OnFailure", func(t *testing.T) {
telegramNotifier.OnFailure(TestService, TestFailure)
assert.Equal(t, 1, len(telegramNotifier.Queue))
})
t.Run("Telegram Check Offline", func(t *testing.T) {
assert.False(t, telegramNotifier.Online)
})
t.Run("Telegram OnSuccess", func(t *testing.T) {
telegramNotifier.OnSuccess(TestService)
assert.Equal(t, 1, len(telegramNotifier.Queue))
})
t.Run("Telegram Check Back Online", func(t *testing.T) {
assert.True(t, telegramNotifier.Online)
})
t.Run("Telegram OnSuccess Again", func(t *testing.T) {
telegramNotifier.OnSuccess(TestService)
assert.Equal(t, 1, len(telegramNotifier.Queue))
})
t.Run("Telegram Send", func(t *testing.T) {
err := telegramNotifier.Send(telegramMessage)
assert.Nil(t, err)
})
t.Run("Telegram Test", func(t *testing.T) {
err := telegramNotifier.OnTest()
assert.Nil(t, err)
})
t.Run("Telegram Queue", func(t *testing.T) {
go notifier.Queue(telegramNotifier)
time.Sleep(3 * time.Second)
assert.Equal(t, telegramToken, telegramNotifier.ApiSecret)
assert.Equal(t, 0, len(telegramNotifier.Queue))
})
}

View File

@ -23,7 +23,7 @@ import (
)
var (
webhookTestUrl = "https://demo.statup.com/api/services"
webhookTestUrl = "https://demo.statping.com"
webhookMessage = `{"id": "%service.Id","name": "%service.Name","online": "%service.Online","issue": "%failure.Issue"}`
apiKey = "application/json"
fullMsg string
@ -99,7 +99,7 @@ func TestWebhookNotifier(t *testing.T) {
t.Run("webhooker Send", func(t *testing.T) {
err := webhook.Send(fullMsg)
assert.Error(t, err)
assert.Nil(t, err)
assert.Equal(t, len(webhook.Queue), 1)
})

View File

@ -444,8 +444,8 @@ HTML, BODY {
background-color: #ffffff; }
.card-body {
font-size: 6pt;
padding: 5px 5px; }
font-size: 10pt;
padding: 0px 10px; }
.lg_number {
font-size: 7.8vw; }

View File

@ -42,8 +42,8 @@
}
.card-body {
font-size: 6pt;
padding: 5px 5px;
font-size: 10pt;
padding: 0px 10px;
}
.lg_number {

View File

@ -1,5 +1,5 @@
{{ define "footer"}}
<div class="footer text-center mb-4">
<div class="footer text-center mb-4 p-2">
{{ if CoreApp.Footer.String }}
{{ CoreApp.Footer.String }}
{{ else }}

View File

@ -78,7 +78,7 @@
{{$failures := $s.LimitedFailures 16}}
<nav class="nav nav-pills flex-column flex-sm-row mt-3" id="service_tabs" role="serviceLists">
<a class="flex-sm-fill text-sm-center nav-link active" id="edit-tab" data-toggle="tab" href="#edit" role="tab" aria-controls="edit" aria-selected="false">Edit Service</a>
<a class="flex-sm-fill text-sm-center nav-link{{ if not $failures }}disabled{{end}}" id="failures-tab" data-toggle="tab" href="#failures" role="tab" aria-controls="failures" aria-selected="true">Failures</a>
<a class="flex-sm-fill text-sm-center nav-link{{ if not $failures }} disabled{{end}}" id="failures-tab" data-toggle="tab" href="#failures" role="tab" aria-controls="failures" aria-selected="true">Failures</a>
<a class="flex-sm-fill text-sm-center nav-link" id="checkins-tab" data-toggle="tab" href="#checkins" role="tab" aria-controls="checkins" aria-selected="false">Checkins</a>
<a class="flex-sm-fill text-sm-center nav-link" id="response-tab" data-toggle="tab" href="#response" role="tab" aria-controls="response" aria-selected="false">Response</a>
</nav>

View File

@ -1 +1 @@
0.79.98
0.79.99