pstream is dead; long live pstream taciturnaxolotl.github.io/pstream-ng/
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

remove it from the backend :(

Pas 11925822 2a4b74bb

+17 -117
-44
src/backend/accounts/region.ts
··· 1 - import { ofetch } from "ofetch"; 2 - 3 - import { getAuthHeaders } from "@/backend/accounts/auth"; 4 - import { AccountWithToken } from "@/stores/auth"; 5 - 6 - export type Region = 7 - | "us-east" 8 - | "us-west" 9 - | "south" 10 - | "asia" 11 - | "europe" 12 - | "unknown"; 13 - 14 - export interface RegionResponse { 15 - region: Region; 16 - lastChecked: number; 17 - userPicked: boolean; 18 - } 19 - 20 - export async function updateRegion( 21 - url: string, 22 - account: AccountWithToken, 23 - region: Region, 24 - userPicked: boolean = false, 25 - ) { 26 - return ofetch<RegionResponse>(`/users/${account.userId}/region`, { 27 - method: "PUT", 28 - headers: getAuthHeaders(account.token), 29 - baseURL: url, 30 - body: { 31 - region, 32 - userPicked, 33 - lastChecked: Math.floor(Date.now() / 1000), 34 - }, 35 - }); 36 - } 37 - 38 - export async function getRegion(url: string, account: AccountWithToken) { 39 - return ofetch<RegionResponse>(`/users/${account.userId}/region`, { 40 - method: "GET", 41 - headers: getAuthHeaders(account.token), 42 - baseURL: url, 43 - }); 44 - }
+3 -18
src/pages/parts/admin/RegionSelectorPart.tsx
··· 1 - import { useState } from "react"; 2 - 3 - import { Region } from "@/backend/accounts/region"; 4 1 import { Dropdown } from "@/components/form/Dropdown"; 5 2 import { Box } from "@/components/layout/Box"; 6 3 import { Heading2 } from "@/components/utils/Text"; 7 - import { useRegionStore } from "@/utils/detectRegion"; 4 + import { Region, useRegionStore } from "@/utils/detectRegion"; 8 5 9 6 export function RegionSelectorPart() { 10 7 const { region, setRegion } = useRegionStore(); 11 - const [isUpdating, setIsUpdating] = useState(false); 12 8 13 9 const regionOptions = [ 14 10 { id: "us-east", name: "US East (Ohio)" }, ··· 18 14 { id: "europe", name: "Europe Central (London)" }, 19 15 ]; 20 16 21 - const handleRegionChange = async (item: { id: string; name: string }) => { 22 - setIsUpdating(true); 23 - try { 24 - await setRegion(item.id as Region, true); 25 - } catch (error) { 26 - console.error("Failed to update region:", error); 27 - } finally { 28 - setIsUpdating(false); 29 - } 30 - }; 31 - 32 17 return ( 33 18 <> 34 19 <Heading2 className="mb-8 mt-12">Region Selector</Heading2> ··· 48 33 regionOptions.find((r) => r.id === region)?.name || 49 34 "Unknown (US East)", 50 35 }} 51 - setSelectedItem={handleRegionChange} 36 + setSelectedItem={(item) => setRegion(item.id as Region, true)} 52 37 direction="up" 53 38 /> 54 39 </div> 55 40 <p className="max-w-[30rem] text-type-danger"> 56 - Use with caution. Changing the region could reset your token! 41 + Use with caution. Changing the region will reset your token! 57 42 </p> 58 43 </Box> 59 44 </>
+14 -55
src/utils/detectRegion.tsx
··· 1 1 import { create } from "zustand"; 2 2 import { persist } from "zustand/middleware"; 3 3 4 - import { Region, getRegion, updateRegion } from "@/backend/accounts/region"; 5 - import { conf } from "@/setup/config"; 6 - import { useAuthStore } from "@/stores/auth"; 4 + export type Region = 5 + | "us-east" 6 + | "us-west" 7 + | "south" 8 + | "asia" 9 + | "europe" 10 + | "unknown"; 7 11 8 12 interface RegionStore { 9 13 region: Region | null; ··· 18 22 region: null, 19 23 lastChecked: null, 20 24 userPicked: false, 21 - setRegion: async (region, userPicked = false) => { 22 - const url = conf().BACKEND_URL; 23 - const account = useAuthStore.getState().account; 24 - 25 - if (url && account) { 26 - try { 27 - const response = await updateRegion( 28 - url, 29 - account, 30 - region, 31 - userPicked, 32 - ); 33 - set({ 34 - region: response.region, 35 - lastChecked: response.lastChecked, 36 - userPicked: response.userPicked, 37 - }); 38 - } catch (error) { 39 - console.error("Failed to update region:", error); 40 - } 41 - } else { 42 - set({ 43 - region, 44 - lastChecked: Math.floor(Date.now() / 1000), 45 - userPicked, 46 - }); 47 - } 25 + setRegion: (region, userPicked = false) => { 26 + set({ 27 + region, 28 + lastChecked: Math.floor(Date.now() / 1000), 29 + userPicked, 30 + }); 48 31 }, 49 32 }), 50 33 { ··· 106 89 107 90 // 1. Check if user manually picked a region (highest priority) 108 91 // 2. Check if we need to refresh the region 109 - // 3. If refresh needed: 110 - // a. Try to get fresh region from backend 111 - // b. If backend region is fresh, use it 112 - // c. If backend region is expired or unavailable, fall back to IP detection 92 + // 3. If refresh needed, fall back to IP detection 113 93 // 4. If no refresh needed, use existing region 114 94 115 95 export async function detectRegion(): Promise<Region> { 116 96 const store = useRegionStore.getState(); 117 - const url = conf().BACKEND_URL; 118 - const account = useAuthStore.getState().account; 119 97 120 98 // If user picked a region, always return that 121 99 if (store.userPicked && store.region) { ··· 133 111 } 134 112 135 113 try { 136 - // Try to get fresh region from backend first 137 - if (url && account) { 138 - try { 139 - const response = await getRegion(url, account); 140 - // Only update if the backend has a fresh region 141 - if ( 142 - response.lastChecked && 143 - Math.floor(Date.now() / 1000) - response.lastChecked < 2592000 144 - ) { 145 - if (!store.userPicked) { 146 - store.setRegion(response.region, response.userPicked); 147 - } 148 - return response.region; 149 - } 150 - } catch (error) { 151 - console.warn("Failed to get region from backend:", error); 152 - } 153 - } 154 - 155 114 // Fallback to IP-based detection 156 115 const response = await fetch("https://ipapi.co/json/"); 157 116 const data = await response.json();