mirror of
https://github.com/ThatGuySam/doesitarm.git
synced 2026-05-15 06:35:20 -07:00
Compare commits
4 commits
a05f8607b8
...
81b2179d0f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
81b2179d0f | ||
|
|
d1f49267c0 | ||
|
|
3d19c60670 | ||
|
|
eaeff51cc9 |
7 changed files with 223 additions and 34 deletions
|
|
@ -16,10 +16,33 @@ addEventListener('fetch', event => {
|
|||
event.respondWith(handleRequest(event.request))
|
||||
})
|
||||
|
||||
const canonicalHost = 'doesitarm.com'
|
||||
const workersDevHost = 'doesitarm-default.samcarlton.workers.dev'
|
||||
const workerHeaderName = 'x-workers-hello'
|
||||
const workerHeaderValue = 'Hello from Cloudflare Workers'
|
||||
|
||||
function redirectToCanonicalHost(url) {
|
||||
url.protocol = 'https:'
|
||||
url.hostname = canonicalHost
|
||||
|
||||
return new Response(null, {
|
||||
headers: {
|
||||
Location: url.toString(),
|
||||
[workerHeaderName]: workerHeaderValue
|
||||
},
|
||||
status: 302
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// Alter Headers - https://developers.cloudflare.com/workers/examples/alter-headers
|
||||
async function handleRequest(request) {
|
||||
// const visitor = ua( process.env.GA_TRACKING_ID )
|
||||
const url = new URL(request.url)
|
||||
|
||||
if (url.hostname === workersDevHost) {
|
||||
return redirectToCanonicalHost(url)
|
||||
}
|
||||
|
||||
const response = await fetch(request)
|
||||
|
||||
|
|
@ -28,7 +51,7 @@ async function handleRequest(request) {
|
|||
const newResponse = new Response(response.body, response)
|
||||
|
||||
// Add a custom header with a value
|
||||
newResponse.headers.append("x-workers-hello", "Hello from Cloudflare Workers")
|
||||
newResponse.headers.append(workerHeaderName, workerHeaderValue)
|
||||
|
||||
// // Delete headers
|
||||
// newResponse.headers.delete("x-header-to-delete")
|
||||
|
|
|
|||
136
helpers/device-list-fallbacks.js
Normal file
136
helpers/device-list-fallbacks.js
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
const rawDeviceList = [
|
||||
{
|
||||
name: '2023 M3 Macbook Pros',
|
||||
enabled: 'yes',
|
||||
type: 'mac-apple-silicon',
|
||||
description: '16 inch and 14 inch M3 Max Macbook Pro designed for pros. ',
|
||||
amazonUrl: 'https://www.apple.com/macbook-pro/',
|
||||
bhUrl: '',
|
||||
adoramaUrl: '',
|
||||
slug: '2023-m3-macbook-pros',
|
||||
endpoint: '/device/2023-m3-macbook-pros'
|
||||
},
|
||||
{
|
||||
name: '2023 M2 Macbook Pros',
|
||||
enabled: 'yes',
|
||||
type: 'mac-apple-silicon',
|
||||
description: '16 inch and 14 inch M2 Max Macbook Pro designed for pros. ',
|
||||
amazonUrl: 'https://amzn.to/3FEuUs1',
|
||||
bhUrl: '',
|
||||
adoramaUrl: '',
|
||||
slug: '2023-m2-macbook-pros',
|
||||
endpoint: '/device/2023-m2-macbook-pros'
|
||||
},
|
||||
{
|
||||
name: '2023 M3 iMac',
|
||||
enabled: 'yes',
|
||||
type: 'mac-apple-silicon',
|
||||
description: 'M3 iMac is the new Apple Silicon desktop optimized with the Apple M3 processor. ',
|
||||
amazonUrl: 'https://www.apple.com/imac/',
|
||||
bhUrl: '',
|
||||
adoramaUrl: '',
|
||||
slug: '2023-m3-imac',
|
||||
endpoint: '/device/2023-m3-imac'
|
||||
},
|
||||
{
|
||||
name: '2023 M2 Pro Mac Mini',
|
||||
enabled: 'yes',
|
||||
type: 'mac-apple-silicon',
|
||||
description: 'M3 Mac Mini is the second generation Apple Silicon iMac for desktop.',
|
||||
amazonUrl: 'https://amzn.to/40yxCsV',
|
||||
bhUrl: '',
|
||||
adoramaUrl: '',
|
||||
slug: '2023-m2-pro-mac-mini',
|
||||
endpoint: '/device/2023-m2-pro-mac-mini'
|
||||
},
|
||||
{
|
||||
name: 'Intel Macs',
|
||||
enabled: 'yes',
|
||||
type: 'intel',
|
||||
description: 'Intel Macs are the classic Macs that succeed the PowerPC Macs and preceeded Apple Silicon. ',
|
||||
amazonUrl: 'https://amzn.to/3h3LQwR',
|
||||
bhUrl: '',
|
||||
adoramaUrl: '',
|
||||
slug: 'intel-macs',
|
||||
endpoint: '/device/intel-macs'
|
||||
},
|
||||
{
|
||||
name: 'iPad',
|
||||
enabled: 'no',
|
||||
type: 'ios',
|
||||
description: '',
|
||||
amazonUrl: 'https://amzn.to/3b67Inz',
|
||||
bhUrl: '',
|
||||
adoramaUrl: '',
|
||||
slug: 'ipad',
|
||||
endpoint: '/device/ipad'
|
||||
},
|
||||
{
|
||||
name: 'iPhone',
|
||||
enabled: 'no',
|
||||
type: 'ios',
|
||||
description: '',
|
||||
amazonUrl: 'https://amzn.to/3uovRxs',
|
||||
bhUrl: '',
|
||||
adoramaUrl: '',
|
||||
slug: 'iphone',
|
||||
endpoint: '/device/iphone'
|
||||
},
|
||||
{
|
||||
name: '2021 M1 Macbook Pros',
|
||||
enabled: 'no',
|
||||
type: 'mac-apple-silicon',
|
||||
description: 'M1 Pro Macbook Pro and M1 Max Macbook Pro are the new Apple Silicon notebooks optimized with the Apple M1 processor and the first Apple silicon designed for pros. ',
|
||||
amazonUrl: 'https://amzn.to/3jiwNQh',
|
||||
bhUrl: '',
|
||||
adoramaUrl: '',
|
||||
slug: '2021-m1-macbook-pros',
|
||||
endpoint: '/device/2021-m1-macbook-pros'
|
||||
},
|
||||
{
|
||||
name: 'M1 Macbook Pro',
|
||||
enabled: 'no',
|
||||
type: 'mac-apple-silicon',
|
||||
description: 'M1 Macbook Pro is the portable first generation Apple Silicon Mac for professionals.',
|
||||
amazonUrl: 'https://amzn.to/3h3BkG1',
|
||||
bhUrl: '',
|
||||
adoramaUrl: '',
|
||||
slug: 'm1-macbook-pro',
|
||||
endpoint: '/device/m1-macbook-pro'
|
||||
},
|
||||
{
|
||||
name: 'M1 Macbook Air',
|
||||
enabled: 'no',
|
||||
type: 'mac-apple-silicon',
|
||||
description: 'M1 Macbook Air is the portable first generation Apple Silicon Mac for users needing a lighter computer.',
|
||||
amazonUrl: 'https://amzn.to/3elKVX5',
|
||||
bhUrl: '',
|
||||
adoramaUrl: '',
|
||||
slug: 'm1-macbook-air',
|
||||
endpoint: '/device/m1-macbook-air'
|
||||
},
|
||||
{
|
||||
name: 'M1 iPad Pro',
|
||||
enabled: 'no',
|
||||
type: 'ios',
|
||||
description: 'M1 iPad Pro is the first mobile Apple device featuring the M1 Apple processor. ',
|
||||
amazonUrl: 'https://amzn.to/3nQY3qe',
|
||||
bhUrl: '',
|
||||
adoramaUrl: '',
|
||||
slug: 'm1-ipad-pro',
|
||||
endpoint: '/device/m1-ipad-pro'
|
||||
},
|
||||
{
|
||||
name: 'M1 iMac',
|
||||
enabled: 'no',
|
||||
type: 'mac-apple-silicon',
|
||||
description: 'M1 iMac is the new Apple Silicon desktop optimized with the Apple M1 processor and the first of the second generation of Apple Silicon Macs. ',
|
||||
amazonUrl: 'https://amzn.to/3vMUnbA',
|
||||
bhUrl: '',
|
||||
adoramaUrl: '',
|
||||
slug: 'm1-imac',
|
||||
endpoint: '/device/m1-imac'
|
||||
}
|
||||
]
|
||||
|
||||
export const deviceListingFallbacks = rawDeviceList.filter( device => device.enabled !== 'no' )
|
||||
|
|
@ -1,37 +1,13 @@
|
|||
import youtubeVideosText from '~/static/api/youtube-videos.json?raw'
|
||||
import appListText from '~/static/app-list.json?raw'
|
||||
import deviceListText from '~/static/device-list.json?raw'
|
||||
import gameListText from '~/static/game-list.json?raw'
|
||||
import videoListingsText from '~/static/api/youtube-video-listings.json?raw'
|
||||
|
||||
import {
|
||||
buildVideoListingFromFetchedVideo,
|
||||
makeVideoSlug
|
||||
} from '~/helpers/build-video-list.js'
|
||||
const trailingCommaPattern = /,\s*([\]}])/g
|
||||
const parsedDeviceList = JSON.parse( deviceListText.replace( trailingCommaPattern, '$1' ) )
|
||||
const parsedAppList = JSON.parse( appListText.replace( trailingCommaPattern, '$1' ) )
|
||||
const parsedGameList = JSON.parse( gameListText.replace( trailingCommaPattern, '$1' ) )
|
||||
const parsedYoutubeVideos = JSON.parse( youtubeVideosText )
|
||||
import { deviceListingFallbacks } from './device-list-fallbacks.js'
|
||||
|
||||
const parsedVideoListings = JSON.parse( videoListingsText )
|
||||
|
||||
export function getDeviceListingBySlug ( slug ) {
|
||||
return parsedDeviceList.find( device => device.slug === slug ) || null
|
||||
}
|
||||
|
||||
function getAllVideoAppsList () {
|
||||
return [
|
||||
...parsedAppList,
|
||||
...parsedGameList
|
||||
]
|
||||
return deviceListingFallbacks.find( device => device.slug === slug ) || null
|
||||
}
|
||||
|
||||
export async function getVideoListingBySlug ( slug ) {
|
||||
const allVideoAppsList = getAllVideoAppsList()
|
||||
|
||||
for ( const [ videoId, fetchedVideo ] of Object.entries( parsedYoutubeVideos ) ) {
|
||||
if ( makeVideoSlug( fetchedVideo.title, videoId ) !== slug ) continue
|
||||
|
||||
return await buildVideoListingFromFetchedVideo( fetchedVideo, videoId, allVideoAppsList )
|
||||
}
|
||||
|
||||
return null
|
||||
return parsedVideoListings[slug] || null
|
||||
}
|
||||
|
|
|
|||
52
scripts/update-youtube-video-listing-fallbacks.js
Normal file
52
scripts/update-youtube-video-listing-fallbacks.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import fs from 'fs-extra'
|
||||
|
||||
import {
|
||||
buildVideoListingFromFetchedVideo,
|
||||
makeVideoSlug
|
||||
} from '~/helpers/build-video-list.js'
|
||||
import { saveYouTubeVideos, youtubeVideoPath } from '~/helpers/api/youtube/build.js'
|
||||
|
||||
const outputPath = './static/api/youtube-video-listings.json'
|
||||
const trailingCommaPattern = /,\s*([\]}])/g
|
||||
|
||||
async function readJsonWithTrailingCommaFallback ( path ) {
|
||||
return JSON.parse(
|
||||
( await fs.readFile( path, 'utf8' ) ).replace( trailingCommaPattern, '$1' )
|
||||
)
|
||||
}
|
||||
|
||||
await saveYouTubeVideos()
|
||||
|
||||
const [
|
||||
fetchedVideos,
|
||||
appList,
|
||||
gameList
|
||||
] = await Promise.all([
|
||||
fs.readJson( youtubeVideoPath ),
|
||||
readJsonWithTrailingCommaFallback( './static/app-list.json' ),
|
||||
readJsonWithTrailingCommaFallback( './static/game-list.json' )
|
||||
])
|
||||
|
||||
const allVideoAppsList = [
|
||||
...appList,
|
||||
...gameList
|
||||
]
|
||||
const videoListingsBySlug = {}
|
||||
|
||||
for ( const [ videoId, fetchedVideo ] of Object.entries( fetchedVideos ) ) {
|
||||
const videoListing = await buildVideoListingFromFetchedVideo(
|
||||
fetchedVideo,
|
||||
videoId,
|
||||
allVideoAppsList
|
||||
)
|
||||
|
||||
if ( videoListing === undefined ) continue
|
||||
|
||||
videoListingsBySlug[ makeVideoSlug( fetchedVideo.title, videoId ) ] = videoListing
|
||||
}
|
||||
|
||||
await fs.outputJson( outputPath, videoListingsBySlug )
|
||||
|
||||
console.log(
|
||||
`Wrote ${ Object.keys( videoListingsBySlug ).length } video listing fallbacks to ${ outputPath }`
|
||||
)
|
||||
1
static/api/.gitignore
vendored
1
static/api/.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
|||
*
|
||||
!.gitignore
|
||||
!youtube-video-listings.json
|
||||
|
|
|
|||
1
static/api/youtube-video-listings.json
Normal file
1
static/api/youtube-video-listings.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -7,9 +7,9 @@ import {
|
|||
|
||||
describe( 'site listing fallbacks', () => {
|
||||
it( 'loads known devices from the bundled device list', () => {
|
||||
expect( getDeviceListingBySlug( 'm1-imac' ) ).toMatchObject({
|
||||
name: 'M1 iMac',
|
||||
endpoint: '/device/m1-imac'
|
||||
expect( getDeviceListingBySlug( '2023-m3-imac' ) ).toMatchObject({
|
||||
name: '2023 M3 iMac',
|
||||
endpoint: '/device/2023-m3-imac'
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue