diff --git a/.github/workflows/black.yaml b/.github/workflows/black.yaml new file mode 100644 index 0000000..3d0810e --- /dev/null +++ b/.github/workflows/black.yaml @@ -0,0 +1,27 @@ +name: Black + +on: + push: + branches: [ master, stable ] + pull_request: + branches: [ master, stable ] + +jobs: + black: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.8 + + - name: Install dependencies + run: | + pip install --upgrade pip + pip install black + + - name: Black check + run: | + black --check butterrobot diff --git a/.github/workflows/docker-build-latest.yaml b/.github/workflows/docker-build-latest.yaml new file mode 100644 index 0000000..de0b1e9 --- /dev/null +++ b/.github/workflows/docker-build-latest.yaml @@ -0,0 +1,21 @@ +name: Build latest tag docker image + +on: + push: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Build the Docker image + run: docker build --tag butterrobot:$(git rev-parse --short HEAD) -f Dockerfile.dev . + + - name: Push into Github packages (latest) + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com -u fmartingr --password-stdin + docker tag butterrobot:$(git rev-parse --short HEAD) docker.pkg.github.com/fmartingr/butterrobot/butterrobot:latest + docker push docker.pkg.github.com/fmartingr/butterrobot/butterrobot:latest diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml new file mode 100644 index 0000000..8db9c98 --- /dev/null +++ b/.github/workflows/pytest.yaml @@ -0,0 +1,32 @@ +name: Pytest + +on: + push: + branches: [ master, stable ] + pull_request: + branches: [ master, stable ] + +jobs: + pytest: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.8] + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + pip install --upgrade pip poetry + poetry install + + - name: Test with pytest + run: | + ls + poetry run pytest --cov=butterrobot --cov=butterrobot_plugins_contrib diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..00984ea --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,47 @@ +name: Release + +on: + push: + branches: + - stable + +jobs: + prepare: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + publish: + runs-on: ubuntu-latest + needs: + - prepare + steps: + - name: Set up Python 3.8 + uses: actions/setup-python@v1 + with: + python-version: 3.8 + + - name: Install poetry + run: | + pip install poetry + + - name: Build and publish + run: | + poetry publish -u ${{ secrets.PYPI_USERNAME }} -p ${{ secrets.PYPI_PASSWORD }} --build + + build: + runs-on: ubuntu-latest + needs: + - prepare + - publish + steps: + - name: Build the Docker image + run: docker build --tag butterrobot:$(git rev-parse --short HEAD) docker + + - name: Push into Github packages (stable) + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com -u fmartingr --password-stdin + docker tag butterrobot:$(git rev-parse --short HEAD) docker.pkg.github.com/fmartingr/butterrobot/butterrobot:stable + docker tag butterrobot:$(git rev-parse --short HEAD) docker.pkg.github.com/fmartingr/butterrobot/butterrobot:$(cat pyproject.toml | grep version | cut -d "\"" -f 2) + docker push docker.pkg.github.com/fmartingr/butterrobot/butterrobot:stable + docker push docker.pkg.github.com/fmartingr/butterrobot/butterrobot:$(cat pyproject.toml | grep version | cut -d "\"" -f 2) diff --git a/.gitignore b/.gitignore index d964ffb..309685e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,10 +4,16 @@ __pycache__ *~ *.cert .env-local +test.py .coverage +# Distribution dist -bin +*.egg-info +pip-wheel-metadata + +# Github Codespaces +pythonenv3.8 + # Butterrobot *.sqlite* -butterrobot.db diff --git a/.goreleaser.yml b/.goreleaser.yml deleted file mode 100644 index a3836e9..0000000 --- a/.goreleaser.yml +++ /dev/null @@ -1,150 +0,0 @@ -version: 2 - -gitea_urls: - api: https://git.nakama.town/api/v1 - download: https://git.nakama.town - -before: - hooks: - - go mod tidy - -git: - ignore_tags: - - "{{ if not .IsNightly }}*-rc*{{ end }}" - -builds: - - binary: butterrobot - main: ./cmd/butterrobot - env: - - CGO_ENABLED=0 - - GIN_MODE=release - tags: - - netgo - - osusergo - goos: - - linux - - windows - - darwin - goarch: - - amd64 - - arm - - arm64 - goarm: - - "7" - ignore: - - goos: darwin - goarch: arm - - goos: windows - goarch: arm - - goos: windows - goarch: arm64 - -archives: - - id: butterrobot - name_template: >- - {{ .ProjectName }}_ - {{- if eq .Os "darwin" }}Darwin{{- else if eq .Os "linux" }}Linux{{- else if eq .Os "windows" }}Windows{{- else }}{{ .Os }}{{ end }}_ - {{- if eq .Arch "amd64" }}x86_64{{- else if eq .Arch "arm64" }}aarch64{{- else }}{{ .Arch }}{{ end }}_{{ .Version }} - format_overrides: - - goos: windows - formats: ['zip'] - -dockers: -- image_templates: - - &amd64_image "git.nakama.town/fmartingr/butterrobot:{{ .Version }}-amd64" - use: buildx - dockerfile: &dockerfile Containerfile - goos: linux - goarch: amd64 - build_flag_templates: - - "--pull" - - "--platform=linux/amd64" -- image_templates: - - &arm64_image "git.nakama.town/fmartingr/butterrobot:{{ .Version }}-arm64" - use: buildx - dockerfile: *dockerfile - goos: linux - goarch: arm64 - build_flag_templates: - - "--pull" - - "--platform=linux/arm64" -- image_templates: - - &armv7_image "git.nakama.town/fmartingr/butterrobot:{{ .Version }}-armv7" - use: buildx - dockerfile: *dockerfile - goos: linux - goarch: arm - goarm: "7" - build_flag_templates: - - "--pull" - - "--platform=linux/arm/v7" - -docker_manifests: - - name_template: "git.nakama.town/fmartingr/butterrobot:{{ .Version }}" - image_templates: - - *amd64_image - - *arm64_image - - *armv7_image - # - name_template: "git.nakama.town/fmartingr/butterrobot:latest" - # image_templates: - # - *amd64_image - # - *arm64_image - # - *armv7_image - -nfpms: - - maintainer: Felipe Martin - description: A chatbot server with customizable commands and triggers - homepage: https://git.nakama.town/fmartingr/butterrobot - license: AGPL-3.0 - formats: - - deb - - rpm - - apk - -upx: - - enabled: true - ids: - - butterrobot - goos: [linux, darwin] - goarch: [amd64, arm, arm64] - goarm: ["7"] - -checksum: - name_template: 'checksums.txt' - -snapshot: - version_template: "{{ incpatch .Version }}-next" - -changelog: - sort: asc - groups: - - title: Features - regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$' - order: 0 - - title: "Fixes" - regexp: '^.*?fix(\([[:word:]]+\))??!?:.+$' - order: 1 - - title: "Performance" - regexp: '^.*?perf(\([[:word:]]+\))??!?:.+$' - order: 2 - - title: API - regexp: '^.*?api(\([[:word:]]+\))??!?:.+$' - order: 3 - - title: Documentation - regexp: '^.*?docs(\([[:word:]]+\))??!?:.+$' - order: 4 - - title: "Tests" - regexp: '^.*?test(\([[:word:]]+\))??!?:.+$' - order: 5 - - title: CI and Delivery - regexp: '^.*?ci(\([[:word:]]+\))??!?:.+$' - order: 6 - - title: Others - order: 999 - filters: - exclude: - - "^deps:" - - "^chore\\(deps\\):" - -release: - prerelease: auto diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..621aa22 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,22 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.2.3 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: flake8 + +- repo: https://github.com/asottile/seed-isort-config + rev: v1.9.2 + hooks: + - id: seed-isort-config +- repo: https://github.com/pre-commit/mirrors-isort + rev: v4.3.20 + hooks: + - id: isort + +- repo: https://github.com/ambv/black + rev: stable + hooks: + - id: black + language_version: python3 diff --git a/.woodpecker/ci.yml b/.woodpecker/ci.yml deleted file mode 100644 index 5b32d48..0000000 --- a/.woodpecker/ci.yml +++ /dev/null @@ -1,23 +0,0 @@ -when: - event: - - push - - pull_request - branch: - - master - -steps: - format: - image: golang:1.24 - commands: - - make format - - git diff --exit-code # Fail if files were changed - - lint: - image: golang:1.24 - commands: - - make ci-lint - - test: - image: golang:1.24 - commands: - - make test diff --git a/.woodpecker/release.yml b/.woodpecker/release.yml deleted file mode 100644 index 39dbf65..0000000 --- a/.woodpecker/release.yml +++ /dev/null @@ -1,16 +0,0 @@ -when: - - event: tag - branch: master - -steps: - - name: Release - image: goreleaser/goreleaser:latest - environment: - GITEA_TOKEN: - from_secret: GITEA_TOKEN - DOCKER_HOST: unix:///var/run/docker.sock - volumes: - - "/var/run/docker.sock:/var/run/docker.sock" - commands: - - docker login -u fmartingr -p $GITEA_TOKEN git.nakama.town - - goreleaser release --clean --parallelism=2 diff --git a/Containerfile b/Containerfile deleted file mode 100644 index 6a9ff7d..0000000 --- a/Containerfile +++ /dev/null @@ -1,6 +0,0 @@ -# This file is used directly by the goreleaser build -# It is used to build the final container image -FROM scratch -WORKDIR / -COPY /butterrobot /usr/bin/butterrobot -ENTRYPOINT ["/usr/bin/butterrobot"] diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 0000000..c1a4a16 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,26 @@ +FROM docker.io/library/alpine:3.11 + +ENV PYTHON_VERSION=3.8.2-r1 +ENV APP_PORT 8080 +ENV BUILD_DIR /tmp/build +ENV APP_PATH /etc/butterrobot + +WORKDIR ${BUILD_DIR} +COPY README.md ${BUILD_DIR}/README.md +COPY poetry.lock ${BUILD_DIR}/poetry.lock +COPY pyproject.toml ${BUILD_DIR}/pyproject.toml +COPY ./butterrobot_plugins_contrib ${BUILD_DIR}/butterrobot_plugins_contrib +COPY ./butterrobot ${BUILD_DIR}/butterrobot +RUN apk --update add curl python3-dev==${PYTHON_VERSION} gcc musl-dev libffi-dev openssl-dev && \ + pip3 install poetry && \ + poetry build && \ + pip3 install ${BUILD_DIR}/dist/butterrobot-*.tar.gz && \ + rm -rf ${BUILD_DIR} && \ + mkdir ${APP_PATH} && \ + chown -R 1000:1000 ${APP_PATH} + +USER 1000 +WORKDIR ${APP_PATH} +COPY ./docker/bin/start-server.sh /usr/local/bin/start-server + +CMD ["/usr/local/bin/start-server"] diff --git a/Makefile b/Makefile index ff08163..2791e1c 100644 --- a/Makefile +++ b/Makefile @@ -1,100 +1,27 @@ -PROJECT_NAME := butterrobot +# Local development +setup: + poetry install -SOURCE_FILES ?=./... +podman@build: + podman build -t fmartingr/butterrobot -f docker/Dockerfile docker -TEST_OPTIONS ?= -v -failfast -race -bench=. -benchtime=100000x -cover -coverprofile=coverage.out -TEST_TIMEOUT ?=1m +podman@build-dev: + podman build -t fmartingr/butterrobot:dev -f Dockerfile.dev . -GOLANGCI_LINT_VERSION ?= v1.64.5 +podman@tag-dev: + podman tag fmartingr/butterrobot:dev registry.int.fmartingr.network/fmartingr/butterrobot:dev -CLEAN_OPTIONS ?=-modcache -testcache +podman@push-dev: + podman push registry.int.fmartingr.network/fmartingr/butterrobot:dev --tls-verify=false -CGO_ENABLED := 0 +podman@dev: + make podman@build-dev + make podman@tag-dev + make podman@push-dev -BUILDS_PATH := ./dist -FROM_MAKEFILE := y +test: + poetry run pytest --cov=butterrobot --cov=butterrobot_plugins_contrib -CONTAINERFILE_NAME := Containerfile -CONTAINER_ALPINE_VERSION := 3.21 -CONTAINER_SOURCE_URL := "https://git.nakama.town/fmartingr/${PROJECT_NAME}" -CONTAINER_MAINTAINER := "Felipe Martin " -CONTAINER_BIN_NAME := ${PROJECT_NAME} - -BUILDX_PLATFORMS := linux/amd64,linux/arm64,linux/arm/v7 - -export PROJECT_NAME -export FROM_MAKEFILE - -export CGO_ENABLED - -export SOURCE_FILES -export TEST_OPTIONS -export TEST_TIMEOUT -export BUILDS_PATH - -export CONTAINERFILE_NAME -export CONTAINER_ALPINE_VERSION -export CONTAINER_SOURCE_URL -export CONTAINER_MAINTAINER -export CONTAINER_BIN_NAME - -export BUILDX_PLATFORMS - -.PHONY: all -all: help - -# this is godly -# https://news.ycombinator.com/item?id=11939200 -.PHONY: help -help: ### this screen. Keep it first target to be default -ifeq ($(UNAME), Linux) - @grep -P '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | \ - awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' -else - @# this is not tested, but prepared in advance for you, Mac drivers - @awk -F ':.*###' '$$0 ~ FS {printf "%15s%s\n", $$1 ":", $$2}' \ - $(MAKEFILE_LIST) | grep -v '@awk' | sort -endif - -.PHONY: clean -clean: ### clean test cache, build files - $(info: Make: Clean) - @rm -rf ${BUILDS_PATH} - @go clean ${CLEAN_OPTIONS} - @-docker buildx rm ${PROJECT_NAME}_builder - -.PHONY: build -build: clean ### builds the project for the setup os/arch combinations - $(info: Make: Build) - @goreleaser --clean --snapshot - -.PHONY: quick-run -quick-run: ### Executes the project using golang - CGO_ENABLED=${CGO_ENABLED} go run ./cmd/${PROJECT_NAME}/*.go - -.PHONY: run -run: ### Executes the project build locally - @make build - ${BUILDS_PATH}/${PROJECT_NAME} - -.PHONY: format -format: ### Executes the formatting pipeline on the project - $(info: Make: Format) - @go fmt ./... - @go mod tidy - -.PHONY: ci-lint -ci-lint: ### Check the project for errors - $(info: Make: Lint) - @go install github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_LINT_VERSION} - @golangci-lint run ./... - -.PHONY: lint -lint: ### Check the project for errors - $(info: Make: Lint) - @golangci-lint run ./... - -.PHONY: test -test: ### Runs the test suite - $(info: Make: Test) - CGO_ENABLED=1 go test ${TEST_OPTIONS} -timeout=${TEST_TIMEOUT} ${SOURCE_FILES} +clean: + rm -rf dist + rm -rf butterrobot.egg-info diff --git a/README.md b/README.md index 920d087..7fb78d6 100644 --- a/README.md +++ b/README.md @@ -1,82 +1,53 @@ # Butter Robot -![Status badge](https://woodpecker.local.fmartingr.dev/api/badges/5/status.svg) +| Stable | Master | +| --- | --- | +| ![Build stable tag docker image](https://github.com/fmartingr/butterrobot/workflows/Build%20stable%20tag%20docker%20image/badge.svg?branch=stable) | ![Build latest tag docker image](https://github.com/fmartingr/butterrobot/workflows/Build%20latest%20tag%20docker%20image/badge.svg?branch=master) | +| ![Pytest](https://github.com/fmartingr/butterrobot/workflows/Pytest/badge.svg?branch=stable) | ![Pytest](https://github.com/fmartingr/butterrobot/workflows/Pytest/badge.svg?branch=master) | -Go framework to create bots for several platforms. +Python framework to create bots for several platforms. ![Butter Robot](./assets/icon@120.png) > What is my purpose? -## Features - -- Support for multiple chat platforms (Slack (untested!), Telegram) -- Plugin system for easy extension -- Admin interface for managing channels and plugins -- Message queue for asynchronous processing - ## Documentation [Go to documentation](./docs) -### Database Management - -ButterRobot includes an automatic database migration system. Migrations are applied automatically when the application starts, ensuring your database schema is always up to date. - -[Learn more about migrations](./docs/migrations.md) - ## Installation -### From Source +### PyPi -```bash -# Clone the repository -git clone https://git.nakama.town/fmartingr/butterrobot.git -cd butterrobot +You can run it directly by installing the package and calling it +with `python` though this is not recommended and only intended for +development purposes. -# Build the application -go build -o butterrobot ./cmd/butterrobot +``` +$ pip install --user butterrobot +$ python -m butterrobot ``` ### Containers -The `fmartingr/butterrobot/butterrobot` container image is published on Github packages: +The `fmartingr/butterrobot/butterrobot` container image is published on Github packages to use with your favourite tool: -```bash -docker pull docker.pkg.git.nakama.town/fmartingr/butterrobot/butterrobot:latest -docker run -d --name butterrobot -p 8080:8080 docker.pkg.git.nakama.town/fmartingr/butterrobot/butterrobot:latest ``` - -## Configuration - -Configuration is done through environment variables: - -- `DEBUG`: Set to "y" to enable debug mode -- `BUTTERROBOT_HOSTNAME`: Hostname for webhook URLs -- `LOG_LEVEL`: Logging level (DEBUG, INFO, WARN, ERROR) -- `SECRET_KEY`: Secret key for sessions and password hashing -- `DATABASE_PATH`: Path to SQLite database file - -### Platform-specific configuration - -#### Slack - -- `SLACK_TOKEN`: Slack app access token -- `SLACK_BOT_OAUTH_ACCESS_TOKEN`: Slack bot OAuth access token - -#### Telegram - -- `TELEGRAM_TOKEN`: Telegram bot token +docker pull docker.pkg.github.com/fmartingr/butterrobot/butterrobot:latest +podman run -d --name fmartingr/butterrobot/butterrobot -p 8080:8080 +``` ## Contributing -```bash +To run the project locally you will need [poetry](https://python-poetry.org/). + +``` git clone git@github.com:fmartingr/butterrobot.git cd butterrobot -go mod download +poetry install ``` -Create a `.env-local` file with the required environment variables: +Create a `.env-local` file with the required environment variables, you have [an example file](.env-example). ``` SLACK_TOKEN=xxx @@ -84,12 +55,8 @@ TELEGRAM_TOKEN=xxx ... ``` -And then you can run it directly: +And then you can run it directly with poetry -```bash -go run ./cmd/butterrobot/main.go ``` - -## License - -GPL-2.0 +docker run -it --rm --env-file .env-local -p 5000:5000 -v $PWD/butterrobot:/etc/app/butterrobot local/butterrobot python -m butterrobot +``` diff --git a/butterrobot/__init__.py b/butterrobot/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/butterrobot/__main__.py b/butterrobot/__main__.py new file mode 100644 index 0000000..2f0182a --- /dev/null +++ b/butterrobot/__main__.py @@ -0,0 +1,6 @@ +from butterrobot.app import app +from butterrobot.config import DEBUG + +# Only used for local development! +# python -m butterrobot +app.run(debug=DEBUG, host="0.0.0.0") diff --git a/butterrobot/admin/__init__.py b/butterrobot/admin/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/butterrobot/admin/blueprint.py b/butterrobot/admin/blueprint.py new file mode 100644 index 0000000..b9442fd --- /dev/null +++ b/butterrobot/admin/blueprint.py @@ -0,0 +1,156 @@ +import os.path +from functools import wraps + +import structlog +from flask import ( + Blueprint, + g, + flash, + request, + session, + url_for, + redirect, + render_template, +) + +from butterrobot.db import UserQuery, ChannelQuery, ChannelPluginQuery +from butterrobot.plugins import get_available_plugins + +admin = Blueprint("admin", __name__, url_prefix="/admin") +admin.template_folder = os.path.join(os.path.dirname(__name__), "templates") +logger = structlog.get_logger(__name__) + + +def login_required(f): + @wraps(f) + def decorated_function(*args, **kwargs): + if g.user is None: + return redirect(url_for("admin.login_view", next=request.path)) + return f(*args, **kwargs) + + return decorated_function + + +@admin.before_app_request +def load_logged_in_user(): + user_id = session.get("user_id") + + if user_id is None: + g.user = None + else: + try: + user = UserQuery.get(id=user_id) + g.user = user + except UserQuery.NotFound: + g.user = None + + +@admin.route("/") +@login_required +def index_view(): + if not session.get("logged_in", False): + return redirect(url_for("admin.login_view")) + return redirect(url_for("admin.channel_list_view")) + + +@admin.route("/login", methods=["GET", "POST"]) +def login_view(): + error = None + if request.method == "POST": + user = UserQuery.check_credentials( + request.form["username"], request.form["password"] + ) + if not user: + flash("Incorrect credentials", category="danger") + else: + session["logged_in"] = True + session["user_id"] = user.id + flash("You were logged in", category="success") + _next = request.args.get("next", url_for("admin.index_view")) + return redirect(_next) + return render_template("login.j2", error=error) + + +@admin.route("/logout") +@login_required +def logout_view(): + session.clear() + flash("You were logged out", category="success") + return redirect(url_for("admin.index_view")) + + +@admin.route("/plugins") +@login_required +def plugin_list_view(): + return render_template("plugin_list.j2", plugins=get_available_plugins().values()) + + +@admin.route("/channels") +@login_required +def channel_list_view(): + return render_template("channel_list.j2", channels=ChannelQuery.all()) + + +@admin.route("/channels/", methods=["GET", "POST"]) +@login_required +def channel_detail_view(channel_id): + if request.method == "POST": + ChannelQuery.update( + channel_id, + enabled=request.form["enabled"] == "true", + ) + flash("Channel updated", "success") + + channel = ChannelQuery.get(channel_id) + return render_template( + "channel_detail.j2", channel=channel, plugins=get_available_plugins() + ) + + +@admin.route("/channel//delete", methods=["POST"]) +@login_required +def channel_delete_view(channel_id): + ChannelQuery.delete(channel_id) + flash("Channel removed", category="success") + return redirect(url_for("admin.channel_list_view")) + + +@admin.route("/channelplugins", methods=["GET", "POST"]) +@login_required +def channel_plugin_list_view(): + if request.method == "POST": + data = request.form + try: + ChannelPluginQuery.create( + data["channel_id"], data["plugin_id"], enabled=data["enabled"] == "y" + ) + flash(f"Plugin {data['plugin_id']} added to the channel", "success") + except ChannelPluginQuery.Duplicated: + flash( + f"Plugin {data['plugin_id']} is already present on the channel", "error" + ) + return redirect(request.headers.get("Referer")) + + channel_plugins = ChannelPluginQuery.all() + return render_template("channel_plugins_list.j2", channel_plugins=channel_plugins) + + +@admin.route("/channelplugins/", methods=["GET", "POST"]) +@login_required +def channel_plugin_detail_view(channel_plugin_id): + if request.method == "POST": + ChannelPluginQuery.update( + channel_plugin_id, + enabled=request.form["enabled"] == "true", + ) + flash("Plugin updated", category="success") + + return redirect(request.headers.get("Referer")) + + +@admin.route("/channelplugins//delete", methods=["POST"]) +@login_required +def channel_plugin_delete_view(channel_plugin_id): + ChannelPluginQuery.delete(channel_plugin_id) + flash("Plugin removed", category="success") + return redirect(request.headers.get("Referer")) diff --git a/internal/admin/templates/_base.html b/butterrobot/admin/templates/_base.j2 similarity index 71% rename from internal/admin/templates/_base.html rename to butterrobot/admin/templates/_base.j2 index 3ebdf85..d1db800 100644 --- a/internal/admin/templates/_base.html +++ b/butterrobot/admin/templates/_base.j2 @@ -4,7 +4,7 @@ - {{.Title}} - ButterRobot Admin + ButterRobot Admin @@ -24,29 +24,27 @@ - {{if .LoggedIn}} + {% if session.logged_in %}