Пример #1
0
def count_large_cargos(b):
    """Gather number of large cargos in each planet."""
    def find_planets():
        return sln.finds(sln.find(b, By.ID, 'planetList'), By.CLASS_NAME,
                         'planetlink')

    num_planets = len(find_planets())
    logging.info('Found {} planets'.format(num_planets))

    fleet = {}
    for i in range(num_planets):
        logging.info('Navigating to planet #{}'.format(i))

        # Need to find the planets again since previous references are stale.
        planets = find_planets()
        planets[i].click()

        # Navigate to fleet view (only needed for the first planet).
        if i == 0:
            logging.info('Navigating to fleet view')
            sln.finds(sln.find(b, By.ID, 'links'), By.CLASS_NAME,
                      'menubutton')[7].click()

        try:
            large_cargos = sln.find(sln.find(b, By.ID, 'button203', timeout=5),
                                    By.CLASS_NAME, 'level').text
        except TimeoutException:
            # Most likely indicates there is no fleet on this planet.
            logging.warn('No fleet on this planet')
            large_cargos = 0
        logging.info('Planet {} has {} large cargos'.format(i, large_cargos))
        fleet[i] = int(large_cargos)

    return fleet
Пример #2
0
def go_to_galaxy_view(b, planet_num):
    """Navigate to galaxy view and return home galaxy and system."""
    planets = sln.finds(sln.find(b, By.ID, 'planetList'), By.CLASS_NAME,
                        'planetlink')
    logging.info('Found {} planets'.format(len(planets)))
    logging.info('Navigating to planet #{}'.format(planet_num))
    planets[planet_num].click()
    logging.info('Navigating to galaxy view')
    sln.finds(sln.find(b, By.ID, 'links'), By.CLASS_NAME,
              'menubutton')[8].click()

    galaxy = int(sln.find(b, By.ID, 'galaxy_input').get_attribute('value'))
    system = int(sln.find(b, By.ID, 'system_input').get_attribute('value'))
    logging.info('Home system is {}:{}'.format(galaxy, system))

    return galaxy, system
Пример #3
0
def alert_if_attacked(b, args):
  """Check if we're being attacked and send an email."""
  alert_div = sln.find(b, By.ID, 'attack_alert')

  # The classes contain "noAttack" if there's no attack and "soon" if there is.
  classes = alert_div.get_attribute('class').split()
  if 'noAttack' in classes:
    logging.info('No attack, exiting')
    return

  # Send an alert email.
  logging.info('Attack! Sending email to {}'.format(args.email_to))
  subject = 'Attack alert'
  body = '{} is being attacked!'.format(sln.find(b, By.ID, 'playerName').text)
  email_lib.send_email(args.smtp_host, args.smtp_port, args.smtp_user,
                       args.smtp_password, args.email_to, subject, body)
Пример #4
0
def go_to_system(b, galaxy, system):
    """Navigate to system and return num ongoing missions."""
    logging.info('Navigating to {}:{}'.format(galaxy, system))
    sln.find(b, By.ID, 'galaxy_input').send_keys(str(galaxy))
    sln.find(b, By.ID, 'system_input').send_keys(str(system))
    sln.find(b, By.CSS_SELECTOR, '#galaxyHeader .btn_blue').click()

    # Wait for loader to appear, then wait for it to disappear.
    sln.wait_until(b, By.ID, 'galaxyLoading', timeout=1, timeout_ok=True)
    sln.wait_until_not(b, By.ID, 'galaxyLoading', timeout=3, timeout_ok=True)

    return int(sln.find(b, By.ID, 'slotUsed').text)
Пример #5
0
def inspect(b, num_already_processed, num_allowed, galaxy, system, args):
    """Inspect a system.

  Args:
    b: Browser.
    num_already_processed: Num already processed in this system.
    num_allowed: Num probes allowed at this point.
    galaxy: Galaxy (for debug).
    system: System (for debug).
    args: Command-line args.

  Returns:
    num_processed: (int) Number of targets newly processed in this system.
    done: (bool) Whether the scan was complete.
  """
    logging.info('Inspecting [{}:{}]...'.format(galaxy, system))

    # Get list of planets in this system.
    players = [
        p for p in sln.finds(
            b, By.CSS_SELECTOR, '.playername', timeout=2, timeout_ok=True)
        if len(p.get_attribute('class').split()) > 1
        and 'js_no_action' not in p.get_attribute('class')
    ]
    logging.info('Found {} players'.format(len(players)))

    # Get list of potential targets based on their class (inactive, strong, etc).
    potential_targets = []
    for player in players:
        classes = player.get_attribute('class').split()
        if len(classes) == 2:  # normal players have 2 classes
            if args.include_normal:
                logging.info('Adding normal player')
                potential_targets.append(player)
        elif any(x in classes for x in [
                'noob', 'vacation', 'vacationlonginactive', 'vacationinactive',
                'banned'
        ]):
            pass
        else:
            for classname, arg, label in [
                ('inactive', args.include_inactive, 'inactive'),
                ('longinactive', args.include_inactive, 'inactive'),
                ('honorableTarget', args.include_honorable, 'honorable'),
                ('stronghonorableTarget', args.include_strong, 'strong'),
            ]:
                if classname in classes:
                    if arg:
                        logging.info('Adding {} player'.format(label))
                        potential_targets.append(player)
                    break
            else:  # no known classname found
                logging.warn(
                    'Skipping unsupported player (classes = {})'.format(
                        classes))
    logging.info('Found {} potential targets'.format(len(potential_targets)))

    # Iterate over potential targets and scan those with rank within bounds.
    num_processed = 0
    for potential_target in potential_targets:
        if num_allowed == 0:
            # Reached max number of concurrent missions.
            return num_processed, False

        # Find player name.
        sln.hover(b, potential_target)
        player_name = potential_target.text

        # Find player ID (sometimes we need to try multiple times).
        player_id, tries = None, 0
        while not player_id and tries < 10:
            tries += 1
            player_id = sln.find(potential_target, By.TAG_NAME,
                                 'a').get_attribute('rel')
        if not player_id:
            logging.warn('Skipping (could not find player ID)')
            continue

        # Find player rank. Sometimes it can't be done e.g. if player name is empty.
        player_rank, tries = None, 0
        while not player_rank and tries < 10:
            tries += 1
            for tooltip in sln.finds(b, By.ID, player_id):
                rank = sln.find(tooltip, By.TAG_NAME, 'a').text
                if rank:
                    player_rank = int(rank)
                    break
        if not player_rank:
            logging.warn('Skipping (could not find player rank')
            continue

        # Find planet name.
        planet_name = sln.find(sln.find(potential_target, By.XPATH, '..'),
                               By.CLASS_NAME, 'planetname').text

        # Find planet position.
        planet_position = int(
            sln.find(sln.find(potential_target, By.XPATH, '..'), By.CLASS_NAME,
                     'position').text)

        logging.info('Potential target: {}:{}:{} [{}] - {} (rank {})'.format(
            galaxy, system, planet_position, planet_name, player_name,
            player_rank))

        if not args.rank_min <= player_rank <= args.rank_max:
            logging.info('Skipping (outside allowed rank bounds)')
            continue

        if num_already_processed:
            logging.info('Skipping (already processed)')
            num_already_processed -= 1
            continue

        logging.info('--> Sending probe to {}:{}:{}'.format(
            galaxy, system, planet_position))
        sln.click(
            b,
            sln.find(sln.find(potential_target, By.XPATH, '..'), By.CLASS_NAME,
                     'espionage'))
        num_processed += 1
        num_allowed -= 1

    return num_processed, True
Пример #6
0
def attack_target(b, coords, planet_num, num_cargos):
    """Attack a planet at given `coords` from `planet_num` with `num_cargos`."""
    # Navigate to planet.
    planets = sln.finds(sln.find(b, By.ID, 'planetList'), By.CLASS_NAME,
                        'planetlink')
    planet = planets[planet_num]
    logging.info('Navigating to planet {}'.format(planet_num))
    planet.click()

    # Navigate to fleet view.
    logging.info('Navigating to fleet view')
    sln.finds(sln.find(b, By.ID, 'links'), By.CLASS_NAME,
              'menubutton')[7].click()

    # Set num cargos.
    large_cargos = sln.find(sln.find(b, By.ID, 'button203'), By.CLASS_NAME,
                            'fleetValues')
    large_cargos.send_keys(str(num_cargos))
    sln.find(b, By.ID, 'continue').click()

    # Set target coords.
    galaxy = sln.find(b, By.ID, 'galaxy')
    system = sln.find(b, By.ID, 'system')
    position = sln.find(b, By.ID, 'position')
    galaxy.clear()
    galaxy.send_keys(str(coords.galaxy))
    system.clear()
    system.send_keys(str(coords.system))
    position.clear()
    position.send_keys(str(coords.position))
    position.send_keys(Keys.RETURN)

    # Launch attack.
    sln.find(b, By.ID, 'missionButton1').click()
    sln.find(b, By.ID, 'start').click()

    # Wait for fleet view to be visible again.
    sln.wait_until(b, By.ID, 'movements')
    logging.info(
        'Launched attack on [{}:{}:{}] with {} cargos from planet {}'.format(
            coords.galaxy, coords.system, coords.position, num_cargos,
            planet_num))
Пример #7
0
def gather_reports(b, args):
    """Gather probe reports."""
    logging.info('Gathering reports...')
    sln.find(b, By.CLASS_NAME, 'messages').click()

    reports = {}
    num_reports = 0
    last_data_msg_id = None  # to know when next page is ready
    while num_reports < args.max_reports:

        # Wait for page to be ready.
        page_ready = False
        while not page_ready:
            logging.info('Waiting for page to be ready')
            time.sleep(0.5)
            try:
                top_msg_id = sln.finds(
                    b, By.CLASS_NAME, 'msg',
                    timeout=5)[0].get_attribute('data-msg-id')
            except StaleElementReferenceException:
                continue
            except TimeoutException:
                # Most likely indicates there are no probe reports.
                logging.warn('Cannot find messages, returning empty list')
                return []
            page_ready = last_data_msg_id is None or last_data_msg_id != top_msg_id
        last_data_msg_id = top_msg_id

        # Iterate over messages.
        for msg in sln.finds(b, By.CLASS_NAME, 'msg'):

            # Parse resources.
            resspans = sln.finds(msg,
                                 By.CLASS_NAME,
                                 'resspan',
                                 timeout=1,
                                 timeout_ok=True)
            if len(resspans) != 3:
                logging.warn('Skipping message: could not parse resources')
                continue
            metal = parse_number(resspans[0].text.split(' ')[1])
            crystal = parse_number(resspans[1].text.split(' ')[1])
            deuterium = parse_number(resspans[2].text.split(' ')[1])

            # Parse fleet info.
            fleet_info = sln.finds(msg, By.CLASS_NAME, 'compacting')[-1]
            counts = sln.finds(fleet_info, By.CLASS_NAME, 'ctn')
            if len(counts) != 2:
                logging.warn('Skipping message: could not parse fleet info')
                continue
            fleet_pts = parse_number(counts[0].text.split(' ')[1])
            defense_pts = parse_number(counts[1].text.split(' ')[1])

            # Parse target coords from the message title.
            title = sln.find(msg, By.CLASS_NAME, 'msg_title')
            links = sln.finds(title, By.TAG_NAME, 'a')
            if len(links) != 1:
                logging.warn('Skipping message: could not parse message title')
                continue
            # Text is of the form "<planet name> [galaxy:system:position]"
            coords = list(
                map(int, links[0].text.split(' ')[-1][1:-1].split(':')))
            if len(coords) != 3:
                logging.warn('Skipping message: could not parse coords')
                continue

            # Add report to the dict.
            key = Coords(coords[0], coords[1], coords[2])
            value = PlanetInfo(metal, crystal, deuterium, fleet_pts,
                               defense_pts)
            reports[key] = value
            num_reports += 1
            logging.info('Report #{}: {}: {}'.format(num_reports, key, value))
            if num_reports >= args.max_reports:
                break

        if num_reports < args.max_reports:
            # Not done, go to next page.
            lis = sln.finds(sln.find(b, By.CLASS_NAME, 'pagination'),
                            By.TAG_NAME, 'li')
            if len(lis) != 5:
                logging.warn('Could not find five elements, returning')
                break
            cur_page, total_pages = lis[2].text.split('/')
            if cur_page == total_pages:
                logging.info('Reached last page')
                break
            lis[3].click()

    def score(x):
        if args.sort_by == 'total':
            return x.metal + x.crystal + x.deuterium
        if args.sort_by == 'metal':
            return x.metal
        if args.sort_by == 'crystal':
            return x.crystal
        if args.sort_by == 'deuterium':
            return x.deuterium

    return sorted(reports.items(), key=lambda x: score(x[1]), reverse=True)
Пример #8
0
 def find_planets():
     return sln.finds(sln.find(b, By.ID, 'planetList'), By.CLASS_NAME,
                      'planetlink')
Пример #9
0
def open_browser_and_connect(args):
    """Open a Chrome browser and connect to OGame account."""
    b = _open_browser(args)

    url = 'http://www.ogame.' + args.tld
    logging.info('Navigating to ' + url)
    b.get(url)

    # Close ad.
    try:
        sln.find(
            sln.find(b, By.CLASS_NAME, 'openX_int_closeButton', timeout=3),
            By.TAG_NAME, 'a').click()
    except TimeoutException:
        pass

    logging.info('Filling login form...')
    sln.find(b, By.ID, 'ui-id-1').click()  # Login tab
    sln.find(b, By.ID, 'usernameLogin').send_keys(args.email)
    sln.find(b, By.ID, 'passwordLogin').send_keys(args.password)
    sln.find(b, By.ID, 'loginSubmit').click()  # login

    # Get list of accounts.
    logging.info('Getting list of accounts...')
    accounts = sln.finds(
        sln.find(sln.find(b, By.ID, 'accountlist'), By.CLASS_NAME, 'rt-tbody'),
        By.CLASS_NAME, 'rt-tr')
    logging.info('Found {} accounts'.format(len(accounts)))

    # Use --univ_name if it was provided
    if args.univ_name:
        account_names = []
        for account in accounts:
            account_name = sln.find(account, By.CLASS_NAME,
                                    'server-name-cell').text
            account_names.append(account_name)
            if account_name == args.univ_name:
                logging.info('Navigating to account {}'.format(account_name))
                sln.find(accounts[args.univ_num], By.TAG_NAME,
                         'button').click()
                break
        else:  # could not find --univ_name
            raise ValueError('Could not find account with --univ_name = {}; '
                             'accounts found are [{}]'.format(
                                 args.univ_name, ', '.join(account_names)))

    # Else use --univ_num
    else:
        if not 0 <= args.univ_num < len(accounts):
            raise ValueError(
                '--univ_num should be between 0 and {}; found {}'.format(
                    len(accounts) - 1, args.univ_num))
        account_name = sln.find(accounts[args.univ_num], By.CLASS_NAME,
                                'server-name-cell').text
        logging.info('Navigating to account {}'.format(account_name))
        sln.find(accounts[args.univ_num], By.TAG_NAME, 'button').click()

    b.switch_to.window(b.window_handles[-1])
    logging.info('Switched to tab ' + b.current_url)

    return b