-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi.js
More file actions
207 lines (182 loc) · 6.43 KB
/
api.js
File metadata and controls
207 lines (182 loc) · 6.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// --- Client-Side API Module ---
const USER_SESSION_KEY = 'oyh_user_session';
// --- UI Sound Effects ---
const UI_SOUND_B64 = 'data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgAZGF0YVEAAAAAAP9/AAAABwD/fQAABAAAAAAAAAAAAAAA//8A/38AAAEAAAAAAAAAAAAA/3wAAAEAAAAA/30AAAEAAAD/fAAA/wAAAAEAAAAAAAAA/3wAAAIAAAAA/30AAAD/fAAA//8AAAEAAAD/fQAAAgAAAP99AAAA//8AAAEAAAD/fQAAAgAAAP99AAAA//8AAAEAAAD/fQAAAgAAAP99AAAA//8AAAEAAAD/fQAAAgAAAP99AAAA//8AAAEAAAD/fQAAAgAAAP99AAAA//8AAAEAAAD/fQAAAgAAAP99AAAA//8=';
let uiAudio = null;
/**
* Plays a short, retro-style UI sound effect.
*/
function playUiSound() {
try {
if (!uiAudio) {
uiAudio = new Audio(UI_SOUND_B64);
uiAudio.volume = 0.3;
}
// Allows playing the sound again before it has finished.
uiAudio.currentTime = 0;
uiAudio.play();
} catch (e) {
console.error("Could not play UI sound", e);
}
}
// --- User & Session Management ---
/**
* Stores user session data (user object and token) in localStorage.
* @param {Object} sessionData - The session data from the login API.
*/
function saveUserSession(sessionData) {
try {
localStorage.setItem(USER_SESSION_KEY, JSON.stringify(sessionData));
} catch (e) {
console.error("Error saving user session to localStorage", e);
}
}
/**
* Retrieves the current user's session data from localStorage.
* @returns {Object|null} The session object or null.
*/
function getUserSession() {
try {
const session = localStorage.getItem(USER_SESSION_KEY);
return session ? JSON.parse(session) : null;
} catch (e)
{
console.error("Error retrieving user session", e);
return null;
}
}
/**
* Signs out the user by clearing their session data.
*/
function signOutUser() {
try {
localStorage.removeItem(USER_SESSION_KEY);
} catch (e) {
console.error("Error signing out user", e);
}
}
/**
* Gets just the user part of the session.
* @returns {Object|null}
*/
function getCurrentUser() {
const session = getUserSession();
return session ? session.user : null;
}
/**
* Gets the current user's auth token from the session.
* @returns {string|null} The auth token or null.
*/
function getAuthToken() {
const session = getUserSession();
return session ? session.session.access_token : null;
}
// --- API Fetch Functions ---
/**
* A helper function to handle fetch requests and responses.
* @param {string} endpoint - The serverless function endpoint (e.g., '/api/auth-login').
* @param {string} method - The HTTP method ('GET', 'POST', etc.).
* @param {Object} [body] - The request payload for POST/PUT requests.
* @param {string} [token] - The user's auth token.
* @returns {Promise<Object>} The JSON response from the server.
*/
async function fetchApi(endpoint, method, body, token) {
const options = {
method,
headers: { 'Content-Type': 'application/json' },
};
if (body) {
options.body = JSON.stringify(body);
}
if (token) {
options.headers['Authorization'] = `Bearer ${token}`;
}
try {
const response = await fetch(endpoint, options);
const contentType = response.headers.get("content-type");
if (contentType && contentType.indexOf("application/json") !== -1) {
const data = await response.json();
if (!response.ok) {
throw new Error(data.error || `HTTP error! status: ${response.status}`);
}
return data;
} else {
const text = await response.text();
console.error("Non-JSON response from server:", text);
throw new Error(`Server returned a non-JSON response. Status: ${response.status}. Check Netlify function logs for endpoint ${endpoint}.`);
}
} catch (error) {
console.error(`API call to ${endpoint} failed:`, error.message);
throw error;
}
}
// --- Exposed API Functions ---
// Auth
async function registerUser(username, email, password) {
return fetchApi('/api/auth-register', 'POST', { username, email, password });
}
async function loginUser(email, password) {
const data = await fetchApi('/api/auth-login', 'POST', { email, password });
if (data.session) {
saveUserSession(data);
}
return data;
}
// Vs. AI
async function getAiResponse(history, systemInstruction, prompt) {
return fetchApi('/api/game-ai-handler', 'POST', { history, systemInstruction, prompt });
}
async function updateStats(result) {
const token = getAuthToken();
if (!token) {
console.warn("Cannot update stats. User not logged in.");
return Promise.resolve({ message: "Not logged in" });
}
return fetchApi('/api/user-stats', 'POST', { result }, token);
}
// Vs. Human
async function getOpenGames() {
const token = getAuthToken();
if (!token) return Promise.reject(new Error("User not authenticated. Please sign in."));
return fetchApi('/api/game-lobby', 'GET', null, token);
}
async function createGame() {
const token = getAuthToken();
if (!token) return Promise.reject(new Error("User not authenticated. Please sign in."));
return fetchApi('/api/game-lobby', 'POST', { action: 'create' }, token);
}
async function joinGame(gameId) {
const token = getAuthToken();
if (!token) return Promise.reject(new Error("User not authenticated. Please sign in."));
return fetchApi('/api/game-lobby', 'POST', { action: 'join', gameId }, token);
}
async function getGameState(gameId) {
const token = getAuthToken();
if (!token) return Promise.reject(new Error("User not authenticated. Please sign in."));
return fetchApi(`/api/game-state?id=${gameId}`, 'GET', null, token);
}
async function sendGameUpdate(gameId, action, text) {
const token = getAuthToken();
if (!token) return Promise.reject(new Error("User not authenticated. Please sign in."));
return fetchApi('/api/game-update', 'POST', { gameId, action, text }, token);
}
// --- Global Event Listeners ---
document.addEventListener('click', (e) => {
const button = e.target.closest('.btn');
if (button && !button.disabled) {
playUiSound();
}
});
// --- Expose functions to the global scope ---
window.registerUser = registerUser;
window.loginUser = loginUser;
window.signOutUser = signOutUser;
window.getCurrentUser = getCurrentUser;
window.getAiResponse = getAiResponse;
window.updateStats = updateStats;
window.playUiSound = playUiSound;
window.getOpenGames = getOpenGames;
window.createGame = createGame;
window.joinGame = joinGame;
window.getGameState = getGameState;
window.sendGameUpdate = sendGameUpdate;