Two teams try and fill in any horizontal, vertical, or diagonal line on a bingo board by playing maps on osu! osu.bingo
osu
at microservice 135 lines 3.5 kB view raw
1import { logger } from '$lib/logger'; 2import type { Osu } from '../osu'; 3 4const BASE_URL = 'https://osu.ppy.sh/api/v2'; 5const AUTH_URL = 'https://osu.ppy.sh/oauth/authorize'; 6const TOKEN_URL = 'https://osu.ppy.sh/oauth/token'; 7 8export const createAuthUrl = ( 9 client_id: string, 10 redirect_uri: string, 11 scopes: Osu.AuthScope[], 12 state?: string 13) => { 14 const params = new URLSearchParams(); 15 params.set('client_id', client_id); 16 params.set('scope', scopes.join(' ')); 17 params.set('response_type', 'code'); 18 params.set('redirect_uri', redirect_uri); 19 if (state) { 20 params.set('state', state); 21 } 22 23 return `${AUTH_URL}?${params.toString()}`; 24}; 25 26export const exchangeAuthCode = async ( 27 code: string, 28 client_id: string, 29 client_secret: string, 30 redirect_uri: string 31): Promise<Osu.AuthorizationCodeTokenResponse> => { 32 const body = { 33 client_id, 34 client_secret, 35 code, 36 grant_type: 'authorization_code', 37 redirect_uri 38 }; 39 40 const tokenReqUrl = `${TOKEN_URL}`; 41 const tokenReq = await fetch(tokenReqUrl, { 42 headers: { 43 Accept: 'application/json', 44 'Content-Type': 'application/json' 45 }, 46 method: 'POST', 47 body: JSON.stringify(body) 48 }); 49 return tokenReq.json(); 50}; 51 52export const getMe = async (access_token: string): Promise<Osu.User> => { 53 const userReq = await fetch(`${BASE_URL}/me`, { 54 headers: { 55 'Content-Type': 'application/json', 56 Accept: 'application/json', 57 Authorization: `Bearer ${access_token}` 58 } 59 }); 60 return userReq.json(); 61}; 62 63// This is a very basic beatmap fetcher 64// Something else should be used in the future to increase 65// The quality of the maps. 66export const getBeatmaps = async (min_sr: number, max_sr: number, access_token: string) => { 67 const params = new URLSearchParams(); 68 params.set('q', `stars>${min_sr} stars<${max_sr}`); 69 70 const beatmapSets = await fetch(`${BASE_URL}/beatmapsets/search?${params.toString()}`, { 71 headers: { 72 'Content-Type': 'application/json', 73 Accept: 'application/json', 74 Authorization: `Bearer ${access_token}` 75 } 76 }); 77 const response = await beatmapSets.json(); 78 const beatmapsets: Osu.Beatmapset[] = response.beatmapsets; 79 80 return beatmapsets; 81}; 82 83export const refreshOAuthToken = async ( 84 token: Bingo.OauthToken, 85 client_id: string, 86 client_secret: string 87): Promise<Osu.AuthorizationCodeTokenResponse | null> => { 88 logger.info(`Updating osu oauth token of ${token.user_id}`, { type: 'token_update' }); 89 const refreshBody = { 90 client_id, 91 client_secret, 92 grant_type: 'refresh_token', 93 refresh_token: token.refresh_token 94 }; 95 96 const refreshReq = await fetch(TOKEN_URL, { 97 method: 'POST', 98 body: JSON.stringify(refreshBody), 99 headers: { 100 'Content-Type': 'application/json', 101 Accept: 'application/json' 102 } 103 }); 104 105 const updatedToken = await refreshReq.json(); 106 107 // Successfully updated 108 if (refreshReq.ok && updatedToken.access_token) { 109 return updatedToken; 110 } 111 return null; 112}; 113 114export const getRecentScores = async (user_id: number, access_token: string) => { 115 const params = new URLSearchParams(); 116 params.set('include_fails', '1'); 117 118 const scores = await fetch(`${BASE_URL}/users/${user_id}/scores/recent?${params.toString()}`, { 119 headers: { 120 'Content-Type': 'application/json', 121 Accept: 'application/json', 122 Authorization: `Bearer ${access_token}`, 123 'x-api-version': '20220705' // Use lazer api 124 } 125 }); 126 const response: Osu.LazerScore[] = await scores.json(); 127 if (scores.ok) { 128 logger.debug(`[${user_id}]: Successfully fetched scores`, { 129 type: 'fetch_user_scores', 130 user_id 131 }); 132 return response; 133 } 134 return null; 135};