about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThomas Dickerson <elfprince13@gmail.com>2024-06-03 20:29:45 -0400
committerGitHub <noreply@github.com>2024-06-03 17:29:45 -0700
commitbd4703ca1e5e4620f8c700e70477d2e0e6b04d67 (patch)
tree602ff24a4ffacdff3b7ed8d9da3b0ae0115585c6
parent891b432eadb6b4a1907943b1219631e1b84329d2 (diff)
downloadvoidsky-bd4703ca1e5e4620f8c700e70477d2e0e6b04d67.tar.zst
Support for Flickr album and group pool embeds (#3936)
* Support for Flickr album and group pool embeds

* Oops, forgot to add flickr to the persisted externalEmbeds schema

* Need a bigint since our id can have more than 52 bits...

* Remove unexpected trailing / from test data to match the expected behavior

* nits

---------

Co-authored-by: Hailey <me@haileyok.com>
-rw-r--r--__tests__/lib/string.test.ts80
-rw-r--r--src/lib/strings/embed-player.ts76
-rw-r--r--src/state/persisted/schema.ts1
3 files changed, 157 insertions, 0 deletions
diff --git a/__tests__/lib/string.test.ts b/__tests__/lib/string.test.ts
index cf21d8dd2..78478a26d 100644
--- a/__tests__/lib/string.test.ts
+++ b/__tests__/lib/string.test.ts
@@ -480,6 +480,26 @@ describe('parseEmbedPlayerFromUrl', () => {
     'https://media.tenor.com/someID/someName.gif',
     'https://media.tenor.com/someID',
     'https://media.tenor.com',
+
+    'https://www.flickr.com/photos/username/albums/72177720308493661',
+    'https://flickr.com/photos/username/albums/72177720308493661',
+    'https://flickr.com/photos/username/albums/72177720308493661/',
+    'https://flickr.com/photos/username/albums/72177720308493661//',
+    'https://flic.kr/s/aHBqjAES3i',
+
+    'https://flickr.com/foetoes/username/albums/3903',
+    'https://flickr.com/albums/3903',
+    'https://flic.kr/s/OolI',
+    'https://flic.kr/t/aHBqjAES3i',
+
+    'https://www.flickr.com/groups/898944@N23/pool',
+    'https://flickr.com/groups/898944@N23/pool',
+    'https://flickr.com/groups/898944@N23/pool/',
+    'https://flickr.com/groups/898944@N23/pool//',
+    'https://flic.kr/go/8WJtR',
+
+    'https://www.flickr.com/groups/898944@N23/',
+    'https://www.flickr.com/groups',
   ]
 
   const outputs = [
@@ -777,6 +797,66 @@ describe('parseEmbedPlayerFromUrl', () => {
     undefined,
     undefined,
     undefined,
+
+    {
+      type: 'flickr_album',
+      source: 'flickr',
+      playerUri: 'https://embedr.flickr.com/photosets/72177720308493661',
+    },
+    {
+      type: 'flickr_album',
+      source: 'flickr',
+      playerUri: 'https://embedr.flickr.com/photosets/72177720308493661',
+    },
+    {
+      type: 'flickr_album',
+      source: 'flickr',
+      playerUri: 'https://embedr.flickr.com/photosets/72177720308493661',
+    },
+    {
+      type: 'flickr_album',
+      source: 'flickr',
+      playerUri: 'https://embedr.flickr.com/photosets/72177720308493661',
+    },
+    {
+      type: 'flickr_album',
+      source: 'flickr',
+      playerUri: 'https://embedr.flickr.com/photosets/72177720308493661',
+    },
+
+    undefined,
+    undefined,
+    undefined,
+    undefined,
+
+    {
+      type: 'flickr_album',
+      source: 'flickr',
+      playerUri: 'https://embedr.flickr.com/groups/898944@N23',
+    },
+    {
+      type: 'flickr_album',
+      source: 'flickr',
+      playerUri: 'https://embedr.flickr.com/groups/898944@N23',
+    },
+    {
+      type: 'flickr_album',
+      source: 'flickr',
+      playerUri: 'https://embedr.flickr.com/groups/898944@N23',
+    },
+    {
+      type: 'flickr_album',
+      source: 'flickr',
+      playerUri: 'https://embedr.flickr.com/groups/898944@N23',
+    },
+    {
+      type: 'flickr_album',
+      source: 'flickr',
+      playerUri: 'https://embedr.flickr.com/groups/898944@N23',
+    },
+
+    undefined,
+    undefined,
   ]
 
   it('correctly grabs the correct id from uri', () => {
diff --git a/src/lib/strings/embed-player.ts b/src/lib/strings/embed-player.ts
index 54649f143..30ced1492 100644
--- a/src/lib/strings/embed-player.ts
+++ b/src/lib/strings/embed-player.ts
@@ -23,6 +23,7 @@ export const embedPlayerSources = [
   'vimeo',
   'giphy',
   'tenor',
+  'flickr',
 ] as const
 
 export type EmbedPlayerSource = (typeof embedPlayerSources)[number]
@@ -42,6 +43,7 @@ export type EmbedPlayerType =
   | 'vimeo_video'
   | 'giphy_gif'
   | 'tenor_gif'
+  | 'flickr_album'
 
 export const externalEmbedLabels: Record<EmbedPlayerSource, string> = {
   youtube: 'YouTube',
@@ -53,6 +55,7 @@ export const externalEmbedLabels: Record<EmbedPlayerSource, string> = {
   spotify: 'Spotify',
   appleMusic: 'Apple Music',
   soundcloud: 'SoundCloud',
+  flickr: 'Flickr',
 }
 
 export interface EmbedPlayerParams {
@@ -375,6 +378,79 @@ export function parseEmbedPlayerFromUrl(
       }
     }
   }
+
+  // this is a standard flickr path! we can use the embedder for albums and groups, so validate the path
+  if (urlp.hostname === 'www.flickr.com' || urlp.hostname === 'flickr.com') {
+    let i = urlp.pathname.length - 1
+    while (i > 0 && urlp.pathname.charAt(i) === '/') {
+      --i
+    }
+
+    const path_components = urlp.pathname.slice(1, i + 1).split('/')
+    if (path_components.length === 4) {
+      // discard username - it's not relevant
+      const [photos, _, albums, id] = path_components
+      if (photos === 'photos' && albums === 'albums') {
+        // this at least has the shape of a valid photo-album URL!
+        return {
+          type: 'flickr_album',
+          source: 'flickr',
+          playerUri: `https://embedr.flickr.com/photosets/${id}`,
+        }
+      }
+    }
+
+    if (path_components.length === 3) {
+      const [groups, id, pool] = path_components
+      if (groups === 'groups' && pool === 'pool') {
+        return {
+          type: 'flickr_album',
+          source: 'flickr',
+          playerUri: `https://embedr.flickr.com/groups/${id}`,
+        }
+      }
+    }
+    // not an album or a group pool, don't know what to do with this!
+    return undefined
+  }
+
+  // link shortened flickr path
+  if (urlp.hostname === 'flic.kr') {
+    const b58alph = '123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'
+    let [_, type, idBase58Enc] = urlp.pathname.split('/')
+    let id = 0n
+    for (const char of idBase58Enc) {
+      const nextIdx = b58alph.indexOf(char)
+      if (nextIdx >= 0) {
+        id = id * 58n + BigInt(nextIdx)
+      } else {
+        // not b58 encoded, ergo not a valid link to embed
+        return undefined
+      }
+    }
+
+    switch (type) {
+      case 'go':
+        const formattedGroupId = `${id}`
+        return {
+          type: 'flickr_album',
+          source: 'flickr',
+          playerUri: `https://embedr.flickr.com/groups/${formattedGroupId.slice(
+            0,
+            -2,
+          )}@N${formattedGroupId.slice(-2)}`,
+        }
+      case 's':
+        return {
+          type: 'flickr_album',
+          source: 'flickr',
+          playerUri: `https://embedr.flickr.com/photosets/${id}`,
+        }
+      default:
+        // we don't know what this is so we can't embed it
+        return undefined
+    }
+  }
 }
 
 export function getPlayerAspect({
diff --git a/src/state/persisted/schema.ts b/src/state/persisted/schema.ts
index 77a79b78e..1860d34de 100644
--- a/src/state/persisted/schema.ts
+++ b/src/state/persisted/schema.ts
@@ -65,6 +65,7 @@ export const schema = z.object({
       spotify: z.enum(externalEmbedOptions).optional(),
       appleMusic: z.enum(externalEmbedOptions).optional(),
       soundcloud: z.enum(externalEmbedOptions).optional(),
+      flickr: z.enum(externalEmbedOptions).optional(),
     })
     .optional(),
   mutedThreads: z.array(z.string()), // should move to server