def start(bot: octobot.OctoBot, ctx: octobot.Context): if ctx.query == "": kbd = telegram.InlineKeyboardMarkup( [[ telegram.InlineKeyboardButton( ctx.localize("Command list"), url=f"https://t.me/{bot.me.username}?start=help") ], [ telegram.InlineKeyboardButton(ctx.localize("Support chat"), url=Settings.support_url) ]]) ctx.reply(ctx.localize( "Hi! I am {bot.me.first_name}, a Telegram bot with features and bugs and blah blah, noone reads /start anyway." ).format(bot=bot), reply_markup=kbd) else: # Proxify to other command update = ctx.update if ctx.args[0].startswith("b64-"): b64data = ctx.args[0].replace("b64-", "", 1) data = base64.urlsafe_b64decode(b64data) logger.debug(f'proxying b64 command {data} ({b64data})') update.message.text = data.decode() else: update.message.text = "/" + ctx.args[0] logger.debug("proxying plaintext command", update.message.text) bot.handle_update(bot, update)
def reload(bot: octobot.OctoBot, ctx): msg: telegram.Message = ctx.reply("Reloading...") msg_res = [] for plugin in bot.discover_plugins()["load_order"]: res = bot.load_plugin(plugin) msg_res.append(f"{plugin} - {res}") bot.update_handlers() ctx.edit("Reload complete. Plugin statuses:\n" + "\n".join(msg_res))
async def test_run_bot(event_loop): # launch a bot config = load_test_config() config[CONFIG_CRYPTO_CURRENCIES] = {"Bitcoin": {"pairs": ["BTC/USDT"]}} bot = OctoBot(config) bot.time_frames = [TimeFrames.ONE_MINUTE] await bot.create_exchange_traders(ignore_config=True) bot.create_evaluation_tasks() await asyncio.sleep(5) await asyncio.get_event_loop().run_in_executor(None, bot.stop_threads)
def warn(bot: octobot.OctoBot, context: octobot.Context): if octobot.Database.redis is None: raise octobot.DatabaseNotAvailable if context.update.message.reply_to_message is None: context.reply(context.localize("Reply to user to give them a warn")) return if octobot.check_permissions( chat=context.chat, user=context.update.message.reply_to_message.from_user, permissions_to_check={"is_admin"})[0]: context.reply(context.localize("Can't warn administrator")) return target_id = context.update.message.reply_to_message.from_user.id target_name = context.update.message.reply_to_message.from_user.first_name user_warns_db_id = create_warn_db_id(context.chat.id, target_id) max_warns = int(context.chat_db.get("max_warns", 3)) reason = context.query if reason == "": reason = context.localize("Warn reason not specified") octobot.Database.redis.lpush(user_warns_db_id, reason) user_warn_count = int(octobot.Database.redis.llen(user_warns_db_id)) action_taken = "" reply_markup = telegram.InlineKeyboardMarkup.from_button( telegram.InlineKeyboardButton( text="Remove last warn", callback_data=f"warn_cancel:{target_id}:{context.chat.id}")) if user_warn_count >= max_warns: action_taken = context.localize( "\n\n<i>User had reached maximum warnings in chat and was banned</i>" ) bot.kick_chat_member(chat_id=context.chat.id, user_id=target_id) octobot.Database.redis.delete(user_warns_db_id) reply_markup = telegram.InlineKeyboardMarkup.from_button( telegram.InlineKeyboardButton( callback_data=f"ban_cancel:{target_id}:{context.chat.id}", text=context.localize("Unban"))) context.reply(context.localize('⚠�<a href="tg://user?id={admin_id}">{admin}</a> warned ' + \ '<a href="tg://user?id={target_id}">{target_name}</a> ' + \ '({warn_count}/{max_warns})' + \ '\nReason: <i>{reason}</i>').format( admin_id=context.user.id, admin=html.escape(context.user.first_name), target_id=target_id, target_name=html.escape(target_name), reason=html.escape(reason), warn_count=user_warn_count, max_warns=max_warns ) + action_taken, parse_mode="HTML", reply_markup=reply_markup)
def send_commands(bot: octobot.OctoBot): command_list = [] for priority, priority_handlers in bot.handlers.items(): for handler in priority_handlers: if isinstance(handler, octobot.CommandHandler): if not (handler.hidden or handler.prefix != "/" or handler.service): for command in handler.command: command_list.append([command, handler.description]) if os.environ.get("DRY_RUN", False): os.makedirs("public", exist_ok=True) with open("public/commands.json", "w") as f: json.dump(command_list, f) else: bot.set_my_commands(command_list)
def _get_tools(): symbol = "BTC/USDT" exchange_traders = {} exchange_traders2 = {} config = load_test_config() time_frame = TimeFrames.ONE_HOUR AdvancedManager.create_class_list(config) symbol_time_frame_updater_thread = SymbolTimeFramesDataUpdaterThread() exchange_manager = ExchangeManager(config, ccxt.binance, is_simulated=True) exchange_inst = exchange_manager.get_exchange() trader_inst = TraderSimulator(config, exchange_inst, 0.3) trader_inst.stop_order_manager() trader_inst2 = TraderSimulator(config, exchange_inst, 0.3) trader_inst2.stop_order_manager() crypto_currency_evaluator = CryptocurrencyEvaluator(config, "Bitcoin", []) symbol_evaluator = SymbolEvaluator(config, symbol, crypto_currency_evaluator) exchange_traders[exchange_inst.get_name()] = trader_inst exchange_traders2[exchange_inst.get_name()] = trader_inst2 symbol_evaluator.set_trader_simulators(exchange_traders) symbol_evaluator.set_traders(exchange_traders2) symbol_evaluator.strategies_eval_lists[exchange_inst.get_name( )] = EvaluatorCreator.create_strategies_eval_list(config) trading_mode_inst = OctoBot.get_trading_mode_class(config)(config, exchange_inst) evaluator_thread_manager = EvaluatorThreadsManager( config, time_frame, symbol_time_frame_updater_thread, symbol_evaluator, exchange_inst, trading_mode_inst, []) trader_inst.portfolio.portfolio["USDT"] = { Portfolio.TOTAL: 2000, Portfolio.AVAILABLE: 2000 } return evaluator_thread_manager, time_frame, symbol_time_frame_updater_thread, symbol_evaluator
def spamwatch_handle_user(bot: octobot.OctoBot, ctx: octobot.Context): if ctx.chat.type != "supergroup": return chat_action = ctx.chat_db.get(SPAMWATCH_DB_KEY, Settings.spamwatch.default_action) if chat_action == "nothing": return chat_action = VALID_ACTIONS[chat_action] banned = check_spamwatch_ban(ctx.user) if banned: chat_action[-1](bot, ctx.chat, ctx.user) bot.send_message( ctx.chat.id, ctx.localize( "{user} is banned in SpamWatch since {ban_date}. Reason: <code>{ban_reason}</code>" ).format(user=ctx.user.mention_html(ctx.localize("User")), ban_date=babel.dates.format_datetime(banned.date, locale=ctx.locale), ban_reason=html.escape(banned.reason)), parse_mode="HTML")
def button_pin(bot: octobot.OctoBot, context: octobot.Context): chat_id, message_id = context.text.split(":")[1:] perm_check, missing_perms = octobot.check_permissions( chat=chat_id, user=context.user.id, bot=bot, permissions_to_check={"can_pin_messages"}) if perm_check: bot.pin_chat_message(chat_id, message_id, disable_notification=True) context.reply(context.localize("Pinned back the old message")) msg = context.update.effective_message.text_html + "\n\n" + context.localize( 'This action was undone by <a href="tg://user?id={admin_id}">{admin}</a>' ).format(admin_id=context.user.id, admin=html.escape(context.user.first_name)) context.edit(msg, parse_mode="HTML") else: context.reply( context.localize( "Sorry, you can't execute this command cause you lack following permissions: {}" ).format(", ".join(missing_perms)))
def _get_tools(): config = load_test_config() symbol = "BTC/USDT" exchange_traders = {} exchange_traders2 = {} time_frame = TimeFrames.FIVE_MINUTES AdvancedManager.create_class_list(config) symbol_time_frame_updater_thread = SymbolTimeFramesDataUpdaterThread() exchange_manager = ExchangeManager(config, ccxt.binance, is_simulated=True) exchange_inst = exchange_manager.get_exchange() trader_inst = TraderSimulator(config, exchange_inst, 0.3) trader_inst.stop_order_manager() trader_inst2 = TraderSimulator(config, exchange_inst, 0.3) trader_inst2.stop_order_manager() trader_inst2.set_enabled(False) trader_inst.portfolio.portfolio["SUB"] = { Portfolio.TOTAL: 0.000000000000000000005, Portfolio.AVAILABLE: 0.000000000000000000005 } trader_inst.portfolio.portfolio["BNB"] = { Portfolio.TOTAL: 0.000000000000000000005, Portfolio.AVAILABLE: 0.000000000000000000005 } trader_inst.portfolio.portfolio["USDT"] = { Portfolio.TOTAL: 2000, Portfolio.AVAILABLE: 2000 } crypto_currency_evaluator = CryptocurrencyEvaluator(config, "Bitcoin", []) symbol_evaluator = SymbolEvaluator(config, symbol, crypto_currency_evaluator) exchange_traders[exchange_inst.get_name()] = trader_inst exchange_traders2[exchange_inst.get_name()] = trader_inst2 symbol_evaluator.set_trader_simulators(exchange_traders) symbol_evaluator.set_traders(exchange_traders2) trading_mode_inst = OctoBot.get_trading_mode_class(config)(config, exchange_inst) _ = EvaluatorThreadsManager(config, time_frame, symbol_time_frame_updater_thread, symbol_evaluator, exchange_inst, trading_mode_inst, []) trading_mode = HighFrequencyMode(config, exchange_inst) trading_mode.add_symbol_evaluator(symbol_evaluator) return config, exchange_inst, trader_inst, symbol, trading_mode
def start_octobot(starting_args): fileConfig(LOGGING_CONFIG_FILE) logger = logging.getLogger("OctoBot Launcher") # Force new log file creation not to log at the previous one's end. logger.parent.handlers[1].doRollover() sys.excepthook = _log_uncaught_exceptions try: if starting_args.version: print(LONG_VERSION) else: # Version logger.info("Version : {0}".format(LONG_VERSION)) logger.info("Loading config files...") config = load_config(error=False) if config is None: raise ConfigError # Handle utility methods before bot initializing if possible if starting_args.packager: Commands.package_manager(config, starting_args.packager) elif starting_args.creator: Commands.tentacle_creator(config, starting_args.creator) elif starting_args.encrypter: Commands.exchange_keys_encrypter() else: config[CONFIG_EVALUATOR] = load_config( CONFIG_EVALUATOR_FILE_PATH, False) if config[CONFIG_EVALUATOR] is None: raise ConfigEvaluatorError config[CONFIG_TRADING_TENTACLES] = load_config( CONFIG_TRADING_FILE_PATH, False) if config[CONFIG_TRADING_TENTACLES] is None: raise ConfigTradingError if starting_args.data_collector: Commands.data_collector(config) elif starting_args.strategy_optimizer: Commands.start_strategy_optimizer( config, starting_args.strategy_optimizer) else: # In those cases load OctoBot from octobot import OctoBot from interfaces.telegram.bot import TelegramApp from services import WebService TelegramApp.enable(config, starting_args.telegram) WebService.enable(config, not starting_args.no_web) update_config_with_args(starting_args, config) bot = OctoBot(config) import interfaces interfaces.__init__(bot, config) try: main.__init__(config) except NameError as e: logging.error( "{0}, impossible to display GUI".format(e)) if starting_args.start: Commands.start_bot(bot, logger) except ConfigError: logger.error("OctoBot can't start without " + CONFIG_FILE + " configuration file.") os._exit(-1) except ModuleNotFoundError as e: if 'tentacles' in str(e): logger.error( "Impossible to start OctoBot, tentacles are missing.\nTo install tentacles, " "please use the following command:\nstart.py -p install all") os._exit(-1) except ConfigEvaluatorError: logger.error( "OctoBot can't start without a valid " + CONFIG_EVALUATOR_FILE_PATH + " configuration file.\nThis file is generated on tentacle " "installation using the following command:\nstart.py -p install all" ) os._exit(-1) except ConfigTradingError: logger.error( "OctoBot can't start without a valid " + CONFIG_TRADING_FILE_PATH + " configuration file.\nThis file is generated on tentacle " "installation using the following command:\nstart.py -p install all" ) os._exit(-1)
def start_octobot(starting_args): fileConfig(LOGGING_CONFIG_FILE) logger = logging.getLogger("OctoBot Launcher") # Force new log file creation not to log at the previous one's end. logger.parent.handlers[1].doRollover() sys.excepthook = _log_uncaught_exceptions try: if starting_args.version: print(LONG_VERSION) else: # Version logger.info("Version : {0}".format(LONG_VERSION)) _check_public_announcements(logger) logger.info("Loading config files...") # configuration loading config = load_config(error=False) if config is None and is_config_empty_or_missing(): logger.info("No configuration found creating default...") init_config() config = load_config(error=False) if config is None: raise ConfigError # Handle utility methods before bot initializing if possible if starting_args.packager: Commands.package_manager(config, starting_args.packager) elif starting_args.creator: Commands.tentacle_creator(config, starting_args.creator) elif starting_args.encrypter: Commands.exchange_keys_encrypter() else: if not tentacles_arch_exists(): logger.info( "No tentacles found. Installing default tentacles ...") Commands.package_manager(config, ["install", "all"], force=True) config[CONFIG_EVALUATOR] = load_config( CONFIG_EVALUATOR_FILE_PATH, False) if config[CONFIG_EVALUATOR] is None: raise ConfigEvaluatorError config[CONFIG_TRADING_TENTACLES] = load_config( CONFIG_TRADING_FILE_PATH, False) if config[CONFIG_TRADING_TENTACLES] is None: raise ConfigTradingError if starting_args.data_collector: Commands.data_collector(config) elif starting_args.strategy_optimizer: Commands.start_strategy_optimizer( config, starting_args.strategy_optimizer) else: # In those cases load OctoBot from octobot import OctoBot from interfaces.bots.telegram.bot import TelegramApp from services import WebService TelegramApp.enable(config, starting_args.telegram) WebService.enable(config, not starting_args.no_web) update_config_with_args(starting_args, config) bot = OctoBot(config) import interfaces interfaces.__init__(bot, config) if not starting_args.no_open_web and not starting_args.no_web: Thread(target=_auto_open_web, args=(config, bot)).start() # set debug_mode = True to activate asyncio debug mode debug_mode = ConfigManager.is_in_dev_mode( config) or FORCE_ASYNCIO_DEBUG_OPTION asyncio.run(Commands.start_bot(bot, logger), debug=debug_mode) except ConfigError: logger.error("OctoBot can't start without " + CONFIG_FILE + " configuration file.") os._exit(-1) except ModuleNotFoundError as e: if 'tentacles' in str(e): logger.error( "Impossible to start OctoBot, tentacles are missing.\nTo install tentacles, " "please use the following command:\nstart.py -p install all") else: logger.exception(e) os._exit(-1) except ConfigEvaluatorError: logger.error( "OctoBot can't start without a valid " + CONFIG_EVALUATOR_FILE_PATH + " configuration file.\nThis file is generated on tentacle " "installation using the following command:\nstart.py -p install all" ) os._exit(-1) except ConfigTradingError: logger.error( "OctoBot can't start without a valid " + CONFIG_TRADING_FILE_PATH + " configuration file.\nThis file is generated on tentacle " "installation using the following command:\nstart.py -p install all" ) os._exit(-1)
elif args.update: Commands.update(logger) else: # In those cases load OctoBot from octobot import OctoBot config[CONFIG_EVALUATOR] = load_config(CONFIG_EVALUATOR_FILE_PATH, False) TelegramApp.enable(config, args.telegram) WebService.enable(config, args.web) bot = OctoBot(config) import interfaces interfaces.__init__(bot, config) if args.data_collector: Commands.data_collector(config) # start crypto bot options else: if args.backtesting: import backtesting backtesting.__init__(bot)
def create_backtesting_bot(config): bot = OctoBot(config) return bot
def ban(bot: octobot.OctoBot, chat: telegram.Chat, user: telegram.User): bot.kick_chat_member(chat.id, user.id)
def kick(bot: octobot.OctoBot, chat: telegram.Chat, user: telegram.User): bot.unban_chat_member(chat.id, user.id)
def start_octobot(starting_args): if starting_args.pause_time is not None: sleep(starting_args.pause_time) fileConfig('config/logging_config.ini') logger = logging.getLogger("OctoBot Launcher") # Force new log file creation not to log at the previous one's end. logger.parent.handlers[1].doRollover() sys.excepthook = _log_uncaught_exceptions # Version logger.info("Version : {0}".format(LONG_VERSION)) # Test update if starting_args.update: Commands.update(logger) else: Commands.check_bot_update(logger) logger.info("Loading config files...") config = load_config() # Handle utility methods before bot initializing if possible if starting_args.packager: Commands.package_manager(config, starting_args.packager) elif starting_args.creator: Commands.tentacle_creator(config, starting_args.creator) else: # In those cases load OctoBot from octobot import OctoBot config[CONFIG_EVALUATOR] = load_config(CONFIG_EVALUATOR_FILE_PATH, False) TelegramApp.enable(config, starting_args.telegram) WebService.enable(config, starting_args.web) bot = OctoBot(config) import interfaces interfaces.__init__(bot, config) if starting_args.data_collector: Commands.data_collector(config) # start crypto bot options else: if starting_args.backtesting: import backtesting backtesting.__init__(bot) config[CONFIG_BACKTESTING][CONFIG_ENABLED_OPTION] = True config[CONFIG_CATEGORY_NOTIFICATION][ CONFIG_ENABLED_OPTION] = False config[CONFIG_TRADER][CONFIG_ENABLED_OPTION] = False config[CONFIG_SIMULATOR][CONFIG_ENABLED_OPTION] = True if starting_args.simulate: config[CONFIG_TRADER][CONFIG_ENABLED_OPTION] = False config[CONFIG_SIMULATOR][CONFIG_ENABLED_OPTION] = True if starting_args.risk is not None and 0 < starting_args.risk <= 1: config[CONFIG_TRADER][ CONFIG_TRADER_RISK] = starting_args.risk if starting_args.start: Commands.start_bot(bot, logger)
def test_run_bot(): # launch a bot config = load_test_config() bot = OctoBot(config) bot.time_frames = [TimeFrames.ONE_MINUTE] bot.create_exchange_traders() bot.create_evaluation_threads() bot.start_threads() # let it run 2 minutes: test will fail if an exception is raised # 1.9 to stop threads before the next time frame time.sleep(1.9 * 60) # stop the bot bot.stop_threads()
async def test_create_bot(): # launch a bot config = load_test_config() bot = OctoBot(config) await asyncio.get_event_loop().run_in_executor(None, bot.stop_threads)
def create_backtesting_bot(config): return OctoBot(config)
def test_create_bot(): # launch a bot config = load_test_config() bot = OctoBot(config) bot.stop_threads()
def test_run_bot(): # launch a bot config = load_test_config() bot = OctoBot(config) bot.time_frames = [TimeFrames.ONE_MINUTE] bot.create_exchange_traders() bot.create_evaluation_threads() bot.start_threads() # let it start time.sleep(5) # stop the bot bot.stop_threads()