diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 535bd91..a62af7f 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -15,18 +15,18 @@ permissions: jobs: build: - runs-on: ubuntu-latest + runs-on: debian-latest steps: - uses: actions/checkout@v3 - - name: Set up Python 3.10 + - name: Set up Python 3.11 uses: actions/setup-python@v3 with: - python-version: "3.10" + python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements/common.txt - - name: Test with unittest - run: | - python -m unittest discover -s tests +# - name: Test with unittest +# run: | +# python -m unittest discover -s tests diff --git a/README.md b/README.md index 16fae92..027dbcd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Stan -Multipurpose Asynchronous Telegram Bot for Python group +Admin Bot for Python Telegram group ### What does this project do? * Send links on command (chat rules, FAQs, libraries etc.) @@ -16,12 +16,11 @@ You can use this project as a pre-coded customizable bot. Original (and currently working example) bot's Telegram username: @LutzPyBot ### How to deploy it? - 1. Clone repository on your linux server into `Stan` user's home directory. - 2. Create virtual environment, activate virtual environment, install required packages from `requirements.txt`. - 3. Create `.env` file in `Stan` directory with 3 variables: `LUTZPYBOT` (Bot Token), `whitelist` (White usernames, comma separated), `whiteids` (White IDs, comma separated) - 4. Install `gunicorn` and `uvicorn` package with `pip install gunicorn uvicorn` - 5. Set webhook using Python interactive shell with `bot.set_webhook()` or manually according [Telegram Bot API Documentation](https://core.telegram.org/bots/api#setwebhook). - 6. Configure nginx as a reverse proxy. Example of Nginx config: + 1. Clone repository to your linux server into `/home/username/Stan/` directory. + 2. Create virtual environment, activate virtual environment, install required packages from `/requirements/common.txt` and `/requirements/prod.txt`. + 3. Create `.env` file in `Stan` directory with 3 variables: `STAN` (Bot Token), `whitelist` (White usernames, comma separated), `whiteids` (White IDs, comma separated) + 4. Set webhook using Python interactive shell with `bot.set_webhook()` or manually according [Telegram Bot API Documentation](https://core.telegram.org/bots/api#setwebhook). + 5. Configure nginx as a reverse proxy. Example of Nginx config: ``` server { server_name rykov7.ru; @@ -44,7 +43,7 @@ Original (and currently working example) bot's Telegram username: @LutzPyBot ``` Then install certbot SSL certificate for this config. - 7. Configure the bot as a daemon: + 6. Configure the bot as a daemon: * Create daemon unit file in `/etc/systemd/system/stan.service` with the next content (replace `inferno` with your username): ``` [Unit] @@ -88,4 +87,6 @@ Standard command pack for bot father includes: * rules - Chat rules * faq - FAQ * books - Pythonista's Library -* lutz - Send Lutz book \ No newline at end of file +* lutz - Send Lutz book +* add - Add quote to Stan's dictionary +* add_spam - Add spam phrase to Stan's dictionary diff --git a/requirements/common.in b/requirements/common.in new file mode 100644 index 0000000..5b6a94c --- /dev/null +++ b/requirements/common.in @@ -0,0 +1,5 @@ +aiohttp +python-dotenv +pyTelegramBotAPI +schedule +SQLAlchemy \ No newline at end of file diff --git a/requirements/common.txt b/requirements/common.txt index 710ce42..ee6c2b3 100644 Binary files a/requirements/common.txt and b/requirements/common.txt differ diff --git a/requirements/prod.in b/requirements/prod.in new file mode 100644 index 0000000..3dd39c9 --- /dev/null +++ b/requirements/prod.in @@ -0,0 +1,4 @@ +-c common.txt +fastapi +gunicorn +uvicorn diff --git a/requirements/prod.txt b/requirements/prod.txt index dc6e3e1..befc91f 100644 Binary files a/requirements/prod.txt and b/requirements/prod.txt differ diff --git a/src/commands.py b/src/commands.py index 9c37632..cf4f44e 100644 --- a/src/commands.py +++ b/src/commands.py @@ -5,8 +5,8 @@ import logging.handlers from telebot import types from .admin_commands import bot -from .constants import (LOG_COMM, FAQ, LIB, RULES, RUS, RUS_ENG_TABLE, ENG_RUS_TABLE, PYTHONCHATRU, ZEN, LUTZ_ID, - BDMTSS_ID) +from .constants import (LOG_COMM, FAQ, LIB, RULES, RUS, RUS_ENG_TABLE, ENG_RUS_TABLE, PYTHONCHATRU, ZEN, LUTZ_BOOK_ID, + BDMTSS_VOICE_ID) from .filters import in_spam_list, in_caption_spam_list, in_delete_list, is_hello_text, is_invalid_name from .helpers import represent_as_get, detect_args, is_admin, fetch_rule, has_warnings, warn_user, warnings_count from .report import update_stats, increment @@ -126,7 +126,7 @@ async def send_lutz(message: types.Message): message.text, ) ) - await bot.send_document(message.chat.id, document=LUTZ_ID, caption="вот, не позорься") + await bot.send_document(message.chat.id, document=LUTZ_BOOK_ID, caption="вот, не позорься") await bot.delete_message(message.chat.id, message.id) @@ -141,7 +141,7 @@ async def send_bdmtss_audio(message: types.Message): message.text, ) ) - await bot.send_voice(message.chat.id, BDMTSS_ID) + await bot.send_voice(message.chat.id, BDMTSS_VOICE_ID) await bot.delete_message(message.chat.id, message.id) diff --git a/src/config.py b/src/config.py index 5dde632..abc0794 100644 --- a/src/config.py +++ b/src/config.py @@ -8,9 +8,9 @@ from .helpers import is_url_reachable load_dotenv() -TOKEN = os.environ.get("LUTZPYBOT") +TOKEN = os.environ.get("STAN") if not TOKEN: - raise LookupError("LUTZPYBOT (token) has not been found in .env") + raise LookupError("STAN (token) has not been found in .env") WHITEIDS = {int(i) for i in os.environ.get("whiteids").split(",")} ROLLBACK = {int(i) for i in os.environ.get("rollback").split(",")} @@ -18,7 +18,7 @@ USE_REMINDER = os.environ.get("use_reminder", "TRUE") == "TRUE" RULES_URL = os.environ.get("rules_url", "https://telegra.ph/pythonchatru-07-07") if not is_url_reachable(RULES_URL): - raise LookupError(f"LUTZPYBOT rules url({RULES_URL}) is not reachable") + raise LookupError(f"STAN rules url({RULES_URL}) is not reachable") logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S") logger.setLevel(logging.ERROR) diff --git a/src/constants.py b/src/constants.py index c8b4955..5a46c14 100644 --- a/src/constants.py +++ b/src/constants.py @@ -84,5 +84,5 @@ RULES_TEXT = ( "Не нужно писать в ЛС.", ) -LUTZ_ID = "BQACAgQAAxkBAAPBYsWJG9Ml0fPrnbU9UyzTQiQSuHkAAjkDAAIstCxSkuRbXAlcqeQpBA" -BDMTSS_ID = "AwACAgIAAxkBAAIJrWOg2WUvLwrf7ahyJxQHB8_nqllwAAL5JQAC2_IJSbhfQIO5YnVmLAQ" +LUTZ_BOOK_ID = "BQACAgQAAxkBAAPBYsWJG9Ml0fPrnbU9UyzTQiQSuHkAAjkDAAIstCxSkuRbXAlcqeQpBA" +BDMTSS_VOICE_ID = "AwACAgIAAxkBAAIJrWOg2WUvLwrf7ahyJxQHB8_nqllwAAL5JQAC2_IJSbhfQIO5YnVmLAQ" diff --git a/tests/test_bot.py b/tests/test_bot.py index f48e73b..c219f04 100644 --- a/tests/test_bot.py +++ b/tests/test_bot.py @@ -6,7 +6,7 @@ from unittest.mock import patch, MagicMock from telebot import asyncio_helper, types, logger # Надо сделать до импорта бота, иначе упадет, так как нет енва в тестах -os.environ["LUTZPYBOT"] = "00000:AAAAAAAAAAAA" +os.environ["STAN"] = "00000:AAAAAAAAAAAA" os.environ["whiteids"] = "100,200,300" os.environ["rollback"] = "1,2,3" os.environ["use_reminder"] = "FALSE" @@ -17,7 +17,7 @@ from src import helpers # нужно не дать делать реальные запросы в тестах, конкретно тут -за Правилами чата helpers.is_url_reachable = lambda a: True from src.commands import bot -from src.constants import BDMTSS_ID, LUTZ_ID, ADMIN_ID, HELLO_EXAMPLES +from src.constants import BDMTSS_VOICE_ID, LUTZ_BOOK_ID, ADMIN_ID, HELLO_EXAMPLES from src.filters import is_white_id, is_invalid_name # отключаем логи бота, в тестах они не нужны @@ -195,13 +195,13 @@ class TestBot(IsolatedAsyncioTestCase): async def test_lutz(self): await self.bot.process_new_updates([get_update('/lutz', reply_to="привет всем")]) self.assertEqual(RESULTS[0][0]['caption'], "вот, не позорься") - self.assertEqual(RESULTS[0][0]['document'], LUTZ_ID) + self.assertEqual(RESULTS[0][0]['document'], LUTZ_BOOK_ID) self.assertEqual(RESULTS[0][1], "sendDocument") self.assertEqual(RESULTS[1][1], "deleteMessage") async def test_bdmtss(self): await self.bot.process_new_updates([get_update('/bdmtss', reply_to="привет всем")]) - self.assertEqual(RESULTS[0][0]['voice'], BDMTSS_ID) + self.assertEqual(RESULTS[0][0]['voice'], BDMTSS_VOICE_ID) self.assertEqual(RESULTS[0][1], "sendVoice") self.assertEqual(RESULTS[1][1], "deleteMessage")