├── .appveyor.yml
├── .github
├── FUNDING.yml
└── workflows
│ └── go.yml
├── .gitignore
├── .gitmodules
├── .goreleaser.yml
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── admin
├── beehive.service
├── beehive.service.conf
└── beehive.sh
├── api
├── api.go
├── bindata_stub.go
├── context
│ └── context.go
└── resources
│ ├── actions
│ ├── actions.go
│ ├── actions_get.go
│ ├── actions_post.go
│ └── actions_response.go
│ ├── bees
│ ├── bees.go
│ ├── bees_delete.go
│ ├── bees_get.go
│ ├── bees_post.go
│ ├── bees_put.go
│ └── bees_response.go
│ ├── chains
│ ├── chains.go
│ ├── chains_delete.go
│ ├── chains_get.go
│ ├── chains_post.go
│ └── chains_response.go
│ ├── hives
│ ├── hives.go
│ ├── hives_get.go
│ └── hives_response.go
│ └── logs
│ ├── logs.go
│ ├── logs_get.go
│ └── logs_response.go
├── app
└── app.go
├── assets
├── bees
│ ├── alertoverbee.png
│ ├── anelpowerctrlbee.png
│ ├── cfddns.png
│ ├── cleverbotbee.png
│ ├── cricketbee.png
│ ├── cronbee.png
│ ├── devrantbee.png
│ ├── discordbee.png
│ ├── efabee.png
│ ├── emailbee.png
│ ├── emailserverbee.png
│ ├── execbee.png
│ ├── facebookbee.png
│ ├── fsnotifybee.png
│ ├── githubbee.png
│ ├── gitterbee.png
│ ├── gotifybee.png
│ ├── horizonboxbee.png
│ ├── htmlextractbee.png
│ ├── huebee.png
│ ├── instapaperbee.png
│ ├── ipify.png
│ ├── ircbee.png
│ ├── jabberbee.png
│ ├── jenkinsbee.png
│ ├── jirabee.png
│ ├── mastodonbee.png
│ ├── mixcloudbee.png
│ ├── mumblebee.png
│ ├── nagiosbee.png
│ ├── notificationbee.png
│ ├── openweathermapbee.png
│ ├── pastebinbee.png
│ ├── prometheusbee.png
│ ├── pushoverbee.png
│ ├── redis.png
│ ├── rocketchatbee.png
│ ├── rssbee.png
│ ├── s3bee.png
│ ├── serialbee.png
│ ├── simplepushbee.png
│ ├── slackbee.png
│ ├── socketbee.png
│ ├── spaceapibee.png
│ ├── sunbee.png
│ ├── telegrambee.png
│ ├── transmissionbee.png
│ ├── travisbee.png
│ ├── tumblrbee.png
│ ├── twiliobee.png
│ ├── twitchbee.png
│ ├── twitterbee.png
│ └── webbee.png
├── logo.png
├── logo_128.png
├── logo_16.png
├── logo_256.png
├── logo_32.png
├── logo_512.png
└── logo_64.png
├── beehive.go
├── bees
├── actions.go
├── alertoverbee
│ ├── README.md
│ ├── alertoverbee.go
│ └── alertoverbeefactory.go
├── anelpowerctrlbee
│ ├── anelpowerctrlbee.go
│ └── anelpowerctrlbeefactory.go
├── bees.go
├── cfddnsbee
│ ├── README.md
│ ├── cfddnsbee.go
│ └── cfddnsbeefactory.go
├── chains.go
├── cleverbotbee
│ ├── README.md
│ ├── cleverbotbee.go
│ └── cleverbotbeefactory.go
├── config.go
├── context.go
├── cricketbee
│ ├── README.md
│ ├── cricketbee.go
│ └── cricketbeefactory.go
├── cronbee
│ ├── cronbee.go
│ ├── cronbeefactory.go
│ └── thoughts.txt
├── descriptors.go
├── devrantbee
│ ├── devrantbee.go
│ └── devrantbeefactory.go
├── discordbee
│ ├── discordbee.go
│ └── discordbeefactory.go
├── efabee
│ ├── efabee.go
│ └── efabeefactory.go
├── emailbee
│ ├── emailbee.go
│ └── emailbeefactory.go
├── emailserverbee
│ ├── emailserverbee.go
│ └── emailserverbeefactory.go
├── events.go
├── execbee
│ ├── execbee.go
│ └── execbeefactory.go
├── facebookbee
│ ├── facebookbee.go
│ └── facebookbeefactory.go
├── factories.go
├── filters.go
├── fsnotifybee
│ ├── README.md
│ ├── fsnotifybee.go
│ └── fsnotifybeefactory.go
├── githubbee
│ ├── events.go
│ ├── githubbee.go
│ └── githubbeefactory.go
├── gitterbee
│ ├── README.md
│ ├── gitterbee.go
│ └── gitterbeefactory.go
├── gotifybee
│ ├── README.md
│ ├── gotifybee.go
│ └── gotifybeefactory.go
├── hellobee
│ ├── hellobee.go
│ └── hellobeefactory.go
├── horizonboxbee
│ ├── horizonboxbee.go
│ └── horizonboxbeefactory.go
├── htmlextractbee
│ ├── htmlextractbee.go
│ └── htmlextractbeefactory.go
├── httpbee
│ ├── httpbee.go
│ └── httpbeefactory.go
├── huebee
│ ├── huebee.go
│ └── huebeefactory.go
├── instapaperbee
│ ├── instapaperbee.go
│ └── instapaperbeefactory.go
├── ipifybee
│ ├── README.md
│ ├── ipifybee.go
│ └── ipifybeefactory.go
├── ircbee
│ ├── ircbee.go
│ ├── ircbeefactory.go
│ └── irctools
│ │ └── irctools.go
├── jabberbee
│ ├── jabberbee.go
│ └── jabberbeefactory.go
├── jenkinsbee
│ ├── jenkinsbee.go
│ └── jenkinsbeefactory.go
├── jirabee
│ ├── events.go
│ ├── jirabee.go
│ └── jirabeefactory.go
├── logs.go
├── mastodonbee
│ ├── README.md
│ ├── events.go
│ ├── mastodonbee.go
│ └── mastodonbeefactory.go
├── mixcloudbee
│ ├── mixcloudbee.go
│ └── mixcloudbeefactory.go
├── mumblebee
│ ├── mumblebee.go
│ └── mumblebeefactory.go
├── nagiosbee
│ ├── nagiosbee.go
│ └── nagiosbeefactory.go
├── notificationbee
│ ├── notificationbee.go
│ ├── notificationbee_osx.go
│ ├── notificationbee_unix.go
│ └── notificationbeefactory.go
├── openweathermapbee
│ ├── README.md
│ ├── event.go
│ ├── openweathermapbee.go
│ └── openweathermapbeefactory.go
├── options.go
├── pastebinbee
│ ├── README.md
│ ├── pastebinbee.go
│ └── pastebinbeefactory.go
├── placeholders.go
├── prometheusbee
│ ├── prometheusbee.go
│ └── prometheusbeefactory.go
├── pushoverbee
│ ├── pushoverbee.go
│ └── pushoverbeefactory.go
├── redisbee
│ ├── README.md
│ ├── redisbee.go
│ └── redisbeefactory.go
├── rocketchatbee
│ ├── README.md
│ ├── client.go
│ ├── rocketchatbee.go
│ └── rocketchatbeefactory.go
├── rssbee
│ ├── rssbee.go
│ └── rssbeefactory.go
├── s3bee
│ ├── README.md
│ ├── s3bee.go
│ └── s3beefactory.go
├── serialbee
│ ├── serialbee.go
│ └── serialbeefactory.go
├── simplepushbee
│ ├── simplepushbee.go
│ └── simplepushbeefactory.go
├── slackbee
│ ├── README.md
│ ├── slackbee.go
│ └── slackbeefactory.go
├── socketbee
│ ├── socketbee.go
│ └── socketbeefactory.go
├── spaceapibee
│ ├── spaceapibee.go
│ └── spaceapibeefactory.go
├── sunbee
│ ├── README.md
│ ├── sunbee.go
│ └── sunbeefactory.go
├── telegrambee
│ ├── README.md
│ ├── telegrambee.go
│ └── telegrambeefactory.go
├── timebee
│ ├── timebee.go
│ └── timebeefactory.go
├── transmissionbee
│ ├── transmissionbee.go
│ └── transmissionbeefactory.go
├── travisbee
│ ├── travisbee.go
│ └── travisbeefactory.go
├── tumblrbee
│ ├── tumblrbee.go
│ └── tumblrbeefactory.go
├── twiliobee
│ ├── README.md
│ ├── twiliobee.go
│ └── twiliobeefactory.go
├── twitchbee
│ ├── twitchbee.go
│ └── twitchbeefactory.go
├── twitterbee
│ ├── twitterbee.go
│ └── twitterbeefactory.go
└── webbee
│ ├── webbee.go
│ └── webbeefactory.go
├── build-constants.go
├── cfg
├── aesbackend.go
├── aesbackend_test.go
├── config.go
├── config_test.go
├── filebackend.go
├── filebackend_test.go
├── membackend.go
├── membackend_test.go
└── testdata
│ ├── beehive-crypto.conf
│ ├── beehive.conf
│ └── beehive.yaml
├── docker-compose.yml
├── docker
└── README.md
├── docs
├── config_encryption.md
└── watchdog.md
├── filters
├── filters.go
└── template
│ ├── templatefilter.go
│ └── templatefilter_test.go
├── go.mod
├── go.sum
├── hives.go
├── hives_linux.go
├── hives_osx.go
├── hives_unix.go
├── templatehelper
├── templatehelper.go
└── templatehelper_test.go
├── tools
├── encrypted-config-wrapper
└── release.sh
└── watchdog_linux.go
/.appveyor.yml:
--------------------------------------------------------------------------------
1 | version: "{build}"
2 |
3 | os: Windows Server 2012 R2
4 |
5 | clone_folder: c:\gopath\src\github.com\muesli\beehive
6 |
7 | environment:
8 | GOPATH: c:\gopath
9 | GO111MODULE: on
10 |
11 | install:
12 | - echo %PATH%
13 | - echo %GOPATH%
14 | - go version
15 | - go env
16 | - git submodule update --init
17 |
18 | build_script:
19 | - go build
20 | - go test -v
21 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: muesli
2 |
--------------------------------------------------------------------------------
/.github/workflows/go.yml:
--------------------------------------------------------------------------------
1 | name: build
2 | on: [push, pull_request]
3 | jobs:
4 | test:
5 | strategy:
6 | matrix:
7 | go-version: [1.13.x, 1.14.x, 1.15.x]
8 | os: [ubuntu-latest, macos-latest]
9 | runs-on: ${{ matrix.os }}
10 | env:
11 | GO111MODULE: "on"
12 | steps:
13 | - name: Install Go
14 | uses: actions/setup-go@v1
15 | with:
16 | go-version: ${{ matrix.go-version }}
17 |
18 | - name: Checkout code
19 | uses: actions/checkout@v1
20 |
21 | - name: Download Go modules
22 | run: go mod download
23 |
24 | - name: Build
25 | run: go build -v ./...
26 |
27 | - name: Test
28 | run: go test ./...
29 |
30 | - name: Coverage
31 | env:
32 | COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33 | run: |
34 | go test -race -covermode atomic -coverprofile=profile.cov ./...
35 | GO111MODULE=off go get github.com/mattn/goveralls
36 | $(go env GOPATH)/bin/goveralls -coverprofile=profile.cov -service=github
37 | if: matrix.go-version == '1.14.x' && matrix.platform == 'ubuntu-latest'
38 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependencies
2 | vendor/
3 |
4 | # Compiled Object files, Static and Dynamic libs (Shared Objects)
5 | *.o
6 | *.a
7 | *.so
8 |
9 | # Folders
10 | _obj
11 | _test
12 | /dist
13 |
14 | # Architecture specific extensions/prefixes
15 | *.[568vq]
16 | [568vq].out
17 |
18 | *.cgo1.go
19 | *.cgo2.c
20 | _cgo_defun.c
21 | _cgo_gotypes.go
22 | _cgo_export.*
23 |
24 | _testmain.go
25 |
26 | *.exe
27 | *.test
28 |
29 | *~
30 | beehive
31 | /beehive.conf
32 | /beehive.yaml
33 |
34 | # Texteditor-specific stuff
35 | .*.sw*
36 | *.sublime-project
37 | *.sublime-workspace
38 |
39 | # Jetbrains IDEs
40 | .idea
41 |
42 | # Embedded assets
43 | api/bindata.go
44 |
45 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "config"]
2 | path = config
3 | url = https://github.com/muesli/beehive-admin-dist.git
4 |
--------------------------------------------------------------------------------
/.goreleaser.yml:
--------------------------------------------------------------------------------
1 | env:
2 | - GO111MODULE=on
3 | before:
4 | hooks:
5 | - go mod download
6 | builds:
7 | -
8 | binary: beehive
9 | ldflags: -s -w -X main.Version={{ .Version }} -X main.CommitSHA={{ .Commit }}
10 | goos:
11 | - linux
12 | - darwin
13 | - windows
14 | goarch:
15 | - amd64
16 | - arm64
17 | - 386
18 | - arm
19 | goarm:
20 | - 6
21 | - 7
22 | ignore:
23 | - goos: darwin
24 | goarch: 386
25 | - goos: linux
26 | goarch: arm
27 | goarm: 7
28 | flags:
29 | - -tags=embed
30 | hooks:
31 | pre: go-bindata --tags embed --pkg api -o api/bindata.go --ignore config/.git assets/... config/...
32 | signs:
33 | - artifacts: checksum
34 | archives:
35 | -
36 | replacements:
37 | darwin: Darwin
38 | linux: Linux
39 | windows: Windows
40 | 386: i386
41 | amd64: x86_64
42 | checksum:
43 | name_template: 'checksums.txt'
44 | snapshot:
45 | name_template: "{{ .Tag }}-next"
46 | changelog:
47 | sort: asc
48 | filters:
49 | exclude:
50 | - '^docs:'
51 | - '^test:'
52 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:alpine AS builder
2 |
3 | LABEL authors="Gabriel Alacchi: alacchi.g@gmail.com, Christian Muehlhaeuser: muesli@gmail.com"
4 |
5 | # Install git & make
6 | # Git is required for fetching the dependencies
7 | RUN apk update && \
8 | apk add --no-cache git make ca-certificates && \
9 | update-ca-certificates
10 |
11 | # Set the working directory for the container
12 | WORKDIR /go/beehive
13 |
14 | # Build the binary
15 | COPY . .
16 | RUN make embed
17 |
18 | FROM alpine
19 |
20 | RUN apk update && \
21 | apk add --no-cache ca-certificates tzdata && \
22 | update-ca-certificates
23 |
24 | COPY --from=builder /go/beehive/beehive /go/bin/beehive
25 |
26 | # Where the admin interface will be served from
27 | ENV CANONICAL_URL=http://localhost:8181
28 |
29 | # Expose the application port
30 | EXPOSE 8181
31 |
32 | # create a volume for the configuration persistence
33 | VOLUME /conf
34 |
35 | # This form of ENTRYPOINT allows the beehive process to catch signals from the `docker stop` command
36 | ENTRYPOINT /go/bin/beehive -config /conf/beehive.conf -bind 0.0.0.0:8181 -canonicalurl ${CANONICAL_URL}
37 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | BEEHIVE_VERSION=0.4.0
2 | COMMIT_SHA=$(shell git rev-parse --short HEAD)
3 |
4 | all: submodule embed
5 |
6 | submodule:
7 | [ -d .git ] && git submodule update --init || true
8 |
9 | noembed: submodule build
10 |
11 | generate:
12 | $(shell go env GOPATH)/bin/go-bindata --tags embed --pkg api -o api/bindata.go --ignore config/.git assets/... config/...
13 |
14 | go-bindata:
15 | [ -f $(shell go env GOPATH)/bin/go-bindata ] || go get -u github.com/kevinburke/go-bindata/go-bindata
16 |
17 | embed: go-bindata generate build
18 |
19 | build:
20 | go build -tags 'embed' -ldflags '-s -w -X main.Version=$(BEEHIVE_VERSION) -X main.CommitSHA=$(COMMIT_SHA)'
21 |
22 | debug: submodule go-bindata generate
23 | go build -tags 'embed' -ldflags '-X main.Version=$(BEEHIVE_VERSION) -X main.CommitSHA=$(COMMIT_SHA)'
24 |
25 | test:
26 | go test -v $(shell go list ./... | grep -v vendor/)
27 |
28 | release:
29 | @./tools/release.sh
30 |
31 | clean:
32 | rm -f beehive
33 |
34 | .PHONY: clean embed go-bindata noembed generate submodule build release all
35 |
--------------------------------------------------------------------------------
/admin/beehive.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=beehive Event daemon
3 | After=network.target
4 |
5 | [Service]
6 | ExecStart=$GOPATH/bin/beehive -config=${config}
7 | User=beehive
8 | Group=users
9 | RestartSec=5
10 | Restart=on-failure
11 | # Enable the software watchdog.
12 | # See https://github.com/muesli/beehive/tree/master/docs/watchdog.md
13 | WatchdogSec=30s
14 |
15 | [Install]
16 | WantedBy=multi-user.target
17 |
--------------------------------------------------------------------------------
/admin/beehive.service.conf:
--------------------------------------------------------------------------------
1 | GOROOT="/usr/local/opt/go"
2 | GOPATH="/home/beehive/go"
3 |
4 | config="/home/beehive/beehive.conf"
5 |
--------------------------------------------------------------------------------
/admin/beehive.sh:
--------------------------------------------------------------------------------
1 | #! /bin/sh
2 |
3 | ### BEGIN INIT INFO
4 | # Provides: beehive
5 | # Required-Start: $syslog
6 | # Required-Stop: $syslog
7 | # Default-Start: 2 3 4 5
8 | # Default-Stop:
9 | # Short-Description: beehive daemon
10 | ### END INIT INFO
11 |
12 | set -e
13 |
14 | # /etc/init.d/beehive: start and stop the beehive daemon
15 |
16 | umask 022
17 |
18 | . /lib/lsb/init-functions
19 |
20 | export GOROOT="/usr/local/opt/go"
21 | export PATH="$GOROOT/bin:$PATH"
22 | export GOPATH="/home/beehive/go"
23 |
24 | BINARY="$GOPATH/bin/beehive"
25 | PIDFILE="/var/run/beehive.pid"
26 | CONFIG="/home/beehive/beehive.conf"
27 |
28 | test -x $BINARY || exit 0
29 |
30 | case "$1" in
31 | start)
32 | log_daemon_msg "Starting beehive daemon" "beehive" || true
33 | if start-stop-daemon --start -b --quiet --oknodo -m --pidfile $PIDFILE --exec $BINARY -- -config="$CONFIG"; then
34 | log_end_msg 0 || true
35 | else
36 | log_end_msg 1 || true
37 | fi
38 | ;;
39 | stop)
40 | log_daemon_msg "Stopping beehive daemon" "beehive" || true
41 | if start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE; then
42 | log_end_msg 0 || true
43 | else
44 | log_end_msg 1 || true
45 | fi
46 | ;;
47 |
48 | reload|force-reload)
49 | log_daemon_msg "Reloading beehive daemon's configuration" "beehive" || true
50 | if start-stop-daemon --stop --signal 1 --quiet --oknodo --pidfile $PIDFILE --exec $BINARY ; then
51 | log_end_msg 0 || true
52 | else
53 | log_end_msg 1 || true
54 | fi
55 | ;;
56 |
57 | restart)
58 | log_daemon_msg "Restarting beehive daemon" "beehive" || true
59 | start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile $PIDFILE
60 | if start-stop-daemon --start -b --quiet --oknodo -m --pidfile $PIDFILE --exec $BINARY -- -config="$CONFIG"; then
61 | log_end_msg 0 || true
62 | else
63 | log_end_msg 1 || true
64 | fi
65 | ;;
66 |
67 | status)
68 | status_of_proc -p $PIDFILE $BINARY beehive && exit 0 || exit $?
69 | ;;
70 |
71 | *)
72 | log_action_msg "Usage: /etc/init.d/beehive {start|stop|reload|restart|status}" || true
73 | exit 1
74 | esac
75 |
76 | exit 0
77 |
--------------------------------------------------------------------------------
/api/bindata_stub.go:
--------------------------------------------------------------------------------
1 | // +build !embed
2 |
3 | // go-bindata (https://github.com/kevinburke/go-bindata) stub
4 | // so beehive also works without embedded assets.
5 | package api
6 |
7 | import "io/ioutil"
8 |
9 | func Asset(asset string) ([]byte, error) {
10 | return ioutil.ReadFile(asset)
11 | }
12 |
--------------------------------------------------------------------------------
/api/context/context.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package context
22 |
23 | import (
24 | "strings"
25 |
26 | restful "github.com/emicklei/go-restful"
27 | "github.com/muesli/smolder"
28 | )
29 |
30 | // APIContext is polly's central context
31 | type APIContext struct {
32 | Config smolder.APIConfig
33 | }
34 |
35 | // NewAPIContext returns a new polly context
36 | func (context *APIContext) NewAPIContext() smolder.APIContext {
37 | ctx := &APIContext{
38 | Config: context.Config,
39 | }
40 | return ctx
41 | }
42 |
43 | // Authentication parses the request for an access-/authtoken and returns the matching user
44 | func (context *APIContext) Authentication(request *restful.Request) (interface{}, error) {
45 | //FIXME: implement this properly
46 |
47 | t := request.QueryParameter("accesstoken")
48 | if len(t) == 0 {
49 | t = request.HeaderParameter("authorization")
50 | if strings.Index(t, " ") > 0 {
51 | t = strings.TrimSpace(strings.Split(t, " ")[1])
52 | }
53 | }
54 |
55 | return nil, nil // context.GetUserByAccessToken(t)
56 | }
57 |
58 | // LogSummary logs out the current context stats
59 | func (context *APIContext) LogSummary() {
60 | }
61 |
--------------------------------------------------------------------------------
/api/resources/actions/actions.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package actions
22 |
23 | import (
24 | "github.com/emicklei/go-restful"
25 | "github.com/muesli/smolder"
26 | )
27 |
28 | // ActionResource is the resource responsible for /actions
29 | type ActionResource struct {
30 | smolder.Resource
31 | }
32 |
33 | var (
34 | _ smolder.GetIDSupported = &ActionResource{}
35 | _ smolder.GetSupported = &ActionResource{}
36 | _ smolder.PostSupported = &ActionResource{}
37 | )
38 |
39 | // Register this resource with the container to setup all the routes
40 | func (r *ActionResource) Register(container *restful.Container, config smolder.APIConfig, context smolder.APIContextFactory) {
41 | r.Name = "ActionResource"
42 | r.TypeName = "action"
43 | r.Endpoint = "actions"
44 | r.Doc = "Manage actions"
45 |
46 | r.Config = config
47 | r.Context = context
48 |
49 | r.Init(container, r)
50 | }
51 |
52 | // Reads returns the model that will be read by POST, PUT & PATCH operations
53 | func (r *ActionResource) Reads() interface{} {
54 | return &ActionPostStruct{}
55 | }
56 |
57 | // Returns returns the model that will be returned
58 | func (r *ActionResource) Returns() interface{} {
59 | return ActionResponse{}
60 | }
61 |
62 | // Validate checks an incoming request for data errors
63 | func (r *ActionResource) Validate(context smolder.APIContext, data interface{}, request *restful.Request) error {
64 | // ps := data.(*ActionPostStruct)
65 | // FIXME
66 | return nil
67 | }
68 |
--------------------------------------------------------------------------------
/api/resources/actions/actions_get.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package actions
22 |
23 | import (
24 | "github.com/muesli/beehive/bees"
25 |
26 | "github.com/emicklei/go-restful"
27 | "github.com/muesli/smolder"
28 | )
29 |
30 | // GetAuthRequired returns true because all requests need authentication
31 | func (r *ActionResource) GetAuthRequired() bool {
32 | return false
33 | }
34 |
35 | // GetByIDsAuthRequired returns true because all requests need authentication
36 | func (r *ActionResource) GetByIDsAuthRequired() bool {
37 | return false
38 | }
39 |
40 | // GetDoc returns the description of this API endpoint
41 | func (r *ActionResource) GetDoc() string {
42 | return "retrieve actions"
43 | }
44 |
45 | // GetParams returns the parameters supported by this API endpoint
46 | func (r *ActionResource) GetParams() []*restful.Parameter {
47 | params := []*restful.Parameter{}
48 | // params = append(params, restful.QueryParameter("user_id", "id of a user").DataType("int64"))
49 |
50 | return params
51 | }
52 |
53 | // GetByIDs sends out all items matching a set of IDs
54 | func (r *ActionResource) GetByIDs(ctx smolder.APIContext, request *restful.Request, response *restful.Response, ids []string) {
55 | resp := ActionResponse{}
56 | resp.Init(ctx)
57 |
58 | for _, id := range ids {
59 | action := bees.GetAction(id)
60 | if action == nil {
61 | r.NotFound(request, response)
62 | return
63 | }
64 |
65 | resp.AddAction(action)
66 | }
67 |
68 | resp.Send(response)
69 | }
70 |
71 | // Get sends out items matching the query parameters
72 | func (r *ActionResource) Get(ctx smolder.APIContext, request *restful.Request, response *restful.Response, params map[string][]string) {
73 | // ctxapi := ctx.(*context.APIContext)
74 | actions := bees.GetActions()
75 | if len(actions) == 0 {
76 | r.NotFound(request, response)
77 | return
78 | }
79 |
80 | resp := ActionResponse{}
81 | resp.Init(ctx)
82 |
83 | for _, action := range actions {
84 | resp.AddAction(&action)
85 | }
86 |
87 | resp.Send(response)
88 | }
89 |
--------------------------------------------------------------------------------
/api/resources/actions/actions_post.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package actions
22 |
23 | import (
24 | "github.com/emicklei/go-restful"
25 | "github.com/muesli/beehive/bees"
26 | "github.com/muesli/smolder"
27 | )
28 |
29 | // ActionPostStruct holds all values of an incoming POST request
30 | type ActionPostStruct struct {
31 | Action struct {
32 | Bee string `json:"bee"`
33 | Name string `json:"name"`
34 | Options bees.Placeholders `json:"options"`
35 | } `json:"action"`
36 | }
37 |
38 | // PostAuthRequired returns true because all requests need authentication
39 | func (r *ActionResource) PostAuthRequired() bool {
40 | return false
41 | }
42 |
43 | // PostDoc returns the description of this API endpoint
44 | func (r *ActionResource) PostDoc() string {
45 | return "create a new action"
46 | }
47 |
48 | // PostParams returns the parameters supported by this API endpoint
49 | func (r *ActionResource) PostParams() []*restful.Parameter {
50 | return nil
51 | }
52 |
53 | // Post processes an incoming POST (create) request
54 | func (r *ActionResource) Post(context smolder.APIContext, data interface{}, request *restful.Request, response *restful.Response) {
55 | resp := ActionResponse{}
56 | resp.Init(context)
57 |
58 | pps := data.(*ActionPostStruct)
59 | action := bees.Action{
60 | ID: bees.UUID(),
61 | Bee: pps.Action.Bee,
62 | Name: pps.Action.Name,
63 | Options: pps.Action.Options,
64 | }
65 | actions := append(bees.GetActions(), action)
66 | bees.SetActions(actions)
67 |
68 | resp.AddAction(&action)
69 | resp.Send(response)
70 | }
71 |
--------------------------------------------------------------------------------
/api/resources/actions/actions_response.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package actions
22 |
23 | import (
24 | "github.com/muesli/beehive/bees"
25 |
26 | "github.com/muesli/smolder"
27 | )
28 |
29 | // ActionResponse is the common response to 'action' requests
30 | type ActionResponse struct {
31 | smolder.Response
32 |
33 | Actions []actionInfoResponse `json:"actions,omitempty"`
34 | actions []*bees.Action
35 | }
36 |
37 | type actionInfoResponse struct {
38 | ID string `json:"id"`
39 | Bee string `json:"bee"`
40 | Name string `json:"name"`
41 | Options bees.Placeholders `json:"options"`
42 | }
43 |
44 | // Init a new response
45 | func (r *ActionResponse) Init(context smolder.APIContext) {
46 | r.Parent = r
47 | r.Context = context
48 |
49 | r.Actions = []actionInfoResponse{}
50 | }
51 |
52 | // AddAction adds a action to the response
53 | func (r *ActionResponse) AddAction(action *bees.Action) {
54 | r.actions = append(r.actions, action)
55 | r.Actions = append(r.Actions, prepareActionResponse(r.Context, action))
56 | }
57 |
58 | // EmptyResponse returns an empty API response for this endpoint if there's no data to respond with
59 | func (r *ActionResponse) EmptyResponse() interface{} {
60 | if len(r.actions) == 0 {
61 | var out struct {
62 | Actions interface{} `json:"actions"`
63 | }
64 | out.Actions = []actionInfoResponse{}
65 | return out
66 | }
67 | return nil
68 | }
69 |
70 | func prepareActionResponse(context smolder.APIContext, action *bees.Action) actionInfoResponse {
71 | // ctx := context.(*context.APIContext)
72 | resp := actionInfoResponse{
73 | ID: (*action).ID,
74 | Bee: (*action).Bee,
75 | Name: (*action).Name,
76 | Options: (*action).Options,
77 | }
78 |
79 | return resp
80 | }
81 |
--------------------------------------------------------------------------------
/api/resources/bees/bees.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package bees
22 |
23 | import (
24 | "github.com/emicklei/go-restful"
25 | "github.com/muesli/smolder"
26 | )
27 |
28 | // BeeResource is the resource responsible for /bees
29 | type BeeResource struct {
30 | smolder.Resource
31 | }
32 |
33 | var (
34 | _ smolder.GetIDSupported = &BeeResource{}
35 | _ smolder.GetSupported = &BeeResource{}
36 | _ smolder.PostSupported = &BeeResource{}
37 | _ smolder.PutSupported = &BeeResource{}
38 | _ smolder.DeleteSupported = &BeeResource{}
39 | )
40 |
41 | // Register this resource with the container to setup all the routes
42 | func (r *BeeResource) Register(container *restful.Container, config smolder.APIConfig, context smolder.APIContextFactory) {
43 | r.Name = "BeeResource"
44 | r.TypeName = "bee"
45 | r.Endpoint = "bees"
46 | r.Doc = "Manage bees"
47 |
48 | r.Config = config
49 | r.Context = context
50 |
51 | r.Init(container, r)
52 | }
53 |
54 | // Reads returns the model that will be read by POST, PUT & PATCH operations
55 | func (r *BeeResource) Reads() interface{} {
56 | return &BeePostStruct{}
57 | }
58 |
59 | // Returns returns the model that will be returned
60 | func (r *BeeResource) Returns() interface{} {
61 | return BeeResponse{}
62 | }
63 |
64 | // Validate checks an incoming request for data errors
65 | func (r *BeeResource) Validate(context smolder.APIContext, data interface{}, request *restful.Request) error {
66 | // ps := data.(*BeePostStruct)
67 | // FIXME
68 | return nil
69 | }
70 |
--------------------------------------------------------------------------------
/api/resources/bees/bees_delete.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package bees
22 |
23 | import (
24 | "github.com/emicklei/go-restful"
25 | "github.com/muesli/beehive/bees"
26 | "github.com/muesli/smolder"
27 | )
28 |
29 | // DeleteAuthRequired returns true because all requests need authentication
30 | func (r *BeeResource) DeleteAuthRequired() bool {
31 | return false
32 | }
33 |
34 | // DeleteDoc returns the description of this API endpoint
35 | func (r *BeeResource) DeleteDoc() string {
36 | return "delete a bee"
37 | }
38 |
39 | // DeleteParams returns the parameters supported by this API endpoint
40 | func (r *BeeResource) DeleteParams() []*restful.Parameter {
41 | return nil
42 | }
43 |
44 | // Delete processes an incoming DELETE request
45 | func (r *BeeResource) Delete(context smolder.APIContext, request *restful.Request, response *restful.Response) {
46 | resp := BeeResponse{}
47 | resp.Init(context)
48 |
49 | id := request.PathParameter("bee-id")
50 | bee := bees.GetBee(id)
51 | if bee == nil {
52 | r.NotFound(request, response)
53 | return
54 | }
55 |
56 | go func() {
57 | bees.DeleteBee(bee)
58 | }()
59 |
60 | resp.Send(response)
61 | }
62 |
--------------------------------------------------------------------------------
/api/resources/bees/bees_get.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package bees
22 |
23 | import (
24 | "github.com/muesli/beehive/bees"
25 |
26 | "github.com/emicklei/go-restful"
27 | "github.com/muesli/smolder"
28 | )
29 |
30 | // GetAuthRequired returns true because all requests need authentication
31 | func (r *BeeResource) GetAuthRequired() bool {
32 | return false
33 | }
34 |
35 | // GetByIDsAuthRequired returns true because all requests need authentication
36 | func (r *BeeResource) GetByIDsAuthRequired() bool {
37 | return false
38 | }
39 |
40 | // GetDoc returns the description of this API endpoint
41 | func (r *BeeResource) GetDoc() string {
42 | return "retrieve bees"
43 | }
44 |
45 | // GetParams returns the parameters supported by this API endpoint
46 | func (r *BeeResource) GetParams() []*restful.Parameter {
47 | params := []*restful.Parameter{}
48 | // params = append(params, restful.QueryParameter("user_id", "id of a user").DataType("int64"))
49 |
50 | return params
51 | }
52 |
53 | // GetByIDs sends out all items matching a set of IDs
54 | func (r *BeeResource) GetByIDs(ctx smolder.APIContext, request *restful.Request, response *restful.Response, ids []string) {
55 | resp := BeeResponse{}
56 | resp.Init(ctx)
57 |
58 | for _, id := range ids {
59 | bee := bees.GetBee(id)
60 | if bee == nil {
61 | r.NotFound(request, response)
62 | return
63 | }
64 |
65 | resp.AddBee(bee)
66 | }
67 |
68 | resp.Send(response)
69 | }
70 |
71 | // Get sends out items matching the query parameters
72 | func (r *BeeResource) Get(ctx smolder.APIContext, request *restful.Request, response *restful.Response, params map[string][]string) {
73 | // ctxapi := ctx.(*context.APIContext)
74 | bees := bees.GetBees()
75 | resp := BeeResponse{}
76 | resp.Init(ctx)
77 |
78 | for _, bee := range bees {
79 | resp.AddBee(bee)
80 | }
81 |
82 | resp.Send(response)
83 | }
84 |
--------------------------------------------------------------------------------
/api/resources/bees/bees_post.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package bees
22 |
23 | import (
24 | "github.com/emicklei/go-restful"
25 | "github.com/muesli/beehive/bees"
26 | "github.com/muesli/smolder"
27 | )
28 |
29 | // BeePostStruct holds all values of an incoming POST request
30 | type BeePostStruct struct {
31 | Bee struct {
32 | Name string `json:"name"`
33 | Namespace string `json:"namespace"`
34 | Description string `json:"description"`
35 | Active bool `json:"active"`
36 | Options bees.BeeOptions `json:"options"`
37 | } `json:"bee"`
38 | }
39 |
40 | // PostAuthRequired returns true because all requests need authentication
41 | func (r *BeeResource) PostAuthRequired() bool {
42 | return false
43 | }
44 |
45 | // PostDoc returns the description of this API endpoint
46 | func (r *BeeResource) PostDoc() string {
47 | return "create a new bee"
48 | }
49 |
50 | // PostParams returns the parameters supported by this API endpoint
51 | func (r *BeeResource) PostParams() []*restful.Parameter {
52 | return nil
53 | }
54 |
55 | // Post processes an incoming POST (create) request
56 | func (r *BeeResource) Post(context smolder.APIContext, data interface{}, request *restful.Request, response *restful.Response) {
57 | resp := BeeResponse{}
58 | resp.Init(context)
59 |
60 | pps := data.(*BeePostStruct)
61 | c, err := bees.NewBeeConfig(pps.Bee.Name, pps.Bee.Namespace, pps.Bee.Description, pps.Bee.Options)
62 | if err != nil {
63 | smolder.ErrorResponseHandler(request, response, err, smolder.NewErrorResponse(
64 | 422, // Go 1.7+: http.StatusUnprocessableEntity,
65 | err,
66 | "BeeResource POST"))
67 | return
68 | }
69 |
70 | bee := bees.StartBee(c)
71 | resp.AddBee(bee)
72 |
73 | resp.Send(response)
74 | }
75 |
--------------------------------------------------------------------------------
/api/resources/bees/bees_put.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package bees
22 |
23 | import (
24 | "github.com/emicklei/go-restful"
25 | "github.com/muesli/beehive/bees"
26 | "github.com/muesli/smolder"
27 | )
28 |
29 | // PutAuthRequired returns true because all requests need authentication
30 | func (r *BeeResource) PutAuthRequired() bool {
31 | return false
32 | }
33 |
34 | // PutDoc returns the description of this API endpoint
35 | func (r *BeeResource) PutDoc() string {
36 | return "update an existing bee"
37 | }
38 |
39 | // PutParams returns the parameters supported by this API endpoint
40 | func (r *BeeResource) PutParams() []*restful.Parameter {
41 | return nil
42 | }
43 |
44 | // Put processes an incoming PUT (update) request
45 | func (r *BeeResource) Put(context smolder.APIContext, data interface{}, request *restful.Request, response *restful.Response) {
46 | resp := BeeResponse{}
47 | resp.Init(context)
48 |
49 | pps := data.(*BeePostStruct)
50 | id := request.PathParameter("bee-id")
51 | bee := bees.GetBee(id)
52 | if bee == nil {
53 | r.NotFound(request, response)
54 | return
55 | }
56 |
57 | (*bee).SetDescription(pps.Bee.Description)
58 | (*bee).ReloadOptions(pps.Bee.Options)
59 |
60 | if pps.Bee.Active {
61 | bees.RestartBee(bee)
62 | } else {
63 | (*bee).Stop()
64 | }
65 |
66 | resp.AddBee(bee)
67 | resp.Send(response)
68 | }
69 |
--------------------------------------------------------------------------------
/api/resources/chains/chains.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package chains
22 |
23 | import (
24 | "github.com/emicklei/go-restful"
25 | "github.com/muesli/smolder"
26 | )
27 |
28 | // ChainResource is the resource responsible for /chains
29 | type ChainResource struct {
30 | smolder.Resource
31 | }
32 |
33 | var (
34 | _ smolder.GetIDSupported = &ChainResource{}
35 | _ smolder.GetSupported = &ChainResource{}
36 | _ smolder.PostSupported = &ChainResource{}
37 | _ smolder.DeleteSupported = &ChainResource{}
38 | )
39 |
40 | // Register this resource with the container to setup all the routes
41 | func (r *ChainResource) Register(container *restful.Container, config smolder.APIConfig, context smolder.APIContextFactory) {
42 | r.Name = "ChainResource"
43 | r.TypeName = "chain"
44 | r.Endpoint = "chains"
45 | r.Doc = "Manage chains"
46 |
47 | r.Config = config
48 | r.Context = context
49 |
50 | r.Init(container, r)
51 | }
52 |
53 | // Reads returns the model that will be read by POST, PUT & PATCH operations
54 | func (r *ChainResource) Reads() interface{} {
55 | return &ChainPostStruct{}
56 | }
57 |
58 | // Returns returns the model that will be returned
59 | func (r *ChainResource) Returns() interface{} {
60 | return ChainResponse{}
61 | }
62 |
63 | // Validate checks an incoming request for data errors
64 | func (r *ChainResource) Validate(context smolder.APIContext, data interface{}, request *restful.Request) error {
65 | // ps := data.(*ChainPostStruct)
66 | // FIXME
67 | return nil
68 | }
69 |
--------------------------------------------------------------------------------
/api/resources/chains/chains_delete.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package chains
22 |
23 | import (
24 | "github.com/emicklei/go-restful"
25 | "github.com/muesli/beehive/bees"
26 | "github.com/muesli/smolder"
27 | )
28 |
29 | // DeleteAuthRequired returns true because all requests need authentication
30 | func (r *ChainResource) DeleteAuthRequired() bool {
31 | return false
32 | }
33 |
34 | // DeleteDoc returns the description of this API endpoint
35 | func (r *ChainResource) DeleteDoc() string {
36 | return "delete a chain"
37 | }
38 |
39 | // DeleteParams returns the parameters supported by this API endpoint
40 | func (r *ChainResource) DeleteParams() []*restful.Parameter {
41 | return nil
42 | }
43 |
44 | // Delete processes an incoming DELETE request
45 | func (r *ChainResource) Delete(context smolder.APIContext, request *restful.Request, response *restful.Response) {
46 | resp := ChainResponse{}
47 | resp.Init(context)
48 |
49 | id := request.PathParameter("chain-id")
50 |
51 | found := false
52 | chains := []bees.Chain{}
53 | for _, v := range bees.GetChains() {
54 | if v.Name == id {
55 | found = true
56 | } else {
57 | chains = append(chains, v)
58 | }
59 | }
60 |
61 | if found {
62 | bees.SetChains(chains)
63 | resp.Send(response)
64 | } else {
65 | r.NotFound(request, response)
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/api/resources/chains/chains_get.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package chains
22 |
23 | import (
24 | "github.com/muesli/beehive/bees"
25 |
26 | "github.com/emicklei/go-restful"
27 | "github.com/muesli/smolder"
28 | )
29 |
30 | // GetAuthRequired returns true because all requests need authentication
31 | func (r *ChainResource) GetAuthRequired() bool {
32 | return false
33 | }
34 |
35 | // GetByIDsAuthRequired returns true because all requests need authentication
36 | func (r *ChainResource) GetByIDsAuthRequired() bool {
37 | return false
38 | }
39 |
40 | // GetDoc returns the description of this API endpoint
41 | func (r *ChainResource) GetDoc() string {
42 | return "retrieve chains"
43 | }
44 |
45 | // GetParams returns the parameters supported by this API endpoint
46 | func (r *ChainResource) GetParams() []*restful.Parameter {
47 | params := []*restful.Parameter{}
48 | // params = append(params, restful.QueryParameter("user_id", "id of a user").DataType("int64"))
49 |
50 | return params
51 | }
52 |
53 | // GetByIDs sends out all items matching a set of IDs
54 | func (r *ChainResource) GetByIDs(ctx smolder.APIContext, request *restful.Request, response *restful.Response, ids []string) {
55 | resp := ChainResponse{}
56 | resp.Init(ctx)
57 |
58 | for _, id := range ids {
59 | chain := bees.GetChain(id)
60 | if chain == nil {
61 | r.NotFound(request, response)
62 | return
63 | }
64 |
65 | resp.AddChain(*chain)
66 | }
67 |
68 | resp.Send(response)
69 | }
70 |
71 | // Get sends out items matching the query parameters
72 | func (r *ChainResource) Get(ctx smolder.APIContext, request *restful.Request, response *restful.Response, params map[string][]string) {
73 | // ctxapi := ctx.(*context.APIContext)
74 | chains := bees.GetChains()
75 | resp := ChainResponse{}
76 | resp.Init(ctx)
77 |
78 | for _, chain := range chains {
79 | resp.AddChain(chain)
80 | }
81 |
82 | resp.Send(response)
83 | }
84 |
--------------------------------------------------------------------------------
/api/resources/chains/chains_post.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package chains
22 |
23 | import (
24 | "errors"
25 |
26 | "github.com/emicklei/go-restful"
27 | "github.com/muesli/beehive/bees"
28 | "github.com/muesli/smolder"
29 | )
30 |
31 | // ChainPostStruct holds all values of an incoming POST request
32 | type ChainPostStruct struct {
33 | Chain struct {
34 | Name string `json:"name"`
35 | Description string `json:"description"`
36 | Event bees.Event `json:"event"`
37 | Filters []string `json:"filters"`
38 | Actions []string `json:"actions"`
39 | } `json:"chain"`
40 | }
41 |
42 | // PostAuthRequired returns true because all requests need authentication
43 | func (r *ChainResource) PostAuthRequired() bool {
44 | return false
45 | }
46 |
47 | // PostDoc returns the description of this API endpoint
48 | func (r *ChainResource) PostDoc() string {
49 | return "create a new chain"
50 | }
51 |
52 | // PostParams returns the parameters supported by this API endpoint
53 | func (r *ChainResource) PostParams() []*restful.Parameter {
54 | return nil
55 | }
56 |
57 | // Post processes an incoming POST (create) request
58 | func (r *ChainResource) Post(context smolder.APIContext, data interface{}, request *restful.Request, response *restful.Response) {
59 | resp := ChainResponse{}
60 | resp.Init(context)
61 |
62 | pps := data.(*ChainPostStruct)
63 | dupe := bees.GetChain(pps.Chain.Name)
64 | if dupe != nil {
65 | smolder.ErrorResponseHandler(request, response, nil, smolder.NewErrorResponse(
66 | 422, // Go 1.7+: http.StatusUnprocessableEntity,
67 | errors.New("A Chain with that name exists already"),
68 | "ChainResource POST"))
69 | return
70 | }
71 |
72 | chain := bees.Chain{
73 | Name: pps.Chain.Name,
74 | Description: pps.Chain.Description,
75 | Event: &pps.Chain.Event,
76 | Actions: pps.Chain.Actions,
77 | Filters: pps.Chain.Filters,
78 | }
79 | chains := append(bees.GetChains(), chain)
80 | bees.SetChains(chains)
81 |
82 | resp.AddChain(chain)
83 | resp.Send(response)
84 | }
85 |
--------------------------------------------------------------------------------
/api/resources/chains/chains_response.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package chains
22 |
23 | import (
24 | "sort"
25 |
26 | restful "github.com/emicklei/go-restful"
27 | "github.com/muesli/beehive/bees"
28 |
29 | "github.com/muesli/smolder"
30 | )
31 |
32 | // ChainResponse is the common response to 'chain' requests
33 | type ChainResponse struct {
34 | smolder.Response
35 |
36 | Chains []chainInfoResponse `json:"chains,omitempty"`
37 | chains map[string]*bees.Chain
38 | }
39 |
40 | type chainInfoResponse struct {
41 | ID string `json:"id"`
42 | Name string `json:"name"`
43 | Description string `json:"description"`
44 | Event *bees.Event `json:"event"`
45 | Filters []string `json:"filters,omitempty"`
46 | Actions []string `json:"actions"`
47 | }
48 |
49 | // Init a new response
50 | func (r *ChainResponse) Init(context smolder.APIContext) {
51 | r.Parent = r
52 | r.Context = context
53 |
54 | r.chains = make(map[string]*bees.Chain)
55 | }
56 |
57 | // AddChain adds a chain to the response
58 | func (r *ChainResponse) AddChain(chain bees.Chain) {
59 | r.chains[chain.Name] = &chain
60 | }
61 |
62 | // Send responds to a request with http.StatusOK
63 | func (r *ChainResponse) Send(response *restful.Response) {
64 | var keys []string
65 | for k := range r.chains {
66 | keys = append(keys, k)
67 | }
68 | sort.Strings(keys)
69 |
70 | for _, k := range keys {
71 | r.Chains = append(r.Chains, prepareChainResponse(r.Context, r.chains[k]))
72 | }
73 |
74 | r.Response.Send(response)
75 | }
76 |
77 | // EmptyResponse returns an empty API response for this endpoint if there's no data to respond with
78 | func (r *ChainResponse) EmptyResponse() interface{} {
79 | if len(r.chains) == 0 {
80 | var out struct {
81 | Chains interface{} `json:"chains"`
82 | }
83 | out.Chains = []chainInfoResponse{}
84 | return out
85 | }
86 | return nil
87 | }
88 |
89 | func prepareChainResponse(context smolder.APIContext, chain *bees.Chain) chainInfoResponse {
90 | // ctx := context.(*context.APIContext)
91 | resp := chainInfoResponse{
92 | ID: (*chain).Name,
93 | Name: (*chain).Name,
94 | Description: (*chain).Description,
95 | Event: (*chain).Event,
96 | Actions: (*chain).Actions,
97 | Filters: (*chain).Filters,
98 | }
99 |
100 | return resp
101 | }
102 |
--------------------------------------------------------------------------------
/api/resources/hives/hives.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package hives
22 |
23 | import (
24 | "github.com/emicklei/go-restful"
25 | "github.com/muesli/smolder"
26 | )
27 |
28 | // HiveResource is the resource responsible for /hives
29 | type HiveResource struct {
30 | smolder.Resource
31 | }
32 |
33 | var (
34 | _ smolder.GetIDSupported = &HiveResource{}
35 | _ smolder.GetSupported = &HiveResource{}
36 | )
37 |
38 | // Register this resource with the container to setup all the routes
39 | func (r *HiveResource) Register(container *restful.Container, config smolder.APIConfig, context smolder.APIContextFactory) {
40 | r.Name = "HiveResource"
41 | r.TypeName = "hive"
42 | r.Endpoint = "hives"
43 | r.Doc = "Manage hives"
44 |
45 | r.Config = config
46 | r.Context = context
47 |
48 | r.Init(container, r)
49 | }
50 |
51 | // Returns returns the model that will be returned
52 | func (r *HiveResource) Returns() interface{} {
53 | return HiveResponse{}
54 | }
55 |
--------------------------------------------------------------------------------
/api/resources/hives/hives_get.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package hives
22 |
23 | import (
24 | "github.com/muesli/beehive/bees"
25 |
26 | "github.com/emicklei/go-restful"
27 | "github.com/muesli/smolder"
28 | )
29 |
30 | // GetAuthRequired returns true because all requests need authentication
31 | func (r *HiveResource) GetAuthRequired() bool {
32 | return false
33 | }
34 |
35 | // GetByIDsAuthRequired returns true because all requests need authentication
36 | func (r *HiveResource) GetByIDsAuthRequired() bool {
37 | return false
38 | }
39 |
40 | // GetDoc returns the description of this API endpoint
41 | func (r *HiveResource) GetDoc() string {
42 | return "retrieve hives"
43 | }
44 |
45 | // GetParams returns the parameters supported by this API endpoint
46 | func (r *HiveResource) GetParams() []*restful.Parameter {
47 | params := []*restful.Parameter{}
48 | // params = append(params, restful.QueryParameter("user_id", "id of a user").DataType("int64"))
49 |
50 | return params
51 | }
52 |
53 | // GetByIDs sends out all items matching a set of IDs
54 | func (r *HiveResource) GetByIDs(ctx smolder.APIContext, request *restful.Request, response *restful.Response, ids []string) {
55 | resp := HiveResponse{}
56 | resp.Init(ctx)
57 |
58 | for _, id := range ids {
59 | hive := bees.GetFactory(id)
60 | if hive == nil {
61 | r.NotFound(request, response)
62 | return
63 | }
64 |
65 | resp.AddHive(hive)
66 | }
67 |
68 | resp.Send(response)
69 | }
70 |
71 | // Get sends out items matching the query parameters
72 | func (r *HiveResource) Get(ctx smolder.APIContext, request *restful.Request, response *restful.Response, params map[string][]string) {
73 | // ctxapi := ctx.(*context.APIContext)
74 | hives := bees.GetFactories()
75 | if len(hives) == 0 { // err != nil {
76 | r.NotFound(request, response)
77 | return
78 | }
79 |
80 | resp := HiveResponse{}
81 | resp.Init(ctx)
82 |
83 | for _, hive := range hives {
84 | resp.AddHive(hive)
85 | }
86 |
87 | resp.Send(response)
88 | }
89 |
--------------------------------------------------------------------------------
/api/resources/logs/logs.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017-2019 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package logs
22 |
23 | import (
24 | "github.com/emicklei/go-restful"
25 | "github.com/muesli/smolder"
26 | )
27 |
28 | // LogResource is the resource responsible for /logs
29 | type LogResource struct {
30 | smolder.Resource
31 | }
32 |
33 | var (
34 | // _ smolder.GetIDSupported = &LogResource{}
35 | _ smolder.GetSupported = &LogResource{}
36 | )
37 |
38 | // Register this resource with the container to setup all the routes
39 | func (r *LogResource) Register(container *restful.Container, config smolder.APIConfig, context smolder.APIContextFactory) {
40 | r.Name = "LogResource"
41 | r.TypeName = "log"
42 | r.Endpoint = "logs"
43 | r.Doc = "Manage logs"
44 |
45 | r.Config = config
46 | r.Context = context
47 |
48 | r.Init(container, r)
49 | }
50 |
51 | // Returns returns the model that will be returned
52 | func (r *LogResource) Returns() interface{} {
53 | return LogResponse{}
54 | }
55 |
--------------------------------------------------------------------------------
/api/resources/logs/logs_get.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017-2019 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package logs
22 |
23 | import (
24 | "github.com/muesli/beehive/bees"
25 |
26 | "github.com/emicklei/go-restful"
27 | "github.com/muesli/smolder"
28 | )
29 |
30 | // GetAuthRequired returns true because all requests need authentication
31 | func (r *LogResource) GetAuthRequired() bool {
32 | return false
33 | }
34 |
35 | // GetByIDsAuthRequired returns true because all requests need authentication
36 | func (r *LogResource) GetByIDsAuthRequired() bool {
37 | return false
38 | }
39 |
40 | // GetDoc returns the description of this API endpoint
41 | func (r *LogResource) GetDoc() string {
42 | return "retrieve logs"
43 | }
44 |
45 | // GetParams returns the parameters supported by this API endpoint
46 | func (r *LogResource) GetParams() []*restful.Parameter {
47 | params := []*restful.Parameter{}
48 | params = append(params, restful.QueryParameter("bee", "id of a bee").DataType("string"))
49 |
50 | return params
51 | }
52 |
53 | // GetByIDs sends out all items matching a set of IDs
54 | /*
55 | func (r *LogResource) GetByIDs(ctx smolder.APIContext, request *restful.Request, response *restful.Response, ids []string) {
56 | resp := LogResponse{}
57 | resp.Init(ctx)
58 |
59 | resp.Send(response)
60 | }
61 | */
62 |
63 | // Get sends out items matching the query parameters
64 | func (r *LogResource) Get(ctx smolder.APIContext, request *restful.Request, response *restful.Response, params map[string][]string) {
65 | // ctxapi := ctx.(*context.APIContext)
66 | bee := request.QueryParameter("bee")
67 |
68 | resp := LogResponse{}
69 | resp.Init(ctx)
70 |
71 | logs := bees.GetLogs(bee)
72 | for _, log := range logs {
73 | resp.AddLog(&log)
74 | }
75 |
76 | resp.Send(response)
77 | }
78 |
--------------------------------------------------------------------------------
/api/resources/logs/logs_response.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2015-2019 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package logs
22 |
23 | import (
24 | "time"
25 |
26 | "github.com/muesli/beehive/bees"
27 |
28 | "github.com/muesli/smolder"
29 | )
30 |
31 | // LogResponse is the common response to 'log' requests
32 | type LogResponse struct {
33 | smolder.Response
34 |
35 | Logs []logInfoResponse `json:"logs,omitempty"`
36 | logs []*bees.LogMessage
37 | }
38 |
39 | type logInfoResponse struct {
40 | ID string `json:"id"`
41 | Bee string `json:"bee"`
42 | Level int64 `json:"level"`
43 | Message string `json:"message"`
44 | Timestamp time.Time `json:"timestamp"`
45 | }
46 |
47 | // Init a new response
48 | func (r *LogResponse) Init(context smolder.APIContext) {
49 | r.Parent = r
50 | r.Context = context
51 |
52 | r.Logs = []logInfoResponse{}
53 | }
54 |
55 | // AddLog adds a log to the response
56 | func (r *LogResponse) AddLog(log *bees.LogMessage) {
57 | r.logs = append(r.logs, log)
58 | r.Logs = append(r.Logs, prepareLogResponse(r.Context, log))
59 | }
60 |
61 | // EmptyResponse returns an empty API response for this endpoint if there's no data to respond with
62 | func (r *LogResponse) EmptyResponse() interface{} {
63 | if len(r.logs) == 0 {
64 | var out struct {
65 | Logs interface{} `json:"logs"`
66 | }
67 | out.Logs = []logInfoResponse{}
68 | return out
69 | }
70 | return nil
71 | }
72 |
73 | func prepareLogResponse(context smolder.APIContext, log *bees.LogMessage) logInfoResponse {
74 | // ctx := context.(*context.APIContext)
75 | resp := logInfoResponse{
76 | ID: (*log).ID,
77 | Bee: (*log).Bee,
78 | Level: int64((*log).MessageType),
79 | Message: (*log).Message,
80 | Timestamp: (*log).Timestamp,
81 | }
82 |
83 | return resp
84 | }
85 |
--------------------------------------------------------------------------------
/app/app.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | // Package app is Beehive's application container. Handles command-line arguments parsing.
22 | package app
23 |
24 | import (
25 | "flag"
26 | )
27 |
28 | // A CliFlag can be added by Beehive modules to map a command-line parameter
29 | // to a local variable
30 | type CliFlag struct {
31 | V interface{}
32 | Name string
33 | Value interface{}
34 | Desc string
35 | }
36 |
37 | var (
38 | appflags []CliFlag
39 | )
40 |
41 | // AddFlags adds CliFlags to appflags
42 | func AddFlags(flags []CliFlag) {
43 | for _, flag := range flags {
44 | appflags = append(appflags, flag)
45 | }
46 | }
47 |
48 | // Run sets up all the cli-param mappings
49 | func Run() {
50 | for _, f := range appflags {
51 | switch f.Value.(type) {
52 | case string:
53 | flag.StringVar((f.V).(*string), f.Name, f.Value.(string), f.Desc)
54 | case bool:
55 | flag.BoolVar((f.V).(*bool), f.Name, f.Value.(bool), f.Desc)
56 | }
57 | }
58 |
59 | flag.Parse()
60 | }
61 |
--------------------------------------------------------------------------------
/assets/bees/alertoverbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/alertoverbee.png
--------------------------------------------------------------------------------
/assets/bees/anelpowerctrlbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/anelpowerctrlbee.png
--------------------------------------------------------------------------------
/assets/bees/cfddns.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/cfddns.png
--------------------------------------------------------------------------------
/assets/bees/cleverbotbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/cleverbotbee.png
--------------------------------------------------------------------------------
/assets/bees/cricketbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/cricketbee.png
--------------------------------------------------------------------------------
/assets/bees/cronbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/cronbee.png
--------------------------------------------------------------------------------
/assets/bees/devrantbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/devrantbee.png
--------------------------------------------------------------------------------
/assets/bees/discordbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/discordbee.png
--------------------------------------------------------------------------------
/assets/bees/efabee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/efabee.png
--------------------------------------------------------------------------------
/assets/bees/emailbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/emailbee.png
--------------------------------------------------------------------------------
/assets/bees/emailserverbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/emailserverbee.png
--------------------------------------------------------------------------------
/assets/bees/execbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/execbee.png
--------------------------------------------------------------------------------
/assets/bees/facebookbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/facebookbee.png
--------------------------------------------------------------------------------
/assets/bees/fsnotifybee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/fsnotifybee.png
--------------------------------------------------------------------------------
/assets/bees/githubbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/githubbee.png
--------------------------------------------------------------------------------
/assets/bees/gitterbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/gitterbee.png
--------------------------------------------------------------------------------
/assets/bees/gotifybee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/gotifybee.png
--------------------------------------------------------------------------------
/assets/bees/horizonboxbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/horizonboxbee.png
--------------------------------------------------------------------------------
/assets/bees/htmlextractbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/htmlextractbee.png
--------------------------------------------------------------------------------
/assets/bees/huebee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/huebee.png
--------------------------------------------------------------------------------
/assets/bees/instapaperbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/instapaperbee.png
--------------------------------------------------------------------------------
/assets/bees/ipify.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/ipify.png
--------------------------------------------------------------------------------
/assets/bees/ircbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/ircbee.png
--------------------------------------------------------------------------------
/assets/bees/jabberbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/jabberbee.png
--------------------------------------------------------------------------------
/assets/bees/jenkinsbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/jenkinsbee.png
--------------------------------------------------------------------------------
/assets/bees/jirabee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/jirabee.png
--------------------------------------------------------------------------------
/assets/bees/mastodonbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/mastodonbee.png
--------------------------------------------------------------------------------
/assets/bees/mixcloudbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/mixcloudbee.png
--------------------------------------------------------------------------------
/assets/bees/mumblebee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/mumblebee.png
--------------------------------------------------------------------------------
/assets/bees/nagiosbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/nagiosbee.png
--------------------------------------------------------------------------------
/assets/bees/notificationbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/notificationbee.png
--------------------------------------------------------------------------------
/assets/bees/openweathermapbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/openweathermapbee.png
--------------------------------------------------------------------------------
/assets/bees/pastebinbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/pastebinbee.png
--------------------------------------------------------------------------------
/assets/bees/prometheusbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/prometheusbee.png
--------------------------------------------------------------------------------
/assets/bees/pushoverbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/pushoverbee.png
--------------------------------------------------------------------------------
/assets/bees/redis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/redis.png
--------------------------------------------------------------------------------
/assets/bees/rocketchatbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/rocketchatbee.png
--------------------------------------------------------------------------------
/assets/bees/rssbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/rssbee.png
--------------------------------------------------------------------------------
/assets/bees/s3bee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/s3bee.png
--------------------------------------------------------------------------------
/assets/bees/serialbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/serialbee.png
--------------------------------------------------------------------------------
/assets/bees/simplepushbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/simplepushbee.png
--------------------------------------------------------------------------------
/assets/bees/slackbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/slackbee.png
--------------------------------------------------------------------------------
/assets/bees/socketbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/socketbee.png
--------------------------------------------------------------------------------
/assets/bees/spaceapibee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/spaceapibee.png
--------------------------------------------------------------------------------
/assets/bees/sunbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/sunbee.png
--------------------------------------------------------------------------------
/assets/bees/telegrambee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/telegrambee.png
--------------------------------------------------------------------------------
/assets/bees/transmissionbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/transmissionbee.png
--------------------------------------------------------------------------------
/assets/bees/travisbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/travisbee.png
--------------------------------------------------------------------------------
/assets/bees/tumblrbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/tumblrbee.png
--------------------------------------------------------------------------------
/assets/bees/twiliobee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/twiliobee.png
--------------------------------------------------------------------------------
/assets/bees/twitchbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/twitchbee.png
--------------------------------------------------------------------------------
/assets/bees/twitterbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/twitterbee.png
--------------------------------------------------------------------------------
/assets/bees/webbee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/bees/webbee.png
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/logo.png
--------------------------------------------------------------------------------
/assets/logo_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/logo_128.png
--------------------------------------------------------------------------------
/assets/logo_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/logo_16.png
--------------------------------------------------------------------------------
/assets/logo_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/logo_256.png
--------------------------------------------------------------------------------
/assets/logo_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/logo_32.png
--------------------------------------------------------------------------------
/assets/logo_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/logo_512.png
--------------------------------------------------------------------------------
/assets/logo_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/assets/logo_64.png
--------------------------------------------------------------------------------
/bees/alertoverbee/README.md:
--------------------------------------------------------------------------------
1 | # AlertOverbee
2 |
3 | This bee can push notification to your iOS or Android device or extension in Chrome as an action to some event.
4 |
5 | You can get your **SOURCE-KEY** and **RECEIVER-KEY** from: https://www.alertover.com/pages/api
6 |
7 | ## APP
8 |
9 | * [iOS APP](https://itunes.apple.com/cn/app/alertover-gao-xiao-mian-fei/id1069760182?l=en&mt=8)
10 | * [Android APP](http://www.wandoujia.com/apps/com.alertover.app)
11 | * [Chrome extension](https://chrome.google.com/webstore/detail/alertover/cgcgodonijnlgljfdbiicdccnldpdgia?hl=zh-CN)
12 |
13 | ## Configuration
14 |
15 | The SOURCE-KEY, RECEIVER-KEY and message content are mandatory. If the message's title is empty, it would be replaced by AlertOver.
16 |
17 | The priority of the message is option, 0 for normal and 1 for emergency, 0 and 1 is string.
18 |
19 | ### Options
20 | ```json
21 | "Bees": [
22 | {
23 | "Name": "alertover example",
24 | "Class": "alertoverbee",
25 | "Description": "This is example of alertoverbee",
26 | "Options": [
27 | {
28 | "Name": "source",
29 | "Value": "SOURCE-KEY"
30 | }
31 | ]
32 | },
33 | ]
34 | ```
35 |
36 | ### Actions
37 |
38 | ```json
39 | "Actions": [
40 | {
41 | "Bee": "alertover example",
42 | "Name": "send",
43 | "Options": [
44 | {
45 | "Name": "receiver",
46 | "Type": "string",
47 | "Value": "RECEIVER-KEY"
48 | },
49 | {
50 | "Name": "title",
51 | "Type": "string",
52 | "Value": ""
53 | },
54 | {
55 | "Name": "content",
56 | "Type": "string",
57 | "Value": ""
58 | },
59 | {
60 | "Name": "url",
61 | "Type": "string",
62 | "Value": ""
63 | },
64 | {
65 | "Name": "priority",
66 | "Type": "string",
67 | "Value": ""
68 | }
69 | ]
70 | },
71 | ]
72 | ```
--------------------------------------------------------------------------------
/bees/alertoverbee/alertoverbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Henson Lu
3 | * 2015-2017 Christian Muehlhaeuser
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Affero General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Affero General Public License
16 | * along with this program. If not, see .
17 | *
18 | * Authors:
19 | * Henson Lu
20 | * Christian Muehlhaeuser
21 | */
22 |
23 | // Package alertoverbee is able to send notifications on AlertOver.
24 | package alertoverbee
25 |
26 | import (
27 | "net/http"
28 | "net/url"
29 | "regexp"
30 |
31 | "github.com/muesli/beehive/bees"
32 | )
33 |
34 | // AlertOverBee is a Bee that is able to send notifications on AlertOver.
35 | type AlertOverBee struct {
36 | bees.Bee
37 | source string
38 | }
39 |
40 | // Action triggers the action passed to it.
41 | func (mod *AlertOverBee) Action(action bees.Action) []bees.Placeholder {
42 | outs := []bees.Placeholder{}
43 |
44 | switch action.Name {
45 | case "send":
46 | var receiver, title, content, weburl, priority string
47 | action.Options.Bind("receiver", &receiver)
48 | action.Options.Bind("title", &title)
49 | action.Options.Bind("content", &content)
50 | action.Options.Bind("url", &weburl)
51 | action.Options.Bind("priority", &priority)
52 |
53 | if priority == "" {
54 | priority = "0"
55 | }
56 |
57 | // the message must be plain text, so
58 | // remove the HTML tags, such as and so on
59 | re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
60 | content = re.ReplaceAllString(content, "\n")
61 |
62 | data := url.Values{
63 | "source": {mod.source},
64 | "receiver": {receiver},
65 | "title": {title},
66 | "content": {content},
67 | "url": {weburl},
68 | "priority": {priority},
69 | }
70 | resp, err := http.PostForm("https://api.alertover.com/v1/alert", data)
71 | if err != nil {
72 | panic(err)
73 | }
74 | defer resp.Body.Close()
75 | if resp.StatusCode == 200 {
76 | mod.Logln("AlertOver send message success.")
77 | }
78 |
79 | default:
80 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
81 | }
82 |
83 | return outs
84 | }
85 |
86 | // ReloadOptions parses the config options and initializes the Bee.
87 | func (mod *AlertOverBee) ReloadOptions(options bees.BeeOptions) {
88 | mod.SetOptions(options)
89 | options.Bind("source", &mod.source)
90 | }
91 |
--------------------------------------------------------------------------------
/bees/anelpowerctrlbee/anelpowerctrlbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | // Package anelpowerctrlbee is a Bee for talking to Anel's PowerCtrl network
22 | // power sockets.
23 | package anelpowerctrlbee
24 |
25 | import (
26 | "net"
27 | "strconv"
28 | "time"
29 |
30 | "github.com/muesli/beehive/bees"
31 | )
32 |
33 | // AnelPowerCtrlBee is a Bee for talking to Anel's PowerCtrl network power
34 | // sockets.
35 | type AnelPowerCtrlBee struct {
36 | bees.Bee
37 |
38 | addr string
39 | user string
40 | password string
41 | }
42 |
43 | func (mod *AnelPowerCtrlBee) anelSwitch(socket int, state bool) bool {
44 | conn, err := net.ListenUDP("udp", &net.UDPAddr{Port: 0})
45 | if err != nil {
46 | mod.LogFatal(err)
47 | }
48 | conn.SetDeadline(time.Now().Add(3 * time.Second))
49 |
50 | addr, err := net.ResolveUDPAddr("udp", mod.addr+":75")
51 | if err != nil {
52 | mod.LogFatal(err)
53 | }
54 |
55 | stateToken := "off"
56 | if state {
57 | stateToken = "on"
58 | }
59 | b := "Sw_" + stateToken + strconv.Itoa(socket) + mod.user + mod.password
60 |
61 | _, err = conn.WriteToUDP([]byte(b), addr)
62 | if err != nil {
63 | mod.LogFatal(err)
64 | }
65 |
66 | return true
67 | }
68 |
69 | // Action triggers the action passed to it.
70 | func (mod *AnelPowerCtrlBee) Action(action bees.Action) []bees.Placeholder {
71 | outs := []bees.Placeholder{}
72 |
73 | switch action.Name {
74 | case "switch":
75 | socket := 0
76 | state := false
77 | action.Options.Bind("socket", &socket)
78 | action.Options.Bind("state", &state)
79 |
80 | mod.anelSwitch(socket, state)
81 |
82 | default:
83 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
84 | }
85 |
86 | return outs
87 | }
88 |
89 | // ReloadOptions parses the config options and initializes the Bee.
90 | func (mod *AnelPowerCtrlBee) ReloadOptions(options bees.BeeOptions) {
91 | mod.SetOptions(options)
92 |
93 | options.Bind("address", &mod.addr)
94 | options.Bind("user", &mod.user)
95 | options.Bind("password", &mod.password)
96 | }
97 |
--------------------------------------------------------------------------------
/bees/cfddnsbee/README.md:
--------------------------------------------------------------------------------
1 | # CFDDNS Bee
2 |
3 | Updates a Cloudflare domain name record with the given IP.
4 |
5 | See https://api.cloudflare.com/#getting-started-endpoints
6 |
7 | ## Configuration
8 |
9 | * email: Cloudflare user email
10 | * key: Cloudflare API key
11 | * domain: Domain name record to update
12 |
13 | ## Ideas
14 |
15 | * Use it in combination with the ipify bee to update a Cloudflare domain every time your public IP changes.
16 |
17 | ## Credits
18 |
19 | Cloudflare logo: https://www.cloudflare.com/logo/
20 |
--------------------------------------------------------------------------------
/bees/cfddnsbee/cfddnsbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 Sergio Rubio
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Sergio Rubio
19 | */
20 |
21 | package cfddns
22 |
23 | import (
24 | "regexp"
25 |
26 | "github.com/cloudflare/cloudflare-go"
27 | "github.com/muesli/beehive/bees"
28 | )
29 |
30 | var domainSplitter = regexp.MustCompile(".+\\.(.+\\..+)")
31 |
32 | // CFDDNSBee updates a Cloudflare domain name
33 | type CFDDNSBee struct {
34 | bees.Bee
35 | client *cloudflare.API
36 | domain string
37 | }
38 |
39 | // Run executes the Bee's event loop.
40 | func (mod *CFDDNSBee) Run(eventChan chan bees.Event) {
41 | }
42 |
43 | // Action triggers the action passed to it.
44 | func (mod *CFDDNSBee) Action(action bees.Action) []bees.Placeholder {
45 | outs := []bees.Placeholder{}
46 |
47 | switch action.Name {
48 | case "update_domain":
49 | address := action.Options.Value("address").(string)
50 | domain := mod.domain
51 | zoneName := domainSplitter.FindStringSubmatch(domain)[1]
52 | // Resolve the zone and record id for the host
53 | zone, err := mod.client.ZoneIDByName(zoneName)
54 | if err != nil {
55 | mod.LogErrorf("zone id resolution failed: %v", err)
56 | return outs
57 | }
58 | recs, err := mod.client.DNSRecords(zone, cloudflare.DNSRecord{Name: domain, Type: "A"})
59 | if err != nil {
60 | mod.LogErrorf("record id resolution failed: %v", err)
61 | return outs
62 | }
63 | if len(recs) != 1 {
64 | mod.LogErrorf("invalid number of DNS records found: %+v", recs)
65 | return outs
66 | }
67 | record := recs[0]
68 |
69 | // Post the Cloudflare dns update
70 | record.Content = address
71 |
72 | if err := mod.client.UpdateDNSRecord(zone, record.ID, record); err != nil {
73 | mod.LogErrorf("dns record update for %s failed: %v", domain, err)
74 | }
75 | default:
76 | mod.LogDebugf("Unknown action triggered in %s: %s", mod.Name(), action.Name)
77 | }
78 |
79 | return outs
80 | }
81 |
82 | // ReloadOptions parses the config options and initializes the Bee.
83 | func (mod *CFDDNSBee) ReloadOptions(options bees.BeeOptions) {
84 | mod.SetOptions(options)
85 | key := options.Value("key").(string)
86 | user := options.Value("email").(string)
87 | mod.domain = options.Value("domain").(string)
88 | c, err := cloudflare.New(key, user)
89 | if err != nil {
90 | mod.LogFatal(err)
91 | }
92 | mod.client = c
93 | }
94 |
--------------------------------------------------------------------------------
/bees/cleverbotbee/README.md:
--------------------------------------------------------------------------------
1 | # Cleverbotbee
2 |
3 | CleverbotBee is a simple bee chatting with cleverbot.
4 | You can send messages to the bot as action and you'll receive the answer as an
5 | event.
6 |
7 | ---
8 |
9 | You'll need an cleverbot api account containing username and key to access the
10 | cleverbot api. You can grab one [here](https://cleverbot.io/keys)
11 |
12 |
--------------------------------------------------------------------------------
/bees/cleverbotbee/cleverbotbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | * Nicolas Martin
20 | */
21 |
22 | // Package cleverbotbee is a Bee that can interact with cleverbot
23 | package cleverbotbee
24 |
25 | import (
26 | "github.com/CleverbotIO/go-cleverbot.io"
27 | "github.com/muesli/beehive/bees"
28 | )
29 |
30 | // CleverbotBee is a Bee that can chat with cleverbot
31 | type CleverbotBee struct {
32 | bees.Bee
33 |
34 | client *cleverbot.Session
35 |
36 | api_user string
37 | api_key string
38 | session_nick string
39 |
40 | evchan chan bees.Event
41 | }
42 |
43 | // Action triggers the action passed to it.
44 | func (mod *CleverbotBee) Action(action bees.Action) []bees.Placeholder {
45 | outs := []bees.Placeholder{}
46 |
47 | switch action.Name {
48 | case "send_message":
49 | var text string
50 | action.Options.Bind("text", &text)
51 |
52 | resp, err := mod.client.Ask(text)
53 | if err != nil {
54 | mod.LogErrorf("Failed to ask cleverbot: %v", err)
55 | return nil
56 | }
57 |
58 | ev := bees.Event{
59 | Bee: mod.Name(),
60 | Name: "answer",
61 | Options: []bees.Placeholder{
62 | {
63 | Name: "answer",
64 | Type: "string",
65 | Value: resp,
66 | },
67 | },
68 | }
69 | mod.evchan <- ev
70 |
71 | default:
72 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
73 | }
74 |
75 | return outs
76 | }
77 |
78 | // Run executes the Bee's event loop.
79 | func (mod *CleverbotBee) Run(eventChan chan bees.Event) {
80 | mod.evchan = eventChan
81 |
82 | client, err := cleverbot.New(mod.api_user, mod.api_key, mod.session_nick)
83 | if err != nil {
84 | mod.LogErrorf("Failed to start session: %v", err)
85 | return
86 | }
87 | mod.client = client
88 |
89 | select {
90 | case <-mod.SigChan:
91 | return
92 | }
93 | }
94 |
95 | // ReloadOptions parses the config options and initializes the Bee.
96 | func (mod *CleverbotBee) ReloadOptions(options bees.BeeOptions) {
97 | mod.SetOptions(options)
98 |
99 | options.Bind("api_user", &mod.api_user)
100 | options.Bind("api_key", &mod.api_key)
101 | options.Bind("session_nick", &mod.session_nick)
102 | }
103 |
--------------------------------------------------------------------------------
/bees/config.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | // Package bees is Beehive's central module system.
22 | package bees
23 |
24 | import "errors"
25 |
26 | // BeeConfig contains all settings for a single Bee.
27 | type BeeConfig struct {
28 | Name string
29 | Class string
30 | Description string
31 | Options BeeOptions
32 | }
33 |
34 | // NewBeeConfig validates a configuration and sets up a new BeeConfig
35 | func NewBeeConfig(name, class, description string, options BeeOptions) (BeeConfig, error) {
36 | if len(name) == 0 {
37 | return BeeConfig{}, errors.New("A Bee's name can't be empty")
38 | }
39 |
40 | b := GetBee(name)
41 | if b != nil {
42 | return BeeConfig{}, errors.New("A Bee with that name already exists")
43 | }
44 |
45 | f := GetFactory(class)
46 | if f == nil {
47 | return BeeConfig{}, errors.New("Invalid class specified")
48 | }
49 |
50 | return BeeConfig{
51 | Name: name,
52 | Class: class,
53 | Description: description,
54 | Options: options,
55 | }, nil
56 | }
57 |
58 | // BeeConfigs returns configs for all Bees.
59 | func BeeConfigs() []BeeConfig {
60 | bs := []BeeConfig{}
61 | for _, b := range bees {
62 | bs = append(bs, (*b).Config())
63 | }
64 |
65 | return bs
66 | }
67 |
--------------------------------------------------------------------------------
/bees/context.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | // Package bees is Beehive's central module system.
22 | package bees
23 |
24 | var (
25 | ctx = NewContext()
26 | )
27 |
28 | type Context struct {
29 | state map[*Bee]map[string]interface{}
30 | }
31 |
32 | func NewContext() *Context {
33 | return &Context{
34 | state: make(map[*Bee]map[string]interface{}),
35 | }
36 | }
37 |
38 | func (c *Context) Set(bee *Bee, key string, value interface{}) {
39 | if _, ok := c.state[bee]; !ok {
40 | c.state[bee] = make(map[string]interface{})
41 | }
42 | c.state[bee][key] = value
43 | }
44 |
45 | func (c *Context) Value(bee *Bee, key string) interface{} {
46 | return c.state[bee][key]
47 | }
48 |
49 | func (c *Context) FillMap(m map[string]interface{}) {
50 | cd := make(map[string]interface{})
51 | for bee, d := range c.state {
52 | cd[bee.Name()] = d
53 | }
54 | m["context"] = cd
55 | }
56 |
57 | func (bee *Bee) ContextSet(key string, value interface{}) {
58 | ctx.Set(bee, key, value)
59 | }
60 |
61 | func (bee *Bee) ContextValue(key string) interface{} {
62 | return ctx.Value(bee, key)
63 | }
64 |
--------------------------------------------------------------------------------
/bees/cricketbee/README.md:
--------------------------------------------------------------------------------
1 | ### Options
2 |
3 | Accepted favourite team value
4 | 1. Ind (India)
5 | 2. WI (West Indies)
6 | 3. Eng (England)
7 | 4. Aus (Australia)
8 | 5. Pak (Pakistan)
9 | 6. Sri (Srilanka)
10 | 7. Ban (Bangladesh)
11 |
12 | ### Events
13 | 1. Run change
14 | 2. Over change
15 | 3. Wicket fall
16 |
--------------------------------------------------------------------------------
/bees/cricketbee/cricketbee.go:
--------------------------------------------------------------------------------
1 | package cricketbee
2 |
3 | /*
4 | * Copyright (C) 2017 Akash Shinde
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published
8 | * by the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | *
19 | * Authors:
20 | * Akash Shinde
21 | */
22 |
23 | import (
24 | "github.com/akashshinde/go_cricket"
25 | "github.com/muesli/beehive/bees"
26 | )
27 |
28 | type CricketBee struct {
29 | bees.Bee
30 | favTeam string
31 | event chan gocricket.ResponseEvent
32 | beeEvt chan bees.Event
33 | }
34 |
35 | func (c *CricketBee) placeholderOptions(r gocricket.ResponseEvent) []bees.Placeholder {
36 | return []bees.Placeholder{
37 | {
38 | Name: "batting_team",
39 | Type: "string",
40 | Value: r.BtTeamName,
41 | },
42 | {
43 | Name: "score",
44 | Type: "string",
45 | Value: r.Runs,
46 | },
47 | {
48 | Name: "wickets",
49 | Type: "string",
50 | Value: r.Wickets,
51 | },
52 | {
53 | Name: "overs",
54 | Type: "string",
55 | Value: r.Overs,
56 | },
57 | }
58 | }
59 |
60 | func (c *CricketBee) announceCricketEvent(response gocricket.ResponseEvent) {
61 | switch response.EventType {
62 | case gocricket.EVENT_OUT:
63 | c.beeEvt <- bees.Event{
64 | Name: "out",
65 | Options: c.placeholderOptions(response),
66 | Bee: c.Name(),
67 | }
68 | case gocricket.EVENT_OVER_CHANGED:
69 | c.beeEvt <- bees.Event{
70 | Name: "over_changed",
71 | Options: c.placeholderOptions(response),
72 | Bee: c.Name(),
73 | }
74 | case gocricket.EVENT_RUN_CHANGE:
75 | c.beeEvt <- bees.Event{
76 | Name: "run_change",
77 | Options: c.placeholderOptions(response),
78 | Bee: c.Name(),
79 | }
80 | }
81 | }
82 |
83 | func (c *CricketBee) Run(cin chan bees.Event) {
84 | evt := make(chan gocricket.ResponseEvent)
85 | // Start Cricket GoRoutine to poll cricket score
86 | cricket := gocricket.NewCricketWatcher(c.favTeam, evt)
87 | cricket.Start()
88 | c.beeEvt = cin
89 | for {
90 | select {
91 | case e := <-evt:
92 | c.announceCricketEvent(e)
93 |
94 | case <-c.SigChan:
95 | return
96 | }
97 | }
98 | }
99 |
100 | // ReloadOptions parses the config options and initializes the Bee.
101 | func (mod *CricketBee) ReloadOptions(options bees.BeeOptions) {
102 | mod.SetOptions(options)
103 | options.Bind("favourite_team", &mod.favTeam)
104 | }
105 |
--------------------------------------------------------------------------------
/bees/cronbee/cronbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Stefan 'glaxx' Luecke
3 | * 2014-2017 Christian Muehlhaeuser
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Affero General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Affero General Public License
16 | * along with this program. If not, see .
17 | *
18 | * Authors:
19 | * Stefan Luecke
20 | * Christian Muehlhaeuser
21 | */
22 |
23 | // Package cronbee is a Bee that acts like a time-based job scheduler (cron).
24 | package cronbee
25 |
26 | import (
27 | "strings"
28 | "time"
29 |
30 | "github.com/muesli/beehive/bees"
31 | "github.com/robfig/cron/v3"
32 | )
33 |
34 | // CronBee is a Bee that acts like a time-based job scheduler (cron).
35 | type CronBee struct {
36 | bees.Bee
37 | input [6]string
38 | eventChan chan bees.Event
39 | }
40 |
41 | func (mod *CronBee) runTask() {
42 | mod.LogDebugf("Running cron task " + strings.Join(mod.input[:], " "))
43 | event := bees.Event{
44 | Bee: mod.Name(),
45 | Name: "time",
46 | Options: []bees.Placeholder{
47 | {
48 | Name: "timestamp",
49 | Type: "string",
50 | Value: time.Now().Format(time.RFC3339),
51 | },
52 | },
53 | }
54 | mod.eventChan <- event
55 | }
56 |
57 | // Run executes the Bee's event loop.
58 | func (mod *CronBee) Run(eventChan chan bees.Event) {
59 | mod.eventChan = eventChan
60 | c := cron.New(cron.WithSeconds())
61 | mod.LogDebugf("Scheduling " + strings.Join(mod.input[:], " "))
62 | _, err := c.AddFunc(strings.Join(mod.input[:], " "), mod.runTask)
63 | if err != nil {
64 | mod.LogFatal(err)
65 | }
66 | c.Start()
67 |
68 | for {
69 | select {
70 | case <-mod.SigChan:
71 | return
72 | }
73 | }
74 | }
75 |
76 | // ReloadOptions parses the config options and initializes the Bee.
77 | func (mod *CronBee) ReloadOptions(options bees.BeeOptions) {
78 | mod.SetOptions(options)
79 |
80 | options.Bind("second", &mod.input[0])
81 | options.Bind("minute", &mod.input[1])
82 | options.Bind("hour", &mod.input[2])
83 | options.Bind("day_of_week", &mod.input[3])
84 | options.Bind("day_of_month", &mod.input[4])
85 | options.Bind("month", &mod.input[5])
86 | }
87 |
--------------------------------------------------------------------------------
/bees/cronbee/thoughts.txt:
--------------------------------------------------------------------------------
1 | 30 0 1 1,6,12 *
2 |
3 | 0 20 * 10 1-5
4 |
5 | 0 0 1,10,15 * *
6 |
7 | 5,10 0 10 * 1
8 |
9 |
10 |
11 |
12 | now: 25.07
13 |
14 | {
15 | months: 1,6,12
16 | days: 1
17 | =
18 | created next timestamp: 01.12
19 | }
20 |
21 | {
22 | months: 10
23 | days: *
24 | hour: 20
25 | minute: 0
26 |
27 | created next timestamp: 01.10 20:00
28 | }
29 |
30 |
31 |
32 | now: 10.07 16:30
33 |
34 | {
35 | months: *
36 | days: 1,10,15
37 | hour: 0
38 | minute: 0
39 |
40 | created next timestamp: 15.07 00:00
41 | }
42 |
43 |
44 | nextValidMonth(now = 7, input = "*") int {
45 | if input == "*" || now == input
46 | return now
47 |
48 | // 5 - 8 => 7
49 | // 5 - 6 => 5
50 | }
51 |
52 |
53 | // expected: 2015.07.01 17:00
54 | nextValidTimestamp(now = 2014.07.31 18:30, input = "0 17 * 7") {
55 | created := "0000.00.00 00:00"
56 |
57 | created.Month := nextValidMonth(07, "7") // -> 7
58 | created.Day := nextValidDay(25, "1") // -> 31
59 | created.Hour := nextValidHour(18, "17") // -> 17
60 |
61 | // 2014.07.31 17:00
62 | if created < now {
63 | created.Day = nextValidDay(31 + 1, "*") // -> 1
64 | // 2014.07.01 17:00
65 | if created < now {
66 | created.Month = nextValidMonth(7 + 1, "7") // -> 7
67 | // 2014.07.01 17:00
68 | if created < now {
69 | created.Year++
70 | // 2015.07.01 17:00
71 | }
72 | }
73 | }
74 | }
75 |
76 | created next timestamp - now() => duration until next event
77 |
--------------------------------------------------------------------------------
/bees/descriptors.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | // Package bees is Beehive's central module system.
22 | package bees
23 |
24 | // EventDescriptor describes an Event provided by a Bee.
25 | type EventDescriptor struct {
26 | Namespace string
27 | Name string
28 | Description string
29 | Options []PlaceholderDescriptor
30 | }
31 |
32 | // ActionDescriptor describes an Action provided by a Bee.
33 | type ActionDescriptor struct {
34 | Namespace string
35 | Name string
36 | Description string
37 | Options []PlaceholderDescriptor
38 | }
39 |
40 | // A PlaceholderDescriptor shows which in & out values a module expects and returns.
41 | type PlaceholderDescriptor struct {
42 | Name string
43 | Description string
44 | Type string
45 | Mandatory bool
46 | }
47 |
48 | // A BeeOptionDescriptor shows which config values a module expects.
49 | type BeeOptionDescriptor struct {
50 | Name string
51 | Description string
52 | Type string
53 | Default interface{}
54 | Mandatory bool
55 | }
56 |
57 | // StateDescriptor describes a State provided by a Bee.
58 | type StateDescriptor struct {
59 | Name string
60 | Description string
61 | Type string
62 | }
63 |
64 | // GetActionDescriptor returns the ActionDescriptor matching an action.
65 | func GetActionDescriptor(action *Action) ActionDescriptor {
66 | bee := GetBee(action.Bee)
67 | if bee == nil {
68 | panic("Bee " + action.Bee + " not registered")
69 | }
70 | factory := (*GetFactory((*bee).Namespace()))
71 | for _, ac := range factory.Actions() {
72 | if ac.Name == action.Name {
73 | return ac
74 | }
75 | }
76 |
77 | return ActionDescriptor{}
78 | }
79 |
80 | // GetEventDescriptor returns the EventDescriptor matching an event.
81 | func GetEventDescriptor(event *Event) EventDescriptor {
82 | bee := GetBee(event.Bee)
83 | if bee == nil {
84 | panic("Bee " + event.Bee + " not registered")
85 | }
86 | factory := (*GetFactory((*bee).Namespace()))
87 | for _, ev := range factory.Events() {
88 | if ev.Name == event.Name {
89 | return ev
90 | }
91 | }
92 |
93 | return EventDescriptor{}
94 | }
95 |
--------------------------------------------------------------------------------
/bees/emailbee/emailbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | // Package emailbee is a Bee that is able to send emails.
22 | package emailbee
23 |
24 | import (
25 | "net"
26 |
27 | "strconv"
28 |
29 | "github.com/go-mail/mail"
30 | "github.com/muesli/beehive/bees"
31 | )
32 |
33 | // EmailBee is a Bee that is able to send emails.
34 | type EmailBee struct {
35 | bees.Bee
36 |
37 | username string
38 | password string
39 | server string
40 | }
41 |
42 | // Action triggers the action passed to it.
43 | func (mod *EmailBee) Action(action bees.Action) []bees.Placeholder {
44 | outs := []bees.Placeholder{}
45 |
46 | switch action.Name {
47 | case "send":
48 | var from, to, plainText, htmlText, subject string
49 | action.Options.Bind("sender", &from)
50 | action.Options.Bind("recipient", &to)
51 | action.Options.Bind("subject", &subject)
52 | action.Options.Bind("text", &plainText)
53 | action.Options.Bind("html", &htmlText)
54 |
55 | m := mail.NewMessage()
56 | if len(from) > 0 {
57 | m.SetHeader("From", from)
58 | } else {
59 | m.SetHeader("From", mod.username)
60 | }
61 | m.SetHeader("To", to)
62 | m.SetHeader("Subject", subject)
63 | if plainText != "" {
64 | m.SetBody("text/plain", plainText)
65 | }
66 | if htmlText != "" {
67 | m.SetBody("text/html", htmlText)
68 | }
69 |
70 | host, portstr, err := net.SplitHostPort(mod.server)
71 | if err != nil {
72 | host = mod.server
73 | portstr = "587"
74 | }
75 | port, _ := strconv.Atoi(portstr)
76 |
77 | if len(mod.username) > 0 && len(mod.password) > 0 {
78 | // With authentication
79 | if err := mail.NewDialer(host, port, mod.username, mod.password).DialAndSend(m); err != nil {
80 | panic(err)
81 | }
82 | } else {
83 | // No Auth
84 | d := mail.Dialer{Host: host, Port: port}
85 | if err := d.DialAndSend(m); err != nil {
86 | panic(err)
87 | }
88 | }
89 |
90 | default:
91 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
92 | }
93 |
94 | return outs
95 | }
96 |
97 | // ReloadOptions parses the config options and initializes the Bee.
98 | func (mod *EmailBee) ReloadOptions(options bees.BeeOptions) {
99 | mod.SetOptions(options)
100 |
101 | options.Bind("username", &mod.username)
102 | options.Bind("password", &mod.password)
103 | options.Bind("address", &mod.server)
104 | }
105 |
--------------------------------------------------------------------------------
/bees/events.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | // Package bees is Beehive's central module system.
22 | package bees
23 |
24 | import (
25 | "fmt"
26 | "runtime/debug"
27 |
28 | log "github.com/sirupsen/logrus"
29 | )
30 |
31 | // An Event describes an event including its parameters.
32 | type Event struct {
33 | Bee string
34 | Name string
35 | Options Placeholders
36 | }
37 |
38 | var (
39 | eventsIn = make(chan Event)
40 | )
41 |
42 | // handleEvents handles incoming events and executes matching Chains.
43 | func handleEvents() {
44 | for {
45 | event, ok := <-eventsIn
46 | if !ok {
47 | log.Println()
48 | log.Println("Stopped event handler!")
49 | break
50 | }
51 |
52 | bee := GetBee(event.Bee)
53 | (*bee).LogEvent()
54 |
55 | log.Debugln()
56 | log.Debugln("Event received:", event.Bee, "/", event.Name, "-", GetEventDescriptor(&event).Description)
57 | for _, v := range event.Options {
58 | vv := truncateString(fmt.Sprintln(v), 1000)
59 | log.Debugln("\tOptions:", vv)
60 | }
61 |
62 | go func() {
63 | defer func() {
64 | if e := recover(); e != nil {
65 | log.Printf("Fatal chain event: %s %s", e, debug.Stack())
66 | }
67 | }()
68 |
69 | execChains(&event)
70 | }()
71 | }
72 | }
73 |
74 | func truncateString(str string, num int) string {
75 | bnoden := str
76 | if len(str) > num {
77 | if num > 3 {
78 | num -= 3
79 | }
80 | bnoden = str[0:num] + "... (" + fmt.Sprint(len(str)-num) + " more characters)"
81 | }
82 | return bnoden
83 | }
84 |
--------------------------------------------------------------------------------
/bees/filters.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | // Package bees is Beehive's central module system.
22 | package bees
23 |
24 | import (
25 | log "github.com/sirupsen/logrus"
26 |
27 | "github.com/muesli/beehive/filters"
28 | )
29 |
30 | // Filter describes a user configured event filter.
31 | type Filter struct {
32 | ID string
33 | Name string
34 | Options FilterOption
35 | }
36 |
37 | // execFilter executes a filter. Returns whether the filter passed or not.
38 | func execFilter(filter string, opts map[string]interface{}) bool {
39 | f := *filters.GetFilter("template")
40 | log.Println("\tExecuting filter:", filter)
41 |
42 | defer func() {
43 | if e := recover(); e != nil {
44 | log.Println("Fatal filter event:", e)
45 | }
46 | }()
47 |
48 | return f.Passes(opts, filter)
49 | }
50 |
--------------------------------------------------------------------------------
/bees/fsnotifybee/README.md:
--------------------------------------------------------------------------------
1 | # FSNotify bee
2 |
3 | Monitors filesystem paths and sends events when files are created, removed or modified.
4 |
5 | ## Configuration
6 |
7 | * path: Path to monitor (file or directory).
8 |
9 | ## Events
10 |
11 | **fsevent**
12 |
13 | * type: the event type received (CREATE, REMOVE, RENAME, CHMOD).
14 | * path: filesystem path that triggered the event.
15 |
16 | ## Credits
17 |
18 | File manager logo: https://openclipart.org/detail/35329/tango-system-file-manager
19 |
--------------------------------------------------------------------------------
/bees/fsnotifybee/fsnotifybee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Sergio Rubio
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Sergio Rubio
19 | */
20 |
21 | package fsnotifybee
22 |
23 | import (
24 | "github.com/fsnotify/fsnotify"
25 | "github.com/muesli/beehive/bees"
26 | )
27 |
28 | type FSNotifyBee struct {
29 | bees.Bee
30 | }
31 |
32 | func (mod *FSNotifyBee) Run(eventChan chan bees.Event) {
33 | watcher, err := fsnotify.NewWatcher()
34 | if err != nil {
35 | mod.LogFatal("error: could not create the fswatcher:", err)
36 | }
37 | defer watcher.Close()
38 |
39 | path := mod.Options().Value("path").(string)
40 | mod.Logf("monitoring %s\n", path)
41 |
42 | err = watcher.Add(path)
43 | if err != nil {
44 | mod.LogErrorf("error: watching %s failed: %v", path, err)
45 | return
46 | }
47 | for {
48 | select {
49 | case <-mod.SigChan:
50 | return
51 | case event := <-watcher.Events:
52 | if event.Op != fsnotify.Write && event.Op != 0 {
53 | sendEvent(mod.Name(), event.Op.String(), event.Name, eventChan)
54 | }
55 | case <-watcher.Errors:
56 | }
57 | }
58 | }
59 |
60 | func (mod *FSNotifyBee) ReloadOptions(options bees.BeeOptions) {
61 | mod.SetOptions(options)
62 | }
63 |
64 | func sendEvent(bee, etype, path string, eventChan chan bees.Event) {
65 | event := bees.Event{
66 | Bee: bee,
67 | Name: "fsevent",
68 | Options: []bees.Placeholder{
69 | {
70 | Name: "type",
71 | Type: "string",
72 | Value: etype,
73 | },
74 | {
75 | Name: "path",
76 | Type: "string",
77 | Value: path,
78 | },
79 | },
80 | }
81 | eventChan <- event
82 | }
83 |
--------------------------------------------------------------------------------
/bees/gitterbee/README.md:
--------------------------------------------------------------------------------
1 | # Rooms
2 | A rooms name is always the the last part of the uri.
3 | For example: `the_beehive/Lobby`
4 |
--------------------------------------------------------------------------------
/bees/gotifybee/README.md:
--------------------------------------------------------------------------------
1 | # GotifyBee
2 |
3 | This bee can push notification to the specified gotify application as an action to some event.
4 |
5 | You can get your **TOKEN** for your specified gotify application by going to the **APPS** section of the gotify server instance
6 | and unhiding the token for your desired application.
7 |
8 | ## APP
9 |
10 | * [Android APP](https://play.google.com/store/apps/details?id=com.github.gotify&hl=en_US&gl=US)
11 | * [Chrome extension](https://chrome.google.com/webstore/detail/gotify-push/cbegkpikakpajcaoblfkeindhhikpfmd?hl=en)
12 |
13 | ## Configuration
14 |
15 | The **message** field is required. If the message's title is empty, it would be replaced by Gotify.
16 |
17 | The priority of the message is option.
18 |
19 | ### Options
20 | ```json
21 | "Bees": [
22 | {
23 | "Name": "gotify example",
24 | "Class": "gotify",
25 | "Description": "This is example of gotify",
26 | "Options": [
27 | {
28 | "Name": "token",
29 | "Value": "TOKEN"
30 | }
31 | ]
32 | },
33 | ]
34 | ```
35 |
36 | ### Actions
37 |
38 | ```json
39 | "Actions": [
40 | {
41 | "Bee": "gotify example",
42 | "Name": "send",
43 | "Options": [
44 | {
45 | "Name": "title",
46 | "Type": "string",
47 | "Value": ""
48 | },
49 | {
50 | "Name": "message",
51 | "Type": "string",
52 | "Value": ""
53 | },
54 | {
55 | "Name": "priority",
56 | "Type": "string",
57 | "Value": ""
58 | }
59 | ]
60 | },
61 | ]
62 | ```
--------------------------------------------------------------------------------
/bees/gotifybee/gotifybee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 deranjer
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * deranjer
19 | */
20 |
21 | // Package gotifybee is able to send notifications on Gotify.
22 | package gotifybee
23 |
24 | import (
25 | "net/http"
26 | "net/url"
27 | "regexp"
28 |
29 | "github.com/muesli/beehive/bees"
30 | )
31 |
32 | // GotifyBee is a Bee that is able to send notifications on Gotify.
33 | type GotifyBee struct {
34 | bees.Bee
35 | token string
36 | serverURL string
37 | }
38 |
39 | // Action triggers the action passed to it.
40 | func (mod *GotifyBee) Action(action bees.Action) []bees.Placeholder {
41 | outs := []bees.Placeholder{}
42 |
43 | switch action.Name {
44 | case "send":
45 | var title, message, priority string
46 | action.Options.Bind("title", &title)
47 | action.Options.Bind("message", &message)
48 | action.Options.Bind("priority", &priority)
49 |
50 | if priority == "" {
51 | priority = "0"
52 | }
53 | if title == "" {
54 | title = "Gotify"
55 | }
56 |
57 | // the message must be plain text, so
58 | // remove the HTML tags, such as and so on
59 | re, _ := regexp.Compile("\\<[\\S\\s]+?\\>")
60 | message = re.ReplaceAllString(message, "\n")
61 |
62 | data := url.Values{
63 | "title": {title},
64 | "message": {message},
65 | "priority": {priority},
66 | }
67 | // Build the URL for sending the message
68 | rawURL := mod.serverURL + "message?token=" + mod.token
69 | resp, err := http.PostForm(rawURL, data)
70 | if err != nil {
71 | panic(err)
72 | }
73 | defer resp.Body.Close()
74 | if resp.StatusCode == 200 {
75 | mod.Logln("Gotify send message success.")
76 | }
77 |
78 | default:
79 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
80 | }
81 |
82 | return outs
83 | }
84 |
85 | // ReloadOptions parses the config options and initializes the Bee.
86 | func (mod *GotifyBee) ReloadOptions(options bees.BeeOptions) {
87 | mod.SetOptions(options)
88 | options.Bind("token", &mod.token)
89 | options.Bind("serverURL", &mod.serverURL)
90 | }
91 |
--------------------------------------------------------------------------------
/bees/hellobee/hellobee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014 Michael Wendland
3 | * 2014-2017 Christian Muehlhaeuser
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Affero General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Affero General Public License
16 | * along with this program. If not, see .
17 | *
18 | * Authors:
19 | * Michael Wendland
20 | * Christian Muehlhaeuser
21 | */
22 |
23 | // Package hellobee is an example for a Bee skeleton, designed to help you get
24 | // started with writing your own Bees.
25 | package hellobee
26 |
27 | import (
28 | "github.com/muesli/beehive/bees"
29 | )
30 |
31 | // HelloBee is an example for a Bee skeleton, designed to help you get started
32 | // with writing your own Bees.
33 | type HelloBee struct {
34 | bees.Bee
35 | }
36 |
37 | // Run executes the Bee's event loop.
38 | func (mod *HelloBee) Run(eventChan chan bees.Event) {
39 | /* ev := bees.Event{
40 | Bee: mod.Name(),
41 | Name: "hello",
42 | Options: []bees.Placeholder{},
43 | }
44 |
45 | eventChan <- ev*/
46 | }
47 |
48 | // Action triggers the action passed to it.
49 | func (mod *HelloBee) Action(action bees.Action) []bees.Placeholder {
50 | return []bees.Placeholder{}
51 | }
52 |
53 | // ReloadOptions parses the config options and initializes the Bee.
54 | func (mod *HelloBee) ReloadOptions(options bees.BeeOptions) {
55 | mod.SetOptions(options)
56 | }
57 |
--------------------------------------------------------------------------------
/bees/hellobee/hellobeefactory.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package hellobee
22 |
23 | import (
24 | "github.com/muesli/beehive/bees"
25 | )
26 |
27 | // HelloBeeFactory is a factory for HelloBees.
28 | type HelloBeeFactory struct {
29 | bees.BeeFactory
30 | }
31 |
32 | // New returns a new Bee instance configured with the supplied options.
33 | func (factory *HelloBeeFactory) New(name, description string, options bees.BeeOptions) bees.BeeInterface {
34 | bee := HelloBee{
35 | Bee: bees.NewBee(name, factory.ID(), description, options),
36 | }
37 | bee.ReloadOptions(options)
38 |
39 | return &bee
40 | }
41 |
42 | // ID returns the ID of this Bee.
43 | func (factory *HelloBeeFactory) ID() string {
44 | return "hellobee"
45 | }
46 |
47 | // Name returns the name of this Bee.
48 | func (factory *HelloBeeFactory) Name() string {
49 | return "Hello"
50 | }
51 |
52 | // Description returns the description of this Bee.
53 | func (factory *HelloBeeFactory) Description() string {
54 | return "A 'Hello World' module for beehive"
55 | }
56 |
57 | func init() {
58 | f := HelloBeeFactory{}
59 | bees.RegisterFactory(&f)
60 | }
61 |
--------------------------------------------------------------------------------
/bees/instapaperbee/instapaperbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 Adam Petrovic
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Adam Petrovic
19 | */
20 |
21 | package instapaperbee
22 |
23 | import (
24 | "net/http"
25 | "net/url"
26 |
27 | "github.com/muesli/beehive/bees"
28 | )
29 |
30 | type InstapaperBee struct {
31 | bees.Bee
32 |
33 | username string
34 | password string
35 | }
36 |
37 | func (mod *InstapaperBee) Action(action bees.Action) []bees.Placeholder {
38 | switch action.Name {
39 | case "save":
40 | var title, page_url string
41 | action.Options.Bind("title", &title)
42 | action.Options.Bind("url", &page_url)
43 |
44 | msg := url.Values{}
45 | msg.Set("username", mod.username)
46 | msg.Set("password", mod.password)
47 | msg.Set("url", page_url)
48 |
49 | if title != "" {
50 | msg.Set("title", title)
51 | }
52 | mod.LogDebugf("Message: %s", msg)
53 | resp, err := http.PostForm("https://www.instapaper.com/api/add", msg)
54 | if err != nil {
55 | panic(err)
56 | }
57 | defer resp.Body.Close()
58 | if resp.StatusCode == 200 {
59 | mod.LogDebugf("Added article to instapaper.")
60 | }
61 | default:
62 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
63 | }
64 | return []bees.Placeholder{}
65 | }
66 |
67 | func (mod *InstapaperBee) ReloadOptions(options bees.BeeOptions) {
68 | mod.SetOptions(options)
69 | options.Bind("username", &mod.username)
70 | options.Bind("password", &mod.password)
71 | }
72 |
--------------------------------------------------------------------------------
/bees/instapaperbee/instapaperbeefactory.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 Adam Petrovic
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Adam Petrovic
19 | */
20 |
21 | package instapaperbee
22 |
23 | import "github.com/muesli/beehive/bees"
24 |
25 | type InstapaperBeeFactory struct {
26 | bees.BeeFactory
27 | }
28 |
29 | func (factory *InstapaperBeeFactory) New(name, description string, options bees.BeeOptions) bees.BeeInterface {
30 | bee := InstapaperBee{
31 | Bee: bees.NewBee(name, factory.ID(), description, options),
32 | }
33 | bee.ReloadOptions(options)
34 | return &bee
35 | }
36 |
37 | func (factory *InstapaperBeeFactory) ID() string {
38 | return "instapaperbee"
39 | }
40 |
41 | func (factory *InstapaperBeeFactory) Name() string {
42 | return "Instapaper"
43 | }
44 |
45 | func (factory *InstapaperBeeFactory) Description() string {
46 | return "Add to Instapaper"
47 | }
48 |
49 | func (factory *InstapaperBeeFactory) Image() string {
50 | return factory.ID() + ".png"
51 | }
52 |
53 | func (factory *InstapaperBeeFactory) LogoColor() string {
54 | return "#808080"
55 | }
56 |
57 | func (factory *InstapaperBeeFactory) Options() []bees.BeeOptionDescriptor {
58 | opts := []bees.BeeOptionDescriptor{
59 | {
60 | Name: "username",
61 | Description: "Instapaper Username / Email",
62 | Type: "string",
63 | Mandatory: true,
64 | },
65 | {
66 | Name: "password",
67 | Description: "Instapaper Password",
68 | Type: "string",
69 | Mandatory: true,
70 | },
71 | }
72 | return opts
73 | }
74 |
75 | func (factory *InstapaperBeeFactory) Actions() []bees.ActionDescriptor {
76 | actions := []bees.ActionDescriptor{
77 | {
78 | Namespace: factory.Name(),
79 | Name: "save",
80 | Description: "Saves a URL to Instapaper",
81 | Options: []bees.PlaceholderDescriptor{
82 | {
83 | Name: "title",
84 | Description: "Article title",
85 | Type: "string",
86 | Mandatory: false,
87 | },
88 | {
89 | Name: "url",
90 | Description: "Article URL",
91 | Type: "string",
92 | Mandatory: true,
93 | },
94 | },
95 | },
96 | }
97 | return actions
98 | }
99 |
100 | func init() {
101 | f := InstapaperBeeFactory{}
102 | bees.RegisterFactory(&f)
103 | }
104 |
--------------------------------------------------------------------------------
/bees/ipifybee/README.md:
--------------------------------------------------------------------------------
1 | # Ipify Bee
2 |
3 | Queries ipify.org for the public IP and sends an event if the IP changed.
4 |
5 | ## Configuration
6 |
7 | * interval: Interval (in seconds) between requests sent to ipify.org
8 |
9 | ## Credits
10 |
11 | ipify logo: https://github.com/rdegges/ipify-www/blob/master/static/images/globe.png
12 |
--------------------------------------------------------------------------------
/bees/ipifybee/ipifybee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 Sergio Rubio
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Sergio Rubio
19 | */
20 |
21 | package ipify
22 |
23 | import (
24 | "time"
25 |
26 | "github.com/muesli/beehive/bees"
27 | "github.com/rdegges/go-ipify"
28 | )
29 |
30 | type IpifyBee struct {
31 | bees.Bee
32 | interval int
33 | }
34 |
35 | func (mod *IpifyBee) getIP(oldIP string, eventChan chan bees.Event) string {
36 | ip, err := ipify.GetIp()
37 | if err != nil {
38 | ip, err = ipify.GetIp()
39 | if err != nil {
40 | panic(err)
41 | }
42 | }
43 |
44 | if oldIP != ip {
45 | ev := bees.Event{
46 | Bee: mod.Name(),
47 | Name: "ip",
48 | Options: []bees.Placeholder{
49 | {
50 | Name: "ip",
51 | Type: "string",
52 | Value: ip,
53 | },
54 | },
55 | }
56 | eventChan <- ev
57 | return ip
58 | }
59 |
60 | return oldIP
61 | }
62 |
63 | // Run executes the Bee's event loop.
64 | func (mod *IpifyBee) Run(eventChan chan bees.Event) {
65 | // protects us against a user setting the wrong value here
66 | if mod.interval < 1 {
67 | mod.interval = defaultUpdateInterval
68 | }
69 |
70 | oldIP := mod.getIP("", eventChan)
71 |
72 | for {
73 | select {
74 | case <-mod.SigChan:
75 | return
76 | case <-time.After(time.Duration(mod.interval) * time.Minute):
77 | mod.LogDebugf("Retrieving public IP from ipify.com")
78 | oldIP = mod.getIP(oldIP, eventChan)
79 | }
80 | }
81 | }
82 |
83 | // Action triggers the action passed to it.
84 | func (mod *IpifyBee) Action(action bees.Action) []bees.Placeholder {
85 | return []bees.Placeholder{}
86 | }
87 |
88 | // ReloadOptions parses the config options and initializes the Bee.
89 | func (mod *IpifyBee) ReloadOptions(options bees.BeeOptions) {
90 | mod.SetOptions(options)
91 | options.Bind("interval", &mod.interval)
92 | }
93 |
--------------------------------------------------------------------------------
/bees/ipifybee/ipifybeefactory.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 Sergio Rubio
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Sergio Rubio
19 | */
20 |
21 | package ipify
22 |
23 | import (
24 | "github.com/muesli/beehive/bees"
25 | )
26 |
27 | const defaultUpdateInterval int = 60
28 |
29 | // IpifyBeeFactory takes care of initializing IpifyBee
30 | type IpifyBeeFactory struct {
31 | bees.BeeFactory
32 | }
33 |
34 | // New returns a new Bee instance configured with the supplied options.
35 | func (factory *IpifyBeeFactory) New(name, description string, options bees.BeeOptions) bees.BeeInterface {
36 | bee := IpifyBee{
37 | Bee: bees.NewBee(name, factory.ID(), description, options),
38 | }
39 | bee.ReloadOptions(options)
40 |
41 | return &bee
42 | }
43 |
44 | // ID returns the ID of this Bee.
45 | func (factory *IpifyBeeFactory) ID() string {
46 | return "ipify"
47 | }
48 |
49 | // Name returns the name of this Bee.
50 | func (factory *IpifyBeeFactory) Name() string {
51 | return "ipify"
52 | }
53 |
54 | // Description returns the description of this Bee.
55 | func (factory *IpifyBeeFactory) Description() string {
56 | return "Monitor your public IP address via ipify.org and notify when the IP changes"
57 | }
58 |
59 | // Image returns the asset name of this Bee (in the assets/bees folder)
60 | func (factory *IpifyBeeFactory) Image() string {
61 | return factory.Name() + ".png"
62 | }
63 |
64 | // Events describes the available events provided by this Bee.
65 | func (factory *IpifyBeeFactory) Events() []bees.EventDescriptor {
66 | events := []bees.EventDescriptor{
67 | {
68 | Namespace: factory.Name(),
69 | Name: "ip",
70 | Description: "The public IP retrieved from ipify.org",
71 | Options: []bees.PlaceholderDescriptor{
72 | {
73 | Name: "ip",
74 | Description: "IP address string",
75 | Type: "string",
76 | },
77 | },
78 | },
79 | }
80 | return events
81 | }
82 |
83 | // Options returns the options available to configure this Bee.
84 | func (factory *IpifyBeeFactory) Options() []bees.BeeOptionDescriptor {
85 | opts := []bees.BeeOptionDescriptor{
86 | {
87 | Name: "interval",
88 | Description: "Interval in minutes to query ipify.org (60 minutes by default)",
89 | Type: "int",
90 | Default: defaultUpdateInterval,
91 | Mandatory: false,
92 | },
93 | }
94 | return opts
95 | }
96 |
97 | func init() {
98 | f := IpifyBeeFactory{}
99 | bees.RegisterFactory(&f)
100 | }
101 |
--------------------------------------------------------------------------------
/bees/ircbee/irctools/irctools.go:
--------------------------------------------------------------------------------
1 | // Package irctools is a collection of convenient IRC styling methods.
2 | package irctools
3 |
4 | /*
5 | func PostTobeehive(host string, channel string, val string) {
6 | addr, err := net.ResolveTCPAddr("tcp", host)
7 | if err != nil {
8 | fmt.Println("Error:", err)
9 | return
10 | }
11 |
12 | conn, err := net.DialTCP("tcp", nil, addr)
13 | if err != nil {
14 | fmt.Println("Error:", err)
15 | return
16 | }
17 | defer conn.Close()
18 |
19 | if len(channel) > 0 {
20 | val = channel + " " + val
21 | }
22 | _, err = conn.Write([]byte(val))
23 | if err != nil {
24 | fmt.Println("Error:", err)
25 | return
26 | }
27 |
28 | _, err = conn.Write([]byte("\n"))
29 | }
30 | */
31 |
32 | // Bold wraps val in bold styling tags.
33 | func Bold(val string) string {
34 | return "\x02" + val + "\x02"
35 | }
36 |
37 | // Colored wraps val in color styling tags.
38 | func Colored(val string, color string) string {
39 | // 00 white 01 black 02 blue (navy) 03 green 04 red 05 brown (maroon)
40 | // 06 purple 07 orange (olive) 08 yellow 09 light green (lime)
41 | // 10 teal (a green/blue cyan) 11 light cyan (cyan) (aqua) 12 light blue (royal)
42 | // 13 pink (light purple) (fuchsia) 14 grey 15 light grey (silver)
43 | c := "01"
44 | switch color {
45 | case "white":
46 | c = "00"
47 | case "black":
48 | c = "01"
49 | case "blue":
50 | c = "02"
51 | case "green":
52 | c = "03"
53 | case "red":
54 | c = "04"
55 | case "brown":
56 | c = "05"
57 | case "purple":
58 | c = "06"
59 | case "orange":
60 | c = "07"
61 | case "yellow":
62 | c = "08"
63 | case "lime":
64 | c = "09"
65 | case "teal":
66 | c = "10"
67 | case "cyan":
68 | c = "11"
69 | case "lightblue":
70 | c = "12"
71 | case "pink":
72 | c = "13"
73 | case "grey":
74 | c = "14"
75 | case "silver":
76 | c = "15"
77 | }
78 |
79 | return "\x03" + c + val + "\x03"
80 | }
81 |
--------------------------------------------------------------------------------
/bees/logs.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | // Package bees is Beehive's central module system.
22 | package bees
23 |
24 | import (
25 | "sort"
26 | "sync"
27 | "time"
28 | )
29 |
30 | // LogMessage stores a log message with its timestamp, type and originating Bee
31 | type LogMessage struct {
32 | ID string
33 | Bee string
34 | Message string
35 | MessageType uint
36 | Timestamp time.Time
37 | }
38 |
39 | var (
40 | logs = make(map[string][]LogMessage)
41 | logMutex sync.RWMutex
42 | )
43 |
44 | // MessageType defines the log level of the log entry we're dealing with
45 | type MessageType uint
46 |
47 | const (
48 | // LogInfo is for info-level log entries
49 | LogInfo MessageType = iota
50 |
51 | // LogError is for error-level log entries
52 | LogError MessageType = iota
53 |
54 | // LogFatal is for fatal-level log entries
55 | LogFatal MessageType = iota
56 |
57 | // LogDebug is for debug-level log entries
58 | LogDebug MessageType = iota
59 | )
60 |
61 | // LogSorter is used for sorting an array of LogMessages by their timestamp
62 | type LogSorter []LogMessage
63 |
64 | func (a LogSorter) Len() int { return len(a) }
65 | func (a LogSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
66 | func (a LogSorter) Less(i, j int) bool { return !a[i].Timestamp.Before(a[j].Timestamp) }
67 |
68 | // NewLogMessage returns a newly composed LogMessage
69 | func NewLogMessage(bee string, message string, messageType MessageType) LogMessage {
70 | return LogMessage{
71 | ID: UUID(),
72 | Bee: bee,
73 | Message: message,
74 | MessageType: uint(messageType),
75 | Timestamp: time.Now(),
76 | }
77 | }
78 |
79 | // Log adds a new LogMessage to the log
80 | func Log(bee string, message string, messageType MessageType) {
81 | logMutex.Lock()
82 | defer logMutex.Unlock()
83 |
84 | logs[bee] = append(logs[bee], NewLogMessage(bee, message, messageType))
85 | }
86 |
87 | // GetLogs returns all logs for a Bee.
88 | func GetLogs(bee string) []LogMessage {
89 | r := []LogMessage{}
90 |
91 | logMutex.RLock()
92 | for b, ls := range logs {
93 | if len(bee) == 0 || bee == b {
94 | for _, l := range ls {
95 | r = append(r, l)
96 | }
97 | }
98 | }
99 | logMutex.RUnlock()
100 |
101 | sort.Sort(LogSorter(r))
102 | return r
103 | }
104 |
--------------------------------------------------------------------------------
/bees/mastodonbee/README.md:
--------------------------------------------------------------------------------
1 | # Mastodonbee
2 |
3 | You'll need to register and authorize the 'beehive' application in mastodon in order to use the mastodonbee.
4 |
5 |
6 | You can use following code snippet:
7 |
8 | ```
9 | package main
10 |
11 | import (
12 | "context"
13 | "fmt"
14 | "log"
15 |
16 | "github.com/mattn/go-mastodon"
17 | )
18 |
19 | func main() {
20 | app, err := mastodon.RegisterApp(context.Background(), &mastodon.AppConfig{
21 | Server: "https://server.address", // Enter _your_ server address here
22 | ClientName: "", // Name for the client
23 | Scopes: "read write follow", // Permission scopes
24 | Website: "", // Optional
25 | })
26 | if err != nil {
27 | log.Fatal(err)
28 | }
29 | // Prints out the ClientID and ClientSecret which you'll need to configure
30 | // beehive propberly
31 | fmt.Printf("client-id : %s\n", app.ClientID)
32 | fmt.Printf("client-secret: %s\n", app.ClientSecret)
33 | }
34 | ```
--------------------------------------------------------------------------------
/bees/notificationbee/notificationbee.go:
--------------------------------------------------------------------------------
1 | // +build dragonfly freebsd linux netbsd openbsd solaris darwin
2 |
3 | /*
4 | * Copyright (C) 2014 Daniel 'grindhold' Brendle
5 | * 2014-2017 Christian Muehlhaeuser
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU Affero General Public License as published
9 | * by the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU Affero General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Affero General Public License
18 | * along with this program. If not, see .
19 | *
20 | * Authors:
21 | * Daniel 'grindhold' Brendle
22 | * Christian Muehlhaeuser
23 | */
24 |
25 | // Package notificationbee is a Bee that can trigger desktop notifications.
26 | package notificationbee
27 |
28 | import (
29 | "strings"
30 |
31 | "github.com/muesli/beehive/bees"
32 | )
33 |
34 | // Urgency level iota
35 | const (
36 | UrgencyLow = uint32(iota)
37 | UrgencyNormal
38 | UrgencyCritical
39 | )
40 |
41 | var (
42 | urgencyMap = map[string]uint32{
43 | "": UrgencyNormal,
44 | "normal": UrgencyNormal,
45 | "low": UrgencyLow,
46 | "critical": UrgencyCritical,
47 | }
48 | )
49 |
50 | // NotificationBee is a Bee that can trigger freedesktop.org DBus
51 | // notifications.
52 | type NotificationBee struct {
53 | bees.Bee
54 | }
55 |
56 | // Run executes the Bee's event loop.
57 | func (mod *NotificationBee) Run(cin chan bees.Event) {
58 | select {
59 | case <-mod.SigChan:
60 | return
61 | }
62 | }
63 |
64 | // Action triggers the action passed to it.
65 | func (mod *NotificationBee) Action(action bees.Action) []bees.Placeholder {
66 | outs := []bees.Placeholder{}
67 |
68 | switch action.Name {
69 | case "notify":
70 | text := ""
71 | u := ""
72 | urgency := UrgencyNormal
73 |
74 | action.Options.Bind("text", &text)
75 | action.Options.Bind("urgency", &u)
76 | text = strings.TrimSpace(text)
77 | urgency, _ = urgencyMap[u]
78 |
79 | if len(text) > 0 {
80 | mod.execAction(text, urgency)
81 | }
82 |
83 | default:
84 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
85 | }
86 | return outs
87 | }
88 |
89 | // ReloadOptions parses the config options and initializes the Bee.
90 | func (mod *NotificationBee) ReloadOptions(options bees.BeeOptions) {
91 | mod.SetOptions(options)
92 | }
93 |
--------------------------------------------------------------------------------
/bees/notificationbee/notificationbee_osx.go:
--------------------------------------------------------------------------------
1 | // +build darwin
2 |
3 | /*
4 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published
8 | * by the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | *
19 | * Authors:
20 | * Christian Muehlhaeuser
21 | */
22 |
23 | // Package notificationbee is a Bee that can trigger desktop notifications.
24 | package notificationbee
25 |
26 | import "github.com/deckarep/gosx-notifier"
27 |
28 | // Run executes the Bee's event loop.
29 | func (mod *NotificationBee) execAction(text string, urgency uint32) {
30 | note := gosxnotifier.NewNotification("Beehive")
31 | note.Title = text
32 | note.Push()
33 | }
34 |
--------------------------------------------------------------------------------
/bees/notificationbee/notificationbee_unix.go:
--------------------------------------------------------------------------------
1 | // +build dragonfly freebsd linux netbsd openbsd solaris
2 |
3 | /*
4 | * Copyright (C) 2014 Daniel 'grindhold' Brendle
5 | * 2014-2017 Christian Muehlhaeuser
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU Affero General Public License as published
9 | * by the Free Software Foundation, either version 3 of the License, or
10 | * (at your option) any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU Affero General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU Affero General Public License
18 | * along with this program. If not, see .
19 | *
20 | * Authors:
21 | * Daniel 'grindhold' Brendle
22 | * Christian Muehlhaeuser
23 | */
24 |
25 | // Package notificationbee is a Bee that can trigger desktop notifications.
26 | package notificationbee
27 |
28 | import (
29 | "fmt"
30 |
31 | dbus "github.com/guelfey/go.dbus"
32 | )
33 |
34 | // Run executes the Bee's event loop.
35 | func (mod *NotificationBee) execAction(text string, urgency uint32) {
36 | conn, err := dbus.SessionBus()
37 | if err != nil {
38 | panic(err)
39 | }
40 |
41 | notifier := conn.Object("org.freedesktop.Notifications", "/org/freedesktop/Notifications")
42 | call := notifier.Call("org.freedesktop.Notifications.Notify", 0, "", uint32(0),
43 | "", "Beehive", text, []string{},
44 | map[string]dbus.Variant{"urgency": dbus.MakeVariant(urgency)}, int32(5000))
45 |
46 | if call.Err != nil {
47 | mod.Logln("(" + fmt.Sprint(urgency) + ") Failed to print message: " + text)
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/bees/openweathermapbee/README.md:
--------------------------------------------------------------------------------
1 | # Openweathermapbee
2 |
3 | ## Available languages
4 | English - en, Russian - ru, Italian - it, Spanish - es (or sp), Ukrainian - uk (or ua), German - de, Portuguese - pt, Romanian - ro, Polish - pl, Finnish - fi, Dutch - nl, French - fr, Bulgarian - bg, Swedish - sv (or se), Chinese Traditional - zh_tw, Chinese Simplified - zh (or zh_cn), Turkish - tr, Croatian - hr, Catalan - ca
5 |
6 | ## Multiple Measurement Systems Available
7 | Fahrenheit (OpenWeatherMap API - imperial)
8 | Celcius (OpenWeatherMap API - metric)
9 | Kelvin (OpenWeatherMap API - internal)
10 |
11 | ---
12 |
13 | To use the OpenweatherMap API, you'll need to obtain an API key. Sign up [here](https://home.openweathermap.org/users/sign_up).
14 |
--------------------------------------------------------------------------------
/bees/openweathermapbee/openweathermapbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | * Nicolas Martin
20 | */
21 |
22 | // Package openweathermapbee is a Bee that can interact with cleverbot
23 | package openweathermapbee
24 |
25 | import (
26 | "github.com/muesli/beehive/bees"
27 |
28 | owm "github.com/briandowns/openweathermap"
29 | )
30 |
31 | // OpenweathermapBee is a Bee that can chat with cleverbot
32 | type OpenweathermapBee struct {
33 | bees.Bee
34 |
35 | current *owm.CurrentWeatherData
36 |
37 | unit string
38 | language string
39 | key string
40 |
41 | evchan chan bees.Event
42 | }
43 |
44 | // Action triggers the action passed to it.
45 | func (mod *OpenweathermapBee) Action(action bees.Action) []bees.Placeholder {
46 | outs := []bees.Placeholder{}
47 |
48 | switch action.Name {
49 | case "get_current_weather":
50 | var location string
51 | action.Options.Bind("location", &location)
52 |
53 | err := mod.current.CurrentByName(location)
54 | if err != nil {
55 | mod.LogErrorf("Failed to fetch weather: %v", err)
56 | return nil
57 | }
58 |
59 | mod.TriggerCurrentWeatherEvent()
60 |
61 | default:
62 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
63 | }
64 |
65 | return outs
66 | }
67 |
68 | // Run executes the Bee's event loop.
69 | func (mod *OpenweathermapBee) Run(eventChan chan bees.Event) {
70 | mod.evchan = eventChan
71 |
72 | current, err := owm.NewCurrent(mod.unit, mod.language, mod.key)
73 | if err != nil {
74 | mod.LogErrorf("Failed to create new current service: %v", err)
75 | return
76 | }
77 | mod.current = current
78 |
79 | select {
80 | case <-mod.SigChan:
81 | return
82 | }
83 | }
84 |
85 | // ReloadOptions parses the config options and initializes the Bee.
86 | func (mod *OpenweathermapBee) ReloadOptions(options bees.BeeOptions) {
87 | mod.SetOptions(options)
88 |
89 | options.Bind("unit", &mod.unit)
90 | options.Bind("language", &mod.language)
91 | options.Bind("key", &mod.key)
92 | }
93 |
--------------------------------------------------------------------------------
/bees/options.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | // Package bees is Beehive's central module system.
22 | package bees
23 |
24 | import "errors"
25 |
26 | // A FilterOption used by filters.
27 | type FilterOption struct {
28 | Name string
29 | Type string
30 | Inverse bool
31 | CaseInsensitive bool
32 | Trimmed bool
33 | Value interface{}
34 | }
35 |
36 | // BeeOptions is an array of BeeOption.
37 | type BeeOptions []BeeOption
38 |
39 | // A BeeOption is used to configure bees.
40 | type BeeOption struct {
41 | Name string
42 | Value interface{}
43 | }
44 |
45 | // Value retrieves a value from a BeeOptions slice.
46 | func (opts BeeOptions) Value(name string) interface{} {
47 | for _, opt := range opts {
48 | if opt.Name == name {
49 | return opt.Value
50 | }
51 | }
52 |
53 | return nil
54 | }
55 |
56 | // Bind a value from a BeeOptions slice.
57 | func (opts BeeOptions) Bind(name string, dst interface{}) error {
58 | v := opts.Value(name)
59 | if v == nil {
60 | return errors.New("Option with name " + name + " not found")
61 | }
62 |
63 | return ConvertValue(v, dst)
64 | }
65 |
--------------------------------------------------------------------------------
/bees/pastebinbee/README.md:
--------------------------------------------------------------------------------
1 | # Pastebinbee
2 |
3 | This bee can post some text on pastebin as an action to some event.
4 |
5 | You can get your **api developer key** from: http://pastebin.com/api
6 |
7 | ## Configuration
8 |
9 | Due to admin interface limitations here are available options
10 | for exposure and expiration of the paste:
11 | * exposure:
12 | * 0 - Public
13 | * 1 - Unlisted
14 | * 2 - Private
15 | * expire:
16 | * N - Never
17 | * 10M - 10 minutes
18 | * 1H - 1 hour
19 | * 1D - 1 day
20 | * 1W - 1 week
21 | * 2W - 2 weeks
22 | * 1M - 1 month
23 |
24 | ### Options
25 | ```json
26 | "Bees": [
27 | {
28 | "Name": "Pastebin example",
29 | "Class": "pastebinbee",
30 | "Description": "This is example of pastebinbee",
31 | "Options": [
32 | {
33 | "Name": "api_dev_key",
34 | "Value": "API_DEVELOPER_KEY"
35 | }
36 | ]
37 | },
38 | ]
39 | ```
40 |
41 | ### Actions
42 |
43 | ```json
44 | "Actions": [
45 | {
46 | "Bee": "Paste",
47 | "Name": "post",
48 | "Options": [
49 | {
50 | "Name": "title",
51 | "Type": "string",
52 | "Value": "beehive"
53 | },
54 | {
55 | "Name": "content",
56 | "Type": "string",
57 | "Value": "testing beehive passed!"
58 | },
59 | {
60 | "Name": "expire",
61 | "Type": "string",
62 | "Value": "1H"
63 | },
64 | {
65 | "Name": "exposure",
66 | "Type": "string",
67 | "Value": "2"
68 | }
69 | ]
70 | },
71 | ]
72 | ```
73 |
--------------------------------------------------------------------------------
/bees/pastebinbee/pastebinbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Sebastian Ławniczak
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Sebastian Ławniczak
19 | */
20 |
21 | // Package pastebinbee is a Bee that can interface with Pastebin.
22 | package pastebinbee
23 |
24 | import (
25 | pastebin "github.com/glaxx/go_pastebin"
26 | "github.com/muesli/beehive/bees"
27 | )
28 |
29 | // PastebinBee is a Bee that can interface with Pastebin.
30 | type PastebinBee struct {
31 | bees.Bee
32 |
33 | client pastebin.Pastebin
34 | apiDevKey string
35 | }
36 |
37 | // Action triggers the action passed to it.
38 | func (mod *PastebinBee) Action(action bees.Action) []bees.Placeholder {
39 | outs := []bees.Placeholder{}
40 |
41 | switch action.Name {
42 | case "post":
43 | title := ""
44 | content := ""
45 | expire := ""
46 | exposure := ""
47 |
48 | action.Options.Bind("title", &title)
49 | action.Options.Bind("content", &content)
50 | action.Options.Bind("expire", &expire)
51 | action.Options.Bind("exposure", &exposure)
52 |
53 | ret, err := mod.client.PasteAnonymous(content, title, "text", expire, exposure)
54 | if err != nil {
55 | mod.LogErrorf("Error occurred during posting to Pastebin: %v", err)
56 | } else {
57 | mod.Logln("Paste URL:", ret)
58 | }
59 |
60 | default:
61 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
62 | }
63 | return outs
64 | }
65 |
66 | // Run executes the Bee's event loop.
67 | func (mod *PastebinBee) Run(eventChan chan bees.Event) {
68 | mod.client = pastebin.NewPastebin(mod.apiDevKey)
69 | }
70 |
71 | // ReloadOptions parses the config options and initializes the Bee.
72 | func (mod *PastebinBee) ReloadOptions(options bees.BeeOptions) {
73 | mod.SetOptions(options)
74 |
75 | options.Bind("api_dev_key", &mod.apiDevKey)
76 | }
77 |
--------------------------------------------------------------------------------
/bees/pushoverbee/pushoverbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Raphael Mutschler
19 | */
20 |
21 | // Package pushoverbee is a Bee that can send pushover notifications.
22 | package pushoverbee
23 |
24 | import (
25 | "net/http"
26 | "net/url"
27 |
28 | "github.com/muesli/beehive/bees"
29 | )
30 |
31 | // PushoverBee is a Bee that sends Pushover notifications
32 | type PushoverBee struct {
33 | bees.Bee
34 |
35 | token string
36 | userToken string
37 | }
38 |
39 | // Run executes the Bee's event loop.
40 | func (mod *PushoverBee) Run(cin chan bees.Event) {
41 | select {
42 | case <-mod.SigChan:
43 | return
44 | }
45 | }
46 |
47 | // Action triggers the action passed to it.
48 | func (mod *PushoverBee) Action(action bees.Action) []bees.Placeholder {
49 | outs := []bees.Placeholder{}
50 |
51 | switch action.Name {
52 | case "send":
53 | var message, title, nurl, urlTitle string
54 | action.Options.Bind("message", &message)
55 | action.Options.Bind("title", &title)
56 | action.Options.Bind("url", &nurl)
57 | action.Options.Bind("url_title", &urlTitle)
58 |
59 | msg := url.Values{}
60 | msg.Set("token", mod.token)
61 | msg.Set("user", mod.userToken)
62 | msg.Set("message", message)
63 |
64 | if nurl != "" {
65 | msg.Set("url", nurl)
66 | }
67 | if urlTitle != "" {
68 | msg.Set("url_title", urlTitle)
69 | }
70 | if title != "" {
71 | msg.Set("title", title)
72 | }
73 |
74 | mod.LogDebugf("Message: %s", msg)
75 | resp, err := http.PostForm("https://api.pushover.net/1/messages.json", msg)
76 | if err != nil {
77 | panic(err)
78 | }
79 | defer resp.Body.Close()
80 | if resp.StatusCode == 200 {
81 | mod.LogDebugf("Pushover send message success.")
82 | }
83 |
84 | default:
85 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
86 | }
87 |
88 | return outs
89 | }
90 |
91 | // ReloadOptions parses the config options and initializes the Bee.
92 | func (mod *PushoverBee) ReloadOptions(options bees.BeeOptions) {
93 | mod.SetOptions(options)
94 | options.Bind("token", &mod.token)
95 | options.Bind("user_token", &mod.userToken)
96 | }
97 |
--------------------------------------------------------------------------------
/bees/redisbee/README.md:
--------------------------------------------------------------------------------
1 | # Redis bee
2 |
3 | Store arbitrary key/value strings in a Redis server.
4 |
5 | ## Configuration
6 |
7 | * host: Redis host (defaults to localhost)
8 | * port: Redis port (defaults to 6379)
9 | * password: Redis server password (defaults to passwordless auth)
10 | * db: Redis database to use (defaults to 0)
11 | * channel: Redis channel to subscribe to (pubsub disabled if not specified)
12 |
13 | ## Ideas
14 |
15 | * Use it in combination with the ipify hive to store your public IP history
16 | * Store URLs sent via POST to the HTTP server hive
17 | * Store all messages received in a Slack channel using the Slack hive
18 |
19 | See [beehive-youtube-dl](https://github.com/rubiojr/beehive-youtube-dl), a sample project that combines multiple hives, including this one.
20 |
21 | ## Credits
22 |
23 | [Redis Icon](https://iconscout.com/icon/redis-4) by Icon Mafia on [Iconscout]](https://iconscout.com)
24 |
--------------------------------------------------------------------------------
/bees/rocketchatbee/README.md:
--------------------------------------------------------------------------------
1 | # Rocket.chat bee
2 |
3 | The [Rocket.Chat](https://rocket.chat/) bee can send messages into a Rocket.Chat channel.
4 |
5 | ## Configuration
6 |
7 | ### Options
8 |
9 | ```json
10 | "Bees":[
11 | {
12 | "Name":"rocketchatmsg",
13 | "Class":"rocketchatbee",
14 | "Description":"my rocket.chat bee",
15 | "Options":[
16 | {
17 | "Name":"url",
18 | "Value":"http://localhost:3000"
19 | },
20 | {
21 | "Name":"user_id",
22 | "Value":"YOUR_USER_ID"
23 | },
24 | {
25 | "Name":"auth_token",
26 | "Value":"YOUR_AUTH_TOKEN"
27 | }
28 | ]
29 | }
30 | ]
31 | ```
32 |
33 | See https://rocket.chat/docs/developer-guides/rest-api/personal-access-tokens/ for reference on how to create a `user_id` and `auth_token`.
34 |
35 | ### Actions
36 |
37 | **send**: send a message to a Rocket.Chat channel. This needs the name of the `channel`, and the `text` to send. If you specify an `alias`, messages posted appear under that username.
38 |
39 | ```json
40 | "Elements":[
41 | {
42 | "Action":{
43 | "Bee":"rocketchatmsg",
44 | "Name":"send",
45 | "Options":[
46 | {
47 | "Name":"channel",
48 | "Value":"info"
49 | },
50 | {
51 | "Name":"text",
52 | "Value":"This is the latest info!"
53 | },
54 | {
55 | "Name":"alias",
56 | "Value":"Informer"
57 | }
58 | ]
59 | ]
60 | }
61 | }
62 | ]
63 | ```
64 |
--------------------------------------------------------------------------------
/bees/rocketchatbee/rocketchatbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Sergio Rubio
3 | * 2017 Christian Muehlhaeuser
4 | * 2019 David Schneider
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published
8 | * by the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | *
19 | * Authors:
20 | * Sergio Rubio
21 | * Christian Muehlhaeuser
22 | * David Schneider
23 | */
24 |
25 | // Package rocketchatbee is a Bee that can connect to Rocketchat.
26 | package rocketchatbee
27 |
28 | import (
29 | "github.com/muesli/beehive/bees"
30 | )
31 |
32 | // RocketchatBee is a Bee that can connect to Rocketchat.
33 | type RocketchatBee struct {
34 | bees.Bee
35 |
36 | client *Client
37 | }
38 |
39 | // Action triggers the action passed to it.
40 | func (mod *RocketchatBee) Action(action bees.Action) []bees.Placeholder {
41 | outs := []bees.Placeholder{}
42 |
43 | switch action.Name {
44 | case "send":
45 | var (
46 | text string
47 | channel string
48 | alias string
49 | )
50 |
51 | action.Options.Bind("text", &text)
52 | action.Options.Bind("channel", &channel)
53 | action.Options.Bind("alias", &alias)
54 |
55 | err := mod.client.SendMessage(channel, text, alias)
56 | if err != nil {
57 | mod.LogErrorf("Failed to send message: %s", err)
58 | return outs
59 | }
60 |
61 | default:
62 | mod.LogErrorf("Unknown action triggered in " + mod.Name() + ": " + action.Name)
63 | }
64 |
65 | return outs
66 | }
67 |
68 | // ReloadOptions parses the config options and initializes the Bee.
69 | func (mod *RocketchatBee) ReloadOptions(options bees.BeeOptions) {
70 | var (
71 | url string
72 | userID string
73 | authToken string
74 | )
75 |
76 | mod.SetOptions(options)
77 |
78 | options.Bind("url", &url)
79 | options.Bind("user_id", &userID)
80 | options.Bind("auth_token", &authToken)
81 |
82 | mod.client = NewClient(url, userID, authToken)
83 |
84 | err := mod.client.TestConnection()
85 | if err != nil {
86 | mod.LogErrorf("Connection to Rocket.Chat failed: %s", err)
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/bees/s3bee/README.md:
--------------------------------------------------------------------------------
1 | # S3 Bee
2 |
3 | Uploads files to S3 compatible storage:
4 |
5 | * AWS Signature Version 4
6 | * Amazon S3
7 | * Minio
8 |
9 | * AWS Signature Version 2
10 | * Google Cloud Storage (Compatibility Mode)
11 | * Openstack Swift + Swift3 middleware
12 | * Ceph Object Gateway
13 | * Riak CS
14 |
15 | See https://github.com/minio/minio-go
16 |
17 | ## Configuration
18 |
19 | * endpoint: S3 host (Path to monitor (file or directory).
20 | * access_key_id: S3 access key. Prefix the value with `env://` to retrieve the key from the environment.
21 | Example: `env://AWS_ACCESS_KEY_ID` or `ASDFWERSDF123WERF`
22 | * secret_access_key: S3 secret access key. Prefix the value with `env://` to retrieve the key from the environment.
23 | Example: `env://AWS_SECRET_ACCESS_KEY` or `vASiudxSHReo4elkajsdklfu827389234sdfsdf`
24 | * use_ssl: Defaults to `true`.
25 | * region: AWS region. Defaults to `us-east-1`.
26 |
27 | ## Actions
28 |
29 | **upload**
30 |
31 | * bucket: target bucket to upload the file.
32 | * path: Source file path.
33 | * object_path: Destination file path. Defaults to the source file name.
34 |
35 | ## Credits
36 |
37 | AWS logo: https://hu.wikipedia.org/wiki/Amazon_S3#/media/File:AWS_Simple_Icons_AWS_Cloud.svg
38 |
--------------------------------------------------------------------------------
/bees/s3bee/s3bee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Sergio Rubio
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Sergio Rubio
19 | */
20 |
21 | package s3bee
22 |
23 | import (
24 | "mime"
25 | "os"
26 | "path/filepath"
27 | "strings"
28 |
29 | "github.com/minio/minio-go"
30 | "github.com/muesli/beehive/bees"
31 | )
32 |
33 | type S3Bee struct {
34 | bees.Bee
35 | client *minio.Client
36 | }
37 |
38 | // Action triggers the action passed to it.
39 | func (bee *S3Bee) Action(action bees.Action) []bees.Placeholder {
40 | outs := []bees.Placeholder{}
41 |
42 | switch action.Name {
43 | case "upload":
44 | bucket := ""
45 | action.Options.Bind("bucket", &bucket)
46 |
47 | path := ""
48 | action.Options.Bind("path", &path)
49 |
50 | objectPath := ""
51 | action.Options.Bind("object_path", &objectPath)
52 |
53 | if objectPath == "" {
54 | objectPath = filepath.Base(path)
55 | }
56 |
57 | _, err := bee.client.FPutObject(bucket, objectPath, path, minio.PutObjectOptions{ContentType: mime.TypeByExtension(filepath.Ext(path))})
58 | if err != nil {
59 | bee.LogFatal(err)
60 | }
61 | default:
62 | panic("Unknown action triggered in " + bee.Name() + ": " + action.Name)
63 | }
64 |
65 | return outs
66 | }
67 |
68 | func (bee *S3Bee) ReloadOptions(options bees.BeeOptions) {
69 | bee.SetOptions(options)
70 |
71 | endpoint := getConfigValue("endpoint", &options)
72 |
73 | var useSSL bool
74 | options.Bind("use_ssl", &useSSL)
75 |
76 | accessKeyID := getConfigValue("access_key_id", &options)
77 | secretAccessKey := getConfigValue("secret_access_key", &options)
78 |
79 | client, err := minio.New(endpoint, accessKeyID, secretAccessKey, useSSL)
80 | if err != nil {
81 | panic(err)
82 | return
83 | }
84 |
85 | bee.client = client
86 | }
87 |
88 | func getConfigValue(key string, options *bees.BeeOptions) string {
89 | var value string
90 | options.Bind(key, &value)
91 |
92 | if strings.HasPrefix(value, "env://") {
93 | buf := strings.TrimPrefix(value, "env://")
94 | value = os.Getenv(string(buf))
95 | }
96 |
97 | return strings.TrimSpace(value)
98 | }
99 |
--------------------------------------------------------------------------------
/bees/simplepushbee/simplepushbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Timm Schäuble
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Timm Schäuble
19 | */
20 |
21 | // Package simplepushbee is a Bee that is able to send push notifications to Android.
22 | package simplepushbee
23 |
24 | import (
25 | "github.com/muesli/beehive/bees"
26 | "github.com/simplepush/simplepush-go"
27 | )
28 |
29 | // SimplepushBee is a Bee that is able to send push notifications to Android.
30 | type SimplepushBee struct {
31 | bees.Bee
32 |
33 | key string
34 | password string
35 | salt string
36 | }
37 |
38 | // Action triggers the action passed to it.
39 | func (mod *SimplepushBee) Action(action bees.Action) []bees.Placeholder {
40 | outs := []bees.Placeholder{}
41 |
42 | switch action.Name {
43 | case "send":
44 | sm := simplepush.Message{
45 | SimplePushKey: mod.key,
46 | Encrypt: mod.password != "",
47 | Password: mod.password,
48 | Salt: mod.salt,
49 | }
50 | action.Options.Bind("title", &sm.Title)
51 | action.Options.Bind("message", &sm.Message)
52 | action.Options.Bind("event", &sm.Event)
53 |
54 | simplepush.Send(sm)
55 |
56 | default:
57 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
58 | }
59 |
60 | return outs
61 | }
62 |
63 | // ReloadOptions parses the config options and initializes the Bee.
64 | func (mod *SimplepushBee) ReloadOptions(options bees.BeeOptions) {
65 | mod.SetOptions(options)
66 |
67 | options.Bind("key", &mod.key)
68 | options.Bind("password", &mod.password)
69 | options.Bind("salt", &mod.salt)
70 | }
71 |
--------------------------------------------------------------------------------
/bees/slackbee/README.md:
--------------------------------------------------------------------------------
1 | # Slack bee
2 |
3 | The [Slack](https://slack.com) bee can send and listen to messages in a Slack channel.
4 |
5 | ## Configuration
6 |
7 | ### Options
8 |
9 | ```json
10 | "Bees":[
11 | {
12 | "Name":"slackmsg",
13 | "Class":"slackbee",
14 | "Description":"slackbee",
15 | "Options":[
16 | {
17 | "Name":"apiKey",
18 | "Value":"env://SLACK_KEY"
19 | },
20 | {
21 | "Name":"channels",
22 | "Value":["rubiojr-test"]
23 | }
24 | ]
25 | }
26 | ]
27 | ```
28 |
29 | **apiKey**: Slack API Key. You can get one from https://api.slack.com/docs/oauth-test-tokens.
30 |
31 | The API key can be added to the recipe/config as-is, via environment variable (`env://MY_API_KEY`) or read from a file (`file:///Users/rubiojr/.slack_key`).
32 |
33 | **channels**: The slack channels to listen on.
34 |
35 | ### Actions
36 |
37 | **send**: send a message to a Slack channel. Needs the name of the channel (not the channel ID), and the text to send. You can use interpolation to send something from the event received:
38 |
39 | ```json
40 | "Elements":[
41 | {
42 | "Action":{
43 | "Bee":"slackmsg",
44 | "Name":"send",
45 | "Options":[
46 | {
47 | "Name":"channel",
48 | "Value":"rubiojr-test2"
49 | },
50 | {
51 | "Name":"text",
52 | "Value":"{{.something}}"
53 | }
54 | ]
55 | }
56 | }
57 | ]
58 | ```
59 |
60 | ## Credits
61 |
62 | Slack logo: https://remoteworkspain.slack.com/brand-guidelines
63 |
--------------------------------------------------------------------------------
/bees/socketbee/socketbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2019 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | // Package socketbee is a Bee that lets you transmit data via UDP sockets.
22 | package socketbee
23 |
24 | import (
25 | "log"
26 | "net"
27 | "strconv"
28 |
29 | "github.com/muesli/beehive/bees"
30 | )
31 |
32 | // SocketBee is a Bee that lets you transmit data via UDP sockets.
33 | type SocketBee struct {
34 | bees.Bee
35 |
36 | eventChan chan bees.Event
37 | }
38 |
39 | // Run executes the Bee's event loop.
40 | func (mod *SocketBee) Run(cin chan bees.Event) {
41 | mod.eventChan = cin
42 |
43 | select {
44 | case <-mod.SigChan:
45 | return
46 | }
47 | }
48 |
49 | // Action triggers the action passed to it.
50 | func (mod *SocketBee) Action(action bees.Action) []bees.Placeholder {
51 | outs := []bees.Placeholder{}
52 |
53 | var data string
54 | var addr string
55 | var port int
56 |
57 | action.Options.Bind("address", &addr)
58 | action.Options.Bind("port", &port)
59 | action.Options.Bind("data", &data)
60 |
61 | switch action.Name {
62 | case "send":
63 | // log.Println("Sending", data, "to", addr, port)
64 |
65 | sa, err := net.ResolveUDPAddr("udp", addr+":"+strconv.Itoa(port))
66 | if err != nil {
67 | log.Panicln(err)
68 | }
69 |
70 | conn, err := net.DialUDP("udp", nil, sa)
71 | if err != nil {
72 | log.Panicln(err)
73 | }
74 |
75 | defer conn.Close()
76 | _, err = conn.Write([]byte(data))
77 | if err != nil {
78 | log.Panicln(err)
79 | }
80 |
81 | default:
82 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
83 | }
84 |
85 | return outs
86 | }
87 |
88 | // ReloadOptions parses the config options and initializes the Bee.
89 | func (mod *SocketBee) ReloadOptions(options bees.BeeOptions) {
90 | mod.SetOptions(options)
91 | }
92 |
--------------------------------------------------------------------------------
/bees/spaceapibee/spaceapibee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | * Johannes Fürmann
20 | */
21 |
22 | // Package spaceapibee is a Bee that can query a spaceapi server.
23 | package spaceapibee
24 |
25 | import (
26 | "encoding/json"
27 | "io/ioutil"
28 | "net/http"
29 |
30 | "github.com/muesli/beehive/bees"
31 | )
32 |
33 | // SpaceAPIBee is a Bee that can query a spaceapi server.
34 | type SpaceAPIBee struct {
35 | bees.Bee
36 |
37 | url string
38 |
39 | evchan chan bees.Event
40 | }
41 |
42 | // Action triggers the action passed to it.
43 | func (mod *SpaceAPIBee) Action(action bees.Action) []bees.Placeholder {
44 | outs := []bees.Placeholder{}
45 |
46 | switch action.Name {
47 | case "status":
48 | type SpaceAPIResult struct {
49 | State struct {
50 | Open bool `json:"open"`
51 | } `json:"state"`
52 | }
53 | apiState := new(SpaceAPIResult)
54 |
55 | // get json data
56 | resp, err := http.Get(mod.url)
57 | if err != nil {
58 | mod.Logln("Error: SpaceAPI instance @ " + mod.url + " not reachable")
59 | } else {
60 | defer resp.Body.Close()
61 | body, _ := ioutil.ReadAll(resp.Body)
62 |
63 | err = json.Unmarshal(body, apiState)
64 | if err != nil {
65 | mod.Logln("Sorry, couldn't unmarshal the JSON data from SpaceAPI Instance @ " + mod.url)
66 | apiState.State.Open = false
67 | }
68 | }
69 |
70 | ev := bees.Event{
71 | Bee: mod.Name(),
72 | Name: "result",
73 | Options: []bees.Placeholder{
74 | {
75 | Name: "open",
76 | Type: "bool",
77 | Value: apiState.State.Open,
78 | },
79 | },
80 | }
81 | mod.evchan <- ev
82 |
83 | default:
84 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
85 | }
86 |
87 | return outs
88 | }
89 |
90 | // Run executes the Bee's event loop.
91 | func (mod *SpaceAPIBee) Run(eventChan chan bees.Event) {
92 | mod.evchan = eventChan
93 | }
94 |
95 | // ReloadOptions parses the config options and initializes the Bee.
96 | func (mod *SpaceAPIBee) ReloadOptions(options bees.BeeOptions) {
97 | mod.SetOptions(options)
98 |
99 | options.Bind("url", &mod.url)
100 | }
101 |
--------------------------------------------------------------------------------
/bees/sunbee/README.md:
--------------------------------------------------------------------------------
1 | # Sunrise/Sunset Bee
2 |
3 | Sends an event when the Sun raises or goes down.
4 |
5 | ## Configuration
6 |
7 | * query: the city that should match the sunrise/sunset event. The query is sent to https://nominatim.openstreetmap.org so your query
8 | should return the latitude, longitude for a valid place.
9 | * offset: the number of seconds to alert before the event happens. Defaults to 2 minutes.
10 |
11 | ## Credits
12 |
13 | Logo: Icon Lauk https://www.iconfinder.com/icons/3859148/forecast_sun_sunrise_sunset_weather_icon
14 |
--------------------------------------------------------------------------------
/bees/sunbee/sunbeefactory.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2020 Sergio Rubio
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Sergio Rubio
19 | */
20 |
21 | package sunbee
22 |
23 | import (
24 | "github.com/muesli/beehive/bees"
25 | )
26 |
27 | // SunBeeFactory is a factory for SunBees.
28 | type SunBeeFactory struct {
29 | bees.BeeFactory
30 | }
31 |
32 | // New returns a new Bee instance configured with the supplied options.
33 | func (factory *SunBeeFactory) New(name, description string, options bees.BeeOptions) bees.BeeInterface {
34 | bee := SunBee{
35 | Bee: bees.NewBee(name, factory.ID(), description, options),
36 | }
37 | bee.ReloadOptions(options)
38 |
39 | return &bee
40 | }
41 |
42 | // ID returns the ID of this Bee.
43 | func (factory *SunBeeFactory) ID() string {
44 | return "sunbee"
45 | }
46 |
47 | // Name returns the name of this Bee.
48 | func (factory *SunBeeFactory) Name() string {
49 | return "Sunset/Sunrise"
50 | }
51 |
52 | // Description returns the description of this Bee.
53 | func (factory *SunBeeFactory) Description() string {
54 | return "Send an event when the Sun raises or goes down"
55 | }
56 |
57 | // Image returns the filename of an image for this Bee.
58 | func (factory *SunBeeFactory) Image() string {
59 | return factory.ID() + ".png"
60 | }
61 |
62 | // Options returns the options available to configure this Bee.
63 | func (factory *SunBeeFactory) Options() []bees.BeeOptionDescriptor {
64 | opts := []bees.BeeOptionDescriptor{
65 | {
66 | Name: "query",
67 | Description: "The name of the city where the sunrise/sunset will happen",
68 | Type: "string",
69 | Mandatory: true,
70 | },
71 | {
72 | Name: "offset",
73 | Description: "Fire the event this number of seconds before sunset/sunrise",
74 | Type: "int",
75 | Default: 0,
76 | Mandatory: false,
77 | },
78 | }
79 | return opts
80 | }
81 |
82 | func (factory *SunBeeFactory) Events() []bees.EventDescriptor {
83 | events := []bees.EventDescriptor{
84 | {
85 | Namespace: factory.Name(),
86 | Name: "sunrise",
87 | Description: "Sunrise is happening",
88 | Options: []bees.PlaceholderDescriptor{},
89 | },
90 | {
91 | Namespace: factory.Name(),
92 | Name: "sunset",
93 | Description: "Sunset is happening",
94 | Options: []bees.PlaceholderDescriptor{},
95 | },
96 | }
97 | return events
98 | }
99 |
100 | func init() {
101 | f := SunBeeFactory{}
102 | bees.RegisterFactory(&f)
103 | }
104 |
--------------------------------------------------------------------------------
/bees/telegrambee/README.md:
--------------------------------------------------------------------------------
1 | # Telegram Bees
2 |
3 | [Telegram](https://telegram.org) bot that sends and receives messages to/from Telegram chats and groups.
4 |
5 |
6 | ## Configuration
7 |
8 | Bee options:
9 |
10 | ```json
11 | "Bees": [{
12 | "Name": "telegram",
13 | "Class": "telegrambee",
14 | "Description": "Telegram bot bee",
15 | "Options": [{
16 | "Name": "apiKey",
17 | "Value": "file:///Users/lalotone/.telegramapi"
18 | }]
19 | }]
20 | ```
21 |
22 | **apiKey**: [Telegram bot](https://core.telegram.org/bots) API Key. Can be added
23 | to the recipe, via environment variable (`env://MY_API_KEY`) or read from a file (`file:///Users/lalotone/.telegram_key`)
24 |
25 | ## Credits
26 |
27 | Telegram image by Telegram Messenger LLP - User:Javitomad, Public Domain, https://commons.wikimedia.org/w/index.php?curid=36861817
28 |
--------------------------------------------------------------------------------
/bees/transmissionbee/transmissionbee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2016 Gonzalo Izquierdo
3 | * 2017 Christian Muehlhaeuser
4 | *
5 | * This program is free software: you can redistribute it and/or modify
6 | * it under the terms of the GNU Affero General Public License as published
7 | * by the Free Software Foundation, either version 3 of the License, or
8 | * (at your option) any later version.
9 | *
10 | * This program is distributed in the hope that it will be useful,
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | * GNU Affero General Public License for more details.
14 | *
15 | * You should have received a copy of the GNU Affero General Public License
16 | * along with this program. If not, see .
17 | *
18 | * Authors:
19 | * Gonzalo Izquierdo
20 | * Christian Muehlhaeuser
21 | */
22 |
23 | // Package transmissionbee is a Bee that can send torrents to Transmission.
24 | package transmissionbee
25 |
26 | import (
27 | "github.com/kr/pretty"
28 | "github.com/odwrtw/transmission"
29 |
30 | "github.com/muesli/beehive/bees"
31 | )
32 |
33 | // TransmissionBee is a Bee that can send torrents to Transmission.
34 | type TransmissionBee struct {
35 | bees.Bee
36 |
37 | client *transmission.Client
38 | }
39 |
40 | // Action triggers the action passed to it.
41 | func (mod *TransmissionBee) Action(action bees.Action) []bees.Placeholder {
42 | outs := []bees.Placeholder{}
43 | switch action.Name {
44 | case "add_torrent":
45 | torrentMsg := ""
46 | action.Options.Bind("torrent", &torrentMsg)
47 |
48 | _, err := mod.client.Add(torrentMsg)
49 | if err != nil {
50 | mod.LogErrorf("Error adding torrent/magnet: %s", err)
51 | }
52 | }
53 | return outs
54 | }
55 |
56 | // ReloadOptions parses the config options and initializes the Bee.
57 | func (mod *TransmissionBee) ReloadOptions(options bees.BeeOptions) {
58 | mod.SetOptions(options)
59 |
60 | conf := transmission.Config{}
61 | options.Bind("url", &conf.Address)
62 | options.Bind("username", &conf.User)
63 | options.Bind("password", &conf.Password)
64 |
65 | t, err := transmission.New(conf)
66 | if err != nil {
67 | pretty.Println(err)
68 | }
69 | mod.client = t
70 | }
71 |
--------------------------------------------------------------------------------
/bees/twiliobee/README.md:
--------------------------------------------------------------------------------
1 | # Twilio bee
2 |
3 | The [Twilio](https://twilio.com) bee can send SMS messages to a phone.
4 |
5 | ## Configuration
6 |
7 | ### Options
8 |
9 | ```json
10 | "Bees": [
11 | {
12 | "Name":"Twilio Example Bee",
13 | "Class":"twiliobee",
14 | "Description":"A bee to demonstrate Twilio with Beehive",
15 | "Options":[
16 | {
17 | "Name": "account_sid",
18 | "Value": "YOUR_TWILIO_ACCOUNT_SID"
19 | },
20 | {
21 | "Name": "auth_token",
22 | "Value": "YOUR_TWILIO_AUTH_TOKEN"
23 | },
24 | {
25 | "Name": "from_number",
26 | "Value": "+15551234567"
27 | },
28 | {
29 | "Name": "to_number",
30 | "Value": "+15559876543"
31 | }
32 | ]
33 | }
34 | ]
35 | ```
36 |
37 | **account_sid** and **auth_token**: Twilio Account SID and Authentication Token. You can sign up and get them from https://www.twilio.com/try-twilio.
38 |
39 | These can be added to the recipe/config as-is (`XXXXXXXX`), via environment variable (`env://MY_ACCOUNT_SID`) or read from a file (`file:///home/james//.twilio_config`).
40 |
41 | **from_number**: Your Twilio phone number. Must be in the format `+15558675309`.
42 |
43 | **to_number**: The phone number to send an SMS message to.
44 |
45 | ### Actions
46 |
47 | **send**: send an SMS message. Needs the body of the message to send. You can use interpolation to send somthing from the event received:
48 |
49 | ```json
50 | "Actions": [
51 | {
52 | "Bee":"Twilio Example Bee",
53 | "Name":"send",
54 | "Options":[
55 | {
56 | "Name":"body",
57 | "Value":"Example body with interpolation: {{.something_from_event}}"
58 | }
59 | ]
60 | }
61 | ]
62 | ```
63 |
64 | ## Credits
65 |
66 | Twilio logo: https://www.twilio.com/press
67 |
--------------------------------------------------------------------------------
/bees/twiliobee/twiliobee.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 James Vaughan
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * James Vaughan
19 | */
20 |
21 | // Package twiliobee is a Bee that is able to send SMS messages.
22 | package twiliobee
23 |
24 | import (
25 | twilio "github.com/carlosdp/twiliogo"
26 | "github.com/muesli/beehive/bees"
27 | )
28 |
29 | // TwilioBee is a Bee that is able to send SMS messages.
30 | type TwilioBee struct {
31 | bees.Bee
32 |
33 | client *twilio.TwilioClient
34 | accountsid string
35 | authtoken string
36 | fromNumber string
37 | toNumber string
38 | }
39 |
40 | // Action triggers the action passed to it.
41 | func (mod *TwilioBee) Action(action bees.Action) []bees.Placeholder {
42 | outs := []bees.Placeholder{}
43 |
44 | switch action.Name {
45 | case "send":
46 | body := ""
47 | action.Options.Bind("body", &body)
48 |
49 | _, err := twilio.NewMessage(mod.client, mod.fromNumber, mod.toNumber, twilio.Body(body))
50 | if err != nil {
51 | mod.LogErrorf("Error sending twilio SMS: %s", err)
52 | }
53 |
54 | default:
55 | panic("Unknown action triggered in " + mod.Name() + ": " + action.Name)
56 | }
57 |
58 | return outs
59 | }
60 |
61 | // Run executes the Bee's event loop.
62 | func (mod *TwilioBee) Run(eventChan chan bees.Event) {
63 | mod.client = twilio.NewClient(mod.accountsid, mod.authtoken)
64 | }
65 |
66 | // ReloadOptions parses the config options and initializes the Bee.
67 | func (mod *TwilioBee) ReloadOptions(options bees.BeeOptions) {
68 | mod.SetOptions(options)
69 |
70 | options.Bind("account_sid", &mod.accountsid)
71 | options.Bind("auth_token", &mod.authtoken)
72 | options.Bind("from_number", &mod.fromNumber)
73 | options.Bind("to_number", &mod.toNumber)
74 | }
75 |
--------------------------------------------------------------------------------
/build-constants.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | var (
4 | Version = "0.0.0"
5 | CommitSHA = "unknown"
6 | )
7 |
--------------------------------------------------------------------------------
/cfg/config_test.go:
--------------------------------------------------------------------------------
1 | package cfg
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 | "testing"
7 | )
8 |
9 | func TestNew(t *testing.T) {
10 | conf, err := New("/foobar")
11 | if err != nil {
12 | t.Fatal("cannot create config from path")
13 | }
14 | if _, ok := conf.Backend().(*FileBackend); !ok {
15 | t.Error("Backend for '/foobar' should be a FileBackend")
16 | }
17 |
18 | conf, err = New("file:///foobar")
19 | if err != nil {
20 | t.Fatal("cannot create config from file:// path")
21 | }
22 | if _, ok := conf.Backend().(*FileBackend); !ok {
23 | t.Error("Backend for 'file:///foobar' should be a FileBackend")
24 | }
25 |
26 | cwd, _ := os.Getwd()
27 | p := filepath.Join(cwd, "testdata/beehive-crypto.conf")
28 | conf, err = New(p)
29 | if err != nil {
30 | t.Fatal(err)
31 | }
32 | if _, ok := conf.Backend().(*AESBackend); !ok {
33 | t.Errorf("Backend for '%s' should be an AESBackend", p)
34 | }
35 |
36 | conf, err = New("mem:")
37 | if err != nil {
38 | t.Fatal("cannot create config from memory")
39 | }
40 | if _, ok := conf.Backend().(*MemBackend); !ok {
41 | t.Error("Backend for 'mem:' should be a MemoryBackend")
42 | }
43 |
44 | _, err = New("c:\\foobar")
45 | if err == nil {
46 | t.Error("Not a valid URL, should return an error")
47 | }
48 |
49 | _, err = New("")
50 | if err == nil {
51 | t.Error("Not a valid URL, should return an error")
52 | }
53 | }
54 |
55 | func TestLoad(t *testing.T) {
56 | conf, err := New("mem://")
57 | if err != nil {
58 | t.Fatal(err)
59 | }
60 | err = conf.Load()
61 | if err != nil {
62 | t.Error("Failed loading the configuration")
63 | }
64 | if conf.URL().Scheme != "mem" {
65 | t.Error("Config URL didn't change")
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/cfg/filebackend.go:
--------------------------------------------------------------------------------
1 | package cfg
2 |
3 | import (
4 | "encoding/json"
5 | "io/ioutil"
6 | "net/url"
7 | "os"
8 | "path/filepath"
9 | "strings"
10 |
11 | "gopkg.in/yaml.v2"
12 | )
13 |
14 | type Format int
15 |
16 | const (
17 | FormatJSON Format = iota
18 | FormatYAML = iota
19 | )
20 |
21 | // FileBackend implements a filesystem backend for the configuration
22 | type FileBackend struct {
23 | format Format
24 | }
25 |
26 | // NewFileBackend returns a FileBackend that handles loading and
27 | // saving files from the local filesytem.
28 | func NewFileBackend() *FileBackend {
29 | return &FileBackend{format: FormatJSON}
30 | }
31 |
32 | // Load loads chains from config
33 | func (fs *FileBackend) Load(u *url.URL) (*Config, error) {
34 | var config Config
35 |
36 | // detect file format by extension
37 | if strings.HasSuffix(u.Path, ".yaml") {
38 | fs.format = FormatYAML
39 | } else if strings.HasSuffix(u.Path, ".yml") {
40 | fs.format = FormatYAML
41 | } else {
42 | fs.format = FormatJSON
43 | }
44 |
45 | if !exist(u.Path) {
46 | return &Config{url: u}, nil
47 | }
48 |
49 | content, err := ioutil.ReadFile(u.Path)
50 | if err != nil {
51 | return &config, err
52 | }
53 |
54 | if fs.format == FormatYAML {
55 | err = yaml.Unmarshal(content, &config)
56 | } else {
57 | err = json.Unmarshal(content, &config)
58 | }
59 | if err != nil {
60 | return nil, err
61 | }
62 | config.backend = fs
63 | config.url = u
64 |
65 | return &config, nil
66 | }
67 |
68 | // Save saves chains to config
69 | func (fs *FileBackend) Save(config *Config) error {
70 | cfgDir := filepath.Dir(config.URL().Path)
71 | if !exist(cfgDir) {
72 | err := os.MkdirAll(cfgDir, 0755)
73 | if err != nil {
74 | return err
75 | }
76 | }
77 |
78 | var content []byte
79 | var err error
80 | if fs.format == FormatYAML {
81 | content, err = yaml.Marshal(config)
82 | } else {
83 | content, err = json.MarshalIndent(config, "", " ")
84 | }
85 | if err != nil {
86 | return err
87 | }
88 | return ioutil.WriteFile(config.URL().Path, content, 0644)
89 | }
90 |
--------------------------------------------------------------------------------
/cfg/membackend.go:
--------------------------------------------------------------------------------
1 | package cfg
2 |
3 | import "net/url"
4 |
5 | // MemBackend implements a dummy memory backend for the configuration
6 | type MemBackend struct {
7 | conf *Config
8 | }
9 |
10 | // NewMemBackend returns a backend that handles loading and saving
11 | // the configuration from memory
12 | func NewMemBackend() *MemBackend {
13 | return &MemBackend{conf: &Config{}}
14 | }
15 |
16 | // Load the config from memory
17 | //
18 | // No need to do anything here, already loaded
19 | func (m *MemBackend) Load(u *url.URL) (*Config, error) {
20 | return m.conf, nil
21 | }
22 |
23 | // Save the config to memory
24 | //
25 | // No need to do anything special here, already in memory
26 | func (m *MemBackend) Save(config *Config) error {
27 | return nil
28 | }
29 |
--------------------------------------------------------------------------------
/cfg/membackend_test.go:
--------------------------------------------------------------------------------
1 | package cfg
2 |
3 | import (
4 | "net/url"
5 | "path/filepath"
6 | "testing"
7 | )
8 |
9 | func TestMemLoad(t *testing.T) {
10 | u, _ := url.Parse("mem://")
11 | backend := NewMemBackend()
12 | _, err := backend.Load(u)
13 | if err != nil {
14 | t.Error("Loading an invalid config file should return an error")
15 | }
16 | }
17 |
18 | func TestMemSave(t *testing.T) {
19 | path := filepath.Join("testdata", "foobar")
20 | u, _ := url.Parse(filepath.Join("testdata", "foobar"))
21 | backend := NewMemBackend()
22 | conf := &Config{url: u}
23 | err := backend.Save(conf)
24 | if err != nil {
25 | t.Errorf("Failed to save the config to memory")
26 | }
27 |
28 | if exist(path) {
29 | t.Error("Configuration file should not exist")
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/cfg/testdata/beehive-crypto.conf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/muesli/beehive/d636b697737dae0523a8c9972c01dbe6227d89ec/cfg/testdata/beehive-crypto.conf
--------------------------------------------------------------------------------
/cfg/testdata/beehive.conf:
--------------------------------------------------------------------------------
1 | {
2 | "Bees": [
3 | {
4 | "Name": "echo",
5 | "Class": "execbee",
6 | "Description": "echo",
7 | "Options": []
8 | }
9 | ],
10 | "Actions": null,
11 | "Chains": []
12 | }
--------------------------------------------------------------------------------
/cfg/testdata/beehive.yaml:
--------------------------------------------------------------------------------
1 | bees:
2 | - name: echo
3 | class: execbee
4 | description: echo
5 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | ---
2 | version: '3'
3 |
4 | services:
5 | beehive:
6 | image: fribbledom/beehive
7 | ports:
8 | - 8181:8181
9 | volumes:
10 | - beehive-conf:/conf
11 | environment:
12 | # be sure not to pass quotes, just the bare url
13 | - CANONICAL_URL=http://localhost:8181
14 |
15 | volumes:
16 | beehive-conf:
17 |
--------------------------------------------------------------------------------
/docker/README.md:
--------------------------------------------------------------------------------
1 | Beehive
2 | =======
3 |
4 | ## Docker Installation
5 |
6 | You can install beehive with docker if you'd prefer not to set up a working Go environment.
7 |
8 | Make sure you have docker installed. See the [install instructions](https://docs.docker.com/engine/getstarted/step_one/).
9 |
10 | ### Using a prebuilt container image
11 |
12 | The simplest way to set up beehive with docker is to simply pull a prebuilt image.
13 |
14 | docker pull fribbledom/beehive
15 |
16 | ### Building your own container image (skip if using a prebuilt image)
17 |
18 | Make sure you're currently in the docker directory of the repository.
19 | You can simply clone the repository with git and cd into the directory.
20 |
21 | git clone --recursive https://github.com/muesli/beehive.git
22 | cd beehive
23 |
24 | Alternatively if you have the package installed with `go get` you can navigate
25 | to `$GOPATH/src/github.com/muesli/beehive`
26 |
27 | Either way once you're there you can build the docker container
28 |
29 | docker build -t beehive .
30 |
31 | If you'd like to push the image up to docker.io so that you can use it elsewhere, you need
32 | to namespace it with your docker.io username.
33 |
34 | docker build -t /beehive .
35 | docker push /beehive
36 |
37 | ## Running a container
38 |
39 | Once you have the image on your machine, it's time to spin up an instance of it!
40 | Of course if you built the container yourself without adding your username, leave out
41 | the `/` in this command.
42 |
43 | docker run --name beehive -d -p 8181:8181 /beehive
44 |
45 | The `--name` parameter will give your container a name so that you can easily reference it with future commands.
46 | The `-d` flag specifies that the container should be run as a daemon.
47 | The `-p` parameter tells docker to map port 8181 on the host machine to port 8181 in the container.
48 | You can expose as many ports as is necessary. If you're running http server bees then you may need to
49 | add additional flags so that those servers can be seen by your machine: `-p 8181:8181 -p 12345:12345 ... -p 34343:34343`
50 |
51 | If ever you want to stop the container, run the following
52 |
53 | docker stop beehive
54 |
55 | Then you can start it again with
56 |
57 | docker start beehive
58 |
59 | #### Note
60 |
61 | This container will store the `beehive.conf` file in a persistent volume.
62 | As long as you use `docker stop` / `docker start` to stop/start the container
63 | the configuration will persist.
64 |
65 | If you'd like to have the container use an old config file, you can mount it as
66 | a volume with `docker run`.
67 |
68 | Suppose you had a config file stored in `/path/to/beehive.conf` then when running the container use
69 |
70 | docker run -d -p 8181:8181 -v /path/to/beehive.conf:/conf/beehive.conf /beehive
71 |
72 | This will tell docker to put your config file at `/conf/beehive.conf` within the container's filesystem.
73 | Thus beehive will startup using your configuration file.
74 |
--------------------------------------------------------------------------------
/docs/config_encryption.md:
--------------------------------------------------------------------------------
1 | # Configuration Encryption
2 |
3 | Beehive's supports encrypting the configuration file using AES+GCM.
4 |
5 | ## Usage
6 |
7 | To encrypt the configuration for the first time, simply start Beehive using a `crypto` URL for the configuration:
8 |
9 | ```
10 | ./beehive --config crypto://mysecret@$HOME/.config/beehive/beehive.conf`
11 | ```
12 |
13 | You could also use the `BEEHIVE_CONFIG_PASSWORD` environment variable to define the password:
14 |
15 | ```
16 | BEEHIVE_CONFIG_PASSWORD=mysecret ./beehive --config crypto://$HOME/.config/beehive/beehive.conf`
17 | ```
18 |
19 | This will use the key `mysecret` to encrypt/decrypt the configuration file.
20 |
21 | Once the configuration has been encrypted, it's no longer necessary to use a `crypto:` URL, Beehive will automatically detect it's encrypted.
22 | That is, something like:
23 |
24 | ```
25 | BEEHIVE_CONFIG_PASSWORD=mysecret beehive --config /path/to/config
26 | ```
27 |
28 | Will happily detect and load an encrypted configuration file.
29 |
30 | ## Using user keyrings to store the password
31 |
32 | A sample wrapper script (Linux only) is provided in [tools/encrypted-config-wrapper] that will read the configuration password from the sessions's keyring.
33 |
34 | Something similar could be written to do it on macOS using Keychain and its `security(1)` CLI.
35 |
36 | ## Decrypting the configuration
37 |
38 | Use `--decrypt` with a valid password:
39 |
40 | ```
41 | beehive --decrypt --config crypto://mysecret@/path/to/config/file
42 | ```
43 |
44 | or using an environment variable:
45 |
46 | ```
47 | BEEHIVE_CONFIG_PASSWORD=mysecret beehive --decrypt --config crypto:///path/to/config/file
48 | ```
49 |
50 | You can also use omit `--config` when using the default configuration path:
51 |
52 | ```
53 | BEEHIVE_CONFIG_PASSWORD=mysecret beehive --decrypt
54 | ```
55 |
56 | ## Troubleshooting
57 |
58 | ```
59 | FATA[0000] Error loading user config file /home/rubiojr/.config/beehive/beehive.conf. err: cipher: message authentication failed
60 | ```
61 |
62 | Means the password used to decrypt the configuration file is not valid.
63 |
64 | ## Notes
65 |
66 | The encrypted configuration file includes a 12 bytes header (`beehiveconf+`) that makes it possible to identify the file as an encrypted configuration file:
67 |
68 | ```
69 | head -c 12 beehive-encrypted.conf
70 | beehiveconf+
71 | ```
72 |
--------------------------------------------------------------------------------
/docs/watchdog.md:
--------------------------------------------------------------------------------
1 | # Systemd's Watchdog integration
2 |
3 | Integrates Beehive with the Systemd's watchdog.
4 |
5 | See http://0pointer.de/blog/projects/watchdog.html
6 |
7 | ## Configuration
8 |
9 | As a system service:
10 |
11 | * Add the service unit to `/etc/systemd/system/beehive.conf`
12 |
13 | Sample service unit:
14 |
15 | ```
16 | [Unit]
17 | Description=Beehive with Systemd's watchdog
18 | [Service]
19 | Type=simple
20 | ExecStart=/usr/bin/beehive --config /path/to/beehive.conf
21 | Restart=on-failure
22 | WatchdogSec=30s
23 |
24 | [Install]
25 | WantedBy=multi-user.target
26 | ```
27 | *Note: change `/path/to/beehive.conf` to a real path pointing to Beehive's config*
28 |
29 | * Enable the new service: `systemctl enable beehive`
30 | * Start the service: `systemctl start beehive`
31 |
32 | Beehive will automatically detect it's running under Systemd and notify Systemd's watchdog every WatchdogSec/3 seconds (10 seconds in this particular case). Note the notification interval is hardcoded to WatchdogSec/3.
--------------------------------------------------------------------------------
/filters/filters.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | // Package filters contains Beehive's filter system.
22 | package filters
23 |
24 | // FilterInterface is an interface all Filters implement.
25 | type FilterInterface interface {
26 | // Name of the filter
27 | Name() string
28 | // Description of the filter
29 | Description() string
30 |
31 | // Execute the filter
32 | Passes(data map[string]interface{}, value string) bool
33 | }
34 |
35 | var (
36 | filters = make(map[string]*FilterInterface)
37 | )
38 |
39 | // RegisterFilter gets called by Filters to register themselves.
40 | func RegisterFilter(filter FilterInterface) {
41 | // log.Println("Filter bee ready:", filter.Name(), "-", filter.Description())
42 | filters[filter.Name()] = &filter
43 | }
44 |
45 | // GetFilter returns a filter with a specific name
46 | func GetFilter(identifier string) *FilterInterface {
47 | filter, ok := filters[identifier]
48 | if ok {
49 | return filter
50 | }
51 |
52 | return nil
53 | }
54 |
--------------------------------------------------------------------------------
/filters/template/templatefilter.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | // Package templatefilter provides a template-based filter.
22 | package templatefilter
23 |
24 | import (
25 | "bytes"
26 | "strings"
27 | "text/template"
28 |
29 | "github.com/muesli/beehive/filters"
30 | "github.com/muesli/beehive/templatehelper"
31 | )
32 |
33 | // TemplateFilter is a template-based filter.
34 | type TemplateFilter struct {
35 | }
36 |
37 | // Name returns the name of this Filter.
38 | func (filter *TemplateFilter) Name() string {
39 | return "template"
40 | }
41 |
42 | // Description returns the description of this Filter.
43 | func (filter *TemplateFilter) Description() string {
44 | return "This filter passes when a template-if returns true"
45 | }
46 |
47 | // Passes returns true when the Filter matched the data.
48 | func (filter *TemplateFilter) Passes(data map[string]interface{}, v string) bool {
49 | var res bytes.Buffer
50 |
51 | if strings.Contains(v, "{{test") {
52 | v = strings.Replace(v, "{{test", "{{if", -1)
53 | v += "true{{end}}"
54 | }
55 |
56 | tmpl, err := template.New("_" + v).Funcs(templatehelper.FuncMap).Parse(v)
57 | if err == nil {
58 | err = tmpl.Execute(&res, data)
59 | }
60 | if err != nil {
61 | panic(err)
62 | }
63 |
64 | return strings.TrimSpace(res.String()) == "true"
65 | }
66 |
67 | func init() {
68 | f := TemplateFilter{}
69 |
70 | filters.RegisterFilter(&f)
71 | }
72 |
--------------------------------------------------------------------------------
/filters/template/templatefilter_test.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2017 Christian Muehlhaeuser
3 | *
4 | * This program is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Affero General Public License as published
6 | * by the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Affero General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Affero General Public License
15 | * along with this program. If not, see .
16 | *
17 | * Authors:
18 | * Christian Muehlhaeuser
19 | */
20 |
21 | package templatefilter
22 |
23 | import (
24 | "testing"
25 | )
26 |
27 | func TestTemplateFilter(t *testing.T) {
28 | f := TemplateFilter{}
29 |
30 | o := map[string]interface{}{}
31 | o["text"] = "hello world"
32 |
33 | if !f.Passes(o, "{{$args := Split .text \" \"}}{{test eq (len $args) 2}}") {
34 | t.Error("TemplateFilter fails on string comparison")
35 | }
36 | if f.Passes(o, "{{$args := Split .text \" \"}}{{test eq (len $args) 3}}") {
37 | t.Error("TemplateFilter fails on string comparison")
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/hives_linux.go:
--------------------------------------------------------------------------------
1 | // +build linux
2 |
3 | /*
4 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published
8 | * by the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | *
19 | * Authors:
20 | * Christian Muehlhaeuser
21 | */
22 |
23 | package main
24 |
25 | import (
26 | _ "github.com/muesli/beehive/bees/notificationbee"
27 | _ "github.com/muesli/beehive/bees/serialbee"
28 | )
29 |
--------------------------------------------------------------------------------
/hives_osx.go:
--------------------------------------------------------------------------------
1 | // +build darwin
2 |
3 | /*
4 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published
8 | * by the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | *
19 | * Authors:
20 | * Christian Muehlhaeuser
21 | */
22 |
23 | package main
24 |
25 | import (
26 | _ "github.com/muesli/beehive/bees/notificationbee"
27 | _ "github.com/muesli/beehive/bees/serialbee"
28 | )
29 |
--------------------------------------------------------------------------------
/hives_unix.go:
--------------------------------------------------------------------------------
1 | // +build dragonfly freebsd linux netbsd openbsd solaris
2 |
3 | /*
4 | * Copyright (C) 2014-2017 Christian Muehlhaeuser
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU Affero General Public License as published
8 | * by the Free Software Foundation, either version 3 of the License, or
9 | * (at your option) any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU Affero General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU Affero General Public License
17 | * along with this program. If not, see .
18 | *
19 | * Authors:
20 | * Christian Muehlhaeuser
21 | */
22 |
23 | package main
24 |
25 | import (
26 | )
27 |
--------------------------------------------------------------------------------
/templatehelper/templatehelper_test.go:
--------------------------------------------------------------------------------
1 | package templatehelper
2 |
3 | import (
4 | "bytes"
5 | "testing"
6 | "text/template"
7 | )
8 |
9 | func executeTemplate(text string, data interface{}) (string, error) {
10 | var res bytes.Buffer
11 | tmpl, err := template.New("_test").Funcs(FuncMap).Parse(text)
12 | if err == nil {
13 | err = tmpl.Execute(&res, data)
14 | }
15 | return res.String(), err
16 | }
17 |
18 | func Test_FuncMap_Positive(t *testing.T) {
19 | t.Parallel()
20 | cases := []struct {
21 | text string
22 | expected string
23 | }{
24 | // sanity checks
25 |
26 | {`{{if true}}ok{{end}}`, "ok"},
27 | {`{{if false}}ok{{end}}`, ""},
28 |
29 | // boolean filters
30 |
31 | {`{{if Matches "123" "\\d+"}}ok{{end}}`, "ok"},
32 | {`{{if Matches "hello" "\\d+"}}ok{{end}}`, ""},
33 |
34 | {`{{if Contains "123" "2"}}ok{{end}}`, "ok"},
35 | {`{{if Contains "123" "4"}}ok{{end}}`, ""},
36 |
37 | {`{{if ContainsAny "123" "24"}}ok{{end}}`, "ok"},
38 | {`{{if ContainsAny "123" "45"}}ok{{end}}`, ""},
39 |
40 | {`{{if EqualFold "HellO" "hello"}}ok{{end}}`, "ok"},
41 | {`{{if EqualFold "ПривеТ" "привет"}}ok{{end}}`, "ok"},
42 | {`{{if EqualFold "good" "goed"}}ok{{end}}`, ""},
43 |
44 | {`{{if HasPrefix "hello" "he"}}ok{{end}}`, "ok"},
45 | {`{{if HasPrefix "hello" "lo"}}ok{{end}}`, ""},
46 |
47 | {`{{if HasSuffix "hello" "lo"}}ok{{end}}`, "ok"},
48 | {`{{if HasSuffix "hello" "he"}}ok{{end}}`, ""},
49 |
50 | // filters returning a string
51 |
52 | {`{{JSON 123}}`, "[123]"},
53 |
54 | {`{{Left "123456" 2}}`, "12"},
55 | {`{{Left "123456" 10}}`, "123456"},
56 |
57 | {`{{Right "123456" 2}}`, "56"},
58 | {`{{Right "123456" 10}}`, "123456"},
59 |
60 | {`{{Last (Split "12,34,56" ",")}}`, "56"},
61 |
62 | {`{{Mid "123456" 2}}`, "3456"},
63 | {`{{Mid "123456" 10}}`, ""},
64 | {`{{Mid "123456" 2 4}}`, "34"},
65 | {`{{Mid "123456" 2 10}}`, "3456"},
66 |
67 | {`{{Join (Split "12,34,56" ",") "|"}}`, "12|34|56"},
68 | {`{{Join (Split "12" ",") "|"}}`, "12"},
69 |
70 | {`{{Repeat "12" 3}}`, "121212"},
71 | {`{{Repeat "12" 0}}`, ""},
72 | {`{{Repeat "" 10}}`, ""},
73 |
74 | {`{{Replace "1234" "23" "56" -1}}`, "1564"},
75 | {`{{Replace "12223" "2" "5" 1}}`, "15223"},
76 | // ...
77 | }
78 |
79 | for _, tcase := range cases {
80 | tcase := tcase // important, needed for running in parallel
81 | t.Run(tcase.text, func(t *testing.T) {
82 | t.Parallel()
83 | result, err := executeTemplate(tcase.text, nil)
84 | if err != nil {
85 | t.Errorf("error executing template: %s", err.Error())
86 | t.FailNow()
87 | }
88 | if result != tcase.expected {
89 | t.Errorf("expected `%s` but actually `%s`", tcase.expected, result)
90 | t.FailNow()
91 | }
92 | })
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/tools/encrypted-config-wrapper:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # Beehive shell wrapper that reads configuration password from the keyring.
3 | # Store the configuration password using secret-tool:
4 | #
5 | # secret-tool store --label "Beehive configuration password" /beehive/secrets/config password
6 | #
7 | # Linux only.
8 | #
9 | set -e
10 |
11 | export BEEHIVE_CONFIG_PASSWORD=$(secret-tool lookup /beehive/secrets/config password)
12 | if [ -z "$BEEHIVE_CONFIG_PASSWORD" ]; then
13 | echo "Beehive's config password not found in keyring." >&2
14 | echo "Add it using 'secret-tool store --label "Beehive configuration password" /beehive/secrets/config password'" >&2
15 | exit 1
16 | fi
17 | beehive --config crypto://$HOME/.config/beehive/beehive.conf
18 |
--------------------------------------------------------------------------------
/tools/release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | if ! command -v goreleaser; then
4 | echo "goreleaser not found"
5 | exit 1
6 | fi
7 |
8 | # Get the highest tag number
9 | VERSION="$(git describe --abbrev=0 --tags)"
10 | VERSION=${VERSION:-'0.0.0'}
11 |
12 | # Get number parts
13 | MAJOR="${VERSION%%.*}"; VERSION="${VERSION#*.}"
14 | MINOR="${VERSION%%.*}"; VERSION="${VERSION#*.}"
15 | PATCH="${VERSION%%.*}"; VERSION="${VERSION#*.}"
16 |
17 | # Increase version
18 | PATCH=$((PATCH+1))
19 |
20 | TAG="${1}"
21 |
22 | if [ "${TAG}" = "" ]; then
23 | TAG="${MAJOR}.${MINOR}.${PATCH}"
24 | fi
25 |
26 | echo "Releasing ${TAG} ..."
27 |
28 | git tag -a -s -m "Release ${TAG}" "${TAG}"
29 | git push --tags
30 | goreleaser release --rm-dist
31 |
--------------------------------------------------------------------------------
/watchdog_linux.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "net/http"
5 | "time"
6 |
7 | "github.com/coreos/go-systemd/daemon"
8 | "github.com/muesli/beehive/api"
9 | log "github.com/sirupsen/logrus"
10 | )
11 |
12 | // Notifies Systemd's watchdog every WatchdogSec/3 seconds when running
13 | // under Systemd and the watchdog feature has been enabled in
14 | // the service unit.
15 | //
16 | // This will no-op when not running under Systemd.
17 | //
18 | // See http://0pointer.de/blog/projects/watchdog.html
19 | // and https://www.freedesktop.org/software/systemd/man/systemd.service.html
20 | //
21 | func init() {
22 | // returns the configured WatchdogSec in the service unit as time.Duration
23 | interval, err := daemon.SdWatchdogEnabled(false)
24 | if err != nil || interval == 0 {
25 | log.Debug("Systemd watchdog not enabled")
26 | return
27 | }
28 |
29 | // We want to notify the watchdog every WatchdogSec/3, that is, if WatchdogSec is
30 | // set to 30 seconds, we'll send a notification to systemd every 10 seconds.
31 | runEvery := interval / 3
32 | log.Debugf("Systemd watchdog notifications every %.2f seconds", runEvery.Seconds())
33 |
34 | go func() {
35 | for {
36 | select {
37 | case <-time.After(runEvery):
38 | resp, err := http.Get(api.CanonicalURL().String())
39 | if err == nil {
40 | resp.Body.Close()
41 | log.Debugf("Systemd watchdog notify")
42 | daemon.SdNotify(false, daemon.SdNotifyWatchdog)
43 | }
44 | }
45 | }
46 | }()
47 | }
48 |
--------------------------------------------------------------------------------