#!/usr/bin/env python
# coding: utf-8
#
Get new Clash API: Done
# Get Clash war stats: Done
# Prep Clash clan war data: Done
# Prep Clash member war data: Done
# Get Discord Bot API keys: Done
# Make Clash player tag and Discord account reference table: Done
# Get test code for Discord Bot API and tag a user: Done
# Get a list of players still missing attacks: Done
# Mention players missing attacks on Discord: Pending
# In[2]:
import requests
import pandas as pd
from datetime import date, datetime, timezone, timedelta
import numpy as np
from google.cloud import bigquery
# In[3]:
api_token = 'token'
today = date.today()
client = bigquery.Client.from_service_account_json(r'ServiceAccount.json')
clan_tags = ["QG9UJ08","Q2JLCVLR","P09YGYU2","2YCCGY8JU"]
# In[4]:
def import_to_gbq(df, destination_table):
try:
## If you want the column and row count then
table_id = destination_table
job_config = bigquery.LoadJobConfig(
schema=[
],
write_disposition="WRITE_TRUNCATE",
)
job = client.load_table_from_dataframe(
df, table_id, job_config=job_config
) # Make an API request.
job.result() # Wait for the job to complete.
table = client.get_table(table_id) # Make an API request.
print("Loaded {} rows and {} columns to {}".format(table.num_rows, len(table.schema), table_id))
except Exception as e:
print(e)
# In[5]:
def get_current_war_data(clan_tag):
url = "https://api.clashofclans.com/v1/clans/%23{clan_tag}/currentwar".format(clan_tag=clan_tag)
r = requests.get(url, headers={"Accept":"application/json", "authorization":"Bearer "+api_token}) #, params = {"limit":20})
data = r.json()
if r.status_code == 200:
if data.get('state') == "inWar" or data.get('state') == "preparation" or data.get('state') == "warEnded":
return data
else:
return None
# In[6]:
# Define a function to calculate time left in hours and minutes (as a decimal)
def calculate_time_left(end_time, utc_offset_hours=0):
war_end_time = datetime.strptime(end_time, "%Y%m%dT%H%M%S.%fZ").replace(tzinfo=timezone.utc)
my_local_time_plus_UTC = datetime.now(timezone.utc) + timedelta(hours=utc_offset_hours)
time_left = war_end_time - my_local_time_plus_UTC
hours_left = time_left.total_seconds() / 3600 # Convert total seconds to hours
return round(hours_left, 1) # Round to 1 decimal place for readability
# In[7]:
# Define a function to extract the required information and create a dictionary with clan high level info, like total stars, attacks, percent destruction.
def extract_clan_info(clan_info):
return {
'clanTag': clan_info.get('tag', ''),
'clanName': clan_info.get('name', ''),
'clanLevel': clan_info.get('clanLevel', 0),
'attacks': clan_info.get('attacks', 0),
'stars': clan_info.get('stars', 0),
'destructionPercentage': clan_info.get('destructionPercentage', 0.00)
}
# Define a function to reformat the clan info for single row representation, for both my clan and enemy clan
def reformat_for_single_row(user_clan, opponent_clan):
combined_data = {}
for key, value in user_clan.items():
combined_data[f'user_{key}'] = value
for key, value in opponent_clan.items():
combined_data[f'opponent_{key}'] = value
return combined_data
# In[8]:
# Define a function to process member attack data
def process_member_attacks(member):
# Initialize default values
attack_details = {
'player_tag': member.get('tag',''),
'name': member.get('name', ''),
'total_attacks': 0,
# 'first_attack_stars': None,
# 'second_attack_stars': None,
# 'first_attack_destruction': None,
# 'second_attack_destruction': None
'first_attack_stars': np.nan,
'second_attack_stars': np.nan,
'first_attack_destruction': np.nan,
'second_attack_destruction': np.nan
}
# Process each attack
attacks = member.get('attacks', [])
attack_details['total_attacks'] = len(attacks)
for i, attack in enumerate(attacks):
if i == 0: # First attack
attack_details['first_attack_stars'] = attack.get('stars', 0)
attack_details['first_attack_destruction'] = attack.get('destructionPercentage', 0)
elif i == 1: # Second attack
attack_details['second_attack_stars'] = attack.get('stars', 0)
attack_details['second_attack_destruction'] = attack.get('destructionPercentage', 0)
return attack_details
# ### Get Aggregated data for each clan and insert in BigQuery for storing
# In[9]:
single_row_df_list = []
members_attacks_df_list = []
try:
for clan_tag in clan_tags:
data = get_current_war_data(clan_tag)
if not data:
print("Clan Tag {clan_tag} not found, please review the tag, or perhaps the clan doesn't have war log public.".format(clan_tag=clan_tag))
else:
# Extract the necessary data for both the user's clan and the enemy clan
start_time = data.get('startTime', '')
end_time = data.get('endTime', '')
war_status = data.get('state', '')
clan_data = data['clan']
opponent_data = data['opponent']
clan_stats = extract_clan_info(clan_data)
opponent_stats = extract_clan_info(opponent_data)
# Reformat the clan and opponent data
single_row_data = reformat_for_single_row(clan_stats, opponent_stats)
# Create a DataFrame from the single row of data
single_row_df = pd.DataFrame([single_row_data])
single_row_df['startTime'] = start_time
single_row_df['endTime'] = end_time
single_row_df['war_end_ts'] = datetime.strptime(end_time, "%Y%m%dT%H%M%S.%fZ")
# Calculate the time left in the war
time_left_in_hours = calculate_time_left(single_row_df['endTime'][0], utc_offset_hours=0)
single_row_df['timeLeft'] = str(time_left_in_hours)
single_row_df['war_status'] = war_status
single_row_df_list.append(single_row_df)
# Get a list of each player clan to see their stats and also add all information into one list/dataframe
members_attack_data = [process_member_attacks(member) for member in data['clan']['members']]
members_attacks_df = pd.DataFrame(members_attack_data)
members_attacks_df['clan_tag'] = "#"+clan_tag
members_attacks_df['war_end_ts'] = datetime.strptime(end_time, "%Y%m%dT%H%M%S.%fZ")
members_attacks_df['timeLeft'] = str(time_left_in_hours)
members_attacks_df['war_status'] = war_status
members_attacks_df_list.append(members_attacks_df)
except Exception as e:
print(e)
#Add all clans from the list into one Dataframe before inserting to BigQuery
final_aggregated_clan_df = pd.concat(single_row_df_list)
final_members_attacks_df = pd.concat(members_attacks_df_list)
# clan_war_status = data.get('state')
# final_members_attacks_df['war_status'] = clan_war_status
# In[10]:
final_aggregated_clan_df
# In[11]:
final_members_attacks_df
# In[12]:
#Load both dataframes as string to bigquery
import_to_gbq(final_aggregated_clan_df.astype(str), 'fleet-parser-330316.luis_stage.stg_coc_clan_war_clan_information')
import_to_gbq(final_members_attacks_df.astype(str), 'fleet-parser-330316.luis_stage.stg_coc_clan_war_player_information')
try:
query_job = client.query('CALL `fleet-parser-330316.luistest.sp_coc_clan_war_clan_information`();')
results = query_job.result()
if query_job.state == 'DONE':
print('Updated fleet-parser-330316.luistest.stg_coc_clan_war_clan_information.')
query_job = client.query('CALL `fleet-parser-330316.luistest.sp_coc_clan_war_player_information`();')
results = query_job.result()
if query_job.state == 'DONE':
print('Updated fleet-parser-330316.luistest.stg_coc_clan_war_player_information.')
except Exception as e:
print(e)