// NOTE: this file is poorly named import { addContestant, getContestants, rmContestant } from "./contestants" const userDataUrl = 'https://oqutjaxxxzzbjtyrfoka.supabase.co/rest/v1/rpc/get_player_data' const postsUrl = 'https://oqutjaxxxzzbjtyrfoka.supabase.co/rest/v1/rpc/get_posts' const playerPostsUrl = 'https://oqutjaxxxzzbjtyrfoka.supabase.co/rest/v1/rpc/get_player_posts' const currentWinnerUrl = 'https://oqutjaxxxzzbjtyrfoka.supabase.co/rest/v1/current_winner?select=*' const winnerArchiveUrl = 'https://oqutjaxxxzzbjtyrfoka.supabase.co/rest/v1/win_archive_view?select=*&limit=50' const ygsUrl = 'https://oqutjaxxxzzbjtyrfoka.supabase.co/rest/v1/rpc/ygs' const contestantsUrl = 'https://oqutjaxxxzzbjtyrfoka.supabase.co/rest/v1/rpc/update_contestants' const victorUrl = 'https://oqutjaxxxzzbjtyrfoka.supabase.co/rest/v1/rpc/update_recent_showdown' const leaderboardUrl = 'https://oqutjaxxxzzbjtyrfoka.supabase.co/rest/v1/rpc/get_paginated_leaderboard' const insertPostUrl = 'https://oqutjaxxxzzbjtyrfoka.supabase.co/rest/v1/rpc/insert_post' const tierIds = [ '1878f11f-782b-43fe-9aa3-cd34e989b174', '629558be-c63d-4255-9bf5-1e98826fa3de', '402261d8-4db8-4e24-8886-90dc6da6fcd1' ] const loadUser = async function() { return new Promise((resolve) => { fetch('https://oqutjaxxxzzbjtyrfoka.supabase.co/rest/v1/rpc/get_player_data', { method: 'POST', // why post? headers: { "APIKey": localStorage.getItem("apikey"), "Authorization": localStorage.getItem("token") } }).then(r => r.json().then(data => ({status: r.status, body: data}))) .then((r) => { // note: when an empty bearer token is provided, the server responds with 200 OK with an empty array as // the body instead of the expected 401. This is a bug with Pithee that we need to account for! if (r.body.length > 0) { resolve({ success: true, user: r.body[0] }) } else if (r.status == 200) { resolve({ success: false, apikeyInvalid: false, tokenInvalid: true, }) } else { resolve({ success: false, apikeyInvalid: true, tokenInvalid: true, }) } }).catch((err) => { alert(err) resolve({ success: false, }) }) }) } const loadUserPosts = async function () { return new Promise((resolve) => { fetch(playerPostsUrl, { method: 'POST', headers: { "apikey": localStorage.getItem('apikey'), "authorization": localStorage.getItem('token'), "Content-Type": "application/json" }, body: null }) .then(r => r.json().then(data => ({status: r.status, body: data}))) .then((r) => { if (r.status >= 200 && r.status <= 299) { // OK range // usually we check if the r.body return array length is 0, but that // fails on this call because the user may not have any posts, so // just resolve resolve(r.body) } else { alert("Your token has expired. Please re-enter your information to keep using Prittee.") window.location.href = '/login' } }) }) } const loadCurrentWinner = async function() { return makePitheeApiCall(currentWinnerUrl, 'GET', null) } const loadWinArchive = async function() { return makePitheeApiCall(winnerArchiveUrl, 'GET', null) } const fetchPosts = async function() { return makePitheeApiCall(postsUrl, 'POST', JSON.stringify({post_quantity: 20})) } const loadLeaderboardPage = async function(page) { return makePitheeApiCall(leaderboardUrl, 'POST', JSON.stringify({ page_number: page, page_size: 25 })) } const updateContestants = async function() { return makePitheeNoContentApiCall(contestantsUrl, 'POST', JSON.stringify({contestants: getContestants()})) } const showdownVictor = async function(victor_id) { return makePitheeNoContentApiCall(victorUrl, 'POST', JSON.stringify({showdown_victor: victor_id})) } const pushPostScore = async function(post) { if (post.tier < 1 || post.tier > 3) { console.log('invalid tier value') return } // just going to leave this unattended. sure I should check if the call // failed, but I won't. Maybe I'll fix it later makePitheeNoContentApiCall(ygsUrl, 'POST', JSON.stringify({ jacks: post.id, films: tierIds[post.tier-1] })) // good one, guys // also update contestants for a three star post // what confuses me is that the contestants for a showdown are stored // client-side, but we still need to push them to the server. why? // if you ask me, the contestants should be all on the server or on // the client. IMO all on the server is better because I don't think // showdown progress is retained upon refresh or login/logout which is silly if (post.tier === 3) { addContestant(post) updateContestants() } } const declareVictor = function (post) { // upon showdown victor, another ygs call is made with the tier3 uuid, // as well as a call to update_recent_showdown // then, ONLY the victor is removed from the contestants // this means that the very next post to reach tier3 triggers a showdown // is this intended behavior? idk, but I will mirror it. makePitheeNoContentApiCall(ygsUrl, 'POST', JSON.stringify({ jacks: post.id, films: tierIds[2] })) // good one, guys showdownVictor(post.id) rmContestant(post) updateContestants() } const insertPost = function (postText) { // the /insert_post endpoint weirdly responds with a string instead of // JSON on success so I can't use the regular makePitheeApiCall function return makePitheeNoContentApiCall(insertPostUrl, 'POST', JSON.stringify({ post_text: postText })) } // /ygs and /update_contestants endpoints do not serve JSON responses so we need this func // ALSO both of those endpoints return 204 OK when a null authorization is given... ??? const makePitheeNoContentApiCall = async function(url, method, body) { return new Promise((resolve) => { fetch(url, { method: method, headers: { "apikey": localStorage.getItem('apikey'), "authorization": localStorage.getItem('token'), "Content-Type": "application/json" }, body: body }) .then((r) => { if (r.status >= 200 && r.status <= 299) { // OK range resolve(r.body) } else if (r.status === 401) { alert("Your token has expired. Please re-enter your information to keep using Prittee.") window.location.href = '/login' } else { // TODO: this is little information for the client. // the server could be responding with a 401 due to expired // key (expected behavior) OR it could be a 500 server error and the client // will not know the difference. This should be fixed! resolve(null) } }) }) } // the API annoyingly returns a 200 OK with an empty array response body // when called with a null api key... const makePitheeApiCall = async function(url, method, body) { return new Promise((resolve) => { fetch(url, { method: method, headers: { "apikey": localStorage.getItem('apikey'), "authorization": localStorage.getItem('token'), "Content-Type": "application/json" }, body: body }) .then(r => r.json().then(data => ({status: r.status, body: data}))) .then((r) => { if (r.status >= 200 && r.status <= 299) { // OK range // check if empty array is given (token is null) if (r.body.length == 0) { alert("Your token has expired. Please re-enter your information to keep using Prittee.") window.location.href = '/login' } resolve(r.body) } else if (r.status === 401) { alert("Your token has expired. Please re-enter your information to keep using Prittee.") window.location.href = '/login' } else { // TODO: this is little information for the client. // the server could be responding with a 401 due to expired // key (expected behavior) OR it could be a 500 server error and the client // will not know the difference. This should be fixed! resolve(null) } }) }) } export { loadUser, loadWinArchive, loadCurrentWinner, fetchPosts, pushPostScore, declareVictor, loadUserPosts, loadLeaderboardPage, insertPost, }