Загрузка...

Fpc плагин автодемпинг с гибкой настройкой

Тема в разделе Python создана пользователем RBLuXe 17 мар 2025. 745 просмотров

Загрузка...
  1. RBLuXe
    RBLuXe Автор темы 17 мар 2025 7 1 июл 2024
    Python
    from __future__ import annotations
    import json
    import time
    from threading import Thread
    from typing import TYPE_CHECKING

    from FunPayAPI.types import LotShortcut

    if TYPE_CHECKING:
    from cardinal import Cardinal
    from FunPayAPI.updater.events import *
    from os.path import exists
    from tg_bot import CBT
    from telebot.types import InlineKeyboardMarkup as K, InlineKeyboardButton as B
    import telebot
    import logging
    from locales.localizer import Localizer
    import tg_bot.static_keyboards

    localizer = Localizer()
    _ = localizer.translate
    NAME = "Autodumping Plugin"
    VERSION = "0.0.7"
    DESCRIPTION = "Автоматически понижает цены в зависимости от цен на рынке."

    CREDITS = "@sidor0912"
    UUID = "186042c8-f735-4f01-a11a-a3945b68b442"
    SETTINGS_PAGE = True
    logger = logging.getLogger("FPC.autodumping_plugin")
    LOGGER_PREFIX = "[AUTODUMPING PLUGIN]"
    SETTINGS = {
    "users_good": [],
    "users_bad": [],
    "currency": "₽",
    "time": 10
    }
    # todo изменить время
    LOTS = {}
    CBT_CHANGE_CURRENCY = "AD_change_curr"
    CBT_TEXT_CHANGE_LOT = "AD_ChangeLot"
    CBT_TEXT_EDIT = "AD_Edit"
    CBT_TEXT_DELETE = "AD_DELETE"


    def init(cardinal: Cardinal):
    if not cardinal.telegram:
    return
    tg = cardinal.telegram
    bot = tg.bot
    if exists("storage/plugins/autodumping_plugin.json"):
    with open("storage/plugins/autodumping_plugin.json", "r", encoding="utf-8") as f:
    global SETTINGS
    settings = json.loads(f.read())
    SETTINGS.update(settings)

    def save_settings():
    with open("storage/plugins/autodumping_plugin.json", "w", encoding="utf-8") as f:
    global SETTINGS
    f.write(json.dumps(SETTINGS, indent=4, ensure_ascii=False))
    logger.info(f"{LOGGER_PREFIX} Настройки сохранены.")

    def save_lots():
    with open("storage/plugins/autodumping_plugin_lots.json", "w", encoding="utf-8") as f:
    global LOTS
    f.write(json.dumps(LOTS, indent=4, ensure_ascii=False))
    logger.info(f"{LOGGER_PREFIX} Настройки лотов сохранены.")

    if exists("storage/plugins/autodumping_plugin_lots.json"):
    with open("storage/plugins/autodumping_plugin_lots.json", "r", encoding="utf-8") as f:
    global LOTS
    LOTS = json.loads(f.read())
    for i, l in LOTS.items():
    if "1_currency" not in l:
    LOTS[i]["1_currency"] = False
    save_lots()

    def open_settings(call: telebot.types.CallbackQuery):
    global SETTINGS
    keyboard = K()
    keyboard.add(B(f"Валюта: {SETTINGS['currency']}", callback_data=f"{CBT_CHANGE_CURRENCY}:"))
    # todo обработка кнопки
    keyboard.add(B(f"Каждые {SETTINGS['time']} минут", url=f"t.me/FPC_pluginss"))
    for lot_id, data in sorted(LOTS.items(), key=lambda x: int(x[0])):
    on = data.get("on")
    kw = data.get("keywords").replace('\n', ' ')[:100].rsplit(" ", 1)[0]
    keyboard.add(B(f"({lot_id}) {'🟢' if on else '🔴'} {kw}", callback_data=f"{CBT_TEXT_CHANGE_LOT}:{lot_id}"))
    keyboard.add(B("➕ Добавить лот", callback_data=f"{CBT_TEXT_CHANGE_LOT}:0"))
    keyboard.add(B("◀ Назад", callback_data=f"{CBT.EDIT_PLUGIN}:{UUID}:0"))
    bot.edit_message_text("В данном разделе Вы можете настроить демпинг.", call.message.chat.id, call.message.id,
    reply_markup=keyboard)
    bot.answer_callback_query(call.id)

    def switch_currency(call: telebot.types.CallbackQuery):
    global SETTINGS
    currencies = ["₽", "$", "€"] * 2
    SETTINGS["currency"] = currencies[currencies.index(SETTINGS["currency"]) + 1]
    save_settings()
    open_settings(call)

    def to_lot_mess(call: telebot.types.CallbackQuery):
    n = call.data.split(":")[-1]
    global LOTS
    if n == "0" and n not in LOTS.keys():
    # todo
    LOTS.setdefault(n, {"on": False,
    "keywords": "Нужно настроить ключевые слова лота.",
    "min": 0,
    "max": 99999,
    "users_good": False,
    "users_bad": False,
    "stars": 5,
    "ignore_0_stars": False,
    "step": 5,
    "divider": 1,
    "1_currency": False
    })
    save_lots()

    keyboard = K()
    keyboard.add(B(f"{'🟢 Включено' if LOTS[n]['on'] else '🔴 Выключено'}",
    callback_data=f"{CBT_TEXT_EDIT}:{n}:on"))
    keyboard.add(B(f"✏ Изменить ключевые слова",
    callback_data=f"{CBT_TEXT_EDIT}:{n}:keywords"))
    keyboard.add(B(f"✏ ID лота: {n}",
    callback_data=f"{CBT_TEXT_EDIT}:{n}:lot_id"))
    keyboard.add(
    B(f"{'🟢' if LOTS[n]['1_currency'] else '🔴'}" + f" Минимум 1 {SETTINGS['currency']} без учета комиссии",
    callback_data=f"{CBT_TEXT_EDIT}:{n}:1_currency"))
    keyboard.add(B(f"✏ Мин. цена: {LOTS[n].get('min')}",
    callback_data=f"{CBT_TEXT_EDIT}:{n}:min"))
    keyboard.add(B(f"✏ Макс. цена: {LOTS[n].get('max')}",
    callback_data=f"{CBT_TEXT_EDIT}:{n}:max"))
    keyboard.add(B(f"✏ Шаг: {LOTS[n].get('step')}",
    callback_data=f"{CBT_TEXT_EDIT}:{n}:step"))
    keyboard.add(B(f"✏ Делитель: {LOTS[n].get('divider')}",
    callback_data=f"{CBT_TEXT_EDIT}:{n}:divider"))
    keyboard.add(B(f"{'🟢' if LOTS[n].get('users_good') else '🔴'} Игнор лотов друзей",
    callback_data=f"{CBT_TEXT_EDIT}:{n}:users_good"))
    keyboard.add(B(f"{'🟢' if LOTS[n].get('users_bad') else '🔴'} Игнор всех, кроме конкурентов",
    callback_data=f"{CBT_TEXT_EDIT}:{n}:users_bad"))
    keyboard.add(B(f"{'🟢' if LOTS[n].get('ignore_0_stars') else '🔴'} Игнор челов без рейтинга",
    callback_data=f"{CBT_TEXT_EDIT}:{n}:ignore_0_stars"))
    keyboard.add(B(f"{LOTS[n].get('stars')}+ ⭐",
    callback_data=f"{CBT_TEXT_EDIT}:{n}:stars"))

    keyboard.add(B(f"🗑 Удалить",
    callback_data=f"{CBT_TEXT_DELETE}:{n}"))
    keyboard.add(B("◀ Назад", callback_data=f"{CBT.PLUGIN_SETTINGS}:{UUID}"))
    txt = f"https://Funpay.com/lots/offer?id={n}\n\n<b>Ключевые слова:</b> {LOTS.get(n).get('keywords')}"
    bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.id, text=txt, reply_markup=keyboard)

    def answer_to_lot_mess(call: telebot.types.CallbackQuery):
    *a, n, key = call.data.split(":")
    global LOTS
    if key in ("max", "min", "keywords", "lot_id", "step", "divider"):
    bot.answer_callback_query(call.id)
    d = {
    "max": "максимальную цену",
    "min": "минимальную цену",
    "keywords": "ключевые слова (<code>|</code> для разделения равнозначных значений)",
    "lot_id": "ID лота",
    "step": "шаг",
    "divider": "делитель"
    }
    text = f'Введите {d.get(key, "что-то")} для https://Funpay.com/lots/offer?id={n} :'
    msg = bot.send_message(call.message.chat.id, text=text,
    reply_markup=tg_bot.static_keyboards.CLEAR_STATE_BTN())
    tg.set_state(call.message.chat.id, msg.id, call.from_user.id, CBT_TEXT_EDIT,
    data={"key": key, "n": n})
    bot.answer_callback_query(call.id)
    return
    if key in ("on", "users_good", "users_bad", "ignore_0_stars", "1_currency"):
    LOTS[n][key] = not LOTS[n][key]
    elif key == "stars":
    LOTS[n][key] = LOTS[n][key] % 5 + 1

    save_lots()
    call.data = f"{CBT_TEXT_CHANGE_LOT}:{n}"
    to_lot_mess(call)
    return

    def to_delete(call: telebot.types.CallbackQuery):
    n = call.data.split(":")[-1]
    global LOTS
    del LOTS[n]
    save_lots()
    open_settings(call)

    def edited(message: telebot.types.Message):
    global LOTS
    text = message.text
    data = tg.get_state(message.chat.id, message.from_user.id)["data"]
    if data.get("key") in ("max", "min", "keywords", "step", "divider"):
    if data.get("key") == "keywords":
    text = text.lower()
    else:
    text = float(text)
    LOTS[data.get("n")][data.get("key")] = text
    elif data.get("key") == "lot_id":
    text = str(int("".join([char for char in text if char.isdigit()])))
    LOTS[text] = LOTS[data.get("n")]
    del LOTS[data.get("n")]
    tg.clear_state(message.chat.id, message.from_user.id, True)
    keyboard = K() \
    .row(B("◀ Назад",
    callback_data=f"{CBT_TEXT_CHANGE_LOT}:{data.get('n') if data.get('key') != 'lot_id' else text}"))
    save_lots()
    bot.reply_to(message, f"✅", reply_markup=keyboard)

    def edit_users_list(message: telebot.types.Message):
    global SETTINGS
    text = message.text
    users = text.split(" ")[1:]
    if (text.startswith("/adl_good")):
    key = "users_good"
    elif (text.startswith("/adl_bad")):
    key = "users_bad"
    else:
    raise Exception()
    for user in users:
    if user not in SETTINGS[key]:
    SETTINGS[key].append(user)
    else:
    SETTINGS[key].remove(user)
    save_settings()
    bot.reply_to(message,
    f"{'Список друзей' if key == 'users_good' else 'Список конкурентов'}:\n{', '.join([f'<code>{i}</code>' for i in SETTINGS[key]])}")

    tg.msg_handler(edited, func=lambda m: tg.check_state(m.chat.id, m.from_user.id, CBT_TEXT_EDIT))
    tg.msg_handler(edit_users_list, func=lambda m: m.text.startswith("/adl_"))
    tg.cbq_handler(to_lot_mess, lambda c: c.data.startswith(f"{CBT_TEXT_CHANGE_LOT}:"))
    tg.cbq_handler(switch_currency, lambda c: f"{CBT_CHANGE_CURRENCY}" in c.data)
    tg.cbq_handler(open_settings, lambda c: f"{CBT.PLUGIN_SETTINGS}:{UUID}" in c.data)
    tg.cbq_handler(answer_to_lot_mess, lambda c: c.data.startswith(f"{CBT_TEXT_EDIT}:"))
    tg.cbq_handler(to_delete, lambda c: c.data.startswith(f"{CBT_TEXT_DELETE}:"))
    cardinal.add_telegram_commands(UUID, [
    (f"adl_good", "Друзья", True),
    (f"adl_bad", "Конкуренты", True),
    ])


    def post_start(cardinal):
    def filter_lots(lot: LotShortcut, my_lot_id):
    global LOTS
    if lot.seller.username == cardinal.account.username:
    return False
    kw = LOTS.get(my_lot_id).get("keywords")
    if not all([any([j in lot.description.lower() for j in i.split("|")]) for i in kw.split("\n")]):
    return False
    if LOTS.get(my_lot_id).get("users_good") and lot.seller.username in SETTINGS.get("users_good"):
    return False
    if LOTS.get(my_lot_id).get("users_bad") and lot.seller.username not in SETTINGS.get("users_bad"):
    return False
    if not (LOTS.get(my_lot_id).get("min") + LOTS.get(my_lot_id).get("step") <= lot.price <= LOTS.get(
    my_lot_id).get("max") + LOTS.get(my_lot_id).get("step")):
    return False
    if lot.seller.stars is None and LOTS.get(my_lot_id).get("ignore_0_stars"):
    return False
    if lot.seller.stars is not None and lot.seller.stars < LOTS.get(my_lot_id).get("stars"):
    return False

    return True

    def get_commission(node_id):
    headers = {
    "accept": "*/*",
    "x-requested-with": "XMLHttpRequest"
    }
    data = {
    "nodeId": node_id,
    "price": 1000
    }
    calc = cardinal.account.method("post", "https://Funpay.com/lots/calc", headers, data).json()["methods"]
    commission = float(
    min([i for i in calc if i.get("unit") == SETTINGS["currency"]], key=lambda x: float(x.get("price"))).get(
    "price")) / 1000
    return commission

    def change_price(cardinal: Cardinal, my_lot_id: int, new_price: float, commission: float, min_1: bool):
    lot_fields = cardinal.account.get_lot_fields(my_lot_id)
    time.sleep(1)
    price_without_comission = new_price / commission
    if price_without_comission < 1 and min_1:
    price_without_comission = 1
    old_price = lot_fields.price
    if r := abs(price_without_comission - old_price) >= 0.001:
    lot_fields.price = price_without_comission
    cardinal.account.save_lot(lot_fields)
    logger.info(
    f"{LOGGER_PREFIX} Сохранил лот $MAGENTA{my_lot_id}$RESET. Цена: {old_price} -> {price_without_comission}")
    else:
    logger.info(
    f"{LOGGER_PREFIX} Цена лота $MAGENTA{my_lot_id}$RESET не изменилась: {old_price} -> {price_without_comission}")

    def process(cardinal):
    global LOTS
    while True:
    logger.info(f"{LOGGER_PREFIX} Новый проход. {'-' * 100}")
    try:
    to_break = False
    result = cardinal.update_lots_and_categories()
    if not result:
    time.sleep(30)
    continue
    my_lots = cardinal.tg_profile.get_sorted_lots(2)
    for category, i in my_lots.items():
    if category.type == SubCategoryTypes.CURRENCY or category.id == 210:
    continue
    category_lots = None
    category_comission = None
    for my_lot_id, lot in i.items():
    if str(lot.currency) != SETTINGS.get("currency"):
    to_break = True
    break
    my_lot_id = str(my_lot_id)
    if str(my_lot_id) not in LOTS.keys() or not LOTS[my_lot_id].get("on"):
    continue
    logger.info(f"{LOGGER_PREFIX} Обрабатываю лот {my_lot_id}.")
    try:
    if category_lots is None:
    category_lots = cardinal.account.get_subcategory_public_lots(category.type, category.id)
    time.sleep(1)
    logger.info(
    f"{LOGGER_PREFIX} Получил {len(category_lots)} лотов категории $MAGENTA{category.fullname}$RESET.")
    if category_comission is None:
    category_comission = get_commission(category.id)
    time.sleep(1)
    logger.info(
    f"{LOGGER_PREFIX} Комиссия раздела {category.fullname} - {category_comission}.")
    category_lots_4_lot = list(filter(lambda x: filter_lots(x, my_lot_id), category_lots))
    logger.info(
    f"{LOGGER_PREFIX} Осталось {len(category_lots_4_lot)} лотов для лота {my_lot_id} после фильрации.")
    min_1 = LOTS[my_lot_id].get("1_currency", False)
    if category_lots_4_lot:
    logger.info(
    f"{LOGGER_PREFIX} Список подходящих лотов: {', '.join([str(l.id) for l in category_lots_4_lot])}")
    min_price_lot = min(category_lots_4_lot, key=lambda x: x.price)
    if str(min_price_lot.currency) != SETTINGS.get("currency"):
    to_break = True
    break
    logger.info(f"{LOGGER_PREFIX} Перебиваем лот {min_price_lot.id} в лоте {my_lot_id}")
    first = min_price_lot.price - LOTS[my_lot_id].get("step")
    change_price(cardinal, my_lot_id, min(LOTS[my_lot_id].get("max"),
    first - first % LOTS[my_lot_id].get("divider")),
    category_comission, min_1)
    else:
    change_price(cardinal, my_lot_id, LOTS[my_lot_id].get("max"), category_comission, min_1)
    time.sleep(1)
    except:
    logger.warning(
    f"{LOGGER_PREFIX} Произошла ошибка при обработке лота {my_lot_id}. Лот пропущен.")
    logger.debug("TRACEBACK", exc_info=True)
    if to_break:
    break
    except:
    logger.warning(
    f"{LOGGER_PREFIX} Произошла ошибка. Итерация пропущена. Следующая попытка через {SETTINGS.get('time')} минут.")
    logger.debug("TRACEBACK", exc_info=True)
    time.sleep(max(SETTINGS.get("time", 0) * 60, 5))

    Thread(target=process, daemon=True, args=(cardinal,)).start()


    BIND_TO_PRE_INIT = [init]
    BIND_TO_POST_START = [post_start]
    BIND_TO_DELETE = None
    сидор, будь мужиком и продавай доверенным лицам свой говнокод
     
  2. RBLuXe
    RBLuXe Автор темы 17 мар 2025 7 1 июл 2024
    туда его! не нужны нам люди, которые крадут наши данные и деньги!
     
  3. RBLuXe
    RBLuXe Автор темы 17 мар 2025 7 1 июл 2024
    хотите разоблачение на кардинал?
     
  4. Кумиров
    Давай
     
  5. Эксфадор
    Эксфадор 17 мар 2025 ПЛАГИНЫ ДЛЯ FPC - t.me/coxerhub 1747 30 авг 2023
    даже так
     
  6. DraftHolder
    окак
     
  7. kash1dd
    kash1dd 17 мар 2025 1 27 июн 2021
    окак
     
  8. 2bz
    2bz 17 мар 2025 Бот для Playerok.com - lolz.live/threads/7845602/ 8198 6 мар 2021
    и нахуя
     
  9. Neftirr
    Neftirr 17 мар 2025 2 12 мар 2023
    ну ты крутой:colobok_cool:
     
  10. led
    и нахуя
     
  11. Jlamsiamji1995
    Jlamsiamji1995 17 мар 2025 Разработка за отзыв - https://lolz.live/threads/8526601/ 7 24 окт 2022
  12. feelingRage
    feelingRage 18 мар 2025 Заблокирован(а) 13 30 июн 2024
    Знаю, что охуел, но похуй :cool_bun:
    А есть ещё что-то от Сидора?
     
    1. Jlamsiamji1995
      feelingRage, да дохуя че есть от него ес честно)
  13. RBLuXe
    RBLuXe Автор темы 18 мар 2025 7 1 июл 2024
    ГОНИТЕ АКТИВА, CЕГОДНЯ СЛИВЕЦ СДЕЛАЕМ
     
    1. feelingRage
      RBLuXe, будем ждать всем разделом :cool_bun:
  14. RBLuXe
    RBLuXe Автор темы 31 мар 2025 7 1 июл 2024
    добыл автостарсы сидора, хотим слив?
     
  15. Heryll
    Heryll 25 апр 2025 trading? sm? 520 3 май 2022
    бекдорчика туда завез?
     
  16. WestLUL
    WestLUL 30 май 2025 3 24 фев 2018
    Не работает почему-то или не могу верно настроить.
     
    30 май 2025 Изменено
Top