Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 0.2.0 #2

Merged
merged 5 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Check project in all branches

on:
workflow_call:
push:
branches-ignore:
- master

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

env:
POSTGRES_USER: inclusive_dance
POSTGRES_PASSWORD: 3d88lacj9327s
POSTGRES_HOST: postgres
POSTGRES_PORT: 5432
POSTGRES_DB: inclusive_dance_bot

REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: 389jf928fhf10
REDIS_DB: '3'

PROJECT_PATH: ./inclusive_dance_bot/
TEST_PATH: ./tests/

jobs:
checking:
runs-on: ubuntu-22.04
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Setup python 3.11
uses: actions/setup-python@v4
with:
python-version: '3.11'

- name: Install dependencies
run: |
python -m pip install -U pip poetry
poetry config virtualenvs.create false
poetry install

- name: Run flake8
run: flake8 --max-line-length 88 --format=default ${{ env.PROJECT_PATH }} 2>&1 | tee flake8.txt

- name: Run black
run: black ${{ env.PROJECT_PATH }} --check

- name: Run bandit
run: bandit -r -ll -iii ${{ env.PROJECT_PATH }} -f json -o ./bandit.json

- name: Run mypy
run: mypy --config-file ./pyproject.toml ${{ env.PROJECT_PATH }}

test:
name: Run service tests with pytest
runs-on: ubuntu-22.04
container: python:3.11-slim
needs: checking
services:
postgres:
image: postgres:15
env:
TZ: UTC
POSTGRES_USER: ${{ env.POSTGRES_USER }}
POSTGRES_DB: ${{ env.POSTGRES_DB }}
POSTGRES_PASSWORD: ${{ env.POSTGRES_PASSWORD }}
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Install dependencies
run: |
python -m pip install -U pip poetry
poetry config virtualenvs.create false
poetry install

- name: Run pytest
run: python -m pytest ${{ env.TEST_PATH }} --junitxml=./junit.xml --cov=${{ env.PROJECT_PATH }} --cov-report=xml
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ default_language_version:

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
rev: v4.5.0
hooks:
- id: check-added-large-files
- id: check-ast
Expand Down Expand Up @@ -33,7 +33,7 @@ repos:
- id: text-unicode-replacement-char

- repo: https://github.com/asottile/pyupgrade
rev: v3.11.1
rev: v3.15.0
hooks:
- id: pyupgrade
args: [--py311-plus]
Expand All @@ -49,7 +49,7 @@ repos:
- --ignore-init-module-imports

- repo: https://github.com/psf/black
rev: 23.9.1
rev: 23.10.1
hooks:
- id: black
language_version: python3.11
Expand Down Expand Up @@ -87,7 +87,7 @@ repos:
- id: docker-compose-check

- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
rev: v2.10.0
rev: v2.11.0
hooks:
- id: pretty-format-yaml
args: [--autofix, --indent, '2', --offset, '2']
Expand Down
39 changes: 39 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
PROJECT_PATH = ./inclusive_dance_bot/
TEST_PATH = ./tests/

HELP_FUN = \
%help; while(<>){push@{$$help{$$2//'options'}},[$$1,$$3] \
if/^([\w-_]+)\s*:.*\#\#(?:@(\w+))?\s(.*)$$/}; \
print"$$_:\n", map" $$_->[0]".(" "x(20-length($$_->[0])))."$$_->[1]\n",\
@{$$help{$$_}},"\n" for keys %help; \

help: ##@Help Show this help
@echo -e "Usage: make [target] ...\n"
@perl -e '$(HELP_FUN)' $(MAKEFILE_LIST)

lint-ci: flake black bandit mypy ##@Linting Run all linters in CI

flake: ##@Linting Run flake8
flake8 --max-line-length 88 --format=default $(PROJECT_PATH) 2>&1 | tee flake8.txt

black: ##@Linting Run black
black $(PROJECT_PATH) --check

bandit: ##@Linting Run bandit
bandit -r -ll -iii $(PROJECT_PATH) -f json -o ./bandit.json

mypy: ##@Linting Run mypy
mypy --config-file ./pyproject.toml $(PROJECT_PATH)

test: ##@Test Run tests with pytest
pytest -vvx $(TEST_PATH)

test-ci: ##@Test Run tests with pytest and coverage in CI
pytest $(TEST_PATH) --junitxml=./junit.xml --cov=$(PROJECT_PATH) --cov-report=xml


local: ##@Develop Run db and redis containers
docker-compose -f docker-compose.dev.yaml up db redis -d

local_down: ##@Develop Stop containers with delete volumes
docker-compose -f docker-compose.dev.yaml down -v
68 changes: 66 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,79 @@

## Stack

<a href="https://github.com/Ileriayo/markdown-badges">
<p align="center">
<img alt="Python" src="https://img.shields.io/badge/python-3670A0?style=for-the-badge&logo=python&logoColor=ffdd54"/>
<img alt="Docker" src="https://img.shields.io/badge/docker-%230db7ed.svg?style=for-the-badge&logo=docker&logoColor=white"/>
<img alt="Postgres" src="https://img.shields.io/badge/postgres-%23316192.svg?style=for-the-badge&logo=postgresql&logoColor=white"/>
<img alt="Redis" src="https://img.shields.io/badge/redis-%23DD0031.svg?style=for-the-badge&logo=redis&logoColor=white"/>
<img alt="GitHub" src="https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white"/>
<img alt="GitHub Actions" src="https://img.shields.io/badge/githubactions-%232671E5.svg?style=for-the-badge&logo=githubactions&logoColor=white"/>
</p>
</a>

## Description

Telegram bot for informing the audience and feedback. You can fully control the bot from the admin menu: change the displayed menus and messages, collect feedback and send out announcements on a schedule.

The bot was created completely asynchronous using [aiogram 3.0+](https://aiogram.dev/), [aiogram-dialogs 2.0+](https://aiogram-dialog.readthedocs.io/en/2.0.0/), [aiomisc](https://aiomisc.readthedocs.io/) and [sqalchemy](https://www.sqlalchemy.org/) libraries.

Initially, this project was developed to help the organization of [Inclusive Dance](https://inclusive-dance.ru/).

## Using

### Environment Variables
### Settings

Environment variables are used to configure the bot for connecting to Telegram, Postgres and Redis.

```bash

TELEGRAM_BOT_TOKEN # your bot token
TELEGRAM_BOT_ADMIN_IDS # Superadmin IDs, who can appoint other admins

DEBUG # Flag for debugging (using in sqlalchemy engine for echo)

POSTGRES_HOST # database host
POSTGRES_PORT # database port
POSTGRES_USER # database user
POSTGRES_PASSWORD # database password
POSTGRES_DB # database name

REDIS_HOST # redis host
REDIS_PORT # redis port
REDIS_PASSWORD # redis password
REDIS_DB # redis db
```

### Docker

You can get image from public Docker Hub from [here](https://hub.docker.com/r/andytakker/inclusive_dance_bot).

```bash
docker pull andytakker/inclusive_dance_bot
```

## Running
### Local

Before you need to create env and install dependencies

```bash
python3.11 -m venv .venv
source .venv/bin/activate
pip install -U pip poetry
poetry install
```

For start the bot local you can use poetry

```bash
poetry run bot
```

### Test

For the main functions of the bot, tests are written using pytest. For running

```bash
pytest -vx ./tests/
```
24 changes: 24 additions & 0 deletions docker-compose.dev.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
version: '3.8'
services:
db:
image: postgres:15
restart: unless-stopped
environment:
POSTGRES_USER: $POSTGRES_USER
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
POSTGRES_DB: $POSTGRES_DB
ports:
- 5432:5432
volumes:
- postgres_data:/var/lib/postgresql/data

redis:
image: redis
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
ports:
- 6379:6379

volumes:
postgres_data:
driver: local
2 changes: 0 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ services:
image: redis
restart: unless-stopped
command: redis-server --requirepass ${REDIS_PASSWORD}
ports:
- 6379:6379

bot:
image: andytakker/inclusive_dance_bot:latest
Expand Down
30 changes: 30 additions & 0 deletions inclusive_dance_bot/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import logging

from aiomisc import Service, entrypoint
from aiomisc_log import basic_config

from inclusive_dance_bot.config import Settings
from inclusive_dance_bot.deps import config_deps
from inclusive_dance_bot.services.bot import AiogramBotService
from inclusive_dance_bot.services.periodic import PeriodicMailingService

log = logging.getLogger(__name__)


def main() -> None:
settings = Settings()
basic_config()
config_deps(app_settings=settings)
services: list[Service] = [
AiogramBotService(),
PeriodicMailingService(
interval=settings.PERIODIC_INTERVAL,
delay=0,
gap=settings.MAILING_GAP,
),
]
with entrypoint(
*services,
) as loop:
log.info("Entrypoint started")
loop.run_forever()
61 changes: 0 additions & 61 deletions inclusive_dance_bot/bot/__main__.py

This file was deleted.

13 changes: 3 additions & 10 deletions inclusive_dance_bot/bot/dialogs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,13 @@
from aiogram import F, Router
from aiogram import Router
from aiogram.filters import Command

from inclusive_dance_bot.bot.dialogs.admins import register_admin_dialogs
from inclusive_dance_bot.bot.dialogs import admins, users
from inclusive_dance_bot.bot.dialogs.commands import start_command
from inclusive_dance_bot.bot.dialogs.users import register_user_dialogs
from inclusive_dance_bot.bot.ui_commands import Commands


def register_dialogs(router: Router) -> None:
dialog_router = Router()

# admin_router = register_admin_dialogs()
# dialog_router.include_router(admin_router)

user_router = register_user_dialogs()
dialog_router.include_router(user_router)

dialog_router.include_routers(admins.dialog_router, users.dialog_router)
dialog_router.message(Command(Commands.START))(start_command)
router.include_router(dialog_router)
Loading