Last active
July 8, 2021 07:04
-
-
Save freshyjmp/d2589f90bdee7a883e5d2441cab9b982 to your computer and use it in GitHub Desktop.
rudimentary example of using custom functions to make API requests w/caching service in Google App Script
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var public_key = 'SET THIS YOURSELF'; | |
var private_key = 'ALSO SET THIS YOURSELF'; | |
var cache = CacheService.getDocumentCache(); | |
const CACHE_KEY = 'cardboard_wealth_token_response'; | |
const GROUP_KEY = 'mtg_groups'; | |
const PRICE_KEY = 'mtg_prices'; | |
const PRODUCT_KEY = 'mtd_products'; | |
function refreshToken() { | |
// We're lazy and like to keep our token response in our super secure app script | |
// If the bearer token has expired, request a new one. Otherwise, nah. | |
var formData = { | |
'grant_type': 'client_credentials', | |
'client_id': public_key, | |
'client_secret': private_key | |
}; | |
var options = { | |
'headers': { | |
'User-Agent': "update this yourself" | |
}, | |
'payload': formData, | |
'method': 'post' | |
}; | |
var url = "https://api.tcgplayer.com/token"; | |
var response = UrlFetchApp.fetch(url, options); | |
Logger.log(response.getContentText()); | |
cache.put(CACHE_KEY, response.getContentText(), 1728000); | |
return response; | |
} | |
function getTokenCache() { | |
var cached = JSON.parse(cache.get(CACHE_KEY)); | |
// if cache is null or if the token has expired, request a new one | |
if (cached != null && Date.now() < Date.parse(cached[".expires"])) { | |
console.log('Token is still valid, returning cached token'); | |
return cached; | |
} | |
if (cached == null) { | |
console.log('Cache key is unset'); | |
} | |
return refreshToken(); | |
} | |
function getPriceCache() { | |
var cached = JSON.parse(cache.get(PRICE_KEY)); | |
if (cached != null) { | |
console.log('Price cache is still valid, returning cache'); | |
return cached; | |
} | |
if (cached == null) { | |
// We'll expire the cache in 24 hours | |
return {} | |
} | |
} | |
function getProductCache() { | |
var cached = JSON.parse(cache.get(PRODUCT_KEY)); | |
if (cached != null) { | |
console.log('Product cache is still valid, returning cache'); | |
return cached; | |
} | |
if (cached == null) { | |
return {} | |
} | |
} | |
function getPriceCacheCount() { | |
var cached = JSON.parse(cache.get(PRICE_KEY)); | |
if (cached != null) { | |
return Object.keys(cached).length; | |
} | |
return 0; | |
} | |
function getOptions(tokenCache) { | |
var options = { | |
'headers': { | |
'User-Agent': "update this yourself", | |
'Accept': 'application/json', | |
'Authorization': 'bearer ' + tokenCache["access_token"] | |
} | |
} | |
return options; | |
} | |
function test() { | |
var tokenCache = getTokenCache(); | |
var product = "Battlebond Booster Box"; | |
var product_Id = queryForProductId(product); | |
console.log(product_Id); | |
console.log(queryForPrice(product_Id)); | |
return tokenCache["access_token"]; | |
} | |
function queryForProductId(product) { | |
var tokenCache = getTokenCache(); | |
var productCache = getProductCache(); | |
if (product in productCache) { | |
return productCache[product] | |
} | |
var url = "https://api.tcgplayer.com/catalog/products?categoryId=1&limit=25&productName=" + encodeURI(product); | |
var options = getOptions(tokenCache); | |
var response = UrlFetchApp.fetch(url, options); | |
response = JSON.parse(response.getContentText()); | |
var productId = response.results[0].productId; | |
productCache[product] = productId; | |
cache.put(PRODUCT_KEY, JSON.stringify(productCache), 31556952); | |
return productId; | |
} | |
function queryForPrice(productId) { | |
var tokenCache = getTokenCache(); | |
var priceCache = getPriceCache(); | |
if (productId in priceCache) { | |
return priceCache[productId]; | |
} | |
var url = "https://api.tcgplayer.com/pricing/product/" + productId; | |
var options = getOptions(tokenCache); | |
var response = UrlFetchApp.fetch(url, options); | |
response = JSON.parse(response.getContentText()); | |
var price = response.results.filter(res => res.subTypeName == "Normal")[0].marketPrice; | |
priceCache[productId] = price; | |
cache.put(PRICE_KEY, JSON.stringify(priceCache), 86000); | |
return price | |
} | |
function queryForGroups() { | |
var tokenCache = getTokenCache(); | |
//cache.remove(GROUP_KEY); | |
var groupCache = JSON.parse(cache.get(GROUP_KEY)); | |
if (groupCache != null){ | |
return groupCache; | |
} | |
// update groupCache when expires | |
if (groupCache == null) { | |
groupCache = { | |
'last_updated': Date.now(), | |
'groups': {} | |
}; | |
} | |
var url = "https://api.tcgplayer.com/catalog/groups?categoryId=1&hasSealed=true&sortOrder=groupId&limit=100"; | |
var options = { | |
'headers': { | |
'User-Agent': "update this yourself", | |
'Accept': 'application/json', | |
'Authorization': 'bearer ' + tokenCache["access_token"] | |
} | |
} | |
//console.log(options); | |
// make first request to determine number of pages, then make repeated requests until all results are obtained | |
var response = UrlFetchApp.fetch(url, options); | |
response = JSON.parse(response.getContentText()); | |
var offset = 0; | |
while(response.totalItems > Object.keys(groupCache.groups).length) { | |
response.results.forEach(element => groupCache.groups[element.name] = element.groupId) | |
// Ensure first page is in array, then continue with offset | |
offset = offset + 100; | |
if (offset < response.totalItems) { | |
response = UrlFetchApp.fetch(url + '&offset=' + offset, options); | |
response = JSON.parse(response.getContentText()); | |
} | |
} | |
cache.put(GROUP_KEY, groupCache, 604800); | |
console.log(groupCache.groups); | |
} | |
function printToken() { | |
var cached = JSON.parse(cache.get(CACHE_KEY)); | |
var sheet = SpreadsheetApp.getActiveSheet(); | |
console.log(cached); | |
console.log(cached["access_token"]); | |
console.log(cached[".expires"]); | |
} | |
function onOpen() { | |
var sheet = SpreadsheetApp.getActiveSpreadsheet(); | |
getTokenCache(); | |
var entries = [{ | |
name : "Refresh", | |
functionName : "refreshLastUpdate" | |
}]; | |
sheet.addMenu("Refresh", entries); | |
}; | |
function refreshLastUpdate() { | |
SpreadsheetApp.getActiveSpreadsheet().getRange('N2').setValue(new Date().toTimeString()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Obviously not production grade but it helps for tracking some products. One could probably go nuts with making the caching more elegant or batching requests but it works enough for the few times of year I'd bother looking at the spreadsheet.