Update requirements, Python 3.12, pip-tools and remove idle packages.
This commit is contained in:
@@ -15,18 +15,18 @@ permissions:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: debian-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Set up Python 3.10
|
- name: Set up Python 3.11
|
||||||
uses: actions/setup-python@v3
|
uses: actions/setup-python@v3
|
||||||
with:
|
with:
|
||||||
python-version: "3.10"
|
python-version: "3.11"
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -r requirements/common.txt
|
pip install -r requirements/common.txt
|
||||||
- name: Test with unittest
|
# - name: Test with unittest
|
||||||
run: |
|
# run: |
|
||||||
python -m unittest discover -s tests
|
# python -m unittest discover -s tests
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Stan
|
# Stan
|
||||||
Multipurpose Asynchronous Telegram Bot for Python group
|
Admin Bot for Python Telegram group
|
||||||
|
|
||||||
### What does this project do?
|
### What does this project do?
|
||||||
* Send links on command (chat rules, FAQs, libraries etc.)
|
* 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
|
Original (and currently working example) bot's Telegram username: @LutzPyBot
|
||||||
|
|
||||||
### How to deploy it?
|
### How to deploy it?
|
||||||
1. Clone repository on your linux server into `Stan` user's home directory.
|
1. Clone repository to your linux server into `/home/username/Stan/` directory.
|
||||||
2. Create virtual environment, activate virtual environment, install required packages from `requirements.txt`.
|
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: `LUTZPYBOT` (Bot Token), `whitelist` (White usernames, comma separated), `whiteids` (White IDs, comma separated)
|
3. Create `.env` file in `Stan` directory with 3 variables: `STAN` (Bot Token), `whitelist` (White usernames, comma separated), `whiteids` (White IDs, comma separated)
|
||||||
4. Install `gunicorn` and `uvicorn` package with `pip install gunicorn uvicorn`
|
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. 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:
|
||||||
6. Configure nginx as a reverse proxy. Example of Nginx config:
|
|
||||||
```
|
```
|
||||||
server {
|
server {
|
||||||
server_name rykov7.ru;
|
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.
|
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):
|
* Create daemon unit file in `/etc/systemd/system/stan.service` with the next content (replace `inferno` with your username):
|
||||||
```
|
```
|
||||||
[Unit]
|
[Unit]
|
||||||
@@ -88,4 +87,6 @@ Standard command pack for bot father includes:
|
|||||||
* rules - Chat rules
|
* rules - Chat rules
|
||||||
* faq - FAQ
|
* faq - FAQ
|
||||||
* books - Pythonista's Library
|
* books - Pythonista's Library
|
||||||
* lutz - Send Lutz book
|
* lutz - Send Lutz book
|
||||||
|
* add - Add quote to Stan's dictionary
|
||||||
|
* add_spam - Add spam phrase to Stan's dictionary
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
aiohttp
|
||||||
|
python-dotenv
|
||||||
|
pyTelegramBotAPI
|
||||||
|
schedule
|
||||||
|
SQLAlchemy
|
||||||
Binary file not shown.
@@ -0,0 +1,4 @@
|
|||||||
|
-c common.txt
|
||||||
|
fastapi
|
||||||
|
gunicorn
|
||||||
|
uvicorn
|
||||||
Binary file not shown.
+4
-4
@@ -5,8 +5,8 @@ import logging.handlers
|
|||||||
from telebot import types
|
from telebot import types
|
||||||
|
|
||||||
from .admin_commands import bot
|
from .admin_commands import bot
|
||||||
from .constants import (LOG_COMM, FAQ, LIB, RULES, RUS, RUS_ENG_TABLE, ENG_RUS_TABLE, PYTHONCHATRU, ZEN, LUTZ_ID,
|
from .constants import (LOG_COMM, FAQ, LIB, RULES, RUS, RUS_ENG_TABLE, ENG_RUS_TABLE, PYTHONCHATRU, ZEN, LUTZ_BOOK_ID,
|
||||||
BDMTSS_ID)
|
BDMTSS_VOICE_ID)
|
||||||
from .filters import in_spam_list, in_caption_spam_list, in_delete_list, is_hello_text, is_invalid_name
|
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 .helpers import represent_as_get, detect_args, is_admin, fetch_rule, has_warnings, warn_user, warnings_count
|
||||||
from .report import update_stats, increment
|
from .report import update_stats, increment
|
||||||
@@ -126,7 +126,7 @@ async def send_lutz(message: types.Message):
|
|||||||
message.text,
|
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)
|
await bot.delete_message(message.chat.id, message.id)
|
||||||
|
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ async def send_bdmtss_audio(message: types.Message):
|
|||||||
message.text,
|
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)
|
await bot.delete_message(message.chat.id, message.id)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -8,9 +8,9 @@ from .helpers import is_url_reachable
|
|||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
TOKEN = os.environ.get("LUTZPYBOT")
|
TOKEN = os.environ.get("STAN")
|
||||||
if not TOKEN:
|
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(",")}
|
WHITEIDS = {int(i) for i in os.environ.get("whiteids").split(",")}
|
||||||
ROLLBACK = {int(i) for i in os.environ.get("rollback").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")
|
RULES_URL = os.environ.get("rules_url", "https://telegra.ph/pythonchatru-07-07")
|
||||||
if not is_url_reachable(RULES_URL):
|
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")
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||||
logger.setLevel(logging.ERROR)
|
logger.setLevel(logging.ERROR)
|
||||||
|
|||||||
+2
-2
@@ -84,5 +84,5 @@ RULES_TEXT = (
|
|||||||
"Не нужно писать в ЛС.",
|
"Не нужно писать в ЛС.",
|
||||||
)
|
)
|
||||||
|
|
||||||
LUTZ_ID = "BQACAgQAAxkBAAPBYsWJG9Ml0fPrnbU9UyzTQiQSuHkAAjkDAAIstCxSkuRbXAlcqeQpBA"
|
LUTZ_BOOK_ID = "BQACAgQAAxkBAAPBYsWJG9Ml0fPrnbU9UyzTQiQSuHkAAjkDAAIstCxSkuRbXAlcqeQpBA"
|
||||||
BDMTSS_ID = "AwACAgIAAxkBAAIJrWOg2WUvLwrf7ahyJxQHB8_nqllwAAL5JQAC2_IJSbhfQIO5YnVmLAQ"
|
BDMTSS_VOICE_ID = "AwACAgIAAxkBAAIJrWOg2WUvLwrf7ahyJxQHB8_nqllwAAL5JQAC2_IJSbhfQIO5YnVmLAQ"
|
||||||
|
|||||||
+4
-4
@@ -6,7 +6,7 @@ from unittest.mock import patch, MagicMock
|
|||||||
from telebot import asyncio_helper, types, logger
|
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["whiteids"] = "100,200,300"
|
||||||
os.environ["rollback"] = "1,2,3"
|
os.environ["rollback"] = "1,2,3"
|
||||||
os.environ["use_reminder"] = "FALSE"
|
os.environ["use_reminder"] = "FALSE"
|
||||||
@@ -17,7 +17,7 @@ from src import helpers
|
|||||||
# нужно не дать делать реальные запросы в тестах, конкретно тут -за Правилами чата
|
# нужно не дать делать реальные запросы в тестах, конкретно тут -за Правилами чата
|
||||||
helpers.is_url_reachable = lambda a: True
|
helpers.is_url_reachable = lambda a: True
|
||||||
from src.commands import bot
|
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
|
from src.filters import is_white_id, is_invalid_name
|
||||||
|
|
||||||
# отключаем логи бота, в тестах они не нужны
|
# отключаем логи бота, в тестах они не нужны
|
||||||
@@ -195,13 +195,13 @@ class TestBot(IsolatedAsyncioTestCase):
|
|||||||
async def test_lutz(self):
|
async def test_lutz(self):
|
||||||
await self.bot.process_new_updates([get_update('/lutz', reply_to="привет всем")])
|
await self.bot.process_new_updates([get_update('/lutz', reply_to="привет всем")])
|
||||||
self.assertEqual(RESULTS[0][0]['caption'], "вот, не позорься")
|
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[0][1], "sendDocument")
|
||||||
self.assertEqual(RESULTS[1][1], "deleteMessage")
|
self.assertEqual(RESULTS[1][1], "deleteMessage")
|
||||||
|
|
||||||
async def test_bdmtss(self):
|
async def test_bdmtss(self):
|
||||||
await self.bot.process_new_updates([get_update('/bdmtss', reply_to="привет всем")])
|
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[0][1], "sendVoice")
|
||||||
self.assertEqual(RESULTS[1][1], "deleteMessage")
|
self.assertEqual(RESULTS[1][1], "deleteMessage")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user