def restock(shop_id): inventory.ensure_np(99999) np = lib.NeoPage() np.get('/objects.phtml', f'obj_type={shop_id}', 'type=shop') items = re_shop_item.findall(np.content) shop_name = re_header.search(np.content)[1].strip() print(f'{len(items)} items found at {shop_name}.') # Look for profitable items best_score = () best = None for obj_info_id, stock_id, g, brr, image, desc, name, stock, price in items: price = lib.amt(price) # TODO: Here we assume that items with the same name but drastically # different value won't restock in shops. For a more fine-grained # search, should search using image as well. true_price = item_db.get_price(name, update=False) or always_buy.get(name) if not true_price: continue print(f'Item: {stock} x {name} for {price} NP. (True price {true_price} NP)') profit = true_price - price score = (name in always_buy, profit, profit / price) if score > best_score: best_score = score best = (name, price, obj_info_id, stock_id, brr) if not best: return if best_score and (best_score[0] or best_score[1] >= MIN_PROFIT and best_score[2] >= MIN_PROFIT_MARGIN): name, price, obj_info_id, stock_id, brr = best np.get('/haggle.phtml', f'obj_info_id={obj_info_id}', f'stock_id={stock_id}', f'brr={brr}') referer = np.referer _x_pwned = re_captcha.search(np.content)[1] np.get('/captcha_show.phtml', f'_x_pwned={_x_pwned}') offer = haggle_price(price) print(f'Trying to buy {name} for {offer} !!') best_x, best_y = find_neopet(np.content, _x_pwned) np.set_referer(referer) print(f'Haggling @ {offer}') np.post('/haggle.phtml', f'current_offer={offer}', f'x={best_x}', f'y={best_y}') if 'I accept your offer' in np.content: print('Bought!') else: print('Not bought :( TODO: See what happened') else: print(f'No worthy items found. Best was {best[0]} (profit {best_score[2]*100:.1f}% = {best_score[1]})') # Learn about unknown items for obj_info_id, stock_id, g, brr, image, desc, name, stock, price in items: try: item_db.get_price(name) except item_db.ShopWizardBannedException: return neotime.now_nst() + datetime.timedelta(minutes=5)
def appraise_item(): # Identifies the price of an item that we know about, but not the price of. items = item_db.query( 'SELECT name FROM items WHERE price IS NULL').fetchall() items = sum((list(x) for x in items), []) if items: item = random.choice(items) print(f'Learning about {item}') try: item_db.update_prices(item, laxness=5) except item_db.ShopWizardBannedException: return neotime.now_nst() + datetime.timedelta(minutes=20)
def magma_pool(): log = open('magma_pool.log', 'a') np = lib.NeoPage(path) np.get(path) now = neotime.now_nst() if np.contains("I'm sorry, only those well-versed"): print('Magma Pool: Not your time.') log.write(f'{now} NO\n') else: print(f'Magma Pool: {now} may be your time!!!') log.write(f'{now} YES\n') log.close()
def my_restock(): stores = [ 68, # Collectable coins 38, # Faerie books 86, # Sea shells 14, # Chocolate factory 58, # Post office 8, # Collectible cards ] result = restock(random.choice(stores)) or neotime.now_nst() if result: result = result + datetime.timedelta(seconds=random.randint(0, 30)) return result
def snowager(): dont_do_again = neotime.now_nst() + datetime.timedelta(hours=1) np = lib.NeoPage(path) if np.contains('The Snowager is awake'): print('Snowager: Awake.') return np.get(path2) if np.contains('You dont want to try and enter again'): print('Snowager: Already done.') return dont_do_again result = np.search(r'<p>(.*?)<p></center><center>') if result: result = lib.strip_tags(result[1]) print(f'Snowager: {result}') return dont_do_again else: print('Snowager: Error.')
def pirate_academy(): np = lib.NeoPage() np.get(path, 'type=status') # TODO: Handle more than one pet, train particular pet, etc. table = np.search( r'<b>Current Course Status</b>.*?<table.*?>.*?<br clear="all">')[0] tds = re.findall(r'<td.*?>(.*?)</td>', table) status = tds[0] stats = tds[1].split('<br>') stats = [re.sub(r'<.*?>', '', s).split()[-1] for s in stats[1:-2] if s] Lvl, Str, Def, Mov, Hp = map(int, stats) time_til = tds[2] if 'Course Finished!' in time_til: pet_name = np.search( r"<form.*?name='pet_name' value='(.*?)'.*?</form>")[1] np.post('/pirates/process_academy.phtml', 'type=complete', f'pet_name={pet_name}') result = lib.strip_tags(np.content.splitlines()[-1]) print(f'Pirate Academy: Finished course. {result}') return pirate_academy() elif 'is not on a course' in status: np.get(path, 'type=courses') r = np.search( r"<select name='pet_name'><option value='(.*?)'>.*? - (.*?)</select>" ) pet_name = r[1] rank = r[2] skill = None if any(stat > 2 * Lvl for stat in [Str, Def, Mov, Hp]): skill = 'Level' else: skill = min(zip([Str, Hp, Def, Mov], ('Strength', 'Endurance', 'Defence', 'Agility')), key=lambda x: x[0])[1] print(f'Pirate Academy: Training {skill} for {pet_name}') np.post('/pirates/process_academy.phtml', 'type=start', f'course_type={skill}', f'pet_name={pet_name}') return pirate_academy() elif "<input type='submit' value='Pay'>" in np.content: print(f'Pirate Academy: Paying for lesson') pet_name = np.search( f"<input type='hidden' name='pet_name' value='(.*?)'>")[1] np.post('/pirates/process_academy.phtml', f'pet_name={pet_name}', 'type=pay') np.get(path, 'type=status') print(f'Status: {lib.strip_tags(status)}') print(f'Stats: Lvl{Lvl} Str{Str} Def{Def} Mov{Mov} Hp{Hp}') print(time_til) total_time = datetime.timedelta() if np.contains('hr'): result = np.search('(\d+) hr') if result: total_time += datetime.timedelta(hours=int(result[1])) if np.contains('minute'): result = np.search('(\d+) minute') if result: total_time += datetime.timedelta(minutes=int(result[1])) if np.contains('second'): result = np.search('(\d+) second') if result: total_time += datetime.timedelta(seconds=int(result[1])) print(f'Time til: {total_time}') return neotime.now_nst() + total_time + datetime.timedelta(minutes=1)
def main(): # State last_done = {} PICKLE_FILE = 'daemon.pickle' if os.path.isfile(PICKLE_FILE): last_done = pickle.load(open(PICKLE_FILE, 'rb')) @atexit.register def save_data(): print('Saving data...') pickle.dump(last_done, open(PICKLE_FILE, 'wb')) for name, f, _next_time in tasks: if name not in last_done: ensure_login() print(f'Never did {name} before. Doing.') f() last_done[name] = now_nst() find_next_task = lambda t: t[2](last_done[t[0]]) failures = [] while True: try: while True: now = now_nst() name, f, next_time = min(tasks, key=find_next_task) nxt = next_time(last_done[name]) #print(f'{name}: Last done {last_done[name]}, next is {nxt}') time_til = (nxt - now).total_seconds() if time_til > 0: print(f'[Doing {name} in {pprint_seconds(time_til)}]') while True: now = now_nst() time_til = (nxt - now).total_seconds() if time_til <= 0: break time.sleep(min(60, time_til)) else: print(f'[Doing {name}]') ensure_login() # This allows individual functions to override the "time at # which the thing was done". For example, this is used to make # sure we only do the Snowager once every time it wakes up. last_done[name] = f() or now_nst() except lib.NotLoggedInError: print('Unable to log in.') except KeyboardInterrupt: print('Shutting down.') break except pycurl.error as e: print('pycurl error:', e) time.sleep(1) except Exception as e: logging.exception('') failures.append(e) if len(failures) > 10: print('Failures:') print(e) print('Too many failures; exiting.') break