mirror of https://github.com/statping/statping
checkins - installer shell script
parent
9a6c91a997
commit
ddb2a10a7c
|
@ -20,6 +20,7 @@ import (
|
|||
"github.com/ararog/timeago"
|
||||
"github.com/hunterlong/statup/types"
|
||||
"github.com/hunterlong/statup/utils"
|
||||
"github.com/jinzhu/gorm"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
@ -49,17 +50,17 @@ func SelectCheckin(api string) *Checkin {
|
|||
return &checkin
|
||||
}
|
||||
|
||||
func (u Checkin) Period() time.Duration {
|
||||
func (u *Checkin) Period() time.Duration {
|
||||
duration, _ := time.ParseDuration(fmt.Sprintf("%vs", u.Interval))
|
||||
return duration
|
||||
}
|
||||
|
||||
func (u Checkin) Grace() time.Duration {
|
||||
func (u *Checkin) Grace() time.Duration {
|
||||
duration, _ := time.ParseDuration(fmt.Sprintf("%vs", u.GracePeriod))
|
||||
return duration
|
||||
}
|
||||
|
||||
func (u Checkin) Expected() time.Duration {
|
||||
func (u *Checkin) Expected() time.Duration {
|
||||
last := u.Last().CreatedAt
|
||||
now := time.Now()
|
||||
lastDir := now.Sub(last)
|
||||
|
@ -67,7 +68,7 @@ func (u Checkin) Expected() time.Duration {
|
|||
return sub
|
||||
}
|
||||
|
||||
func (u Checkin) Last() CheckinHit {
|
||||
func (u *Checkin) Last() CheckinHit {
|
||||
var hit CheckinHit
|
||||
checkinHitsDB().Where("checkin = ?", u.Id).Last(&hit)
|
||||
return hit
|
||||
|
@ -79,13 +80,18 @@ func (u *Checkin) Hits() []CheckinHit {
|
|||
return checkins
|
||||
}
|
||||
|
||||
func (u *Checkin) Create() (int64, error) {
|
||||
if u.CreatedAt.IsZero() {
|
||||
u.CreatedAt = time.Now()
|
||||
func (u *Checkin) Update() (int64, error) {
|
||||
fmt.Println("updating: ", u.Id, u.ApiKey)
|
||||
exists := checkinDB().Find(&u).RecordNotFound()
|
||||
var row *gorm.DB
|
||||
if !exists {
|
||||
row = checkinDB().Update(&u)
|
||||
} else {
|
||||
u.ApiKey = utils.RandomString(7)
|
||||
row = checkinDB().Create(&u)
|
||||
}
|
||||
u.ApiKey = utils.NewSHA1Hash(7)
|
||||
row := checkinDB().Create(u)
|
||||
if row.Error == nil {
|
||||
fmt.Println("found: ", exists, u.Id, u.Service, u.Interval, u.GracePeriod, u.ApiKey)
|
||||
if row.Error != nil {
|
||||
utils.Log(2, row.Error)
|
||||
return 0, row.Error
|
||||
}
|
||||
|
|
|
@ -126,27 +126,37 @@ func (u *Hit) BeforeCreate() (err error) {
|
|||
}
|
||||
|
||||
func (u *Failure) BeforeCreate() (err error) {
|
||||
u.CreatedAt = time.Now().UTC()
|
||||
if u.CreatedAt.IsZero() {
|
||||
u.CreatedAt = time.Now().UTC()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (u *User) BeforeCreate() (err error) {
|
||||
u.CreatedAt = time.Now().UTC()
|
||||
if u.CreatedAt.IsZero() {
|
||||
u.CreatedAt = time.Now().UTC()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (u *Service) BeforeCreate() (err error) {
|
||||
u.CreatedAt = time.Now().UTC()
|
||||
if u.CreatedAt.IsZero() {
|
||||
u.CreatedAt = time.Now().UTC()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (u *Checkin) BeforeCreate() (err error) {
|
||||
u.CreatedAt = time.Now().UTC()
|
||||
if u.CreatedAt.IsZero() {
|
||||
u.CreatedAt = time.Now().UTC()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (u *CheckinHit) BeforeCreate() (err error) {
|
||||
u.CreatedAt = time.Now().UTC()
|
||||
if u.CreatedAt.IsZero() {
|
||||
u.CreatedAt = time.Now().UTC()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -89,14 +89,14 @@ func InsertSampleData() error {
|
|||
Interval: 300,
|
||||
GracePeriod: 300,
|
||||
})
|
||||
checkin1.Create()
|
||||
checkin1.Update()
|
||||
|
||||
checkin2 := ReturnCheckin(&types.Checkin{
|
||||
Service: s2.Id,
|
||||
Interval: 900,
|
||||
GracePeriod: 300,
|
||||
})
|
||||
checkin2.Create()
|
||||
checkin2.Update()
|
||||
|
||||
checkTime := time.Now().Add(-24 * time.Hour)
|
||||
for i := 0; i <= 60; i++ {
|
||||
|
|
|
@ -49,10 +49,10 @@ func SelectService(id int64) *Service {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) Checkin() Checkin {
|
||||
var hits Checkin
|
||||
servicesDB().Where("service = ?", s.Id).First(&hits)
|
||||
return hits
|
||||
func (s *Service) Checkin() *Checkin {
|
||||
var checkin types.Checkin
|
||||
checkinDB().Find(&checkin, "service = ?", s.Id)
|
||||
return &Checkin{&checkin}
|
||||
}
|
||||
|
||||
// SelectAllServices returns a slice of *core.Service to be store on []*core.Services, should only be called once on startup.
|
||||
|
|
|
@ -0,0 +1,246 @@
|
|||
#!/usr/bin/env bash
|
||||
VERSION="3.4.0"
|
||||
VERBOSE=false
|
||||
SSLOPTION=false
|
||||
AWSREGION="us-west-2"
|
||||
US_W_1="ami-7be8a103"
|
||||
US_W_2="ami-7be8a103"
|
||||
US_E_1="ami-7be8a103"
|
||||
US_E_2="ami-7be8a103"
|
||||
AWS_CLI=$(which aws)
|
||||
AWS_ECS="$AWS_CLI --output json"
|
||||
|
||||
function usage() {
|
||||
cat <<EOM
|
||||
##### Statup Installer #####
|
||||
A simple shell script that will help you install Statup on your local machine, AWS, or Docker.
|
||||
|
||||
Commands:
|
||||
aws Create a new EC2 instance running Statup
|
||||
docker Start the latest Statup Docker image
|
||||
docker-compose Create Statup with a Postgres database
|
||||
|
||||
Available Flags:
|
||||
-k | --aws-access-key AWS Access Key ID. May also be set as environment variable AWS_ACCESS_KEY_ID
|
||||
-s | --aws-secret-key AWS Secret Access Key. May also be set as environment variable AWS_SECRET_ACCESS_KEY
|
||||
-r | --region AWS Region Name. May also be set as environment variable AWS_DEFAULT_REGION
|
||||
-v | --version Print out the current version of this tool
|
||||
-x | --verbose Verbose output
|
||||
Visit the github repo at: https://github.com/hunterlong/statup
|
||||
EOM
|
||||
exit 3
|
||||
}
|
||||
|
||||
# Check requirements
|
||||
function require() {
|
||||
command -v "$1" > /dev/null 2>&1 || {
|
||||
echo "Some of the required software is not installed:"
|
||||
echo " please install $1" >&2;
|
||||
exit 4;
|
||||
}
|
||||
}
|
||||
|
||||
function setAWSPresets {
|
||||
if [ -z ${AWS_DEFAULT_REGION+x} ];
|
||||
then unset AWS_DEFAULT_REGION
|
||||
else
|
||||
AWS_ECS="$AWS_ECS --region $AWS_DEFAULT_REGION"
|
||||
fi
|
||||
if [ -z ${AWS_PROFILE+x} ];
|
||||
then unset AWS_PROFILE
|
||||
else
|
||||
AWS_ECS="$AWS_ECS --profile $AWS_PROFILE"
|
||||
fi
|
||||
}
|
||||
|
||||
function awsAskRegion {
|
||||
if [ -z ${AWS_DEFAULT_REGION+x} ]; then
|
||||
read -p "Enter the AWS Region: " AWSREGION
|
||||
else
|
||||
AWSREGION=$AWS_DEFAULT_REGION
|
||||
fi
|
||||
}
|
||||
|
||||
function askEC2Name {
|
||||
read -p "Enter the Name for EC2 Instance: " SERVERNAME
|
||||
}
|
||||
|
||||
function askSSLOption {
|
||||
read -p "Do you want to install a SSL certificate? (y/N):" SSLOPTION
|
||||
}
|
||||
|
||||
function askSSLDomain {
|
||||
read -p "Enter the Domain to attach the SSL certificate on: " SSLDOMAIN
|
||||
}
|
||||
|
||||
function askSSLEmail {
|
||||
read -p "Enter the Email for Lets Encrypt: " SSLEMAIL
|
||||
}
|
||||
|
||||
function askEC2KeyName {
|
||||
read -p "Enter the Keypair for EC2 Instance: " EC2KEYNAME
|
||||
}
|
||||
|
||||
function askSecurityName {
|
||||
read -p "Enter a name for the new Security Group: " EC2SECGROUP
|
||||
}
|
||||
|
||||
function awsSecurityGroup {
|
||||
echo "Running task: Creating Security Group";
|
||||
GROUPID=`$AWS_ECS ec2 create-security-group --group-name "$EC2SECGROUP" --description "Statup HTTP Server on port 80 and 443" | jq -r .GroupId`
|
||||
echo "Created new security group: $GROUPID";
|
||||
awsAuthSecurityGroup
|
||||
}
|
||||
|
||||
function awsAuthSecurityGroup {
|
||||
$AWS_ECS ec2 authorize-security-group-ingress --group-id $GROUPID --protocol tcp --port 80 --cidr 0.0.0.0/0
|
||||
$AWS_ECS ec2 authorize-security-group-ingress --group-id $GROUPID --protocol tcp --port 443 --cidr 0.0.0.0/0
|
||||
echo "Authorize security group to be open on ports 80 and 443";
|
||||
}
|
||||
|
||||
function awsCreateEC2 {
|
||||
NEW_SRV=`$AWS_ECS ec2 run-instances --image-id $US_W_2 --count 1 --instance-type t2.nano --key-name $EC2KEYNAME --security-group-ids $GROUPID`
|
||||
INSTANCE_ID=`echo $NEW_SRV | jq .Instances[0].InstanceId`
|
||||
EC2_STATUS=`echo $NEW_SRV | .Instances[0].StateReason.Message`
|
||||
echo "New EC2 instance created: $INSTANCE_ID with status $EC2_STATUS";
|
||||
}
|
||||
|
||||
function ec2TaskComplete {
|
||||
echo "New EC2 instance is ready! $INSTANCE_ID with status $EC2_STATUS";
|
||||
echo "Instance ID: $INSTANCE_ID with status $EC2_STATUS";
|
||||
echo "Public DNS: $EC2_DNS";
|
||||
if [ $SSLOPTION == "y" ]; then
|
||||
echo "Now you have to add a CNAME DNS record on $SSLDOMAIN pointing to $EC2_DNS"
|
||||
fi
|
||||
}
|
||||
|
||||
function checkEC2Instance {
|
||||
SRV_INFO=`$AWS_ECS ec2 describe-instances --instance-ids $INSTANCE_ID`
|
||||
EC2_STATUS=$(echo "${SRV_INFO}" | jq .Reservations[0].Instances[0].State.Name)
|
||||
EC2_DNS=$(echo "${SRV_INFO}" | jq .Reservations[0].Instances[0].PublicDnsName)
|
||||
EC2_STATUS=$(echo "${SRV_INFO}" | jq .Reservations[0].Instances[0].State.Name)
|
||||
if [ $EC2_STATUS == '"pending"' ]; then
|
||||
echo "EC2 instance is still being created: $INSTANCE_ID";
|
||||
sleep 3
|
||||
checkEC2Instance
|
||||
fi
|
||||
}
|
||||
|
||||
function awsTest {
|
||||
INSTANCE_ID="i-0768e3d5ba00897af"
|
||||
checkEC2Instance
|
||||
ec2TaskComplete
|
||||
}
|
||||
|
||||
function awsTask {
|
||||
setAWSPresets
|
||||
askEC2Name
|
||||
awsAskRegion
|
||||
askSecurityName
|
||||
askEC2KeyName
|
||||
askSSLOption
|
||||
if [ $SSLOPTION == "y" ]; then
|
||||
askSSLDomain
|
||||
askSSLEmail
|
||||
fi
|
||||
awsSecurityGroup
|
||||
awsCreateEC2
|
||||
checkEC2Instance
|
||||
ec2TaskComplete
|
||||
}
|
||||
|
||||
function localTask {
|
||||
echo "installing locally"
|
||||
}
|
||||
|
||||
function dockerTask {
|
||||
echo "installing docker"
|
||||
}
|
||||
|
||||
function dockerComposeTask {
|
||||
echo "installing docker compose"
|
||||
}
|
||||
|
||||
if [ "$BASH_SOURCE" == "$0" ]; then
|
||||
set -o errexit
|
||||
set -o pipefail
|
||||
set -u
|
||||
set -e
|
||||
# If no args are provided, display usage information
|
||||
if [ $# == 0 ]; then usage; fi
|
||||
|
||||
COMMD=$1
|
||||
|
||||
# Loop through arguments, two at a time for key and value
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
key="$1"
|
||||
|
||||
case $key in
|
||||
-k|--aws-access-key)
|
||||
AWS_ACCESS_KEY_ID="$2"
|
||||
shift # past argument
|
||||
;;
|
||||
-s|--aws-secret-key)
|
||||
AWS_SECRET_ACCESS_KEY="$2"
|
||||
shift # past argument
|
||||
;;
|
||||
-r|--region)
|
||||
AWS_DEFAULT_REGION="$2"
|
||||
shift # past argument
|
||||
;;
|
||||
-x|--verbose)
|
||||
VERBOSE=true
|
||||
;;
|
||||
-v|--version)
|
||||
echo ${VERSION}
|
||||
echo "$2"
|
||||
usage
|
||||
exit 2
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
shift # past argument or value
|
||||
done
|
||||
|
||||
if [ $VERBOSE == true ]; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
case $COMMD in
|
||||
aws)
|
||||
require aws
|
||||
require jq
|
||||
awsTask
|
||||
exit 0
|
||||
;;
|
||||
awstest)
|
||||
require aws
|
||||
require jq
|
||||
awsTest
|
||||
exit 0
|
||||
;;
|
||||
docker)
|
||||
require docker
|
||||
dockerTask
|
||||
exit 0
|
||||
;;
|
||||
docker-compose)
|
||||
require docker-compose
|
||||
dockerComposeTask
|
||||
exit 0
|
||||
;;
|
||||
local)
|
||||
localTask
|
||||
shift # past argument
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
shift # past argument or value
|
||||
fi
|
||||
exit 0
|
||||
|
||||
fi
|
|
@ -141,20 +141,8 @@ var handlerFuncs = func(w http.ResponseWriter, r *http.Request) template.FuncMap
|
|||
return utils.Timestamp(t).Ago()
|
||||
},
|
||||
"Duration": func(t time.Duration) string {
|
||||
var out string
|
||||
duration, _ := time.ParseDuration(fmt.Sprintf("%vs", t.Seconds()))
|
||||
if duration.Minutes() < 1 {
|
||||
out = fmt.Sprintf("%0.0f second", duration.Seconds())
|
||||
if duration.Seconds() >= 2 {
|
||||
out += "s"
|
||||
}
|
||||
} else {
|
||||
out = fmt.Sprintf("%0.0f minute", duration.Minutes())
|
||||
if duration.Minutes() >= 2 {
|
||||
out += "s"
|
||||
}
|
||||
}
|
||||
return out
|
||||
return utils.FormatDuration(duration)
|
||||
},
|
||||
"ToUnix": func(t time.Time) int64 {
|
||||
return t.UTC().Unix()
|
||||
|
|
|
@ -53,7 +53,6 @@ func Router() *mux.Router {
|
|||
r.Handle("/dashboard", http.HandlerFunc(dashboardHandler)).Methods("GET")
|
||||
r.Handle("/dashboard", http.HandlerFunc(loginHandler)).Methods("POST")
|
||||
r.Handle("/logout", http.HandlerFunc(logoutHandler))
|
||||
r.Handle("/checkin/{id}", http.HandlerFunc(checkinUpdateHandler))
|
||||
r.Handle("/plugins/download/{name}", http.HandlerFunc(pluginsDownloadHandler))
|
||||
r.Handle("/plugins/{name}/save", http.HandlerFunc(pluginSavedHandler)).Methods("POST")
|
||||
r.Handle("/help", http.HandlerFunc(helpHandler))
|
||||
|
@ -87,6 +86,7 @@ func Router() *mux.Router {
|
|||
r.Handle("/service/{id}/delete", http.HandlerFunc(servicesDeleteHandler))
|
||||
r.Handle("/service/{id}/delete_failures", http.HandlerFunc(servicesDeleteFailuresHandler)).Methods("GET")
|
||||
r.Handle("/service/{id}/checkin", http.HandlerFunc(checkinCreateUpdateHandler)).Methods("POST")
|
||||
r.Handle("/checkin/{id}", http.HandlerFunc(checkinUpdateHandler))
|
||||
|
||||
// API SERVICE Routes
|
||||
r.Handle("/api/services", http.HandlerFunc(apiAllServicesHandler)).Methods("GET")
|
||||
|
|
|
@ -261,15 +261,12 @@ func checkinCreateUpdateHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
vars := mux.Vars(r)
|
||||
service := core.SelectService(utils.StringInt(vars["id"]))
|
||||
|
||||
checkin := service.Checkin()
|
||||
interval := utils.StringInt(r.PostForm.Get("interval"))
|
||||
grace := utils.StringInt(r.PostForm.Get("grace"))
|
||||
checkin := core.ReturnCheckin(&types.Checkin{
|
||||
Service: service.Id,
|
||||
Interval: interval,
|
||||
GracePeriod: grace,
|
||||
})
|
||||
checkin.Create()
|
||||
checkin.Interval = interval
|
||||
checkin.GracePeriod = grace
|
||||
checkin.Update()
|
||||
executeResponse(w, r, "service.html", service, fmt.Sprintf("/service/%v", service.Id))
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
{{define "form_checkin"}}
|
||||
<form action="/service/{{.Id}}/checkin" method="POST">
|
||||
<form action="/checkin/{{.Id}}" method="POST">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12 col-sm-12">
|
||||
<label for="checkin_interval" class="col-sm-4 col-form-label">Check Interval (in seconds)</label>
|
||||
<input type="number" name="interval" class="form-control" id="checkin_interval" value="30" placeholder="60">
|
||||
<div class="col-md-4 col-sm-4">
|
||||
<label for="checkin_interval" class="col-form-label">Check Interval (in seconds)</label>
|
||||
<input type="number" name="interval" class="form-control" id="checkin_interval" value="{{.Interval}}" placeholder="60">
|
||||
</div>
|
||||
<div class="col-md-12 col-sm-12">
|
||||
<label for="grace_period" class="col-sm-4 col-form-label">Grace Period </label>
|
||||
<input type="number" name="grace" class="form-control" id="grace_period" value="30" placeholder="60">
|
||||
<div class="col-md-4 col-sm-4">
|
||||
<label for="grace_period" class="col-form-label">Grace Period</label>
|
||||
<input type="number" name="grace" class="form-control" id="grace_period" value="{{.GracePeriod}}" placeholder="60">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<div class="col-md-4 col-sm-4">
|
||||
<label for="checkin_interval" class="col-form-label"></label>
|
||||
<button type="submit" class="btn btn-success d-block">Save Checkin</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -77,15 +77,7 @@
|
|||
|
||||
{{if Auth}}
|
||||
|
||||
<div class="col-12 mt-4">
|
||||
|
||||
<h3>Edit Service</h3>
|
||||
|
||||
{{template "form_service" $s}}
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-12 mt-4{{if eq $s.Type "tcp"}} d-none{{end}}">
|
||||
<div class="col-12 mt-4{{if ne $s.Type "http"}} d-none{{end}}">
|
||||
<h3>Last Response</h3>
|
||||
<textarea rows="8" class="form-control" readonly>{{ $s.LastResponse }}</textarea>
|
||||
<div class="form-group row mt-2">
|
||||
|
@ -96,28 +88,33 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 mt-4">
|
||||
<h3>Edit Service</h3>
|
||||
{{template "form_service" $s}}
|
||||
</div>
|
||||
|
||||
<div class="col-12 mt-4">
|
||||
<h3>Service Checkin</h3>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Checkin</th>
|
||||
<th scope="col">Report Period<br>Grace Period</th>
|
||||
<th scope="col">Last Seen</th>
|
||||
<th scope="col">Expected</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="col">Checkin</th>
|
||||
<th scope="col">Report Period<br>Grace Period</th>
|
||||
<th scope="col">Last Seen</th>
|
||||
<th scope="col">Expected</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{$ch := $s.Checkin}}
|
||||
<tr>
|
||||
<tr class="{{ if lt $ch.Expected 0}}bg-danger text-white{{else}}bg-light{{end}}">
|
||||
<td>{{CoreApp.Domain}}/checkin/{{$ch.ApiKey}}</td>
|
||||
<td>every {{Duration $ch.Period}}<br>{{Duration $ch.Grace}} grace period</td>
|
||||
<td>every {{Duration $ch.Period}}<br>after {{Duration $ch.Grace}}</td>
|
||||
<td>{{Ago $ch.Last.CreatedAt}}</td>
|
||||
<td>{{ if lt $ch.Expected 0}}{{Duration $ch.Expected}} ago{{else}}in {{Duration $ch.Expected}}{{end}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{{template "form_checkin" $s}}
|
||||
{{template "form_checkin" $ch}}
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -46,7 +46,6 @@ type Service struct {
|
|||
LastStatusCode int `gorm:"-" json:"status_code"`
|
||||
LastOnline time.Time `gorm:"-" json:"last_online"`
|
||||
Failures []interface{} `gorm:"-" json:"failures,omitempty"`
|
||||
//Checkins []*Checkin `gorm:"-" json:"checkins,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceInterface interface {
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
// 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 utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
func FormatDuration(d time.Duration) string {
|
||||
var out string
|
||||
if d.Hours() >= 24 {
|
||||
out = fmt.Sprintf("%0.0f day", d.Hours()/24)
|
||||
if (d.Hours() / 24) >= 2 {
|
||||
out += "s"
|
||||
}
|
||||
return out
|
||||
} else if d.Hours() >= 1 {
|
||||
out = fmt.Sprintf("%0.0f hour", d.Hours())
|
||||
if d.Hours() >= 2 {
|
||||
out += "s"
|
||||
}
|
||||
return out
|
||||
} else if d.Minutes() >= 1 {
|
||||
out = fmt.Sprintf("%0.0f minute", d.Minutes())
|
||||
if d.Minutes() >= 2 {
|
||||
out += "s"
|
||||
}
|
||||
return out
|
||||
} else if d.Seconds() >= 1 {
|
||||
out = fmt.Sprintf("%0.0f second", d.Seconds())
|
||||
if d.Seconds() >= 2 {
|
||||
out += "s"
|
||||
}
|
||||
return out
|
||||
} else if rev(d.Hours()) >= 24 {
|
||||
out = fmt.Sprintf("%0.0f day", rev(d.Hours()/24))
|
||||
if rev(d.Hours()/24) >= 2 {
|
||||
out += "s"
|
||||
}
|
||||
return out
|
||||
} else if rev(d.Hours()) >= 1 {
|
||||
out = fmt.Sprintf("%0.0f hour", rev(d.Hours()))
|
||||
if rev(d.Hours()) >= 2 {
|
||||
out += "s"
|
||||
}
|
||||
return out
|
||||
} else if rev(d.Minutes()) >= 1 {
|
||||
out = fmt.Sprintf("%0.0f minute", rev(d.Minutes()))
|
||||
if rev(d.Minutes()) >= 2 {
|
||||
out += "s"
|
||||
}
|
||||
return out
|
||||
} else {
|
||||
out = fmt.Sprintf("%0.0f second", rev(d.Seconds()))
|
||||
if rev(d.Seconds()) >= 2 {
|
||||
out += "s"
|
||||
}
|
||||
return out
|
||||
}
|
||||
}
|
||||
|
||||
func rev(f float64) float64 {
|
||||
return f * -1
|
||||
}
|
Loading…
Reference in New Issue