squashed
This commit is contained in:
commit
2ee1722836
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
local.env
|
||||||
|
**/*.pyc
|
||||||
|
test/
|
||||||
|
newsmaker.session
|
||||||
|
newsmaker.session-journal
|
||||||
|
newsmaker.session.bup
|
27
.vscode/launch.json
vendored
Normal file
27
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Python Debugger: main.py",
|
||||||
|
"type": "debugpy",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "src/main.py",
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"envFile": "${workspaceFolder}/local.env"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Python Debugger: signin.py",
|
||||||
|
"type": "debugpy",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "src/signin.py",
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"envFile": "${workspaceFolder}/local.env"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
13
Dockerfile
Normal file
13
Dockerfile
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
FROM python:3.10
|
||||||
|
|
||||||
|
RUN apt-get install libpq-dev -y
|
||||||
|
|
||||||
|
ADD requirements.txt requirements.txt
|
||||||
|
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
|
||||||
|
ADD src /app
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ENTRYPOINT [ "python", "./main.py" ]
|
44
docker-compose.yaml
Normal file
44
docker-compose.yaml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
version: '3.3'
|
||||||
|
|
||||||
|
networks:
|
||||||
|
jedoist:
|
||||||
|
external: true
|
||||||
|
|
||||||
|
services:
|
||||||
|
|
||||||
|
bot:
|
||||||
|
# build: ./
|
||||||
|
image: localhost:5001/jedoist:${APP_VERSION}
|
||||||
|
environment:
|
||||||
|
- BOT_TOKEN=${BOT_TOKEN}
|
||||||
|
- VK_CLIENT_ID=${VK_CLIENT_ID}
|
||||||
|
- VK_SECRET_KEY=${VK_SECRET_KEY}
|
||||||
|
- BOT_OWNER_ID=258985362
|
||||||
|
- DB_HOST=jedoist-db
|
||||||
|
- DB_NAME=jedoist-db
|
||||||
|
- DB_USER=${DB_USER}
|
||||||
|
- DB_PASS=${DB_PASS}
|
||||||
|
- VOICES_PATH=${VOICES_PATH}
|
||||||
|
- CONFIG_FILE=/mnt/config.json
|
||||||
|
restart: always
|
||||||
|
depends_on:
|
||||||
|
- bot-db
|
||||||
|
networks:
|
||||||
|
- jedoist
|
||||||
|
volumes:
|
||||||
|
- ${CONFIG_FILE}:/mnt/config.json
|
||||||
|
|
||||||
|
bot-db:
|
||||||
|
image: postgres:14
|
||||||
|
container_name: jedoist-db
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: ${DB_USER}
|
||||||
|
POSTGRES_PASSWORD: ${DB_PASS}
|
||||||
|
POSTGRES_DB: jedoist-db
|
||||||
|
networks:
|
||||||
|
- jedoist
|
||||||
|
volumes:
|
||||||
|
- ${DB_VOLUME}:/var/lib/postgresql/data
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
aiohttp==3.9.5
|
||||||
|
telethon==1.36.0
|
11
src/bot/__init__.py
Normal file
11
src/bot/__init__.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Get the current script's directory
|
||||||
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
# Get the parent directory by going one level up
|
||||||
|
parent_dir = os.path.dirname(current_dir)
|
||||||
|
|
||||||
|
# Add the parent directory to sys.path
|
||||||
|
sys.path.append(parent_dir)
|
124
src/bot/bot.py
Normal file
124
src/bot/bot.py
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
from settings import config
|
||||||
|
import logging
|
||||||
|
import re
|
||||||
|
from telethon import TelegramClient, events
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
class Bot():
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
session_file: str,
|
||||||
|
config_file: str,
|
||||||
|
api_id: str,
|
||||||
|
api_hash: int,
|
||||||
|
owner_id: int) -> None:
|
||||||
|
self.__config_file = config_file
|
||||||
|
self.__config = None
|
||||||
|
self.__me = None
|
||||||
|
self.__owner_id = owner_id
|
||||||
|
self.__reload()
|
||||||
|
self.__bot = TelegramClient(session_file, api_id, api_hash)
|
||||||
|
|
||||||
|
@self.__bot.on(events.NewMessage(incoming=True, pattern='!whoami'))
|
||||||
|
async def onMessageWhoami(event):
|
||||||
|
await event.reply("{0}".format(event.chat_id))
|
||||||
|
await self.__bot.send_read_acknowledge(event.chat_id, event.message)
|
||||||
|
raise events.StopPropagation
|
||||||
|
|
||||||
|
@self.__bot.on(events.NewMessage(incoming=True, pattern="!reload"))
|
||||||
|
async def onMessageReload(event):
|
||||||
|
self.__reload()
|
||||||
|
await event.reply("Reloaded")
|
||||||
|
await self.__bot.send_read_acknowledge(event.chat_id, event.message)
|
||||||
|
raise events.StopPropagation
|
||||||
|
|
||||||
|
@self.__bot.on(events.NewMessage(incoming=True, pattern="!chats"))
|
||||||
|
async def onMessageChats(event):
|
||||||
|
await self.__send_all_chats_to_owner()
|
||||||
|
await self.__bot.send_read_acknowledge(event.chat_id, event.message)
|
||||||
|
raise events.StopPropagation
|
||||||
|
|
||||||
|
@self.__bot.on(events.ChatAction)
|
||||||
|
async def onChatAction(event):
|
||||||
|
if event.user_left and event.user.id == self.__me:
|
||||||
|
await self.__bot.send_message(owner_id, "Я вышел из чата: {0}".format(event.chat_id))
|
||||||
|
if event.user_joined and event.user.id == self.__me:
|
||||||
|
await self.__bot.send_message(owner_id, "Я вошел в чат: {0}".format(event.chat_id))
|
||||||
|
|
||||||
|
@self.__bot.on(events.NewMessage(incoming=True))
|
||||||
|
async def onNewMessage(event):
|
||||||
|
if event.message is None:
|
||||||
|
return
|
||||||
|
chat_id = event.chat_id
|
||||||
|
message = event.message
|
||||||
|
logger.debug("Received message in chat {0}: {1}".format(chat_id, message.text if not message == None else "<No Text>"))
|
||||||
|
await self.__process_message(event, chat_id, message)
|
||||||
|
|
||||||
|
def start(self) -> None:
|
||||||
|
self.__bot.start()
|
||||||
|
self.__bot.loop.run_until_complete(self.__identity())
|
||||||
|
self.__bot.run_until_disconnected()
|
||||||
|
|
||||||
|
def __reload(self) -> None:
|
||||||
|
self.__config = config.Config(filename=self.__config_file)
|
||||||
|
|
||||||
|
async def __send_all_chats_to_owner(self) -> None:
|
||||||
|
text = ""
|
||||||
|
async for dialog in self.__bot.iter_dialogs():
|
||||||
|
text = text + "{0} - {1}\n".format(dialog.id, dialog.name)
|
||||||
|
await self.__bot.send_message(self.__owner_id, text)
|
||||||
|
|
||||||
|
async def __process_message(self, event, chat_id, message):
|
||||||
|
configs = self.__config.get_on_message_for_chat_id(chat_id)
|
||||||
|
if configs == None:
|
||||||
|
return
|
||||||
|
if not isinstance(configs, list):
|
||||||
|
return
|
||||||
|
for config in configs:
|
||||||
|
filter = config['filter'] if 'filter' in config else None
|
||||||
|
action = config['action'] if 'action' in config else None
|
||||||
|
action_type = action['type'] if 'type' in action else None
|
||||||
|
if action == None or action_type == None:
|
||||||
|
return
|
||||||
|
if not filter == None:
|
||||||
|
if await self.__needs_skip(filter, message):
|
||||||
|
return
|
||||||
|
if action_type == 'forward':
|
||||||
|
destination = action['chatId'] if 'chatId' in action else None
|
||||||
|
if destination == None:
|
||||||
|
return
|
||||||
|
await event.forward_to(destination)
|
||||||
|
|
||||||
|
async def __needs_skip(self, filter: dict, message) -> bool:
|
||||||
|
filter_type = filter['type'] if 'type' in filter else None
|
||||||
|
filter_value = filter['value'] if 'value' in filter else None
|
||||||
|
if filter_type == None or filter_value == None:
|
||||||
|
return True
|
||||||
|
text = str(message.text)
|
||||||
|
if text == None:
|
||||||
|
if not message.reply_to == None:
|
||||||
|
reply = await self.__get_reply(message.chat_id, message)
|
||||||
|
return await self.__needs_skip(filter, reply)
|
||||||
|
return True
|
||||||
|
if filter_type == 'contain':
|
||||||
|
if text.find(filter_value) == -1:
|
||||||
|
if not message.reply_to == None:
|
||||||
|
reply = await self.__get_reply(message.chat_id, message)
|
||||||
|
return await self.__needs_skip(filter, reply)
|
||||||
|
return True
|
||||||
|
elif filter_type == 'regexp':
|
||||||
|
if not re.match(filter_value, text):
|
||||||
|
if not message.reply_to == None:
|
||||||
|
reply = await self.__get_reply(message.chat_id, message)
|
||||||
|
return await self.__needs_skip(filter, reply)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
async def __get_reply(self, chat_id, message):
|
||||||
|
return await self.__bot.get_messages(chat_id, ids=message.reply_to.reply_to_msg_id)
|
||||||
|
|
||||||
|
async def __identity(self) -> None:
|
||||||
|
me = await self.__bot.get_me()
|
||||||
|
self.__me = me.id
|
20
src/main.py
Normal file
20
src/main.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import os
|
||||||
|
from bot.bot import Bot
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logging.basicConfig(format="%(asctime)s | %(name)s | %(levelname)s | %(message)s")
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.setLevel(logging.INFO)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
session_file = os.environ['SESSION_FILE']
|
||||||
|
api_id = os.environ['TG_APP_ID']
|
||||||
|
api_hash = os.environ['TG_APP_HASH']
|
||||||
|
owner_id = int(os.environ['TG_OWNER_ID'])
|
||||||
|
config_file = os.environ['CONFIG_FILE']
|
||||||
|
bot = Bot(session_file=session_file,
|
||||||
|
api_id=api_id,
|
||||||
|
api_hash=api_hash,
|
||||||
|
config_file=config_file,
|
||||||
|
owner_id=owner_id)
|
||||||
|
bot.start()
|
11
src/settings/__init__.py
Normal file
11
src/settings/__init__.py
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Get the current script's directory
|
||||||
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
# Get the parent directory by going one level up
|
||||||
|
parent_dir = os.path.dirname(current_dir)
|
||||||
|
|
||||||
|
# Add the parent directory to sys.path
|
||||||
|
sys.path.append(parent_dir)
|
21
src/settings/config.py
Normal file
21
src/settings/config.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import json
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
class Config():
|
||||||
|
|
||||||
|
def __init__(self, filename: str) -> None:
|
||||||
|
self.__filename = filename
|
||||||
|
self.__config = {}
|
||||||
|
self.__read()
|
||||||
|
|
||||||
|
def get_on_message_for_chat_id(self, chat_id: int) -> Optional[dict]:
|
||||||
|
chat_id_str = str(chat_id)
|
||||||
|
if 'onMessage' in self.__config:
|
||||||
|
on_message = self.__config['onMessage']
|
||||||
|
if chat_id_str in on_message:
|
||||||
|
return on_message[chat_id_str]
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __read(self) -> None:
|
||||||
|
with open(self.__filename, 'r') as f:
|
||||||
|
self.__config = json.load(f)
|
10
src/signin.py
Normal file
10
src/signin.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import os
|
||||||
|
from telethon import TelegramClient
|
||||||
|
|
||||||
|
# Use your own values from my.telegram.org
|
||||||
|
api_id = os.environ['TG_APP_ID']
|
||||||
|
api_hash = os.environ['TG_APP_HASH']
|
||||||
|
|
||||||
|
# The first parameter is the .session file name (absolute paths allowed)
|
||||||
|
with TelegramClient('newsmaker.session', api_id, api_hash) as client:
|
||||||
|
client.loop.run_until_complete(client.send_message('me', 'Hello, myself!'))
|
Loading…
Reference in New Issue
Block a user