feat: imgur proxying for blocked countries (#7104)

This commit is contained in:
Calum H.
2026-08-11 16:40:03 +00:00
committed by GitHub
parent 26e05ee9e5
commit 2d567b93ce
12 changed files with 167 additions and 37 deletions
+1 -1
View File
@@ -300,7 +300,7 @@ const {
setModpackAlreadyInstalledModal,
handleModpackDuplicateCreateAnyway,
handleModpackDuplicateGoToInstance,
} = setupProviders(notificationManager, popupNotificationManager)
} = setupProviders(tauriApiClient, notificationManager, popupNotificationManager)
const news = ref([])
const displayedServerInviteNotifications = new Set()
+4
View File
@@ -1,3 +1,4 @@
import type { AbstractModrinthClient } from '@modrinth/api-client'
import type { AbstractPopupNotificationManager, AbstractWebNotificationManager } from '@modrinth/ui'
import { setupCreationModal } from './setup/creation-modal'
@@ -5,11 +6,14 @@ import { setupFileDropProvider } from './setup/file-drop'
import { setupFilePickerProvider } from './setup/file-picker'
import { setupInstanceImportProvider } from './setup/instance-import'
import { setupTagsProvider } from './setup/tags'
import { setupUserCountryProvider } from './setup/user-country'
export function setupProviders(
client: AbstractModrinthClient,
notificationManager: AbstractWebNotificationManager,
_popupNotificationManager: AbstractPopupNotificationManager,
) {
setupUserCountryProvider(client)
setupTagsProvider(notificationManager)
setupFileDropProvider()
setupFilePickerProvider()
@@ -0,0 +1,16 @@
import type { AbstractModrinthClient } from '@modrinth/api-client'
import { provideUserCountry } from '@modrinth/ui'
import { ref } from 'vue'
export function setupUserCountryProvider(client: AbstractModrinthClient) {
const country = ref('US')
void client.labrinth.geoip
.getCountry()
.then((detectedCountry) => {
country.value = detectedCountry ?? country.value
})
.catch(() => {})
return provideUserCountry(country)
}
+3
View File
@@ -15,9 +15,12 @@ import { I18nDebugPanel, LoadingBar, NotificationPanel } from '@modrinth/ui'
import AdsConsentNotification from '~/components/ui/AdsConsentNotification.vue'
import { setupProviders } from '~/providers/setup.ts'
import { setupUserCountryProvider } from '~/providers/setup/user-country.ts'
import { useAuth } from './composables/auth'
setupUserCountryProvider()
const auth = await useAuth()
setupProviders(auth)
</script>
+2 -36
View File
@@ -1,6 +1,6 @@
import type { ISO3166 } from '@modrinth/api-client'
import { useUserCountry as useInjectedUserCountry } from '@modrinth/ui'
import { useRequestHeaders, useState } from '#imports'
import { countries, subdivisions } from '~/generated/state.json'
export const useCountries = () => {
@@ -35,38 +35,4 @@ export const useSubdivisions = (countryCode: ComputedRef<string> | Ref<string> |
return computed(() => byCountry[unref(code)] ?? [])
}
export const useUserCountry = () => {
const country = useState<string>('userCountry', () => 'US')
const fromServer = useState<boolean>('userCountryFromServer', () => false)
if (import.meta.server) {
const headers = useRequestHeaders(['cf-ipcountry', 'accept-language'])
const cf = headers['cf-ipcountry']
if (cf) {
country.value = cf.toUpperCase()
fromServer.value = true
} else {
const al = headers['accept-language'] || ''
const tag = al.split(',')[0]
const val = tag.split('-')[1]?.toLowerCase()
if (val) {
country.value = val
fromServer.value = true
}
}
}
if (import.meta.client) {
onMounted(() => {
if (fromServer.value) return
// @ts-expect-error - ignore TS not knowing about navigator.userLanguage
const lang = navigator.language || navigator.userLanguage || ''
const region = lang.split('-')[1]
if (region) {
country.value = region.toUpperCase()
}
})
}
return country
}
export const useUserCountry = useInjectedUserCountry
@@ -0,0 +1,41 @@
import { provideUserCountry } from '@modrinth/ui'
import { onMounted } from 'vue'
import { useRequestHeaders, useState } from '#imports'
function getCountryFromLocale(locale: string | undefined) {
if (!locale) return undefined
try {
return new Intl.Locale(locale).region?.toUpperCase()
} catch {
return undefined
}
}
export function setupUserCountryProvider() {
const country = useState<string>('userCountry', () => 'US')
const fromServer = useState<boolean>('userCountryFromServer', () => false)
if (import.meta.server) {
const headers = useRequestHeaders(['cf-ipcountry', 'accept-language'])
const cloudflareCountry = headers['cf-ipcountry']
const locale = headers['accept-language']?.split(',')[0]?.split(';')[0]?.trim()
const detectedCountry = cloudflareCountry?.toUpperCase() ?? getCountryFromLocale(locale)
if (detectedCountry) {
country.value = detectedCountry
fromServer.value = true
}
}
if (import.meta.client) {
onMounted(() => {
if (!fromServer.value) {
country.value = getCountryFromLocale(navigator.language) ?? country.value
}
})
}
return provideUserCountry(country)
}