Basic functionality working
Some checks failed
Deploy and Push Docker Image / BuildAndPush (push) Failing after 14s
Some checks failed
Deploy and Push Docker Image / BuildAndPush (push) Failing after 14s
This commit is contained in:
28
.gitea/workflows/docker-build.yml
Normal file
28
.gitea/workflows/docker-build.yml
Normal file
@ -0,0 +1,28 @@
|
||||
name: Deploy and Push Docker Image
|
||||
run-name: ${{ gitea.actor }} deploying to production 🚀
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
BuildAndPush:
|
||||
runs-on: ubuntu
|
||||
steps:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v3
|
||||
- name: Login to Docker Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: gitea.henriburau.de
|
||||
username: ${{ gitea.actor }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN}}
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
file: build/Dockerfile
|
||||
push: true
|
||||
platforms: linux/arm64,linux/amd64
|
||||
tags: |
|
||||
gitea.henriburau.de/ace966/WeeWooWebhook:latest
|
||||
gitea.henriburau.de/ace966/WeeWooWebhook:${{ gitea.run_id }}
|
||||
18
build/Dockerfile
Normal file
18
build/Dockerfile
Normal file
@ -0,0 +1,18 @@
|
||||
FROM golang:1.24-alpine AS builder
|
||||
|
||||
# Set working directory
|
||||
WORKDIR /app
|
||||
|
||||
# Copy source code
|
||||
COPY . .
|
||||
|
||||
# Build the Go binary statically
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -o weewoowebhook /app/cmd/wee_woo_webhook/main.go
|
||||
|
||||
FROM scratch
|
||||
|
||||
# Copy statically built binary from the builder
|
||||
COPY --from=builder /app/weewoowebhook /weewoowebhook
|
||||
|
||||
# Set the binary as the container entrypoint
|
||||
ENTRYPOINT ["/weewoowebhook"]
|
||||
19
cmd/wee_woo_webhook/main.go
Normal file
19
cmd/wee_woo_webhook/main.go
Normal file
@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"gitea.henriburau.de/ace966/WeeWooWebhook/internal/olc"
|
||||
"gitea.henriburau.de/ace966/WeeWooWebhook/internal/server"
|
||||
)
|
||||
|
||||
const (
|
||||
WeeWooAddr = "http://192.168.1.167"
|
||||
)
|
||||
|
||||
func main() {
|
||||
officeLightClient := olc.NewClient(WeeWooAddr)
|
||||
server := server.NewServer(officeLightClient)
|
||||
|
||||
log.Fatal(server.ListenAndServe())
|
||||
}
|
||||
3
go.mod
Normal file
3
go.mod
Normal file
@ -0,0 +1,3 @@
|
||||
module gitea.henriburau.de/ace966/WeeWooWebhook
|
||||
|
||||
go 1.23.5
|
||||
84
internal/model/uptime_kuma_webhook_request.go
Normal file
84
internal/model/uptime_kuma_webhook_request.go
Normal file
@ -0,0 +1,84 @@
|
||||
package model
|
||||
|
||||
const (
|
||||
MonitorStatusDown = 0
|
||||
MonitorStatusUp = 1
|
||||
)
|
||||
|
||||
type UptimeKumaWebhookRequest struct {
|
||||
Heartbeat struct {
|
||||
MonitorID int `json:"monitorID"`
|
||||
Status int `json:"status"`
|
||||
Time string `json:"time"`
|
||||
Msg string `json:"msg"`
|
||||
Important bool `json:"important"`
|
||||
Duration int `json:"duration"`
|
||||
Timezone string `json:"timezone"`
|
||||
TimezoneOffset string `json:"timezoneOffset"`
|
||||
LocalDateTime string `json:"localDateTime"`
|
||||
} `json:"heartbeat"`
|
||||
Monitor struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Description any `json:"description"`
|
||||
PathName string `json:"pathName"`
|
||||
Parent any `json:"parent"`
|
||||
ChildrenIDs []any `json:"childrenIDs"`
|
||||
URL string `json:"url"`
|
||||
Method string `json:"method"`
|
||||
Hostname any `json:"hostname"`
|
||||
Port any `json:"port"`
|
||||
Maxretries int `json:"maxretries"`
|
||||
Weight int `json:"weight"`
|
||||
Active bool `json:"active"`
|
||||
ForceInactive bool `json:"forceInactive"`
|
||||
Type string `json:"type"`
|
||||
Timeout int `json:"timeout"`
|
||||
Interval int `json:"interval"`
|
||||
RetryInterval int `json:"retryInterval"`
|
||||
ResendInterval int `json:"resendInterval"`
|
||||
Keyword any `json:"keyword"`
|
||||
InvertKeyword bool `json:"invertKeyword"`
|
||||
ExpiryNotification bool `json:"expiryNotification"`
|
||||
IgnoreTLS bool `json:"ignoreTls"`
|
||||
UpsideDown bool `json:"upsideDown"`
|
||||
PacketSize int `json:"packetSize"`
|
||||
Maxredirects int `json:"maxredirects"`
|
||||
AcceptedStatuscodes []string `json:"accepted_statuscodes"`
|
||||
DNSResolveType string `json:"dns_resolve_type"`
|
||||
DNSResolveServer string `json:"dns_resolve_server"`
|
||||
DNSLastResult any `json:"dns_last_result"`
|
||||
DockerContainer string `json:"docker_container"`
|
||||
DockerHost any `json:"docker_host"`
|
||||
ProxyID any `json:"proxyId"`
|
||||
NotificationIDList struct {
|
||||
Num5 bool `json:"5"`
|
||||
} `json:"notificationIDList"`
|
||||
Tags []any `json:"tags"`
|
||||
Maintenance bool `json:"maintenance"`
|
||||
MqttTopic string `json:"mqttTopic"`
|
||||
MqttSuccessMessage string `json:"mqttSuccessMessage"`
|
||||
DatabaseQuery any `json:"databaseQuery"`
|
||||
AuthMethod any `json:"authMethod"`
|
||||
GrpcURL any `json:"grpcUrl"`
|
||||
GrpcProtobuf any `json:"grpcProtobuf"`
|
||||
GrpcMethod any `json:"grpcMethod"`
|
||||
GrpcServiceName any `json:"grpcServiceName"`
|
||||
GrpcEnableTLS bool `json:"grpcEnableTls"`
|
||||
RadiusCalledStationID any `json:"radiusCalledStationId"`
|
||||
RadiusCallingStationID any `json:"radiusCallingStationId"`
|
||||
Game any `json:"game"`
|
||||
GamedigGivenPortOnly bool `json:"gamedigGivenPortOnly"`
|
||||
HTTPBodyEncoding string `json:"httpBodyEncoding"`
|
||||
JSONPath any `json:"jsonPath"`
|
||||
ExpectedValue any `json:"expectedValue"`
|
||||
KafkaProducerTopic any `json:"kafkaProducerTopic"`
|
||||
KafkaProducerBrokers []any `json:"kafkaProducerBrokers"`
|
||||
KafkaProducerSsl bool `json:"kafkaProducerSsl"`
|
||||
KafkaProducerAllowAutoTopicCreation bool `json:"kafkaProducerAllowAutoTopicCreation"`
|
||||
KafkaProducerMessage any `json:"kafkaProducerMessage"`
|
||||
Screenshot any `json:"screenshot"`
|
||||
IncludeSensitiveData bool `json:"includeSensitiveData"`
|
||||
} `json:"monitor"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
57
internal/olc/office_light_client.go
Normal file
57
internal/olc/office_light_client.go
Normal file
@ -0,0 +1,57 @@
|
||||
package olc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
type OfficeLightClient struct {
|
||||
BaseURL string
|
||||
Client *http.Client
|
||||
}
|
||||
|
||||
func NewClient(baseURL string) *OfficeLightClient {
|
||||
return &OfficeLightClient{
|
||||
BaseURL: baseURL,
|
||||
Client: &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (olc *OfficeLightClient) SetLightState(state bool) error {
|
||||
endpoint := fmt.Sprintf("%s/state", olc.BaseURL)
|
||||
stateString := "off"
|
||||
if state {
|
||||
stateString = "on"
|
||||
}
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("state", stateString)
|
||||
|
||||
reqURL := fmt.Sprintf("%s?%s", endpoint, params.Encode())
|
||||
resp, err := olc.Client.Post(reqURL, "application/x-www-form-urlencoded", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (olc *OfficeLightClient) SetColor(r, g, b uint8) error {
|
||||
endpoint := fmt.Sprintf("%s/color", olc.BaseURL)
|
||||
params := url.Values{}
|
||||
params.Set("r", fmt.Sprintf("%d", r))
|
||||
params.Set("g", fmt.Sprintf("%d", g))
|
||||
params.Set("b", fmt.Sprintf("%d", b))
|
||||
|
||||
reqURL := fmt.Sprintf("%s?%s", endpoint, params.Encode())
|
||||
resp, err := olc.Client.Post(reqURL, "application/x-www-form-urlencoded", nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return nil
|
||||
}
|
||||
28
internal/server/server.go
Normal file
28
internal/server/server.go
Normal file
@ -0,0 +1,28 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"gitea.henriburau.de/ace966/WeeWooWebhook/internal/olc"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
OfficeLightClient *olc.OfficeLightClient
|
||||
downServices map[int]bool
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
func NewServer(olc *olc.OfficeLightClient) *Server {
|
||||
return &Server{
|
||||
OfficeLightClient: olc,
|
||||
downServices: make(map[int]bool),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) ListenAndServe() error {
|
||||
fmt.Println("Server listening on :8085/wehook...")
|
||||
http.HandleFunc("/webhook", s.webhookHandler())
|
||||
return http.ListenAndServe(":8085", nil)
|
||||
}
|
||||
56
internal/server/webhook.go
Normal file
56
internal/server/webhook.go
Normal file
@ -0,0 +1,56 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"gitea.henriburau.de/ace966/WeeWooWebhook/internal/model"
|
||||
)
|
||||
|
||||
func (s *Server) webhookHandler() http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
var data model.UptimeKumaWebhookRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
|
||||
http.Error(w, "Invalid JSON", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("Received webhook msg: %s\n", data.Msg)
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
wasDown := s.downServices[data.Monitor.ID]
|
||||
|
||||
switch data.Heartbeat.Status {
|
||||
case model.MonitorStatusDown:
|
||||
if !wasDown {
|
||||
s.downServices[data.Heartbeat.MonitorID] = true
|
||||
log.Printf("Service DOWN: %s", data.Monitor.Name)
|
||||
go s.activateEmergencyLight()
|
||||
}
|
||||
case model.MonitorStatusUp:
|
||||
if wasDown {
|
||||
delete(s.downServices, data.Heartbeat.MonitorID)
|
||||
log.Printf("Service UP: %s", data.Monitor.Name)
|
||||
if len(s.downServices) == 0 {
|
||||
go s.deactivateEmergencyLight()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintln(w, "Received")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) activateEmergencyLight() {
|
||||
s.OfficeLightClient.SetColor(255, 0, 0) // Set to red
|
||||
s.OfficeLightClient.SetLightState(true) // Turn on
|
||||
}
|
||||
|
||||
func (s *Server) deactivateEmergencyLight() {
|
||||
s.OfficeLightClient.SetLightState(false) // Turn off
|
||||
}
|
||||
Reference in New Issue
Block a user