Skip to content

Configuration ideas

Kirill Müller edited this page Sep 19, 2024 · 44 revisions

Feel free to add your own ideas for how to use Finicky.

Force https for all urls

rewrite: [{
    match: ({url}) => url.protocol === "http",
    url: {
        protocol: "https"
    }
}]

Matching an array of multiple apps

handlers: [{
    // Open any link clicked in Mail & Outlook in Google Chrome
    match: ({opener}) =>
        ["com.apple.mail", "com.microsoft.Outlook"].includes(opener.bundleId),
    browser: "Google Chrome"
}]

or

handlers: [{
    // Open any link clicked in Mail & Outlook in Google Chrome
    match: ({opener}) =>
        ["Mail", "Microsoft Outlook"].includes(opener.name),
    browser: "Google Chrome"
}]

Open links of example.com including 'Finicky' in the path

handlers: [{
    match: ({url}) =>
        url.host.includes("example.com") && url.pathname.includes("Finicky"),
    browser: "Firefox"
}]

Replace domain of urls to amazon.com with smile.amazon.com

rewrite: [{
    match: "amazon.com/*",
    url: {
        host: "smile.amazon.com"
    }
}]

Remove all marketing/tracking information from urls

rewrite: [{
    match: () => true, // Execute rewrite on all incoming urls to make this example easier to understand
    url: ({url}) => {
        const removeKeysStartingWith = ["utm_", "uta_"]; // Remove all query parameters beginning with these strings
        const removeKeys = ["fbclid", "gclid"]; // Remove all query parameters matching these keys

        const search = url.search
            .split("&")
            .map((parameter) => parameter.split("="))
            .filter(([key]) => !removeKeysStartingWith.some((startingWith) => key.startsWith(startingWith)))
            .filter(([key]) => !removeKeys.some((removeKey) => key === removeKey));

        return {
            ...url,
            search: search.map((parameter) => parameter.join("=")).join("&"),
        };
    },
}]

Redirect google links to duckduckgo.com

rewrite: [{
    match: finicky.matchDomains(["google.com"]),
    url: "https://duckduckgo.com"
}]

Open Trello links in Trello app

handlers: [{
    match: finicky.matchDomains(["trello.com"]),
    url: ({url}) =>
        ({...url, protocol: "trello"}),
    browser: "Trello"
}]

Open Spotify links in Spotify app

handlers: [{
    match: finicky.matchDomains("open.spotify.com"),
    browser: "Spotify"
}]

Open Zoom links in Zoom app with or without password

  handlers: [{
    match: /zoom\.us\/join/,
    browser: "us.zoom.xos"
  }],
  rewrite: [{
    match: ({
      url
    }) => url.host.includes("zoom.us") && url.pathname.includes("/j/"),
    url({
      url
    }) {
      try {
        var pass = '&pwd=' + url.search.match(/pwd=(\w*)/)[1];
      } catch {
        var pass = ""
      }
      var conf = 'confno=' + url.pathname.match(/\/j\/(\d+)/)[1];
      return {
        search: conf + pass,
        pathname: '/join',
        protocol: "zoommtg"
      }
    }
  }]

Open Apple Music links in the Music app

handlers: [{
    // Open Apple Music links directly in Music.app
    match: [
        "music.apple.com*",
        "geo.music.apple.com*",
    ],
    url: {
        protocol: "itmss"
    },
    browser: "Music",
}]

Open Microsoft Teams links in the native app

handlers: [{
    match: finicky.matchHostnames(['teams.microsoft.com']),
    browser: 'com.microsoft.teams',
    url: ({url}) =>
        ({...url, protocol: 'msteams'}),
}]

Open Figma links in Figma app

handlers: [{
    match: "https://www.figma.com/file/*",
    browser: "Figma",
}]

Skip vk.com link tracking (vk.com/away.php)

rewrite: [{
    match: /vk\.com\/away.php/,
    url: ({url}) => {
        const match = url.search.match(/to=(.+)/)
        return !match ? url : decodeURIComponent(decodeURIComponent(match[1]));
    }
}]

Match multiple conditions

For example, you may want to only open matching URLs in a specific browser when opening those URLs from within a particular application. In that case, you need to match on both the opener and the url:

handlers: [{
    // Open Google Drive in Firefox if opened from Slack
    match: ({opener, url}) =>
        opener.bundleId === "com.tinyspeck.slackmacgap" && url.host.includes("drive.google.com"),
    browser: "Firefox"
}]

Open Jitsi links in Jitsi desktop app for MacOS

handlers: [{
    match: ({url}) => url.host.includes("jitsi.your-selfhosted-server.com") ||
        url.host.includes("meet.jit.si"),
    url: ({url}) => {
        return {
            ...url,
            protocol: "jitsi-meet",
            host: url.host,
            pathname: url.pathname
        };
    },
    browser: "/Applications/Jitsi\ Meet.app"
}]

Open links clicked in Telegram in specific Profile in Edge

Save following AppleScript as Application with name edge-profile-1

on open location input
	do shell script "/Applications/Microsoft\\ Edge.app/Contents/MacOS/Microsoft\\ Edge --profile-directory=\"Profile 1\" '" & input & "'"
end open location

Than use it as browser

{
    match: ({opener}) => ["Telegram"].includes(opener.name),
    browser: 'com.apple.ScriptEditor.id.edge-profile-1'
}

Open installed desktop applications instead of web apps

This example assumes you have installed Figma, Linear, and Slite desktop apps. But you can make it work with any other app.

Requirements

  • install the targeted apps you want to support,
  • check their URL schemes with:
defaults read /Applications/THE_APP.app/Contents/Info.plist CFBundleURLTypes

finicky Configuration

handlers: [{
  match: ({url}) => !url.protocol.match(/^https?$/),
  browser: "Finder"
}],

rewrite: [{
  match: ({url}) => url.host.split('.').some((c) => ['figma', 'linear', 'slite'].includes(c)),
  url: ({url}) => {
    const protocol = url.host.match(/\.?(\w+)\.\w\w\w?$/)[1];
    const exceptions = { 'linear': ['uploads.linear.app'] };
    if (!(protocol in exceptions) || !exceptions[protocol].includes(url.host)) {
      return {...url, protocol };
    }
    return url;
  }
}]

Open Discord links in Discord app

handlers: [{
  match: "https://discord.com/*",
  url: { protocol: "discord" },
  browser: "Discord",
}]

Jump to #report on Spamcop pages

rewrite: [{
  match: finicky.matchHostnames("www.spamcop.net"),
  url: { hash: "report" }
}]

Rewrite TikTok videos to random Proxitok proxies to avoid creating TikTok user

rewrite: [{
  // Redirect Tiktok video links to use Proxitok public proxies
  match: ({ url }) => (url.host.endsWith("tiktok.com") && url.pathname.startsWith('/@')) || url.host.endsWith("vm.tiktok.com"),
  url: ({ url }) => {
    // See more https://github.com/pablouser1/ProxiTok/wiki/Public-instances
    const selectRandomTikTokProxy = () => {
      const TIKTOK_PROXIES = [
        "proxitok.pabloferreiro.es", // Official
        "proxitok.pussthecat.org",
        "tok.habedieeh.re",
        "proxitok.esmailelbob.xyz",
        "proxitok.privacydev.net",
        "tok.artemislena.eu",
        "tok.adminforge.de",
        "tt.vern.cc",
        "cringe.whatever.social",
        "proxitok.lunar.icu",
        "proxitok.privacy.com.de",
        "cringe.seitan-ayoub.lol",
        "cringe.datura.network",
        "tt.opnxng.com",
        "tiktok.wpme.pl",
        "proxitok.r4fo.com",
        "proxitok.belloworld.it",
      ]
      return TIKTOK_PROXIES[Math.floor(Math.random() * TIKTOK_PROXIES.length)]
    }
    return {
      protocol: "https",
      host: selectRandomTikTokProxy(),
      // Prepend pathname with /@placeholder/video to match ProkiTok urls
      pathname: (url.pathname.startsWith('/@') ? url.pathname : `/@placeholder/video${url.pathname}`)
    }
  }
]}