Initial implementations
Okay not really, but I have lost the original git repo so this is where we're at qq
This commit is contained in:
parent
8936cccd29
commit
1ff0631915
14
Makefile
Normal file
14
Makefile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
token-current:
|
||||||
|
zip wow-token-current.zip wow-token-current.py
|
||||||
|
|
||||||
|
token-historical:
|
||||||
|
zip wow-token-historical.zip wow-token-historical.py
|
||||||
|
|
||||||
|
token-updater:
|
||||||
|
cd venv/lib/python3.9/site-packages && zip -r ../../../../wow-token-updater.zip .
|
||||||
|
zip -g wow-token-updater.zip wow-token-updater.py
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -v wow-token-current.zip wow-token-historical.zip wow-token-updater.zip
|
||||||
|
|
||||||
|
all: token-current token-historical token-updater
|
162
wow-token-updater.py
Normal file
162
wow-token-updater.py
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import datetime
|
||||||
|
import time
|
||||||
|
import boto3
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
dynamo_client = boto3.client('dynamodb', region_name='us-east-1')
|
||||||
|
timestream_client = boto3.client('timestream-write', region_name='us-east-1')
|
||||||
|
current_table = os.environ['TABLE_NAME']
|
||||||
|
recent_table = os.environ['RECENT_TABLE_NAME']
|
||||||
|
|
||||||
|
|
||||||
|
# a lambda handler to handle eventbridge triggered vents
|
||||||
|
def lambda_handler(event, context):
|
||||||
|
regions = ['us', 'eu', 'kr', 'tw']
|
||||||
|
live_prices = get_combined_live_price()
|
||||||
|
print(live_prices)
|
||||||
|
current_time_epoch = int(datetime.datetime.utcnow().timestamp())
|
||||||
|
for region in regions:
|
||||||
|
print(f'Updating {region.upper()}...')
|
||||||
|
update_token_price(region, current_time_epoch, live_prices[region])
|
||||||
|
|
||||||
|
|
||||||
|
def update_token_price(region: str, current_time_epoch: int, live_price: int):
|
||||||
|
stored_price = get_stored_price(region)
|
||||||
|
print(f'Current stored price {stored_price}')
|
||||||
|
if stored_price != live_price:
|
||||||
|
update_stored_token_price(region, live_price, current_time_epoch)
|
||||||
|
update_recent_token_price(region, live_price, current_time_epoch)
|
||||||
|
update_timestream_token_price(region, live_price, current_time_epoch)
|
||||||
|
else:
|
||||||
|
# price hasn't changed
|
||||||
|
print(f'Price has not changed for {region.upper()}')
|
||||||
|
|
||||||
|
|
||||||
|
# update the current price records in DynamoDB
|
||||||
|
def update_stored_token_price(region: str, price: int, current_time_epoch: int) -> None:
|
||||||
|
dynamo_client.update_item(
|
||||||
|
TableName=current_table,
|
||||||
|
Key={
|
||||||
|
'region': {
|
||||||
|
'S': region
|
||||||
|
}
|
||||||
|
},
|
||||||
|
UpdateExpression='SET price = :p, current_time = :t',
|
||||||
|
ExpressionAttributeValues={
|
||||||
|
':p': {
|
||||||
|
'S': str(price)
|
||||||
|
},
|
||||||
|
':t': {
|
||||||
|
'S': str(current_time_epoch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# ReturnValues="UPDATED_NEW"
|
||||||
|
)
|
||||||
|
print(f'Updated {region.upper()} price to {price}')
|
||||||
|
|
||||||
|
|
||||||
|
# add a record to the recent token price table in DynamoDB
|
||||||
|
def update_recent_token_price(region: str, price: int, current_time_epoch: int) -> None:
|
||||||
|
dynamo_client.put_item(
|
||||||
|
TableName=recent_table,
|
||||||
|
Item={
|
||||||
|
'region': {
|
||||||
|
'S': region
|
||||||
|
},
|
||||||
|
'price': {
|
||||||
|
'S': str(price)
|
||||||
|
},
|
||||||
|
'timestamp': {
|
||||||
|
'N': str(current_time_epoch)
|
||||||
|
},
|
||||||
|
'expire': {
|
||||||
|
'N': str(current_time_epoch + (60 * 60 * 24 * 31 * 12))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# ReturnValues="UPDATED_NEW"
|
||||||
|
)
|
||||||
|
print(f'Added {region.upper()} price {price} to {recent_table} table')
|
||||||
|
|
||||||
|
|
||||||
|
def update_timestream_token_price(region: str, price: int, current_time_epoch: int) -> None:
|
||||||
|
record_inserted = False
|
||||||
|
while not record_inserted:
|
||||||
|
try:
|
||||||
|
print('Attempting to write to Timestream')
|
||||||
|
timestream_client.write_records(
|
||||||
|
DatabaseName=os.environ['TIMESTREAM_DATABASE'],
|
||||||
|
TableName=f'{region}-price-history',
|
||||||
|
Records=[
|
||||||
|
build_timestream_record(region, price, current_time_epoch),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
record_inserted = True
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Error writing to Timestream: {e}')
|
||||||
|
time.sleep(2)
|
||||||
|
print(f'Updated {region.upper()} price to {price} in Timestream')
|
||||||
|
|
||||||
|
|
||||||
|
def build_timestream_record(region: str, price: int, current_time_epoch: int) -> dict:
|
||||||
|
return {
|
||||||
|
'Dimensions': [
|
||||||
|
{
|
||||||
|
'Name': 'region',
|
||||||
|
'Value': region,
|
||||||
|
'DimensionValueType': 'VARCHAR'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'MeasureName': 'price',
|
||||||
|
'MeasureValue': str(price),
|
||||||
|
'MeasureValueType': 'BIGINT',
|
||||||
|
'Time': str(current_time_epoch),
|
||||||
|
'TimeUnit': 'SECONDS',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# get the current stored token price from dynamodb
|
||||||
|
def get_stored_price(region: str) -> int:
|
||||||
|
response = dynamo_client.get_item(
|
||||||
|
TableName=current_table,
|
||||||
|
Key={
|
||||||
|
'region': {
|
||||||
|
'S': region
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return int(response['Item']['price']['S'])
|
||||||
|
|
||||||
|
|
||||||
|
def get_combined_live_price() -> dict:
|
||||||
|
return {
|
||||||
|
'us': get_token_price_from_blizzard('us'),
|
||||||
|
'eu': get_token_price_from_blizzard('eu'),
|
||||||
|
'kr': get_token_price_from_blizzard('kr'),
|
||||||
|
'tw': get_token_price_from_blizzard('tw')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_token_price_from_blizzard(region: str):
|
||||||
|
api_endpoint = f'https://{region}.api.blizzard.com/data/wow/token/index'
|
||||||
|
params = {'namespace': f'{os.environ.get("BLIZZARD_NAMESPACE")}-{region}'}
|
||||||
|
headers = {'Authorization': f'Bearer {get_oauth_token()}'}
|
||||||
|
response = requests.get(api_endpoint, params=params, headers=headers)
|
||||||
|
return int(response.json()['price'])
|
||||||
|
|
||||||
|
|
||||||
|
def get_oauth_token():
|
||||||
|
url = 'https://us.battle.net/oauth/token'
|
||||||
|
payload = {
|
||||||
|
'grant_type': 'client_credentials',
|
||||||
|
'client_id': os.environ.get('BLIZZARD_CLIENT_ID'),
|
||||||
|
'client_secret': os.environ.get('BLIZZARD_CLIENT_SECRET')
|
||||||
|
}
|
||||||
|
response = requests.post(url, data=payload)
|
||||||
|
return json.loads(response.text)['access_token']
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
lambda_handler(None, None)
|
Loading…
Reference in New Issue
Block a user