✨ Pull user profile
This commit is contained in:
		| @@ -19,7 +19,8 @@ | |||||||
|     "next": "15.1.3", |     "next": "15.1.3", | ||||||
|     "react": "^19.0.0", |     "react": "^19.0.0", | ||||||
|     "react-dom": "^19.0.0", |     "react-dom": "^19.0.0", | ||||||
|     "react-hook-form": "^7.54.2" |     "react-hook-form": "^7.54.2", | ||||||
|  |     "zustand": "^5.0.2" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|     "typescript": "^5", |     "typescript": "^5", | ||||||
|   | |||||||
| @@ -3,6 +3,8 @@ import type { AppProps } from 'next/app' | |||||||
| import { Box, createTheme, CssBaseline, ThemeProvider } from '@mui/material' | import { Box, createTheme, CssBaseline, ThemeProvider } from '@mui/material' | ||||||
| import { Roboto } from 'next/font/google' | import { Roboto } from 'next/font/google' | ||||||
| import { CapAppBar } from '@/components/CapAppBar' | import { CapAppBar } from '@/components/CapAppBar' | ||||||
|  | import { useUserStore } from '@/services/user' | ||||||
|  | import { useEffect } from 'react' | ||||||
|  |  | ||||||
| const fontRoboto = Roboto({ | const fontRoboto = Roboto({ | ||||||
|   subsets: ['latin'], |   subsets: ['latin'], | ||||||
| @@ -23,6 +25,12 @@ const siteTheme = createTheme({ | |||||||
| }) | }) | ||||||
|  |  | ||||||
| export default function App({ Component, pageProps }: AppProps) { | export default function App({ Component, pageProps }: AppProps) { | ||||||
|  |   const userStore = useUserStore() | ||||||
|  |  | ||||||
|  |   useEffect(() => { | ||||||
|  |     userStore.fetchUser() | ||||||
|  |   }, []) | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       <style jsx global>{` |       <style jsx global>{` | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ import axios, { AxiosInstance } from 'axios' | |||||||
| import applyCaseMiddleware from 'axios-case-converter' | import applyCaseMiddleware from 'axios-case-converter' | ||||||
| import { hasCookie, getCookie, setCookie } from 'cookies-next/client' | import { hasCookie, getCookie, setCookie } from 'cookies-next/client' | ||||||
|  |  | ||||||
| const baseURL = 'https://api.solsynth.dev' | const baseURL = 'https://api.sn.solsynth.dev' | ||||||
|  |  | ||||||
| export let sni: AxiosInstance = (() => { | export let sni: AxiosInstance = (() => { | ||||||
|   const inst = axios.create({ |   const inst = axios.create({ | ||||||
| @@ -29,12 +29,16 @@ async function refreshToken(): Promise<string | undefined> { | |||||||
|   if (!hasCookie('nex_user_atk') || !hasCookie('nex_user_rtk')) return |   if (!hasCookie('nex_user_atk') || !hasCookie('nex_user_rtk')) return | ||||||
|  |  | ||||||
|   const ogTk: string = getCookie('nex_user_atk')! |   const ogTk: string = getCookie('nex_user_atk')! | ||||||
|   if (!isTokenExpired(ogTk)) return |   if (!isTokenExpired(ogTk)) return ogTk | ||||||
|  |  | ||||||
|   const resp = await axios.post('/cgi/id/auth/token', { |   const resp = await axios.post( | ||||||
|  |     '/cgi/id/auth/token', | ||||||
|  |     { | ||||||
|       refresh_token: getCookie('nex_user_rtk')!, |       refresh_token: getCookie('nex_user_rtk')!, | ||||||
|       grant_type: 'refresh_token', |       grant_type: 'refresh_token', | ||||||
|   }) |     }, | ||||||
|  |     { baseURL }, | ||||||
|  |   ) | ||||||
|   const atk: string = resp.data['accessToken'] |   const atk: string = resp.data['accessToken'] | ||||||
|   const rtk: string = resp.data['refreshToken'] |   const rtk: string = resp.data['refreshToken'] | ||||||
|   setCookie('nex_user_atk', atk, { path: '/', maxAge: 2592000 }) |   setCookie('nex_user_atk', atk, { path: '/', maxAge: 2592000 }) | ||||||
|   | |||||||
							
								
								
									
										82
									
								
								src/services/user.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/services/user.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | |||||||
|  | import { create } from 'zustand' | ||||||
|  | import { sni } from './network' | ||||||
|  | import { hasCookie } from 'cookies-next/client' | ||||||
|  |  | ||||||
|  | interface SnAccount { | ||||||
|  |   id: number | ||||||
|  |   createdAt: Date | ||||||
|  |   updatedAt: Date | ||||||
|  |   deletedAt?: Date | null | ||||||
|  |   confirmedAt?: Date | null | ||||||
|  |   contacts?: SnAccountContact[] | null | ||||||
|  |   avatar: string | ||||||
|  |   banner: string | ||||||
|  |   description: string | ||||||
|  |   name: string | ||||||
|  |   nick: string | ||||||
|  |   permNodes: Record<string, any> | ||||||
|  |   profile?: SnAccountProfile | null | ||||||
|  |   badges: SnAccountBadge[] | ||||||
|  |   suspendedAt?: Date | null | ||||||
|  |   affiliatedId?: number | null | ||||||
|  |   affiliatedTo?: number | null | ||||||
|  |   automatedBy?: number | null | ||||||
|  |   automatedId?: number | null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | interface SnAccountContact { | ||||||
|  |   accountId: number | ||||||
|  |   content: string | ||||||
|  |   createdAt: Date | ||||||
|  |   deletedAt?: Date | null | ||||||
|  |   id: number | ||||||
|  |   isPrimary: boolean | ||||||
|  |   isPublic: boolean | ||||||
|  |   type: number | ||||||
|  |   updatedAt: Date | ||||||
|  |   verifiedAt?: Date | null | ||||||
|  | } | ||||||
|  |  | ||||||
|  | interface SnAccountProfile { | ||||||
|  |   id: number | ||||||
|  |   accountId: number | ||||||
|  |   birthday?: Date | null | ||||||
|  |   createdAt: Date | ||||||
|  |   deletedAt?: Date | null | ||||||
|  |   experience: number | ||||||
|  |   firstName: string | ||||||
|  |   lastName: string | ||||||
|  |   lastSeenAt?: Date | null | ||||||
|  |   updatedAt: Date | ||||||
|  | } | ||||||
|  |  | ||||||
|  | interface SnAccountBadge { | ||||||
|  |   id: number | ||||||
|  |   createdAt: Date | ||||||
|  |   updatedAt: Date | ||||||
|  |   deletedAt?: Date | null | ||||||
|  |   type: string | ||||||
|  |   accountId: number | ||||||
|  |   metadata: Record<string, any> | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export interface UserStore { | ||||||
|  |   account: SnAccount | undefined | ||||||
|  |   fetchUser: () => Promise<SnAccount | undefined> | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export const useUserStore = create<UserStore>((set) => ({ | ||||||
|  |   account: undefined, | ||||||
|  |   fetchUser: async (): Promise<SnAccount | undefined> => { | ||||||
|  |     if (!hasCookie('nex_user_atk')) return | ||||||
|  |     try { | ||||||
|  |       const resp = await sni.get<SnAccount>('/cgi/id/users/me') | ||||||
|  |       set({ account: resp.data }) | ||||||
|  |       console.log('[Authenticator] Logged in as @' + resp.data.name) | ||||||
|  |       return resp.data | ||||||
|  |     } catch (err) { | ||||||
|  |       console.error('[Authenticator] Unable to get user profile: ', err) | ||||||
|  |       return | ||||||
|  |     } | ||||||
|  |   }, | ||||||
|  | })) | ||||||
		Reference in New Issue
	
	Block a user