Bluesky app fork with some witchin' additions 馃挮
at jean/pds-label 151 lines 3.9 kB view raw
1import {type LocationGeocodedAddress} from 'expo-location' 2 3import {IS_ANDROID} from '#/env' 4import {logger} from '#/geolocation/logger' 5import {type Geolocation} from '#/geolocation/types' 6import {device} from '#/storage' 7 8/** 9 * Maps full US region names to their short codes. 10 * 11 * Context: in some cases, like on Android, we get the full region name instead 12 * of the short code. We may need to expand this in the future to other 13 * countries, hence the prefix. 14 */ 15export const USRegionNameToRegionCode: { 16 [regionName: string]: string 17} = { 18 Alabama: 'AL', 19 Alaska: 'AK', 20 Arizona: 'AZ', 21 Arkansas: 'AR', 22 California: 'CA', 23 Colorado: 'CO', 24 Connecticut: 'CT', 25 Delaware: 'DE', 26 Florida: 'FL', 27 Georgia: 'GA', 28 Hawaii: 'HI', 29 Idaho: 'ID', 30 Illinois: 'IL', 31 Indiana: 'IN', 32 Iowa: 'IA', 33 Kansas: 'KS', 34 Kentucky: 'KY', 35 Louisiana: 'LA', 36 Maine: 'ME', 37 Maryland: 'MD', 38 Massachusetts: 'MA', 39 Michigan: 'MI', 40 Minnesota: 'MN', 41 Mississippi: 'MS', 42 Missouri: 'MO', 43 Montana: 'MT', 44 Nebraska: 'NE', 45 Nevada: 'NV', 46 ['New Hampshire']: 'NH', 47 ['New Jersey']: 'NJ', 48 ['New Mexico']: 'NM', 49 ['New York']: 'NY', 50 ['North Carolina']: 'NC', 51 ['North Dakota']: 'ND', 52 Ohio: 'OH', 53 Oklahoma: 'OK', 54 Oregon: 'OR', 55 Pennsylvania: 'PA', 56 ['Rhode Island']: 'RI', 57 ['South Carolina']: 'SC', 58 ['South Dakota']: 'SD', 59 Tennessee: 'TN', 60 Texas: 'TX', 61 Utah: 'UT', 62 Vermont: 'VT', 63 Virginia: 'VA', 64 Washington: 'WA', 65 ['West Virginia']: 'WV', 66 Wisconsin: 'WI', 67 Wyoming: 'WY', 68} 69 70/** 71 * Normalizes a `LocationGeocodedAddress` into a `Geolocation`. 72 * 73 * We don't want or care about the full location data, so we trim it down and 74 * normalize certain fields, like region, into the format we need. 75 */ 76export function normalizeDeviceLocation( 77 location: LocationGeocodedAddress, 78): Geolocation { 79 let {isoCountryCode, region} = location 80 let regionCode: string | undefined = region ?? undefined 81 82 /* 83 * Android doesn't give us ISO 3166-2 short codes. We need these for US 84 */ 85 if (IS_ANDROID) { 86 if (region && isoCountryCode === 'US') { 87 /* 88 * We need short codes for US states. If we can't remap it, just drop it 89 * entirely for now. 90 */ 91 regionCode = USRegionNameToRegionCode[region] ?? undefined 92 } else { 93 /* 94 * Outside the US, we don't need regionCodes for now, so just drop it. 95 */ 96 regionCode = undefined 97 } 98 } 99 100 return { 101 countryCode: isoCountryCode ?? undefined, 102 regionCode, 103 } 104} 105 106/** 107 * Combines precise location data with the geolocation config fetched from the 108 * IP service, with preference to the precise data. 109 */ 110export function mergeGeolocations( 111 device?: Geolocation, 112 geolocationService?: Geolocation, 113): Geolocation { 114 let geolocation: Geolocation = { 115 countryCode: geolocationService?.countryCode ?? undefined, 116 regionCode: geolocationService?.regionCode ?? undefined, 117 } 118 // prefer GPS 119 if (device?.countryCode) { 120 geolocation = device 121 } 122 logger.debug('merged geolocation data', { 123 device, 124 service: geolocationService, 125 merged: geolocation, 126 }) 127 return geolocation 128} 129 130/** 131 * Gets the IP-based geolocation as a string in the format of 132 * "countryCode-regionCode", or just "countryCode" if regionCode is not 133 * available. 134 * 135 * IMPORTANT: this method should only return IP-based data, not the user's GPS 136 * based data. IP-based data we can already infer from requests, but for 137 * consistency between frontend and backend, we sometimes want to share the 138 * value we have on the frontend with the backend. 139 */ 140export function getIPGeolocationString() { 141 const geo = device.get(['geolocationServiceResponse']) 142 if (!geo) return 143 const {countryCode, regionCode} = geo 144 if (countryCode) { 145 if (regionCode) { 146 return `${countryCode}-${regionCode}` 147 } else { 148 return countryCode 149 } 150 } 151}