def alarm(bot, job): global exchange_interface, fibonacci, new_results, updater, logger global users_config, users_exchanges, users_market_data, users_indicators chat_id = job.context user_id = 'usr_{}'.format(chat_id) _market_data = users_market_data[user_id] _config = users_config[user_id] _notifier = Notifier(_config.notifiers, _market_data, _config.settings['enable_charts']) _notifier.telegram_client.set_updater(updater) #Getting custom results for each user messages = dict() for _exchange in _market_data: if _exchange in users_exchanges[user_id] : messages[_exchange] = dict() for _market_pair in _market_data[_exchange]: if len(new_results[_exchange][_market_pair]) > 0: messages[_exchange][_market_pair] = copy.deepcopy(new_results[_exchange][_market_pair]) if len(messages[_exchange]) > 0 : _notifier.notify_telegram(messages, users_indicators[user_id])
def chart(bot, update, args): """Send a chart image for a specific market pair and candle period.""" global market_data, users_config chat_id = update.message.chat_id user_id = 'usr_{}'.format(chat_id) _market_data = users_market_data[user_id] _config = users_config[user_id] _notifier = Notifier(_config.notifiers, _market_data, _config.settings['enable_charts']) _notifier.telegram_client.set_updater(updater) logger.info('Processing command for chat_id %s' % str(chat_id)) try: exchange = args[0].strip().lower() market_pair = args[1].strip().upper() if market_pair in market_data[exchange]: candle_period = args[2].strip().lower() _notifier.notify_telegram_chart(chat_id, exchange, market_pair, candle_period) else: update.message.reply_text('Market pair %s is not configured!' % market_pair) except (IndexError, ValueError) as err: logger.error('Error on chart() command... %s', err) update.message.reply_text('Usage: /chart <exchange> <market_pair> <candle_period>') update.message.reply_text('Usage: /chart binance xrp/usdt 4h')
def feedback(self, develop, app_key, cer_file, key_file, server_info): notifier = Notifier('feedback', develop, app_key, cer_file, key_file, server_info) if develop: self.notifiers[app_key + ":dev:feedback"] = notifier else: self.notifiers[app_key + ":pro:feedback"] = notifier notifier.run()
def push(self, develop, app_key, cer_file, key_file, server_info): notifier = Notifier('push', develop, app_key, cer_file, key_file, server_info) if develop: self.notifiers[app_key + ":dev:push"] = notifier else: self.notifiers[app_key + ":pro:push"] = notifier notifier.run()
def contact(): name = request.vars.name email = request.vars.mail phone = request.vars.phpne message= request.vars.message from notification import Notifier notifier = Notifier(db) if notifier.send_email(email, "contact_user", email=email, name=name, phone=phone, message=message): return 'Thanks, we have sent you a email...' return 'Uppps there is an error... Please verify you have the SMTP server configured.'
def push(self, develop, app_key, cer_file, key_file, server_info, channel=None): notifier = Notifier('push', develop, app_key, cer_file, key_file, server_info, channel) channel = ':%s' % channel if channel else '' if develop: self.notifiers[app_key + ":dev:push" + channel] = notifier else: self.notifiers[app_key + ":pro:push" + channel] = notifier notifier.run()
def __configure_default(self, behaviour_config): """Configures and returns the default behaviour class. Args: behaviour_config (dict): A dictionary of configuration values pertaining to the behaviour. Returns: DefaultBehaviour: A class of functionality for the default behaviour. """ exchange_interface = ExchangeInterface(self.config.exchanges) strategy_analyzer = StrategyAnalyzer() notifier = Notifier(self.config.notifiers) behaviour = DefaultBehaviour( behaviour_config, exchange_interface, strategy_analyzer, notifier ) return behaviour
def __configure_simple_bot(self, behaviour_config): """Configures and returns the bot behaviour class. Args: behaviour_config (dict): A dictionary of configuration values pertaining to the behaviour. Returns: SimpleBotBehaviour: A class of functionality for the rsi bot behaviour. """ exchange_interface = ExchangeInterface(self.config.exchanges) strategy_analyzer = StrategyAnalyzer() notifier = Notifier(self.config.notifiers) db_handler = DatabaseHandler(self.config.database) behaviour = SimpleBotBehaviour( behaviour_config, exchange_interface, strategy_analyzer, notifier, db_handler ) return behaviour
def run_from_config(config_ff, threadID): # Load settings and create the config object config = Configuration(config_ff) settings = config.settings # Set up logger logs.configure_logging(settings['log_level'], settings['log_mode']) logger = structlog.get_logger() logger.info(" %s", threadID) # Configure and run configured behaviour. exchange_interface = ExchangeInterface(config.exchanges) notifier = Notifier(config.notifiers, config) behaviour = Behaviour(config, exchange_interface, notifier) while True: if settings['run_on_start']: start = time.time() behaviour.run(settings['market_pairs'], settings['output_mode']) end = time.time() dif = end - start wait_for = settings['update_interval'] - int(dif) logger.info("Sleeping for %s seconds", wait_for) time.sleep(wait_for) else: logger.info("Run on start not enabled waiting for %s seconds", settings['wait_and_run']) time.sleep(settings['wait_and_run'])
def main(): """Initializes the application """ # Load settings and create the config object config = Configuration() settings = config.settings # Set up logger logs.configure_logging(settings['log_level'], settings['log_mode']) logger = structlog.get_logger() # Configure and run configured behaviour. exchange_interface = ExchangeInterface(config.exchanges) if settings['market_pairs']: market_pairs = settings['market_pairs'] logger.info("Found configured markets: %s", market_pairs) market_data = exchange_interface.get_exchange_markets( markets=market_pairs) else: logger.info("No configured markets, using all available on exchange.") market_data = exchange_interface.get_exchange_markets() # notifier = Notifier(config.notifiers, market_data) thread_list = [] for exchange in market_data: num = 1 for chunk in split_market_data(market_data[exchange]): market_data_chunk = dict() market_data_chunk[exchange] = { key: market_data[exchange][key] for key in chunk } notifier = Notifier(config.notifiers, config.indicators, market_data_chunk) behaviour = Behaviour(config, exchange_interface, notifier) workerName = "Worker-{}".format(num) worker = AnalysisWorker(workerName, behaviour, notifier, market_data_chunk, settings, logger) thread_list.append(worker) worker.daemon = True worker.start() time.sleep(60) num += 1 logger.info('All workers are running!') for worker in thread_list: worker.join()
def configure_rsi_bot(self, behaviour_config): exchange_interface = ExchangeInterface( self.config.fetch_exchange_config()) strategy_analyzer = StrategyAnalyzer(exchange_interface) notifier = Notifier(self.config.fetch_notifier_config()) db_handler = DatabaseHandler(self.config.fetch_database_config()) behaviour = RSIBot(behaviour_config, exchange_interface, strategy_analyzer, notifier, db_handler) return behaviour
def __init__(self, server_host, server_port, server_prompt, username, password, buffer_size): self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.settimeout(300) self.buffer_size = buffer_size self.server_host = server_host self.server_port = server_port self.server_prompt = server_prompt self.username = username self.password = password.password self.sock.connect((self.server_host, self.server_port)) self.notifier = Notifier()
def configure_default(self, behaviour_config): exchange_interface = ExchangeInterface( self.config.fetch_exchange_config()) strategy_analyzer = StrategyAnalyzer(exchange_interface) notifier = Notifier(self.config.fetch_notifier_config()) behaviour = DefaultBehaviour(behaviour_config, exchange_interface, strategy_analyzer, notifier) return behaviour
def main(): # Load settings and create the config object secrets = {} if os.path.isfile('secrets.json'): secrets = json.load(open('secrets.json')) config = json.load(open('default-config.json')) config.update(secrets) config['settings']['market_pairs'] = os.environ.get('MARKET_PAIRS', config['settings']['market_pairs']) config['settings']['loglevel'] = os.environ.get('LOGLEVEL', config['settings']['loglevel']) config['settings']['app_mode'] = os.environ.get('APP_MODE', config['settings']['app_mode']) config['exchanges']['bittrex']['required']['key'] = os.environ.get('BITTREX_KEY', config['exchanges']['bittrex']['required']['key']) config['exchanges']['bittrex']['required']['secret'] = os.environ.get('BITTREX_SECRET', config['exchanges']['bittrex']['required']['secret']) config['notifiers']['twilio']['required']['key'] = os.environ.get('TWILIO_KEY', config['notifiers']['twilio']['required']['key']) config['notifiers']['twilio']['required']['secret'] = os.environ.get('TWILIO_SECRET', config['notifiers']['twilio']['required']['secret']) config['notifiers']['twilio']['required']['sender_number'] = os.environ.get('TWILIO_SENDER_NUMBER', config['notifiers']['twilio']['required']['sender_number']) config['notifiers']['twilio']['required']['receiver_number'] = os.environ.get('TWILIO_RECEIVER_NUMBER', config['notifiers']['twilio']['required']['receiver_number']) config['notifiers']['gmail']['required']['username'] = os.environ.get('GMAIL_USERNAME', config['notifiers']['gmail']['required']['username']) config['notifiers']['gmail']['required']['password'] = os.environ.get('GMAIL_PASSWORD', config['notifiers']['gmail']['required']['password']) config['notifiers']['gmail']['required']['destination_emails'] = os.environ.get('GMAIL_DESTINATION_EMAILS', config['notifiers']['gmail']['required']['destination_emails']) # Set up logger logs.configure_logging(config['settings']['loglevel'], config['settings']['app_mode']) logger = structlog.get_logger() exchange_interface = ExchangeInterface(config) strategy_analyzer = StrategyAnalyzer(config) notifier = Notifier(config) # The coin pairs coin_pairs = [] if config['settings']['market_pairs']: coin_pairs = config['settings']['market_pairs'].translate(str.maketrans('', '', whitespace)).split(",") else: user_markets = exchange_interface.get_user_markets() for user_market in user_markets['info']: if 'BTC' in user_market['Currency']: continue market_pair = user_market['Currency'] + '/BTC' coin_pairs.append(market_pair) logger.debug(coin_pairs) while True: get_signal(coin_pairs, strategy_analyzer, notifier)
def __configure_reporter(self, behaviour_config): """Configures and returns the reporter behaviour class. Args: behaviour_config (dict): A dictionary of configuration values pertaining to the behaviour. Returns: ReporterBehaviour: A class of functionality for the reporter behaviour. """ exchange_interface = ExchangeInterface(self.config.exchanges) notifier = Notifier(self.config.notifiers) db_handler = DatabaseHandler(self.config.database) behaviour = ReporterBehaviour(behaviour_config, exchange_interface, notifier, db_handler) return behaviour
def convert(args, config): """Converts a file using the soecified conversion arguments""" episode_db = EpisodeDatabase.load_from_cache(config) series_metadata = episode_db.get_tracked_series_by_keyword(args.keyword) if args.keyword is not None and series_metadata is None: print(f"Keyword '{args.keyword}' was not found in the database") else: mapper = FileMapper(episode_db) file_map = mapper.map_files(args.source, args.destination, args.keyword) for src_file, dest_file in file_map: converted_dest_file = "".join( config.conversion.string_substitutions.get(c, c) for c in dest_file) converter = Converter(src_file, converted_dest_file, config.conversion.ffmpeg_location) converter.convert_file(convert_video=args.convert_video, convert_audio=args.convert_audio, convert_subtitles=args.convert_subtitles, dry_run=args.dry_run) if args.notify: if args.dry_run: print( "Operation complete. Not sending notification on dry run.") else: if config.notification is None: print( "No config notification settings in settings file. Not notifying." ) elif (config.notification.receiving_number is None or config.notification.receiving_number == ""): print( "No recipient number specified in notification settings in settings " "file. Not notifying.") else: notifier = Notifier.create_default_notifier(config) if notifier is not None: notifier.notify( config.notification.receiving_number, f"Conversion of {args.source} complete.")
def main(): """Initializes the application """ # Load settings and create the config object config = Configuration() settings = config.settings # Set up logger logs.configure_logging(settings['log_level'], settings['log_mode']) logger = structlog.get_logger() # Configure and run configured behaviour. exchange_interface = ExchangeInterface(config.exchanges) notifier = Notifier(config.notifiers) behaviour = Behaviour(config, exchange_interface, notifier) while True: behaviour.run(settings['market_pairs'], settings['output_mode']) logger.info("Sleeping for %s seconds", settings['update_interval']) time.sleep(settings['update_interval'])
def main(): # Load settings and create the config object config = conf.Configuration() settings = config.fetch_settings() exchange_config = config.fetch_exchange_config() notifier_config = config.fetch_notifier_config() behaviour_config = config.fetch_behaviour_config() # Set up logger logs.configure_logging(settings['loglevel'], settings['app_mode']) exchange_interface = ExchangeInterface(exchange_config) strategy_analyzer = StrategyAnalyzer(exchange_interface) notifier = Notifier(notifier_config) behaviour_manager = Behaviour(behaviour_config) behaviour = behaviour_manager.get_behaviour(settings['selected_task']) behaviour.run(settings['symbol_pairs'], settings['update_interval'], exchange_interface, strategy_analyzer, notifier)
def __configure_rsi_bot(self, behaviour_config): """Configures and returns the rsi bot behaviour class. Args: behaviour_config (dict): A dictionary of configuration values pertaining to the behaviour. Returns: RSIBot: A class of functionality for the rsi bot behaviour. """ exchange_interface = ExchangeInterface( self.config.get_exchange_config()) strategy_analyzer = StrategyAnalyzer(exchange_interface) notifier = Notifier(self.config.get_notifier_config()) db_handler = DatabaseHandler(self.config.get_database_config()) behaviour = RSIBot(behaviour_config, exchange_interface, strategy_analyzer, notifier, db_handler) return behaviour
#!/usr/bin/env python3 import config config.TIME_REQUIRED = 83 config.ALWAYS_NOTIFY_IDS = {71} from notification import Notifier from shared import Spawns spawns = Spawns() # Victreebell pokemon = { 'encounter_id': 93253523, 'spawn_id': 3502935, 'pokemon_id': 71, 'time_till_hidden_ms': 84000, 'lat': 40.776714, 'lon': -111.888558, 'individual_attack': 14, 'individual_defense': 14, 'individual_stamina': 14, 'move_1': 13, 'move_2': 14, 'valid': True } notifier = Notifier(spawns) print(notifier.notify(pokemon, 2))
class Connection: def __init__(self, server_host, server_port, server_prompt, username, password, buffer_size): self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.settimeout(300) self.buffer_size = buffer_size self.server_host = server_host self.server_port = server_port self.server_prompt = server_prompt self.username = username self.password = password.password self.sock.connect((self.server_host, self.server_port)) self.notifier = Notifier() def connect(self, listening=False): # Print data until server prompts for a username, in which case it # will be entered. self.read_until('login: '******'password: '******'tell danieldelpaso hi! %s' % datetime.datetime.utcnow()) logging.debug('Connected!') #If almost 60 minutes have passed, close the connection. while (datetime.datetime.utcnow() - curr_time).seconds < 3540: try: line = self.read_line() if line and listening: logging.info(line) self.process_line(line.strip()) except runtime.DeadlineExceededError: logging.debug('Deadline Exceeded Error') logging.debug("59 minutes have passed, connection restarting") def process_line(self, line): if line.startswith('Game notification:'): self.notifier.handle_game_notification(line) #Select doesn't work on GAE. def read_line(self): try: recv = self.sock.recv(self.buffer_size).replace(self.server_prompt, "") except: logging.debug('Failed to read line.') return None return recv ''' readlist, _, _ = select([self.sock, sys.stdin], [], []) for sock in readlist: if sock == sys.stdin: command = sys.stdin.readline() self.write_line(command) logging.info('Sending command: %s' % command) if sock == self.sock: recv = self.sock.recv(self.buffer_size).replace(self.server_prompt, "") logging.info(recv) return recv ''' def read_until(self, end_str): recv = self.sock.recv(self.buffer_size).replace(self.server_prompt, "") while end_str not in str(recv): logging.info(recv) def write_line(self, str): str += "\n" self.sock.send(str)
class Worker: """Single worker walking on the map""" network_executor = ThreadPoolExecutor(config.NETWORK_THREADS) download_hash = "11dcdeb848ed224924f8a8e14d94d620c8966d44" g = {'seen': 0, 'captchas': 0} db_processor = DatabaseProcessor() spawns = db_processor.spawns accounts = load_accounts() if config.CACHE_CELLS: cell_ids = load_pickle('cells') or {} loop = get_event_loop() login_semaphore = Semaphore(config.SIMULTANEOUS_LOGINS) if config.CAPTCHA_KEY: session = requests.Session() proxies = None proxy = None if config.PROXIES: if len(config.PROXIES) == 1: proxy = config.PROXIES.pop() else: proxies = config.PROXIES.copy() if config.NOTIFY: notifier = Notifier(spawns) g['sent'] = 0 def __init__(self, worker_no): self.worker_no = worker_no self.logger = getLogger('worker-{}'.format(worker_no)) # account information try: self.account = self.extra_queue.get_nowait() except Empty as e: raise ValueError( "You don't have enough accounts for the number of workers specified in GRID." ) from e self.username = self.account['username'] self.location = self.account.get('location', get_start_coords(worker_no)) self.inventory_timestamp = self.account.get('inventory_timestamp') # last time of any request self.last_request = self.account.get('time', 0) # last time of a request that requires user interaction in the game self.last_action = self.last_request # last time of a GetMapObjects request self.last_gmo = self.last_request self.items = self.account.get('items', {}) self.num_captchas = 0 self.eggs = {} self.unused_incubators = [] # API setup if self.proxies: self.new_proxy(set_api=False) self.initialize_api() # State variables self.busy = BusyLock() self.killed = False # Other variables self.after_spawn = None self.speed = 0 self.account_start = None self.total_seen = 0 self.error_code = 'INIT' self.item_capacity = 350 self.visits = 0 self.pokestops = config.SPIN_POKESTOPS self.next_spin = 0 def initialize_api(self): device_info = get_device_info(self.account) self.logged_in = False self.ever_authenticated = False self.empty_visits = 0 self.account_seen = 0 self.api = PGoApi(device_info=device_info) if config.HASH_KEY: self.api.activate_hash_server(config.HASH_KEY) self.api.set_position(*self.location) if self.proxy: self.api.set_proxy({'http': self.proxy, 'https': self.proxy}) self.api.set_logger(self.logger) if self.account.get('provider') == 'ptc' and self.account.get( 'refresh'): self.api._auth_provider = AuthPtc( username=self.username, password=self.account['password'], timeout=config.LOGIN_TIMEOUT) self.api._auth_provider.set_refresh_token( self.account.get('refresh')) self.api._auth_provider._access_token = self.account.get('auth') self.api._auth_provider._access_token_expiry = self.account.get( 'expiry') if self.api._auth_provider.check_access_token(): self.api._auth_provider._login = True self.logged_in = True self.ever_authenticated = True def new_proxy(self, set_api=True): self.proxy = self.proxies.pop() if not self.proxies: self.proxies.update(config.PROXIES) if set_api: self.api.set_proxy({'http': self.proxy, 'https': self.proxy}) def swap_circuit(self, reason=''): time_passed = monotonic() - CIRCUIT_TIME[self.proxy] if time_passed > 180: socket = config.CONTROL_SOCKS[self.proxy] with Controller.from_socket_file(path=socket) as controller: controller.authenticate() controller.signal(Signal.NEWNYM) CIRCUIT_TIME[self.proxy] = monotonic() CIRCUIT_FAILURES[self.proxy] = 0 self.logger.warning('Changed circuit on {p} due to {r}.'.format( p=self.proxy, r=reason)) else: self.logger.info('Skipped changing circuit on {p} because it was ' 'changed {s} seconds ago.'.format(p=self.proxy, s=time_passed)) async def login(self): """Logs worker in and prepares for scanning""" self.logger.info('Trying to log in') self.error_code = '^' async with self.login_semaphore: if self.killed: return False self.error_code = 'LOGIN' for attempt in range(-1, config.MAX_RETRIES): try: await self.loop.run_in_executor( self.network_executor, partial(self.api.set_authentication, username=self.username, password=self.account['password'], provider=self.account.get('provider', 'ptc'), timeout=config.LOGIN_TIMEOUT)) except ex.AuthTimeoutException: if attempt >= config.MAX_RETRIES - 1: raise else: self.logger.warning('Login attempt timed out.') else: break if not self.ever_authenticated: if config.APP_SIMULATION: await self.app_simulation_login() else: # do one startup request instead of the whole login flow # will receive the full inventory and the download_hash request = self.api.create_request() request.download_remote_config_version(platform=1, app_version=5301) await self.call(request, stamp=False, buddy=False, settings=True, dl_hash=False) await random_sleep(.1, .462) self.ever_authenticated = True self.logged_in = True self.error_code = None self.account_start = time() return True async def app_simulation_login(self): self.error_code = 'APP SIMULATION' self.logger.info('Starting RPC login sequence (iOS app simulation)') # empty request 1 request = self.api.create_request() await self.call(request, chain=False) await random_sleep(0.3, 0.4) # empty request 2 request = self.api.create_request() await self.call(request, chain=False) await random_sleep(.3, .4) # request 1: get_player request = self.api.create_request() request.get_player(player_locale=config.PLAYER_LOCALE) responses = await self.call(request, chain=False) get_player = responses.get('GET_PLAYER', {}) tutorial_state = get_player.get('player_data', {}).get('tutorial_state', []) self.item_capacity = get_player.get('player_data', {}).get('max_item_storage', 350) if get_player.get('banned', False): raise ex.BannedAccountException await random_sleep(.7, 1.2) version = 5301 # request 2: download_remote_config_version request = self.api.create_request() request.download_remote_config_version(platform=1, app_version=version) responses = await self.call(request, stamp=False, buddy=False, settings=True, dl_hash=False) inventory_items = responses.get('GET_INVENTORY', {}).get('inventory_delta', {}).get('inventory_items', []) player_level = None for item in inventory_items: player_stats = item.get('inventory_item_data', {}).get('player_stats', {}) if player_stats: player_level = player_stats.get('level') break await random_sleep(.78, .95) # request 3: get_asset_digest request = self.api.create_request() request.get_asset_digest(platform=1, app_version=version) await self.call(request, buddy=False, settings=True) await random_sleep(.9, 3.4) if (config.COMPLETE_TUTORIAL and tutorial_state is not None and not all(x in tutorial_state for x in (0, 1, 3, 4, 7))): self.logger.warning('Starting tutorial') await self.complete_tutorial(tutorial_state) else: # request 4: get_player_profile request = self.api.create_request() request.get_player_profile() await self.call(request, settings=True) await random_sleep(.3, .5) if player_level: # request 5: level_up_rewards request = self.api.create_request() request.level_up_rewards(level=player_level) await self.call(request, settings=True) await random_sleep(.45, .7) else: self.logger.warning('No player level') # request 6: register_background_device request = self.api.create_request() request.register_background_device(device_type='apple_watch') await self.call(request, action=0.1) self.logger.info('Finished RPC login sequence (iOS app simulation)') self.error_code = None return True async def complete_tutorial(self, tutorial_state): self.error_code = 'TUTORIAL' if 0 not in tutorial_state: await random_sleep(1, 5) request = self.api.create_request() request.mark_tutorial_complete(tutorials_completed=0) await self.call(request, buddy=False) if 1 not in tutorial_state: await random_sleep(5, 12) request = self.api.create_request() request.set_avatar( player_avatar={ 'hair': randint(1, 5), 'shirt': randint(1, 3), 'pants': randint(1, 2), 'shoes': randint(1, 6), 'gender': randint(0, 1), 'eyes': randint(1, 4), 'backpack': randint(1, 5) }) await self.call(request, buddy=False) await random_sleep(.3, .5) request = self.api.create_request() request.mark_tutorial_complete(tutorials_completed=1) await self.call(request, buddy=False, action=1) await random_sleep(.5, .6) request = self.api.create_request() request.get_player_profile() await self.call(request) starter_id = None if 3 not in tutorial_state: await random_sleep(1, 1.5) request = self.api.create_request() request.get_download_urls(asset_id=[ '1a3c2816-65fa-4b97-90eb-0b301c064b7a/1477084786906000', 'aa8f7687-a022-4773-b900-3a8c170e9aea/1477084794890000', 'e89109b0-9a54-40fe-8431-12f7826c8194/1477084802881000' ]) await self.call(request) await random_sleep(1, 1.6) request = self.api.create_request() await self.call(request, chain=False) await random_sleep(6, 13) request = self.api.create_request() starter = choice((1, 4, 7)) request.encounter_tutorial_complete(pokemon_id=starter) await self.call(request, action=1) await random_sleep(.5, .6) request = self.api.create_request() request.get_player(player_locale=config.PLAYER_LOCALE) responses = await self.call(request) inventory = responses.get('GET_INVENTORY', {}).get('inventory_delta', {}).get('inventory_items', []) for item in inventory: pokemon = item.get('inventory_item_data', {}).get('pokemon_data') if pokemon: starter_id = pokemon.get('id') if 4 not in tutorial_state: await random_sleep(5, 12) request = self.api.create_request() request.claim_codename(codename=self.username) await self.call(request, action=1) await random_sleep(1, 1.3) request = self.api.create_request() request.mark_tutorial_complete(tutorials_completed=4) await self.call(request, buddy=False) await sleep(.1) request = self.api.create_request() request.get_player(player_locale=config.PLAYER_LOCALE) await self.call(request) if 7 not in tutorial_state: await random_sleep(4, 10) request = self.api.create_request() request.mark_tutorial_complete(tutorials_completed=7) await self.call(request) if starter_id: await random_sleep(3, 5) request = self.api.create_request() request.set_buddy_pokemon(pokemon_id=starter_id) await self.call(request, action=1) await random_sleep(.8, 1.8) await sleep(.2) return True def update_inventory(self, inventory_items): for thing in inventory_items: obj = thing.get('inventory_item_data', {}) if 'item' in obj: item = obj['item'] item_id = item.get('item_id') self.items[item_id] = item.get('count', 0) elif config.INCUBATE_EGGS: if ('pokemon_data' in obj and obj['pokemon_data'].get('is_egg')): egg = obj['pokemon_data'] egg_id = egg.get('id') self.eggs[egg_id] = egg elif 'egg_incubators' in obj: self.unused_incubators = [] for item in obj['egg_incubators'].get('egg_incubator', []): if 'pokemon_id' in item: continue if item.get('item_id') == 901: self.unused_incubators.append(item) else: self.unused_incubators.insert(0, item) async def call(self, request, chain=True, stamp=True, buddy=True, settings=False, dl_hash=True, action=None): if chain: request.check_challenge() request.get_hatched_eggs() if stamp and self.inventory_timestamp: request.get_inventory( last_timestamp_ms=self.inventory_timestamp) else: request.get_inventory() request.check_awarded_badges() if settings: if dl_hash: request.download_settings(hash=self.download_hash) else: request.download_settings() if buddy: request.get_buddy_walked() try: refresh = HashServer.status.get('period') while HashServer.status.get('remaining') < 5 and time() < refresh: self.error_code = 'HASH WAITING' wait = refresh - time() + 1 await sleep(wait) refresh = HashServer.status.get('period') except TypeError: pass now = time() if action: # wait for the time required, or at least a half-second if self.last_action > now + .5: await sleep(self.last_action - now) else: await sleep(0.5) for _ in range(-1, config.MAX_RETRIES): try: response = await self.loop.run_in_executor( self.network_executor, request.call) if response: break else: raise ex.MalformedResponseException('empty response') except ex.HashingOfflineException: self.logger.warning('Hashing server busy or offline.') self.error_code = 'HASHING OFFLINE' await sleep(7.5) except ex.NianticOfflineException: self.logger.warning('Niantic busy or offline.') self.error_code = 'NIANTIC OFFLINE' await random_sleep() except ex.HashingQuotaExceededException: self.logger.warning('Exceeded your hashing quota, sleeping.') self.error_code = 'QUOTA EXCEEDED' refresh = HashServer.status.get('period') now = time() if refresh: if refresh > now: await sleep(refresh - now + 1) else: await sleep(5) else: await sleep(30) except ex.NianticThrottlingException: self.logger.warning('Server throttling - sleeping for a bit') self.error_code = 'THROTTLE' await random_sleep(11, 22, 12) except (ex.MalformedResponseException, ex.UnexpectedResponseException) as e: self.logger.warning(e) self.error_code = 'MALFORMED RESPONSE' await random_sleep(10, 14, 11) if not response: raise MaxRetriesException self.last_request = time() if action: # pad for time that action would require self.last_action = self.last_request + action responses = response.get('responses') if chain: delta = responses.get('GET_INVENTORY', {}).get('inventory_delta', {}) timestamp = delta.get('new_timestamp_ms') inventory_items = delta.get('inventory_items', []) if inventory_items: self.update_inventory(inventory_items) self.inventory_timestamp = timestamp or self.inventory_timestamp d_hash = responses.get('DOWNLOAD_SETTINGS', {}).get('hash') self.download_hash = d_hash or self.download_hash if self.check_captcha(responses): self.logger.warning( '{} has encountered a CAPTCHA, trying to solve'.format( self.username)) self.g['captchas'] += 1 await self.handle_captcha(responses) return responses def travel_speed(self, point): '''Fast calculation of travel speed to point''' if self.busy.locked(): return None time_diff = max(time() - self.last_request, config.SCAN_DELAY) if time_diff > 60: self.error_code = None distance = get_distance(self.location, point) # conversion from meters/second to miles/hour speed = (distance / time_diff) * 2.236936 return speed async def bootstrap_visit(self, point): for _ in range(0, 3): if await self.visit(point, bootstrap=True): return True self.error_code = '∞' self.simulate_jitter(0.00005) return False async def visit(self, point, bootstrap=False): """Wrapper for self.visit_point - runs it a few times before giving up Also is capable of restarting in case an error occurs. """ visited = False try: altitude = self.spawns.get_altitude(point) altitude = uniform(altitude - 1, altitude + 1) self.location = point + [altitude] self.api.set_position(*self.location) if not self.logged_in: if not await self.login(): return False return await self.visit_point(point, bootstrap=bootstrap) except (ex.AuthException, ex.NotLoggedInException): self.logger.warning('{} is not authenticated.'.format( self.username)) self.error_code = 'NOT AUTHENTICATED' await sleep(1) await self.swap_account(reason='login failed') except CaptchaException: self.error_code = 'CAPTCHA' self.g['captchas'] += 1 await sleep(1) await self.bench_account() except CaptchaSolveException: self.error_code = 'CAPTCHA' await sleep(1) await self.swap_account(reason='solving CAPTCHA failed') except MaxRetriesException: self.logger.warning('Hit the maximum number of attempt retries.') self.error_code = 'MAX RETRIES' except ex.TempHashingBanException: self.error_code = 'HASHING BAN' self.logger.error( 'Temporarily banned from hashing server for using invalid keys.' ) await sleep(185) except ex.BannedAccountException: self.error_code = 'BANNED' self.logger.warning('{} is banned'.format(self.username)) await sleep(1) await self.remove_account() except ex.NianticIPBannedException: self.error_code = 'IP BANNED' if config.CONTROL_SOCKS: self.swap_circuit('IP ban') await random_sleep(minimum=25, maximum=35) elif self.proxies: self.logger.warning('Swapping out {} due to IP ban.'.format( self.proxy)) proxy = self.proxy while proxy == self.proxy: self.new_proxy() await random_sleep(minimum=12, maximum=20) else: self.logger.error('IP banned.') await sleep(150) except ex.HashServerException as e: self.logger.warning(e) self.error_code = 'HASHING ERROR' except ex.PgoapiError as e: self.logger.exception('pgoapi error') self.error_code = 'PGOAPI ERROR' except Exception: self.logger.exception('A wild exception appeared!') self.error_code = 'EXCEPTION' await sleep(1) return False async def visit_point(self, point, bootstrap=False): if bootstrap: self.error_code = '∞' else: self.error_code = '!' latitude, longitude = point self.logger.info('Visiting {0[0]:.4f},{0[1]:.4f}'.format(point)) start = time() rounded = round_coords(point, precision=4) if config.CACHE_CELLS and rounded in self.cell_ids: cell_ids = list(self.cell_ids[rounded]) else: cell_ids = get_cell_ids(*rounded, radius=500) if config.CACHE_CELLS: try: self.cell_ids[rounded] = array('L', cell_ids) except OverflowError: self.cell_ids[rounded] = tuple(cell_ids) since_timestamp_ms = [0] * len(cell_ids) request = self.api.create_request() request.get_map_objects(cell_id=cell_ids, since_timestamp_ms=since_timestamp_ms, latitude=latitude, longitude=longitude) diff = self.last_gmo + config.SCAN_DELAY - time() if diff > 0: await sleep(diff + .25) responses = await self.call(request) self.last_gmo = time() map_objects = responses.get('GET_MAP_OBJECTS', {}) sent = False pokemon_seen = 0 forts_seen = 0 points_seen = 0 if map_objects.get('status') == 3: raise ex.BannedAccountException('GMO code 3') elif map_objects.get('status') != 1: self.logger.warning('MapObjects code: {}'.format( map_objects.get('status'))) self.empty_visits += 1 if self.empty_visits > 3: reason = '{} empty visits'.format(self.empty_visits) await self.swap_account(reason) raise ex.UnexpectedResponseException time_of_day = map_objects.get('time_of_day', 0) if config.ITEM_LIMITS and self.bag_full(): await self.clean_bag() for map_cell in map_objects['map_cells']: request_time_ms = map_cell['current_timestamp_ms'] for pokemon in map_cell.get('wild_pokemons', []): pokemon_seen += 1 # Accurate times only provided in the last 90 seconds invalid_tth = (pokemon['time_till_hidden_ms'] < 0 or pokemon['time_till_hidden_ms'] > 90000) normalized = self.normalize_pokemon(pokemon, request_time_ms) if invalid_tth: despawn_time = self.spawns.get_despawn_time( normalized['spawn_id'], normalized['seen']) if despawn_time: normalized['expire_timestamp'] = despawn_time normalized['time_till_hidden_ms'] = ( despawn_time * 1000) - request_time_ms normalized['valid'] = 'fixed' else: normalized['valid'] = False else: normalized['valid'] = True if config.NOTIFY and self.notifier.eligible(normalized): if config.ENCOUNTER: normalized.update(await self.encounter(pokemon)) sent = self.notify(normalized, time_of_day) if (normalized not in SIGHTING_CACHE and normalized not in MYSTERY_CACHE): self.account_seen += 1 if (config.ENCOUNTER == 'all' and 'individual_attack' not in normalized): try: normalized.update(await self.encounter(pokemon)) except Exception: self.logger.exception( 'Exception during encounter.') self.db_processor.add(normalized) for fort in map_cell.get('forts', []): if not fort.get('enabled'): continue forts_seen += 1 if fort.get('type') == 1: # pokestops if 'lure_info' in fort: norm = self.normalize_lured(fort, request_time_ms) pokemon_seen += 1 if norm not in SIGHTING_CACHE: self.account_seen += 1 self.db_processor.add(norm) pokestop = self.normalize_pokestop(fort) self.db_processor.add(pokestop) if self.pokestops and not self.bag_full( ) and time() > self.next_spin: cooldown = fort.get('cooldown_complete_timestamp_ms') if not cooldown or time() > cooldown / 1000: await self.spin_pokestop(pokestop) else: self.db_processor.add(self.normalize_gym(fort)) if config.MORE_POINTS or bootstrap: for point in map_cell.get('spawn_points', []): points_seen += 1 try: p = (point['latitude'], point['longitude']) if p in self.spawns.known_points or not Bounds.contain( p): continue self.spawns.add_mystery(p) except (KeyError, TypeError): self.logger.warning( 'Spawn point exception ignored. {}'.format(point)) pass if config.INCUBATE_EGGS and len(self.unused_incubators) > 0 and len( self.eggs) > 0: await self.incubate_eggs() if pokemon_seen > 0: self.error_code = ':' self.total_seen += pokemon_seen self.g['seen'] += pokemon_seen self.empty_visits = 0 if CIRCUIT_FAILURES: CIRCUIT_FAILURES[self.proxy] = 0 else: self.empty_visits += 1 if forts_seen == 0: self.error_code = '0 SEEN' else: self.error_code = ',' if self.empty_visits > 3: reason = '{} empty visits'.format(self.empty_visits) await self.swap_account(reason) if CIRCUIT_FAILURES: CIRCUIT_FAILURES[self.proxy] += 1 if CIRCUIT_FAILURES[self.proxy] > 20: reason = '{} empty visits'.format( CIRCUIT_FAILURES[self.proxy]) self.swap_circuit(reason) self.visits += 1 if config.MAP_WORKERS: self.worker_dict.update([ (self.worker_no, ((latitude, longitude), start, self.speed, self.total_seen, self.visits, pokemon_seen, sent)) ]) self.logger.info( 'Point processed, %d Pokemon and %d forts seen!', pokemon_seen, forts_seen, ) self.update_accounts_dict(auth=False) return pokemon_seen + forts_seen + points_seen async def spin_pokestop(self, pokestop): self.error_code = '$' pokestop_location = pokestop['lat'], pokestop['lon'] distance = get_distance(self.location, pokestop_location) # permitted interaction distance - 2 (for some jitter leeway) # estimation of spinning speed limit if distance > 38 or self.speed > 22: return False # randomize location up to ~1.4 meters self.simulate_jitter(amount=0.00001) request = self.api.create_request() request.fort_details(fort_id=pokestop['external_id'], latitude=pokestop['lat'], longitude=pokestop['lon']) responses = await self.call(request, action=1.5) name = responses.get('FORT_DETAILS', {}).get('name') request = self.api.create_request() request.fort_search(fort_id=pokestop['external_id'], player_latitude=self.location[0], player_longitude=self.location[1], fort_latitude=pokestop['lat'], fort_longitude=pokestop['lon']) responses = await self.call(request, action=1) result = responses.get('FORT_SEARCH', {}).get('result', 0) if result == 1: self.logger.info('Spun {}.'.format(name)) elif result == 2: self.logger.info( 'The server said {n} was out of spinning range. {d:.1f}m {s:.1f}MPH' .format(n=name, d=distance, s=self.speed)) elif result == 3: self.logger.warning('{} was in the cooldown period.'.format(name)) elif result == 4: self.logger.warning( 'Could not spin {n} because inventory was full. {s}'.format( n=name, s=sum(self.items.values()))) elif result == 5: self.logger.warning( 'Could not spin {} because the daily limit was reached.'. format(name)) self.pokestops = False else: self.logger.warning('Failed spinning {n}: {r}'.format(n=name, r=result)) self.next_spin = time() + config.SPIN_COOLDOWN self.error_code = '!' return responses async def encounter(self, pokemon): pokemon_point = pokemon['latitude'], pokemon['longitude'] distance_to_pokemon = get_distance(self.location, pokemon_point) self.error_code = '~' if distance_to_pokemon > 47: percent = 1 - (46 / distance_to_pokemon) lat_change = (self.location[0] - pokemon['latitude']) * percent lon_change = (self.location[1] - pokemon['longitude']) * percent self.location = [ self.location[0] - lat_change, self.location[1] - lon_change, uniform(self.location[2] - 3, self.location[2] + 3) ] self.api.set_position(*self.location) delay_required = (distance_to_pokemon * percent) / 8 if delay_required < 1.5: delay_required = triangular(1.25, 4, 2) else: self.simulate_jitter() delay_required = triangular(1.25, 4, 2) if time() - self.last_request < delay_required: await sleep(delay_required) request = self.api.create_request() request = request.encounter(encounter_id=pokemon['encounter_id'], spawn_point_id=pokemon['spawn_point_id'], player_latitude=self.location[0], player_longitude=self.location[1]) responses = await self.call(request, action=2.25) response = responses.get('ENCOUNTER', {}) pokemon_data = response.get('wild_pokemon', {}).get('pokemon_data', {}) if 'cp' in pokemon_data: for iv in ('individual_attack', 'individual_defense', 'individual_stamina'): if iv not in pokemon_data: pokemon_data[iv] = 0 pokemon_data['probability'] = response.get( 'capture_probability', {}).get('capture_probability') self.error_code = '!' return pokemon_data def bag_full(self): return sum(self.items.values()) >= self.item_capacity async def clean_bag(self): self.error_code = '|' rec_items = {} limits = config.ITEM_LIMITS for item, count in self.items.items(): if item in limits and count > limits[item]: discard = count - limits[item] if discard > 50: rec_items[item] = randint(50, discard) else: rec_items[item] = discard removed = 0 for item, count in rec_items.items(): request = self.api.create_request() request.recycle_inventory_item(item_id=item, count=count) responses = await self.call(request, action=2) if responses.get('RECYCLE_INVENTORY_ITEM', {}).get('result', 0) != 1: self.logger.warning("Failed to remove item %d", item) else: removed += count self.logger.info("Removed %d items", removed) self.error_code = '!' async def incubate_eggs(self): # copy the list, as self.call could modify it as it updates the inventory incubators = self.unused_incubators.copy() for egg in sorted(self.eggs.values(), key=lambda x: x.get('egg_km_walked_target')): if egg.get('egg_incubator_id'): continue if not incubators: break inc = incubators.pop() if inc.get('item_id') == 901 or egg.get('egg_km_walked_target', 0) > 9: request = self.api.create_request() request.use_item_egg_incubator(item_id=inc.get('id'), pokemon_id=egg.get('id')) responses = await self.call(request, action=5) ret = responses.get('USE_ITEM_EGG_INCUBATOR', {}).get('result', 0) if ret == 4: self.logger.warning( "Failed to use incubator because it was already in use." ) elif ret != 1: self.logger.warning( "Failed to apply incubator {} on {}, code: {}".format( inc.get('id', 0), egg.get('id', 0), ret)) async def handle_captcha(self, responses): if self.num_captchas >= config.CAPTCHAS_ALLOWED: self.logger.error( "{} encountered too many CAPTCHAs, removing.".format( self.username)) raise CaptchaException self.error_code = 'C' self.num_captchas += 1 url = responses.get('CHECK_CHALLENGE', {}).get('challenge_url') site_key = '6LeeTScTAAAAADqvhqVMhPpr_vB9D364Ia-1dSgK' try: requrl = "http://2captcha.com/in.php?key={}&method=userrecaptcha&googlekey={}&pageurl={}" response = self.session.post(requrl.format(config.CAPTCHA_KEY, site_key, url), timeout=5).text except Exception as e: self.logger.error('Got an error while trying to solve CAPTCHA. ' 'Check your API Key and account balance.') raise CaptchaSolveException from e if 'ERROR_ZERO_BALANCE' in response: config.CAPTCHA_KEY = None self.logger.error( "Error: 2Captcha reported zero balance, disabling CAPTCHA solving" ) raise CaptchaException if not response.startswith('OK|'): self.logger.error( "Failed to submit CAPTCHA for solving: {}".format(response)) raise CaptchaSolveException captcha_id = str(response.split('|')[1]) try: # Get the response, retry every 5 seconds if it's not ready while True: recaptcha_response = self.session.get( "http://2captcha.com/res.php?key={}&action=get&id={}". format(config.CAPTCHA_KEY, captcha_id), timeout=20).text if 'CAPCHA_NOT_READY' not in recaptcha_response: break await sleep(5) except Exception as e: self.logger.error('Got an error while trying to solve CAPTCHA. ' 'Check your API Key and account balance.') raise CaptchaSolveException from e if not recaptcha_response.startswith('OK|'): self.logger.error("Failed to get CAPTCHA response: {}".format( recaptcha_response)) raise CaptchaSolveException token = str(recaptcha_response.split('|')[1]) request = self.api.create_request() request.verify_challenge(token=token) try: responses = await self.call(request) self.update_accounts_dict() self.logger.warning("Successfully solved CAPTCHA") except CaptchaException: self.logger.warning( "CAPTCHA #{} for {} was not solved correctly, trying again". format(captcha_id, self.username)) # try again await self.handle_captcha(responses) def simulate_jitter(self, amount=0.00002): '''Slightly randomize location, by up to ~2.8 meters by default.''' self.location = [ uniform(self.location[0] - amount, self.location[0] + amount), uniform(self.location[1] - amount, self.location[1] + amount), uniform(self.location[2] - 1, self.location[2] + 1) ] self.api.set_position(*self.location) def notify(self, norm, time_of_day): self.error_code = '*' notified = self.notifier.notify(norm, time_of_day) if notified: self.g['sent'] += 1 self.error_code = '!' return notified def update_accounts_dict(self, captcha=False, banned=False, auth=True): self.account['captcha'] = captcha self.account['banned'] = banned self.account['location'] = self.location self.account['time'] = self.last_request self.account['inventory_timestamp'] = self.inventory_timestamp self.account['items'] = self.items if auth and self.api._auth_provider: self.account['refresh'] = self.api._auth_provider._refresh_token if self.api._auth_provider.check_access_token(): self.account['auth'] = self.api._auth_provider._access_token self.account[ 'expiry'] = self.api._auth_provider._access_token_expiry else: self.account['auth'], self.account['expiry'] = None, None self.accounts[self.username] = self.account async def remove_account(self): self.error_code = 'REMOVING' self.logger.warning('Removing {} due to ban.'.format(self.username)) self.update_accounts_dict(banned=True) await self.new_account() async def bench_account(self): self.error_code = 'BENCHING' self.logger.warning('Swapping {} due to CAPTCHA.'.format( self.username)) self.update_accounts_dict(captcha=True) self.captcha_queue.put(self.account) await self.new_account() async def swap_account(self, reason='', lock=False): self.error_code = 'SWAPPING' self.logger.warning('Swapping out {u} because {r}.'.format( u=self.username, r=reason)) if lock: await self.busy.acquire() self.update_accounts_dict() while self.extra_queue.empty(): if self.killed: return False await sleep(15) self.extra_queue.put(self.account) await self.new_account(lock) async def new_account(self, lock=False): while self.extra_queue.empty(): if self.killed: return False await sleep(15) self.account = self.extra_queue.get() self.username = self.account.get('username') self.location = self.account.get('location', (0, 0, 0)) self.inventory_timestamp = self.account.get('inventory_timestamp') self.last_request = self.account.get('time', 0) self.last_action = self.last_request self.last_gmo = self.last_request self.items = self.account.get('items', {}) self.num_captchas = 0 self.pokestops = config.SPIN_POKESTOPS self.eggs = {} self.unused_incubators = [] self.initialize_api() self.error_code = None if lock: self.busy.release() def seen_per_second(self, now): try: seconds_active = now - self.account_start if seconds_active < 120: return None return self.account_seen / seconds_active except TypeError: return None def kill(self): """Marks worker as killed Killed worker won't be restarted. """ self.error_code = 'KILLED' self.killed = True if self.ever_authenticated: self.update_accounts_dict() @staticmethod def normalize_pokemon(raw, now): """Normalizes data coming from API into something acceptable by db""" return { 'type': 'pokemon', 'encounter_id': raw['encounter_id'], 'pokemon_id': raw['pokemon_data']['pokemon_id'], 'expire_timestamp': round( (now + raw['time_till_hidden_ms']) / 1000), 'lat': raw['latitude'], 'lon': raw['longitude'], 'spawn_id': get_spawn_id(raw), 'time_till_hidden_ms': raw['time_till_hidden_ms'], 'seen': round(raw['last_modified_timestamp_ms'] / 1000) } @staticmethod def normalize_lured(raw, now): return { 'type': 'pokemon', 'encounter_id': raw['lure_info']['encounter_id'], 'pokemon_id': raw['lure_info']['active_pokemon_id'], 'expire_timestamp': raw['lure_info']['lure_expires_timestamp_ms'] / 1000, 'lat': raw['latitude'], 'lon': raw['longitude'], 'spawn_id': -1, 'time_till_hidden_ms': raw['lure_info']['lure_expires_timestamp_ms'] - now, 'valid': 'pokestop' } @staticmethod def normalize_gym(raw): return { 'type': 'fort', 'external_id': raw['id'], 'lat': raw['latitude'], 'lon': raw['longitude'], 'team': raw.get('owned_by_team', 0), 'prestige': raw.get('gym_points', 0), 'guard_pokemon_id': raw.get('guard_pokemon_id', 0), 'last_modified': round(raw['last_modified_timestamp_ms'] / 1000), } @staticmethod def normalize_pokestop(raw): return { 'type': 'pokestop', 'external_id': raw['id'], 'lat': raw['latitude'], 'lon': raw['longitude'] } @staticmethod def check_captcha(responses): challenge_url = responses.get('CHECK_CHALLENGE', {}).get('challenge_url', ' ') verify = responses.get('VERIFY_CHALLENGE', {}) success = verify.get('success') if challenge_url != ' ' and not success: if config.CAPTCHA_KEY and not verify: return True else: raise CaptchaException else: return False @property def status(self): """Returns status message to be displayed in status screen""" if self.error_code: msg = self.error_code else: msg = 'P{seen}'.format(seen=self.total_seen) return '[W{worker_no}: {msg}]'.format(worker_no=self.worker_no, msg=msg)
def main(): # Load settings and create the config object secrets = {} if os.path.isfile('secrets.json'): secrets = json.load(open('secrets.json')) config = json.load(open('default-config.json')) config.update(secrets) config['settings']['market_pairs'] = os.environ.get( 'MARKET_PAIRS', config['settings']['market_pairs']) config['settings']['loglevel'] = os.environ.get('LOGLEVEL', logging.INFO) config['exchanges']['bittrex']['required']['key'] = os.environ.get( 'BITTREX_KEY', config['exchanges']['bittrex']['required']['key']) config['exchanges']['bittrex']['required']['secret'] = os.environ.get( 'BITTREX_SECRET', config['exchanges']['bittrex']['required']['secret']) config['notifiers']['twilio']['required']['key'] = os.environ.get( 'TWILIO_KEY', config['notifiers']['twilio']['required']['key']) config['notifiers']['twilio']['required']['secret'] = os.environ.get( 'TWILIO_SECRET', config['notifiers']['twilio']['required']['secret']) config['notifiers']['twilio']['required'][ 'sender_number'] = os.environ.get( 'TWILIO_SENDER_NUMBER', config['notifiers']['twilio']['required']['sender_number']) config['notifiers']['twilio']['required'][ 'receiver_number'] = os.environ.get( 'TWILIO_RECEIVER_NUMBER', config['notifiers']['twilio']['required']['receiver_number']) config['notifiers']['gmail']['required']['username'] = os.environ.get( 'GMAIL_USERNAME', config['notifiers']['gmail']['required']['username']) config['notifiers']['gmail']['required']['password'] = os.environ.get( 'GMAIL_PASSWORD', config['notifiers']['gmail']['required']['password']) config['notifiers']['gmail']['required'][ 'destination_emails'] = os.environ.get( 'GMAIL_DESTINATION_EMAILS', config['notifiers']['gmail']['required']['destination_emails']) # Set up logger LOGGER = logging.getLogger(__name__) LOGGER.setLevel(config['settings']['loglevel']) LOG_FORMAT = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') LOG_HANDLE = logging.StreamHandler() LOG_HANDLE.setLevel(logging.DEBUG) LOG_HANDLE.setFormatter(LOG_FORMAT) LOGGER.addHandler(LOG_HANDLE) exchange_interface = ExchangeInterface(config) strategy_analyzer = StrategyAnalyzer(config) notifier = Notifier(config) # The coin pairs coin_pairs = [] if config['settings']['market_pairs']: coin_pairs = config['settings']['market_pairs'].translate( str.maketrans('', '', whitespace)).split(",") else: user_markets = exchange_interface.get_user_markets() for user_market in user_markets['info']: if 'BTC' in user_market['Currency']: continue market_pair = user_market['Currency'] + '/BTC' coin_pairs.append(market_pair) LOGGER.debug(coin_pairs) while True: get_signal(coin_pairs, strategy_analyzer, notifier)
#! /usr/bin/python from notification import Notifier Notification_Settings_File = 'Notification_Settings.csv' notifier = Notifier() notifier.load_config(Notification_Settings_File) notifier.tweet('Found a Poop!', 'Poop', 'poop.png', 'High') notifier.email('Found a Poop!', 'Poop', 'poop.png', 'High')