diff --git a/chromedriver.exe b/chromedriver.exe deleted file mode 100644 index cb54d37..0000000 Binary files a/chromedriver.exe and /dev/null differ diff --git a/docker-compose.yaml b/docker-compose.yaml deleted file mode 100644 index 1fe305d..0000000 --- a/docker-compose.yaml +++ /dev/null @@ -1,40 +0,0 @@ -version: "3" - -services: - rabbitmq: - image: rabbitmq:3.11.0-management - container_name: rabbimq - hostname: line - environment: - - RABBITMQ_DEFAULT_USER=MonkeDLyugge - - RABBITMQ_DEFAULT_PASS=TlVa474367636656565 - volumes: - - ./rabbitmq:/var/lib/rabbitmq - ports: - - 5672:5672 - - 15672:15672 - restart: always - tele_bot: - build: ./telegram/tele_bot - container_name: tele_bot - command: python tele_bot/main.py - ports: - - 8000:8000 - volumes: - - ./telegram:/tele_bot - listener: - build: ./telegram/listener - container_name: listener - command: python listener/listener.py - ports: - - 8001:8001 - volumes: - - ./telegram:/listener - counter: - build: ./src - container_name: counter - command: python main.py - ports: - - 8002:8002 - - diff --git a/src/main.py b/src/main.py deleted file mode 100644 index 5d52bc4..0000000 --- a/src/main.py +++ /dev/null @@ -1,59 +0,0 @@ -import json - -import get_offers -import counter -from db_requests import db_session - -import pika -import traceback, sys - -if __name__ == "__main__": - db_session.global_init() - - connection_parameters = pika.ConnectionParameters('localhost', 15672) - connection = pika.BlockingConnection(connection_parameters) - channel = connection.channel() - channel.queue_declare(queue="from_bot_to_parser", durable=True) - channel.queue_declare(queue="from_parser_to_bot") - - - def callback(ch, method, properties, body): - requests_body = json.loads(body) - # [message.chat.id,user_currency,user_limit,user_bank,user_stock_markets] - chat_id = requests_body[0] - user_currency = requests_body[1] - user_limit = requests_body[2] - user_bank = requests_body[3] - user_stock = requests_body[4] - # TODO Протестировать работу get_limit_list - all_offers = get_offers.get_offers(user_currency, ["BTC", "USDT", "ETH", "BUSD", "BNB"], - get_offers.get_limits_list(user_limit), - user_stock, user_bank) - # ТО ЧТО ОТПРАВЛЕТЕ В БОТА ОБРАТНО - message = "" - - for one_limit_id in all_offers: - message = message + f"Это связки для следующих значений лимита: {one_limit_id[0]} \n" - for offers in one_limit_id[1:]: - message = message + counter.Counter(offers) + "\n" - message = message + "\n" - - channel.basic_publish(exchange='', - routing_key='from_parser_to_bot', - body=json.dumps([chat_id, message]), - properties=pika.BasicProperties( - delivery_mode=2 - )) - - - channel.basic_consume(callback, queue="from_bot_to_parser") - - try: - channel.start_consuming() - except KeyboardInterrupt: - channel.stop_consuming() - except Exception: - channel.stop_consuming() - traceback.print_exc(file=sys.stdout) - - channel.close() diff --git a/telegram/docker-compose.yaml b/telegram/docker-compose.yaml new file mode 100644 index 0000000..49d5990 --- /dev/null +++ b/telegram/docker-compose.yaml @@ -0,0 +1,39 @@ +version: '3.7' + +services: + + rabbitmq: + image: 'rabbitmq:latest' + + ports: + - '5672:5672' + - '15672:15672' + environment: + RABBITMQ_DEFAULT_USER: "guest" + RABBITMQ_DEFAULT_PASS: "guest" + networks: + - network + + telebot: + depends_on: + - rabbitmq + build: tele_bot/ + environment: + AMQP_URL: 'amqp://rabbitmq?connection_attempts=5&retry_delay=5' + command: python3.9 main.py + networks: + - network + + server: + depends_on: + - rabbitmq + build: src/ + environment: + AMQP_URL: 'amqp://rabbitmq?connection_attempts=5&retry_delay=5' + command: python3.9 src/main.py + networks: + - network + +networks: + network: + driver: bridge diff --git a/telegram/listener/Dockerfile b/telegram/listener/Dockerfile deleted file mode 100644 index 67b15a1..0000000 --- a/telegram/listener/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM python:3.9 -ENV PYTHONDONTWRITEBYTECODE=1 -ENV PYTHONUNBUFFERED=1 -WORKDIR /listener -COPY . . -RUN pip install --upgrade pip -RUN pip install -r requirements.txt - -# listener - # listener - #... - # tele_bot - #... diff --git a/telegram/listener/listener.py b/telegram/listener/listener.py deleted file mode 100644 index 1680a30..0000000 --- a/telegram/listener/listener.py +++ /dev/null @@ -1,61 +0,0 @@ -import json - -import pika -import traceback, sys -import json -import telebot -from telebot import types - -from telegram.tele_bot.main import currency - -API_KEY = "5630556319:AAHEgv_ykF1L5EADrJnzte6DTy9eyJg8nbE" - -START_OVER_BUTTON = "НАЧАТЬ СНАЧАЛА" -HELP_BUTTON = "ПОМОЩЬ" -START_BUTTON = "НАЧАТЬ ТРЕЙДИТЬ" - - -bot = telebot.TeleBot(API_KEY) - -@bot.message_handler(commands=['start']) -def start(message): - mess = 'Привет. Я бот, созданный для того, чтобы преумножить твой капитал с помощью сделок на криптовалютных ' \ - 'биржах! Важно понимать, что за одну сделку ты не заработаешь на новый майбах, даже можешь и потерять свои ' \ - 'деньги, но на дистанции ты точно заработаешь кругленькую сумму! Если тебе что-то не понятно или ты ' \ - 'пользуешься нашим ботов впервые, то смело жми/пиши "Help". Желаю удачи! \n P.S Мы не являемся брокерами, ' \ - 'не владеем инсайдерской информацией, наш бот пользуется открытой информации из интернета и предлагает ' \ - 'вариант заработка. Мы не несем ответственность за ваши операции, вся информация несет только лишь ' \ - 'рекомендательный характер ' - markup = types.ReplyKeyboardMarkup() - buttons = list(map(lambda el: types.KeyboardButton(el), - [HELP_BUTTON, START_BUTTON])) - markup.add(*buttons) - bot.send_message(message.chat.id, mess, reply_markup=markup) - - bot.register_next_step_handler(message, currency) - -def answer(message): - connection_params = pika.ConnectionParameters('localhost', 5672) - connection = pika.BlockingConnection(connection_params) - channel = connection.channel() - - markup = types.ReplyKeyboardMarkup() - buttons = [START_OVER_BUTTON, HELP_BUTTON] - markup.add(*buttons) - def callback(ch, method, properties, body): - request = json.loads(body) - bot.send_message(body[0], body[1], reply_markup=markup) - bot.register_next_step_handler(message, start) - - channel.basic_consume(callback, queue="from_parser_to_bot") - - try: - channel.start_consuming() - except KeyboardInterrupt: - channel.stop_consuming() - except Exception: - channel.stop_consuming() - traceback.print_exc(file=sys.stdout) - -answer('') - diff --git a/telegram/src/Dockerfile b/telegram/src/Dockerfile new file mode 100644 index 0000000..26868d2 --- /dev/null +++ b/telegram/src/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9 +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +COPY . /src +RUN pip install --upgrade pip +RUN pip install -r src/requirements.txt \ No newline at end of file diff --git a/src/counter.py b/telegram/src/counter.py similarity index 87% rename from src/counter.py rename to telegram/src/counter.py index bff621c..c7b8500 100644 --- a/src/counter.py +++ b/telegram/src/counter.py @@ -92,16 +92,19 @@ def dfs(v: int, p: int): dfs(0, -1) ans = str() pos = N - 1 - while pos != 0: - cur_offer = prev[pos] - if cur_offer.init_coin != cur_offer.receive_coin: - ans += "Buy " if cur_offer.sell_buy else "Sell " - ans += "Taker " if cur_offer.maker_commission > cur_offer.taker_commission else "Maker " - ans += cur_offer.market + " " + cur_offer.init_coin + " " + cur_offer.receive_coin + " " - ans += cur_offer.payment + " -> " - else: - ans += cur_offer.init_coin + " Transfer to next market -> " - pos = PosByOffer(cur_offer, "receive") + for i in range(3): + try: + cur_offer = prev[pos] + if cur_offer.init_coin != cur_offer.receive_coin: + ans += "Buy " if cur_offer.sell_buy else "Sell " + ans += "Taker " if cur_offer.maker_commission > cur_offer.taker_commission else "Maker " + ans += cur_offer.market + " " + cur_offer.init_coin + " " + cur_offer.receive_coin + " " + ans += cur_offer.payment + " -> " + else: + ans += cur_offer.init_coin + " Transfer to next market -> " + pos = PosByOffer(cur_offer, "receive") + except Exception: + break if dp[N - 1] >= 0: ans += "PROFITABLY!" else: diff --git a/telegram/src/db_requests/db_session.py b/telegram/src/db_requests/db_session.py new file mode 100644 index 0000000..0008c99 --- /dev/null +++ b/telegram/src/db_requests/db_session.py @@ -0,0 +1,28 @@ +import sqlalchemy as sa +import sqlalchemy.ext.declarative as dec +import sqlalchemy.orm as orm +from sqlalchemy.orm import Session + +SqlAlchemyBase = dec.declarative_base() + +__factory = None + + +def global_init(): + global __factory + + if __factory: + return + + conn_str = f'postgresql://postgres:NP9IGumJsdIvnDfVkOd0@containers-us-west-192.railway.app:6504/railway' + print(f'Подключение к базе данных по адресу {conn_str}') + + engine = sa.create_engine(conn_str) + __factory = orm.sessionmaker(bind=engine) + + SqlAlchemyBase.metadata.create_all(engine) + + +def create_session() -> Session: + global __factory + return __factory() diff --git a/telegram/src/db_requests/offers.py b/telegram/src/db_requests/offers.py new file mode 100644 index 0000000..acbc8aa --- /dev/null +++ b/telegram/src/db_requests/offers.py @@ -0,0 +1,23 @@ +import sqlalchemy +from sqlalchemy_serializer import SerializerMixin +import sys +sys.path.append('..') + +from src.db_requests.db_session import SqlAlchemyBase + + +class Offer(SqlAlchemyBase, SerializerMixin): # Это класс, описывающий таблицу в бд + __tablename__ = 'offers' + __table_args__ = {'extend_existing': True} + + id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True, autoincrement=True) + market = sqlalchemy.Column(sqlalchemy.Text) + payment = sqlalchemy.Column(sqlalchemy.Text) + sell_buy = sqlalchemy.Column(sqlalchemy.Integer) + init_coin = sqlalchemy.Column(sqlalchemy.Text) + receive_coin = sqlalchemy.Column(sqlalchemy.Text) + id_limit = sqlalchemy.Column(sqlalchemy.Integer) + price = sqlalchemy.Column(sqlalchemy.Float) + maker_commission = sqlalchemy.Column(sqlalchemy.Float) + taker_commission = sqlalchemy.Column(sqlalchemy.Float) + diff --git a/src/get_offers.py b/telegram/src/get_offers.py similarity index 81% rename from src/get_offers.py rename to telegram/src/get_offers.py index 43eff56..943eede 100644 --- a/src/get_offers.py +++ b/telegram/src/get_offers.py @@ -1,15 +1,19 @@ -from db_requests import db_session -from db_requests.offers import Offer - +from src.db_requests import db_session +from src.db_requests.offers import Offer limits = {1: 1000, 2: 5000, 3: 10000, 4: 25000, 5: 50000, 6: 100000} +rev_limits = {1000: 1, 5000: 2, 10000: 3, 25000: 4, 50000: 5, 100000: 6} + def get_limits_list(limit): limit = int(limit) cur_limit_id = [] for lim in sorted(rev_limits.keys())[::-1]: - if limit <= lim: + if limit >= lim: cur_limit_id.append(rev_limits[lim]) + break + if len(cur_limit_id) == 0: + cur_limit_id.append(1) kol_iteration = 0 lim = cur_limit_id[0] - 1 while kol_iteration < 2 and lim > 0: @@ -30,6 +34,7 @@ def get_offers(cur_fiat: list, cur_cripto: list, cur_limit_id: list, cur_market: for it_payment in cur_payment: for it_market in cur_market: for it_fiat in cur_fiat: + # print(it_limit_id, it_crypto, it_payment, it_market, it_fiat) # TODO проверить, что с .lower(), всё работает offers = sessions.query(Offer).filter(Offer.market == it_market.lower(), Offer.init_coin == it_fiat, @@ -42,9 +47,14 @@ def get_offers(cur_fiat: list, cur_cripto: list, cur_limit_id: list, cur_market: Offer.payment == it_payment, Offer.id_limit == it_limit_id).all() for offer in offers: + if offer is None: + continue ans.append(offer) for offer in rev_offers: + if offer is None: + continue ans.append(offer) ans_for_one_limit_id.append(ans) all_offers.append(ans_for_one_limit_id) + sessions.close() return all_offers diff --git a/telegram/src/main.py b/telegram/src/main.py new file mode 100644 index 0000000..e9347e7 --- /dev/null +++ b/telegram/src/main.py @@ -0,0 +1,50 @@ +import sys +import json +sys.path.append("..") + +from src import get_offers +from src import counter +from src.db_requests import db_session +import pika + + +def on_request(ch, method, props, body): + args = json.loads(body.decode("utf-8")) + response = run(args) + ch.basic_publish(exchange="", routing_key=props.reply_to, + properties=pika.BasicProperties(correlation_id=props.correlation_id), body=response) + ch.basic_ack(delivery_tag=method.delivery_tag) + + +def run(requests_body): + db_session.global_init() + + # [user_currency,user_limit,user_bank,user_stock_markets] + user_currency = requests_body["user_currency"] + user_limit = int(requests_body["user_limit"]) + user_bank = requests_body["user_bank"] + user_stock = requests_body["user_stock_markets"] + all_offers = get_offers.get_offers([user_currency], ["BTC", "USDT", "ETH", "BUSD", "BNB"], + get_offers.get_limits_list(user_limit), + user_stock, user_bank) + message = "" + for one_limit_id in all_offers: + message = message + f"Это связки для следующих значений лимита: {one_limit_id[0]} \n" + for offers in one_limit_id[1:]: + message = message + counter.Counter(offers) + "\n" + message = message + "\n" + + return message + + +if __name__ == "__main__": + import time + time.sleep(20) + connection = pika.BlockingConnection(pika.URLParameters("amqp://guest:guest@rabbitmq:5672/%2F")) + channel = connection.channel() + + channel.queue_declare(queue="rpc_queue") + channel.basic_qos(prefetch_count=1) + channel.basic_consume(queue="rpc_queue", on_message_callback=on_request) + + channel.start_consuming() diff --git a/telegram/listener/requirements.txt b/telegram/src/requirements.txt similarity index 75% rename from telegram/listener/requirements.txt rename to telegram/src/requirements.txt index cff8855..663179f 100644 --- a/telegram/listener/requirements.txt +++ b/telegram/src/requirements.txt @@ -1,5 +1,3 @@ -pyvirtualdisplay==3.0 -selenium==4.6.1 pyTelegramBotAPI==4.8.0 sqlalchemy==1.4.42 sqlalchemy_serializer==1.4.1 diff --git a/telegram/tele_bot/Dockerfile b/telegram/tele_bot/Dockerfile index 0ac83fc..5a0e2c1 100644 --- a/telegram/tele_bot/Dockerfile +++ b/telegram/tele_bot/Dockerfile @@ -1,7 +1,7 @@ FROM python:3.9 ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 -WORKDIR /tele_bot + COPY . . RUN pip install --upgrade pip -RUN pip install -r requirements.txt +RUN pip install -r requirements.txt \ No newline at end of file diff --git a/telegram/tele_bot/main.py b/telegram/tele_bot/main.py index 8b87410..38f3211 100644 --- a/telegram/tele_bot/main.py +++ b/telegram/tele_bot/main.py @@ -1,13 +1,14 @@ -import telebot -from telebot import types +import uuid import pika +import telebot import json +from telebot import types API_KEY = "5630556319:AAHEgv_ykF1L5EADrJnzte6DTy9eyJg8nbE" ALL_MARKETS = ['Binance', 'ByBit', 'Huobi'] ALL_CURRENCY = ['RUB', 'USD', 'EUR', 'CNY', 'GBP'] -ALL_BANKS = ['Raiffeisenbank', 'Sberbank', 'Tinkoff"'] +ALL_BANKS = ['Raiffeisenbank', 'Sberbank', 'Tinkoff'] START_OVER_BUTTON = "НАЧАТЬ СНАЧАЛА" START_BUTTON = "НАЧАТЬ ТРЕЙДИТЬ" @@ -28,6 +29,37 @@ bot = telebot.TeleBot(API_KEY) +class RpcClient: + def __init__(self): + # TODO проверить правильное название host + self.connection = pika.BlockingConnection(pika.URLParameters("amqp://guest:guest@rabbitmq:5672/%2F")) + self.channel = self.connection.channel() + result = self.channel.queue_declare(queue='', exclusive=True) + + self.callback_queue = result.method.queue + + self.channel.basic_consume(queue=self.callback_queue, on_message_callback=self.on_response, auto_ack=True) + + self.response = None + self.corr_id = None + + def on_response(self, ch, method, props, body): + if self.corr_id == props.correlation_id: + self.response = body + + def call(self, user_currency, user_limit, user_bank, user_stock_markets): + self.response = None + self.corr_id = str(uuid.uuid4()) + self.channel.basic_publish(exchange='', routing_key="rpc_queue", + properties=pika.BasicProperties(reply_to=self.callback_queue, + correlation_id=self.corr_id), + body=json.dumps({"user_currency": user_currency, "user_limit": user_limit, + "user_bank": user_bank, + "user_stock_markets": user_stock_markets}).encode("utf-8")) + self.connection.process_data_events(time_limit=None) + return self.response + + def user_clear(): global user_limit user_limit = 0 @@ -38,6 +70,7 @@ def user_clear(): global user_stock_markets user_stock_markets = ALL_MARKETS.copy() + @bot.message_handler(commands=['help']) def help(message): helping_message = "Привет! Для начала взаимодействия с нашим ботом ты должен выбрать валюту(пока доступны " \ @@ -76,6 +109,17 @@ def start(message): def currency(message): + if message.text.strip() == HELP_BUTTON: + help(message) + return + elif message.text.strip() != START_BUTTON: + bot.send_message(message.chat.id, INVALID_STRING) + start(message) + return + markup = types.ReplyKeyboardMarkup() + buttons = list(map(lambda el: types.KeyboardButton(el), + [HELP_BUTTON, START_OVER_BUTTON] + ALL_CURRENCY)) + markup.add(*buttons) if message.text.strip() == HELP_BUTTON: help(message) return @@ -116,7 +160,7 @@ def limit(message): buttons = list(map(lambda el: types.KeyboardButton(el), [HELP_BUTTON, START_OVER_BUTTON])) markup.add(*buttons) - mess = 'Введи свою ставку (1000 RUB минимум)' # TO DO Если будем делать для многих валют, то тут надо + mess = 'Введи свою ставку (1000 RUB минимум)' # TO DO Если будем делать для многих валют, то тут надо # TO DO параметризовть лимит для разных валют bot.send_message(message.chat.id, mess, reply_markup=markup) bot.register_next_step_handler(message, stock_markets) @@ -253,30 +297,24 @@ def pre_answer(message): help(message) return elif message.text.strip() == DONE: - connection_params = pika.ConnectionParameters('localhost', 5672) - connection = pika.BlockingConnection(connection_params) - channel = connection.channel() - - channel.queue_declare(queue="from_bot_to_parser", durable=True) - channel.basic_publish(exchange='', - routing_key='from_bot_to_parser', - body=json.dumps([message.chat.id, - user_currency, - user_limit, - user_bank, - user_stock_markets]), - properties=pika.BasicProperties( - delivery_mode=2 - )) markup = types.ReplyKeyboardMarkup() buttons = [START_OVER_BUTTON, HELP_BUTTON] markup.add(*buttons) mess = 'Работаем...' bot.send_message(message.chat.id, mess, reply_markup=markup) - connection.close() + response = send_message_to_rpc_queue(user_currency, user_limit, user_bank, user_stock_markets) + bot.send_message(message.chat.id, response, reply_markup=markup) + bot.register_next_step_handler(message, start) else: bot.send_message(message.chat.id, INVALID_STRING) bank(message) return + +def send_message_to_rpc_queue(user_currency, user_limit, user_bank, user_stock_markets): + client = RpcClient() + response = client.call(user_currency, user_limit, user_bank, user_stock_markets) + return response + + bot.polling(none_stop=True) diff --git a/telegram/tele_bot/requirements.txt b/telegram/tele_bot/requirements.txt index cff8855..663179f 100644 --- a/telegram/tele_bot/requirements.txt +++ b/telegram/tele_bot/requirements.txt @@ -1,5 +1,3 @@ -pyvirtualdisplay==3.0 -selenium==4.6.1 pyTelegramBotAPI==4.8.0 sqlalchemy==1.4.42 sqlalchemy_serializer==1.4.1