示例#1
0
def test_get_member_history_quit_and_rejoin():
    date = datetime(2019, 2, 12, 7, 32, 1, 0)
    date2 = datetime(2019, 2, 12, 7, 32, 2, 0)
    timestamp = datetime.timestamp(date)
    timestamp2 = datetime.timestamp(date2)
    members = __fake_members__.copy()
    del members[2]

    h = history.get_member_history(members, date, __fake_history__, None)
    h2 = history.get_member_history(__fake_members__, date2, h, None)

    h_member = h['members'][__fake_members__[2].tag]
    h2_member = h2['members'][__fake_members__[2].tag]

    assert h_member['status'] == 'absent'
    assert h_member['events'][1]['event'] == 'quit'
    assert h_member['events'][1]['type'] == 'left'
    assert h_member['events'][1]['date'] == timestamp
    assert h2_member['status'] == 'present'
    assert h2_member['events'][1]['event'] == 'quit'
    assert h2_member['events'][1]['type'] == 'left'
    assert h2_member['events'][1]['date'] == timestamp
    assert h2_member['events'][2]['event'] == 'join'
    assert h2_member['events'][2]['type'] == 're-join'
    assert h2_member['events'][2]['date'] == timestamp2
示例#2
0
def test_get_member_history_donations_reset():
    date = datetime(2019, 2, 12, 7, 32, 1, 0)
    timestamp = datetime.timestamp(date)
    members_copy = copy.deepcopy(__fake_members__)
    members_copy[0].donations = 5
    h = history.get_member_history(__fake_members__, date, __fake_history__, None)
    h2 = history.get_member_history(members_copy, date, h, None)

    members = h2['members']
    assert members[__fake_members__[0].tag]['donations'] == 5
    assert members[__fake_members__[0].tag]['donations_last_week'] == __fake_members__[0].donations
示例#3
0
def test_get_member_history_unchanged():
    """ Getting history twice. Nothing should be changed except the
    timestamp """
    date = datetime(2019, 2, 12, 7, 32, 1, 0)
    date2 = datetime(2019, 2, 12, 7, 32, 2, 0)
    timestamp = datetime.timestamp(date)
    timestamp2 = datetime.timestamp(date2)

    h = history.get_member_history(__fake_members__, date, None, None)
    h2 = history.get_member_history(__fake_members__, date2, h, None)

    assert h['last_update'] == timestamp
    assert h2['last_update'] == timestamp2
    assert h['members'] == h2['members']
示例#4
0
def test_get_member_history_role_change():
    date = datetime(2019, 2, 12, 7, 32, 1, 0)
    timestamp = datetime.timestamp(date)
    h = history.get_member_history(__fake_members__, __fake_history__, None,
                                   date)

    members = h['members']

    assert h['last_update'] == timestamp
    assert members[__fake_members__[1]['tag']]['status'] == 'present'
    assert members[__fake_members__[1]
                   ['tag']]['events'][1]['event'] == 'role change'
    assert members[__fake_members__[1]
                   ['tag']]['events'][1]['type'] == 'demotion'
    assert members[__fake_members__[1]
                   ['tag']]['events'][1]['role'] == __fake_members__[1]['role']
    assert members[__fake_members__[1]
                   ['tag']]['events'][1]['date'] == timestamp

    assert members[__fake_members__[2]['tag']]['status'] == 'present'
    assert members[__fake_members__[2]
                   ['tag']]['events'][1]['event'] == 'role change'
    assert members[__fake_members__[2]
                   ['tag']]['events'][1]['type'] == 'promotion'
    assert members[__fake_members__[2]
                   ['tag']]['events'][1]['role'] == __fake_members__[2]['role']
    assert members[__fake_members__[2]
                   ['tag']]['events'][1]['date'] == timestamp
示例#5
0
def test_war_participation_activity_update():
    date = datetime(2019, 2, 12, 7, 32, 1, 0)
    h = history.get_member_history(__fake_members__, __fake_history__,
                                   __fake_currentwar__, date)

    h_member = h['members'][__fake_members__[0].tag]
    assert h_member['last_activity_date'] == datetime.timestamp(date)
示例#6
0
def test_get_member_history_new():
    date = datetime(2019, 2, 12, 7, 32, 0, 0)
    timestamp = datetime.timestamp(date)
    h = history.get_member_history(__fake_members__, date, None, None)

    assert h['last_update'] == timestamp
    for member in __fake_members__:
        assert h['members'][member.tag]['role'] == member.role
        assert h['members'][member.tag]['status'] == 'present'
        assert h['members'][member.tag]['events'][0]['event'] == 'join'
        assert h['members'][member.tag]['events'][0]['type'] == 'new'
        assert h['members'][member.tag]['events'][0]['role'] == member.role
        assert h['members'][member.tag]['events'][0]['date'] == 0
示例#7
0
def test_process_absent_members(tmpdir):
    config_file = tmpdir.mkdir('test_get_suggestions').join('testfile')
    config_file.write(__config_file_score__ +
                      '\nthreshold_demote=-999999\nthreshold_promote=9999999')
    config = load_config_file(config_file.realpath())

    h = history.get_member_history(__fake_clan__['member_list'],
                                   __fake_history_old_member__)

    absent_members = crtools.process_absent_members(config, h['members'])

    assert len(absent_members) == 1
    assert absent_members[0]['tag'] == '#ZZZZZZ'
示例#8
0
def test_get_suggestions_kick(tmpdir):
    config_file = tmpdir.mkdir('test_get_suggestions').join('testfile')
    config_file.write(__config_file_score__ + '\nmin_clan_size=1')
    config = load_config_file(config_file.realpath())

    h = history.get_member_history(__fake_clan__['member_list'], None)

    members = crtools.process_members(config, __fake_clan__, __fake_warlog__,
                                      {"state": "notInWar"}, h)

    suggestions = crtools.get_suggestions(config, members, __fake_clan__)

    print(suggestions)

    assert suggestions[0].startswith('Kick')
    assert members[3]['name'] in suggestions[0]
示例#9
0
def test_get_suggestions_recruit(tmpdir):
    config_file = tmpdir.mkdir('test_get_suggestions').join('testfile')
    config_file.write(__config_file_score__ +
                      '\nthreshold_demote=-999999\nthreshold_promote=9999999')
    config = load_config_file(config_file.realpath())

    h = history.get_member_history(__fake_clan__['member_list'], None)

    members = crtools.process_members(config, __fake_clan__, __fake_warlog__,
                                      {"state": "notInWar"}, h)

    suggestions = crtools.get_suggestions(config, members, __fake_clan__)

    print(suggestions)

    assert len(suggestions) == 1
    assert suggestions[0] == config['strings']['suggestionRecruit']
def test_get_suggestions_kick(tmpdir):
    config_file = tmpdir.mkdir('test_get_suggestions').join('testfile')
    config_file.write(__config_file_score__ + '\nmin_clan_size=1')
    config = load_config_file(config_file.realpath())

    h = history.get_member_history(__fake_clan__.member_list, None)

    members = crtools.process_members(config, __fake_clan__, __fake_warlog__,
                                      __fake_currentwar_notinwar__, h)

    suggestions = crtools.get_suggestions(config, members,
                                          __fake_clan__.required_trophies)

    print(suggestions)

    assert suggestions[0].startswith('Kick')
    assert members[3].name in suggestions[0]
示例#11
0
def test_get_suggestions_promote_demote(tmpdir):
    config_file = tmpdir.mkdir('test_get_suggestions').join('testfile')
    config_file.write(__config_file_score__ + '\nthreshold_promote=10')
    config = load_config_file(config_file.realpath())

    h = history.get_member_history(__fake_clan__['member_list'], None)

    members = crtools.process_members(config, __fake_clan__, __fake_warlog__,
                                      {"state": "notInWar"}, h)

    suggestions = crtools.get_suggestions(config, members, __fake_clan__)

    print(suggestions)

    assert suggestions[0].startswith('Demote')
    assert members[2]['name'] in suggestions[0]
    assert suggestions[1].startswith('Promote') or suggestions[2].startswith(
        'Promote')
    assert members[4]['name'] in suggestions[1] or members[4][
        'name'] in suggestions[2]
def test_get_suggestions_promote_demote(tmpdir):
    config_file = tmpdir.mkdir('test_get_suggestions').join('testfile')
    config_file.write(__config_file_score__ + '\nthreshold_promote=10')
    config = load_config_file(config_file.realpath())

    h = history.get_member_history(__fake_clan__.member_list, None)

    members = crtools.process_members(config, __fake_clan__, __fake_warlog__,
                                      __fake_currentwar_notinwar__, h)

    suggestions = crtools.get_suggestions(config, members,
                                          __fake_clan__.required_trophies)

    print(suggestions)

    assert suggestions[0].startswith('Demote')
    assert members[2].name in suggestions[0]
    assert suggestions[1].startswith('Promote') or suggestions[2].startswith(
        'Promote')
    assert members[4].name in suggestions[1] or members[4].name in suggestions[
        2]
示例#13
0
def test_donations_score(tmpdir):
    config_file = tmpdir.mkdir('test_donations_score').join('testfile')
    config_file.write(__config_file_score__)
    config = load_config_file(config_file.realpath())

    calc = ScoreCalculator(config)

    war = ProcessedCurrentWar(
        config=config, current_war=pyroyale.WarCurrent(state='notInWar'))
    member_history = history.get_member_history(__fake_member_list__,
                                                config['crtools']['timestamp'],
                                                '{}', war)
    date = datetime(2019, 2, 12, 7, 32, 1, 0)

    member_6 = MemberFactory(config=config,
                             current_war=war,
                             clan=__fake_clan__,
                             member_history=member_history,
                             warlog=pyroyale.WarLog(items=[]),
                             days_from_donation_reset=6).get_processed_member(
                                 __fake_member_list__[0])
    member_3 = MemberFactory(config=config,
                             current_war=war,
                             clan=__fake_clan__,
                             member_history=member_history,
                             warlog=pyroyale.WarLog(items=[]),
                             days_from_donation_reset=3).get_processed_member(
                                 __fake_member_list__[0])
    member_0 = MemberFactory(config=config,
                             current_war=war,
                             clan=__fake_clan__,
                             member_history=member_history,
                             warlog=pyroyale.WarLog(items=[]),
                             days_from_donation_reset=0).get_processed_member(
                                 __fake_member_list__[0])

    assert calc.get_member_donations_score(member_6) == 11
    assert calc.get_member_donations_score(member_3) == 18
    assert calc.get_member_donations_score(member_0) == 31
示例#14
0
def test_donations_score(tmpdir):
    config_file = tmpdir.mkdir('test_donations_score').join('testfile')
    config_file.write(__config_file_score__)
    config = load_config_file(config_file.realpath())

    date = datetime(2019, 2, 12, 7, 32, 1, 0)
    timestamp = datetime.timestamp(date)
    members = history.get_member_history(__fake_clan__['member_list'],
                                         __fake_history__, None,
                                         date)["members"]

    member_tag_0 = __fake_clan__['member_list'][0]['tag']
    member_6 = crtools.enrich_member_with_history(
        config, __fake_clan__['member_list'][0], members, 6, date)
    member_3 = crtools.enrich_member_with_history(
        config, __fake_clan__['member_list'][0], members, 3, date)
    member_0 = crtools.enrich_member_with_history(
        config, __fake_clan__['member_list'][0], members, 0, date)

    assert crtools.donations_score(config, member_6) == 11
    assert crtools.donations_score(config, member_3) == 18
    assert crtools.donations_score(config, member_0) == 31
示例#15
0
def test_get_suggestions_nosuggestions(tmpdir):
    config_file = tmpdir.mkdir('test_get_suggestions').join('testfile')
    config_file.write(
        __config_file_score__ +
        '\nthreshold_demote=-999999\nthreshold_promote=9999999\nmin_clan_size={}'
        .format(crtools.MAX_CLAN_SIZE))
    config = load_config_file(config_file.realpath())

    war = ProcessedCurrentWar(
        config=config, current_war=pyroyale.WarCurrent(state='notInWar'))
    factory = MemberFactory(config=config,
                            member_history=history.get_member_history(
                                __fake_clan__.member_list,
                                config['crtools']['timestamp'], '{}', war),
                            current_war=war,
                            clan=__fake_clan__,
                            warlog=pyroyale.WarLog(items=[]))

    members = []
    for i in range(0, crtools.MAX_CLAN_SIZE):
        member = factory.get_processed_member(
            pyroyale.ClanMember(tag="#AAAAAA",
                                name="LeaderPerson",
                                role="leader",
                                exp_level=13,
                                trophies=9999,
                                donations=9999,
                                arena=pyroyale.Arena(id=54000012,
                                                     name='Legendary Arena'),
                                last_seen="20190802T154619.000Z"))
        member.safe = True
        members.append(member)

    suggestions = crtools.get_suggestions(config, members,
                                          __fake_clan__.required_trophies)

    assert len(suggestions) == 1
    assert suggestions[-1] == config['strings']['suggestionNone']
def build_dashboard(config):  # pragma: no coverage
    """Compile and render clan dashboard."""

    print('- requesting info for clan id: {}'.format(config['api']['clan_id']))

    clan, warlog, current_war = get_data_from_api(config)

    # Create temporary directory. All file writes, until the very end,
    # will happen in this directory, so that no matter what we do, it
    # won't hose existing stuff.
    tempdir = tempfile.mkdtemp(config['paths']['temp_dir_name'])

    # Putting everything in a `try`...`finally` to ensure `tempdir` is removed
    # when we're done. We don't want to pollute the user's disk.
    try:
        output_path = os.path.expanduser(config['paths']['out'])

        # process data from API
        current_war_processed = ProcessedCurrentWar(current_war, config)
        clan_processed = ProcessedClan(clan, current_war_processed, config)

        member_history = history.get_member_history(
            clan.member_list, config['crtools']['timestamp'],
            io.get_previous_history(output_path), current_war_processed)

        members_processed = process_members(config, clan, warlog,
                                            current_war_processed,
                                            member_history)
        recent_wars = process_recent_wars(config, warlog)
        former_members = process_absent_members(config,
                                                member_history['members'])

        io.parse_templates(
            config, member_history, tempdir, clan_processed, members_processed,
            former_members, current_war_processed, recent_wars,
            get_suggestions(config, members_processed,
                            clan_processed.required_trophies),
            get_scoring_rules(config))

        if (config['crtools']['debug'] == True):
            # archive outputs of API for debugging
            io.dump_debug_logs(
                tempdir, {
                    'clan':
                    clan.to_dict(),
                    'warlog':
                    warlog.to_dict(),
                    'current_war':
                    current_war.to_dict(),
                    'clan-processed':
                    clan_processed,
                    'members-processed':
                    members_processed,
                    'current_war-processed':
                    current_war_processed,
                    'recentwars-processed':
                    list(map(lambda war: war.to_dict(), recent_wars))
                })

        # if fankit is previously downloaded, it will copy fankit. Otherwise,
        # if fankit is enabled, it will download it.
        fankit.get_fankit(tempdir, output_path, config['paths']['use_fankit'])

        io.copy_static_assets(tempdir, config['paths']['clan_logo'],
                              config['paths']['favicon'])

        io.move_temp_to_output_dir(tempdir, output_path)

        discord.trigger_webhooks(config, current_war, members_processed)

    except Exception as e:
        logger.error('error: {}'.format(e))

    finally:
        # Ensure that temporary directory gets deleted no matter what
        shutil.rmtree(tempdir)
示例#17
0
def build_dashboard(config):  # pragma: no coverage
    """Compile and render clan dashboard."""

    logger.debug('crtools version v{}'.format(__version__))
    logger.debug('pyroyale version v{}'.format(pyroyale.__version__))
    logger.debug(config)

    # Create temporary directory. All file writes, until the very end,
    # will happen in this directory, so that no matter what we do, it
    # won't hose existing stuff.
    tempdir = tempfile.mkdtemp(config['paths']['temp_dir_name'])

    # Putting everything in a `try`...`finally` to ensure `tempdir` is removed
    # when we're done. We don't want to pollute the user's disk.
    try:
        output_path = os.path.expanduser(config['paths']['out'])

        # Get clan data and war log from API.
        api = pyroyale.ClashRoyaleAPI(config['api']['api_key'],
                                      config['api']['clan_id'])
        clan = api.clan.clan_info()
        warlog = api.clan.warlog()
        current_war = api.clan.current_war()

        # process data from API
        current_war_processed = process_current_war(config, current_war)
        clan_processed = process_clan(config, clan, current_war)
        member_history = history.get_member_history(
            clan['memberList'], io.get_previous_history(output_path),
            current_war)
        members_processed = process_members(config, clan, warlog, current_war,
                                            member_history)
        recent_wars = process_recent_wars(config, warlog)
        former_members = process_absent_members(config,
                                                member_history['members'])

        io.parse_templates(
            config, member_history, tempdir, clan_processed, members_processed,
            former_members, current_war_processed, recent_wars,
            get_suggestions(config, members_processed, clan_processed),
            get_scoring_rules(config))

        if (config['crtools']['debug'] == True):
            # archive outputs of API for debugging
            io.dump_debug_logs(
                tempdir, {
                    'clan': clan,
                    'warlog': warlog,
                    'currentwar': current_war,
                    'clan-processed': clan_processed,
                    'members-processed': members_processed,
                    'currentwar-processed': current_war_processed,
                    'recentwars-processed': recent_wars
                })

        if config['paths']['use_fankit']:
            fankit.get_fankit(tempdir, output_path)

        io.copy_static_assets(tempdir, config['paths']['clan_logo'],
                              config['paths']['favicon'])

        io.move_temp_to_output_dir(tempdir, output_path)

    except pyroyale.ClashRoyaleAPIAuthenticationError as e:
        msg = 'developer.clashroyale.com authentication error: {}'.format(e)
        if not config['api']['api_key']:
            msg += '\n - API key not provided'
        else:
            msg += '\n - API key not valid'
        logger.error(msg)

    except pyroyale.ClashRoyaleAPIClanNotFound as e:
        logger.error('developer.clashroyale.com: {}'.format(e))

    except pyroyale.ClashRoyaleAPIError as e:
        logger.error('developer.clashroyale.com error: {}'.format(e))

    except pyroyale.ClashRoyaleAPIMissingFieldsError as e:
        logger.error('error: {}'.format(e))

    finally:
        # Ensure that temporary directory gets deleted no matter what
        shutil.rmtree(tempdir)
示例#18
0
def build_dashboard(config):  # pragma: no coverage
    """Compile and render clan dashboard."""

    logger.debug('crtools version v{}'.format(__version__))
    #logger.debug('pyroyale version v{}'.format(pyroyale.__version__))
    logger.debug(config)

    # Create temporary directory. All file writes, until the very end,
    # will happen in this directory, so that no matter what we do, it
    # won't hose existing stuff.
    tempdir = tempfile.mkdtemp(config['paths']['temp_dir_name'])

    # get API instance
    configuration = pyroyale.Configuration()
    configuration.api_key['authorization'] = config['api']['api_key']
    api = pyroyale.ClansApi(pyroyale.ApiClient(configuration))

    # Putting everything in a `try`...`finally` to ensure `tempdir` is removed
    # when we're done. We don't want to pollute the user's disk.
    try:
        output_path = os.path.expanduser(config['paths']['out'])

        # Get clan data and war log from API.
        clan = api.get_clan(config['api']['clan_id']).to_dict()
        warlog = api.get_clan_war_log(config['api']['clan_id']).to_dict()
        current_war = api.get_current_war(config['api']['clan_id']).to_dict()

        # process data from API
        current_war_processed = process_current_war(config, current_war)
        clan_processed = process_clan(config, clan, current_war)
        member_history = history.get_member_history(
            clan['member_list'], io.get_previous_history(output_path),
            current_war)
        members_processed = process_members(config, clan, warlog, current_war,
                                            member_history)
        recent_wars = process_recent_wars(config, warlog)
        former_members = process_absent_members(config,
                                                member_history['members'])

        io.parse_templates(
            config, member_history, tempdir, clan_processed, members_processed,
            former_members, current_war_processed, recent_wars,
            get_suggestions(config, members_processed, clan_processed),
            get_scoring_rules(config))

        if (config['crtools']['debug'] == True):
            # archive outputs of API for debugging
            io.dump_debug_logs(
                tempdir, {
                    'clan': clan,
                    'warlog': warlog,
                    'currentwar': current_war,
                    'clan-processed': clan_processed,
                    'members-processed': members_processed,
                    'currentwar-processed': current_war_processed,
                    'recentwars-processed': recent_wars
                })

        # if fankit is previously downloaded, it will copy fankit. Otherwise,
        # if fankit is enabled, it will download it.
        fankit.get_fankit(tempdir, output_path, config['paths']['use_fankit'])

        io.copy_static_assets(tempdir, config['paths']['clan_logo'],
                              config['paths']['favicon'])

        io.move_temp_to_output_dir(tempdir, output_path)

    except ApiException as e:
        logger.error('error: {}'.format(e))

    finally:
        # Ensure that temporary directory gets deleted no matter what
        shutil.rmtree(tempdir)