├── .eslintrc.json ├── .github ├── ISSUE_TEMPLATE │ ├── broken-bypass.yml.old │ ├── bug-report.yml.old │ ├── config.yml │ └── new-bypass.yml.old ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── PR_bot.yml │ ├── Release.yml │ ├── WebStoreDeploy.yml │ ├── codeql-analysis.yml │ ├── issues.yml │ ├── main.yml │ └── pull.yml ├── .gitignore ├── .ip_logger_patterns.php ├── .prettierrc ├── .update_locales.php ├── CONTRIBUTING.md ├── CONTRIBUTORS.md ├── LICENSE ├── PRIVACY.md ├── README.md ├── crowdin.yml ├── docs ├── Bypassed.md ├── CODE_STYLE.md ├── CONTRIBUTING.md ├── CONTRIBUTORS.md ├── Git_CLI.md ├── INSTALLING.md └── PRIVACY.md ├── package-lock.json ├── package.json ├── platform_spec ├── chromium │ └── manifest.json └── firefox │ └── manifest.json ├── scripts ├── build.js └── build_js │ ├── injection_script_template.js │ └── utils.js ├── src ├── _locales │ ├── af │ │ └── messages.json │ ├── am │ │ └── messages.json │ ├── an │ │ └── messages.json │ ├── ar │ │ └── messages.json │ ├── ast │ │ └── messages.json │ ├── az │ │ └── messages.json │ ├── bg │ │ └── messages.json │ ├── bn-IN │ │ └── messages.json │ ├── bn │ │ └── messages.json │ ├── br │ │ └── messages.json │ ├── bs │ │ └── messages.json │ ├── ca │ │ └── messages.json │ ├── ckb │ │ └── messages.json │ ├── cs │ │ └── messages.json │ ├── cy │ │ └── messages.json │ ├── da │ │ └── messages.json │ ├── de-AT │ │ └── messages.json │ ├── de-CH │ │ └── messages.json │ ├── de-LI │ │ └── messages.json │ ├── de │ │ └── messages.json │ ├── el │ │ └── messages.json │ ├── en │ │ └── messages.json │ ├── eo │ │ └── messages.json │ ├── es │ │ └── messages.json │ ├── et │ │ └── messages.json │ ├── fa │ │ └── messages.json │ ├── fi │ │ └── messages.json │ ├── fil │ │ └── messages.json │ ├── fr │ │ └── messages.json │ ├── ga-IE │ │ └── messages.json │ ├── gd │ │ └── messages.json │ ├── gl │ │ └── messages.json │ ├── gu-IN │ │ └── messages.json │ ├── he │ │ └── messages.json │ ├── hi │ │ └── messages.json │ ├── hmn │ │ └── messages.json │ ├── hr │ │ └── messages.json │ ├── hu │ │ └── messages.json │ ├── hy-AM │ │ └── messages.json │ ├── id │ │ └── messages.json │ ├── it │ │ └── messages.json │ ├── ja │ │ └── messages.json │ ├── jv │ │ └── messages.json │ ├── ka │ │ └── messages.json │ ├── kn │ │ └── messages.json │ ├── ko │ │ └── messages.json │ ├── lo │ │ └── messages.json │ ├── lt │ │ └── messages.json │ ├── lv │ │ └── messages.json │ ├── mi │ │ └── messages.json │ ├── mk │ │ └── messages.json │ ├── ml-IN │ │ └── messages.json │ ├── ms │ │ └── messages.json │ ├── my │ │ └── messages.json │ ├── nl │ │ └── messages.json │ ├── no │ │ └── messages.json │ ├── pl │ │ └── messages.json │ ├── pt-BR │ │ └── messages.json │ ├── pt-PT │ │ └── messages.json │ ├── ro │ │ └── messages.json │ ├── ru │ │ └── messages.json │ ├── sh │ │ └── messages.json │ ├── si-LK │ │ └── messages.json │ ├── sk │ │ └── messages.json │ ├── sl │ │ └── messages.json │ ├── sq │ │ └── messages.json │ ├── sr │ │ └── messages.json │ ├── su │ │ └── messages.json │ ├── sv-SE │ │ └── messages.json │ ├── ta │ │ └── messages.json │ ├── te │ │ └── messages.json │ ├── th │ │ └── messages.json │ ├── tr │ │ └── messages.json │ ├── uk │ │ └── messages.json │ ├── uz │ │ └── messages.json │ ├── vi │ │ └── messages.json │ ├── yi │ │ └── messages.json │ ├── zh-CN │ │ └── messages.json │ ├── zh-TW │ │ └── messages.json │ └── zu │ │ └── messages.json ├── bypasses │ ├── 1link.js │ ├── 1shortlink.js │ ├── BypassDefinition.js │ ├── acortalink.js │ ├── admaven.js │ ├── adtival.js │ ├── akoam.js │ ├── akwam.js │ ├── an1.js │ ├── androidtop.js │ ├── anonym.js │ ├── apkhubs.js │ ├── blitly.js │ ├── blogtech.js │ ├── bluemediafile.js │ ├── boost.js │ ├── brpaper.js │ ├── bstlar.js │ ├── cbrun.js │ ├── cheatsquad.js │ ├── clictune.js │ ├── complete2unlock.js │ ├── cpmlink.js │ ├── crackedappsstore.js │ ├── curseforge.js │ ├── daominhha.js │ ├── earnme.js │ ├── enlacito.js │ ├── favpng.js │ ├── fclc.js │ ├── filedm.js │ ├── filefactory.js │ ├── filehorse.js │ ├── filepuma.js │ ├── firefaucet.js │ ├── fiveplay.js │ ├── forex1pro.js │ ├── fourshared.js │ ├── fssquad.js │ ├── gamesmega.js │ ├── get2clickblogspot.js │ ├── getwallpapers.js │ ├── gixen.js │ ├── idnation.js │ ├── indishare.js │ ├── leitup.js │ ├── letsboost.js │ ├── liblink.js │ ├── linegee.js │ ├── linksht.js │ ├── linkspy.js │ ├── linkvertise.js │ ├── lkc21.js │ ├── lnk.js │ ├── lnk2.js │ ├── lnk2cc.js │ ├── longfiles.js │ ├── lootlink.js │ ├── mangalist.js │ ├── manualsbooks.js │ ├── mobi2c.js │ ├── mydramalist.js │ ├── oko.js │ ├── onelink.js │ ├── onepieceex.js │ ├── onlinefix.js │ ├── oracle.js │ ├── ouo.js │ ├── oxy.js │ ├── pcgamestorrents.js │ ├── pirateproxy.js │ ├── portableapps.js │ ├── ps4linux.js │ ├── rekonise.js │ ├── ryn.js │ ├── sfile.js │ ├── shortenbuddy.js │ ├── shortly.js │ ├── shortmoz.js │ ├── softpedia.js │ ├── sourceforge.js │ ├── spaste.js │ ├── squidssh.js │ ├── srtam.js │ ├── sub2unlock.js │ ├── sub4unlock.js │ ├── syosetu.js │ ├── tii.js │ ├── tiklat.js │ ├── tlgd.js │ ├── uiz.js │ ├── uploadking.js │ ├── uploadrar.js │ ├── ux9.js │ ├── vk.js │ ├── wadooo.js │ ├── workclick.js │ ├── workink.js │ └── ytsubme.js ├── helpers │ ├── dom.js │ └── infobox.js ├── html │ ├── base.js │ ├── before-navigate.html │ ├── before-navigate.js │ ├── blocked.html │ ├── consent.html │ ├── consent.js │ ├── crowd-bypassed.html │ ├── crowd-bypassed.js │ ├── i18n.js │ ├── noscript.html │ ├── options.html │ ├── options.js │ ├── popup.html │ ├── popup.js │ ├── style.css │ ├── tracker-bypass.html │ └── tracker-bypass.js ├── icon │ ├── 128.png │ ├── 150.png │ ├── 176.png │ ├── 48.png │ ├── 512.png │ └── branding.png ├── icon_disabled │ ├── 128.png │ ├── 150.png │ ├── 176.png │ ├── 48.png │ └── 512.png ├── js │ ├── background.js │ ├── constants.js │ ├── content_script.js │ ├── injection_script-original.js │ └── rules.json └── version.txt └── tests ├── bypasses.json ├── index.js └── package.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "es2021": true 5 | }, 6 | "extends": ["eslint:recommended", "prettier"], 7 | "overrides": [ 8 | ], 9 | "parserOptions": { 10 | "ecmaVersion": "latest", 11 | "sourceType": "module" 12 | }, 13 | "rules": { 14 | }, 15 | "globals": { 16 | "browser" :"readonly", 17 | "chrome" :"readonly" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/broken-bypass.yml.old: -------------------------------------------------------------------------------- 1 | name: Broken Bypass 2 | description: A bypass is misbehaving or no-longer working 3 | labels: [Broken-bypass] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | ## Note 9 | Issues are not a place to go ask support questions. 10 | Please ask support questions on the [Discord](https://discord.gg/RSAf7b5njt). 11 | 12 | ### **Please don't submit multiple issue about the same website. [Search](https://github.com/FastForwardTeam/FastForward/labels/Broken-bypass) if the domain has been reported before filing the issue.** 13 | Thanks for taking the time to fill out this form! 14 | 15 | ### MV3 has less bypasses than MV2 version, we are working to migrate all bypasses. 16 | - type: input 17 | id: domain 18 | attributes: 19 | label: Link 20 | description: Submit the link you are trying to bypass. 21 | placeholder: 'Just the name of the site. example: gotiny.cc/p4bwaa' 22 | validations: 23 | required: true 24 | ### Removed: duplicate field 25 | #- type: input 26 | #id: site 27 | # attributes: 28 | #label: Link 29 | #description: Submit the exact link you are on. 30 | #placeholder: 'Example: https://www.google.com/webhp' 31 | #validations: 32 | #required: true 33 | ### Removed: duplicate field 34 | - type: dropdown 35 | id: version 36 | attributes: 37 | label: Version 38 | description: What version of the extension are you running? 39 | options: 40 | - Manifest-v2 41 | - Manifest-v3 42 | validations: 43 | required: true 44 | - type: dropdown 45 | id: browsers 46 | attributes: 47 | label: What browser(s) are you seeing the problem on? 48 | multiple: true 49 | options: 50 | - Firefox browsers 51 | - Chrome browsers (includes brave, edge, opera, etc) 52 | validations: 53 | required: true 54 | - type: dropdown 55 | id: os 56 | attributes: 57 | label: What platform are you seeing the problem on? 58 | options: 59 | - Computer (Windows, Linux, MacOS) 60 | - Phone (Android) 61 | validations: 62 | required: true 63 | - type: textarea 64 | attributes: 65 | label: Anything else? 66 | description: | 67 | Images? Videos? Anything that will give us more context about the issue you are encountering! 68 | The more information you give us, the fast we will solve the issue 69 | 70 | Tip: You can attach images files by clicking this area to highlight it and then dragging files in. 71 | validations: 72 | required: false 73 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.yml.old: -------------------------------------------------------------------------------- 1 | name: Bug report 2 | title: "[Bug] " 3 | description: Something is not working in the extension 4 | labels: [Bug] 5 | body: 6 | - type: markdown 7 | attributes: 8 | value: | 9 | ## Note 10 | Issues are not a place to go ask support questions. 11 | Please ask support questions on the [Discord](https://discord.gg/RSAf7b5njt). 12 | 13 | ### **This form is not for reporting sites that are not bypassed** 14 | Thanks for taking the time to fill out this form! 15 | - type: textarea 16 | id: body 17 | attributes: 18 | label: Body 19 | description: Description of the issue you are facing 20 | validations: 21 | required: true 22 | - type: dropdown 23 | id: version 24 | attributes: 25 | label: Version 26 | description: What version of the extension are you running? 27 | options: 28 | - Manifest-v2 29 | - Manifest-v3 30 | validations: 31 | required: true 32 | - type: dropdown 33 | id: browsers 34 | attributes: 35 | label: What browser(s) are you seeing the problem on? 36 | multiple: true 37 | options: 38 | - Firefox browsers 39 | - Chrome browsers (includes brave, edge, opera, etc) 40 | validations: 41 | required: true 42 | - type: dropdown 43 | id: os 44 | attributes: 45 | label: What platform are you seeing the problem on? 46 | options: 47 | - Computer (Windows, Linux, MacOS) 48 | - Phone (Android) 49 | validations: 50 | required: true 51 | - type: textarea 52 | attributes: 53 | label: Anything else? 54 | description: | 55 | Images? Videos? Anything that will give us more context about the issue you are encountering! 56 | 57 | Tip: You can attach images files by clicking this area to highlight it and then dragging files in. 58 | validations: 59 | required: false 60 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Discord 4 | url: https://discord.gg/RSAf7b5njt 5 | about: We arent maintaining the extension anymore, but you can still join our Discord to chat with us. 6 | #- name: Issues 7 | #url: https://github.com/FastForwardTeam/FastForward/issues?q=label%3ANew-bypass 8 | #about: Please search before issues to check if a site is already submitted. 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/new-bypass.yml.old: -------------------------------------------------------------------------------- 1 | name: New Bypass 2 | description: "A website isn't bypassed" 3 | labels: [New-bypass] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | ## Note 9 | Issues are not a place to go ask support questions. 10 | Please ask support questions on the [Discord](https://discord.gg/RSAf7b5njt). 11 | 12 | ### **Please don't submit multiple issues about the same website. [Search](https://github.com/FastForwardTeam/FastForward/labels/New-bypass) if the domain has been reported before filing the issue.** 13 | Thanks for taking the time to fill out this form! 14 | ### Disabled: duplicated field 15 | #- type: input 16 | #id: domain 17 | #attributes: 18 | #label: Domain 19 | #description: Submit one website only. 20 | #placeholder: 'Just the name of the site. example: https://google.com' 21 | #validations: 22 | #required: true 23 | ### Disabled: duplicated field 24 | - type: input 25 | id: site 26 | attributes: 27 | label: Link 28 | description: Submit the exact link you are on. Please mark as NSFW if the site contains material suitable for ages 18+ only. 29 | placeholder: 'Example: https://www.google.com/webhp' 30 | validations: 31 | required: true 32 | - type: dropdown 33 | id: version 34 | attributes: 35 | label: Version 36 | description: What version of the extension are you running? 37 | options: 38 | - Manifest-v2 39 | - Manifest-v3 40 | validations: 41 | required: true 42 | - type: dropdown 43 | id: browsers 44 | attributes: 45 | label: What browser(s) are you using? 46 | multiple: true 47 | options: 48 | - Firefox browsers 49 | - Chrome browsers (includes brave, edge, opera, etc) 50 | validations: 51 | required: true 52 | - type: dropdown 53 | id: os 54 | attributes: 55 | label: What platform are you using? 56 | options: 57 | - Computer (Windows, Linux, MacOS) 58 | - Phone (Android) 59 | validations: 60 | required: true 61 | - type: textarea 62 | attributes: 63 | label: (Optional) Anything else? 64 | description: | 65 | Images? Videos? Anything that will give us more context about the issue you are encountering! 66 | 67 | Tip: You can attach images files by clicking this area to highlight it and then dragging files in. 68 | validations: 69 | required: false 70 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "github-actions" 4 | on: 5 | push: 6 | pull_request: 7 | types: [opened] 8 | directory: ".github/workflows" 9 | schedule: 10 | interval: "weekly" 11 | - package-ecosystem: "npm" 12 | on: 13 | push: 14 | pull_request: 15 | types: [opened] 16 | directory: "/" 17 | schedule: 18 | interval: "weekly" 19 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | Fix(es): 2 | 3 | 4 | 5 | - [ ] I made sure there are no unnecessary changes in the code; 6 | - [ ] Tested on Chromium (Includes Opera, Brave, Vivaldi, Edge, etc); 7 | - [ ] Tested on Firefox. 8 | -------------------------------------------------------------------------------- /.github/workflows/PR_bot.yml: -------------------------------------------------------------------------------- 1 | name: Comment on pull request 2 | on: 3 | workflow_run: 4 | workflows: ['Pull_req'] 5 | types: [completed] 6 | jobs: 7 | pr_comment: 8 | if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/github-script@v3 12 | with: 13 | # This snippet is public-domain, taken from 14 | # https://github.com/oprypin/nightly.link/blob/master/.github/workflows/pr-comment.yml 15 | script: | 16 | const {owner, repo} = context.repo; 17 | const run_id = ${{github.event.workflow_run.id}}; 18 | const pull_head_sha = '${{github.event.workflow_run.head_sha}}'; 19 | const pull_user_id = ${{github.event.sender.id}}; 20 | const issue_number = await (async () => { 21 | const pulls = await github.pulls.list({owner, repo}); 22 | for await (const {data} of github.paginate.iterator(pulls)) { 23 | for (const pull of data) { 24 | if (pull.head.sha === pull_head_sha && pull.user.id === pull_user_id) { 25 | return pull.number; 26 | } 27 | } 28 | } 29 | })(); 30 | if (issue_number) { 31 | core.info(`Using pull request ${issue_number}`); 32 | } else { 33 | return core.error(`No matching pull request found`); 34 | } 35 | const {data: {artifacts}} = await github.actions.listWorkflowRunArtifacts({owner, repo, run_id}); 36 | if (!artifacts.length) { 37 | return core.error(`No artifacts found`); 38 | } 39 | let body = `Download the artifacts for this pull request:\n`; 40 | for (const art of artifacts) { 41 | body += `\n* [${art.name}.zip](https://nightly.link/${owner}/${repo}/actions/artifacts/${art.id}.zip)`; 42 | } 43 | const {data: comments} = await github.issues.listComments({repo, owner, issue_number}); 44 | const existing_comment = comments.find((c) => c.user.login === 'github-actions[bot]'); 45 | if (existing_comment) { 46 | core.info(`Updating comment ${existing_comment.id}`); 47 | await github.issues.updateComment({repo, owner, comment_id: existing_comment.id, body}); 48 | } else { 49 | core.info(`Creating a comment`); 50 | await github.issues.createComment({repo, owner, issue_number, body}); 51 | } 52 | -------------------------------------------------------------------------------- /.github/workflows/Release.yml: -------------------------------------------------------------------------------- 1 | name: Tag and Release 2 | on: 3 | workflow_dispatch: 4 | inputs: 5 | version: 6 | description: 'Version' 7 | required: true 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout repository 14 | uses: actions/checkout@v3 15 | 16 | - name: Setup Node.js 17 | uses: actions/setup-node@v3 18 | with: 19 | node-version: 'lts/*' 20 | 21 | - name: Install dependencies 22 | run: npm ci 23 | 24 | - name: Update version 25 | run: echo '${{ github.event.inputs.version }}' > src/version.txt 26 | 27 | - name: Build extension 28 | run: node ./scripts/build.js all ver 29 | 30 | - name: Sign for Firefox 31 | run: npx web-ext sign --source-dir /builds/FastForward.firefox --api-key ${{ secrets.FIREFOX_API_KEY }} --api-secret ${{ secrets.FIREFOX_API_SECRET }} 32 | 33 | - name: Tag 34 | env: 35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 36 | run: | 37 | git config --global user.email "git@fastforward.team" 38 | git config --global user.name "FastForward Team" 39 | git tag -a ${{ github.event.inputs.version }} -m "Version ${{ github.event.inputs.version }}" 40 | git push origin ${{ github.event.inputs.version }} 41 | 42 | - name: Release 43 | uses: softprops/action-gh-release@v1 44 | with: 45 | files: | 46 | web-ext-artifacts/*.xpi 47 | build/dist/FastForward_chromium* 48 | -------------------------------------------------------------------------------- /.github/workflows/WebStoreDeploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy to all web stores 2 | 3 | on: workflow_dispatch 4 | 5 | jobs: 6 | Build_and_upload: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | with: 11 | fetch-depth: 0 12 | ref: manifest-v3 13 | - name: Make package 14 | run: | 15 | npm install 16 | node ./scripts/build.js 17 | - name: Read commit number 18 | id: read_commit_number 19 | run: | 20 | VERSION=$(jq -r '.version' manifest.json) 21 | COMMIT_NUMBER=$(echo $VERSION | cut -d '.' -f 2) 22 | echo "::set-output name=commit_number::$COMMIT_NUMBER" 23 | - name: Browser Platform Publisher 24 | uses: PlasmoHQ/bpp@v3.2.1 25 | with: 26 | keys: ${{ secrets.BPP_KEYS }} 27 | chrome-file: ./build/dist/FastForward_chromium_${{ steps.read_commit_number.outputs.commit_number }}.zip 28 | edge-file: ./build/dist/FastForward_chromium_${{ steps.read_commit_number.outputs.commit_number }}.zip 29 | firefox-file: ./build/dist/FastForward_firefox_${{ steps.read_commit_number.outputs.commit_number }}.xpi 30 | version-file: ./build/dist/FastForward.firefox/manifest.json 31 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | # For most projects, this workflow file will not need changing; you simply need 2 | # to commit it to your repository. 3 | # 4 | # You may wish to alter this file to override the set of languages analyzed, 5 | # or to provide custom queries or build logic. 6 | # 7 | # ******** NOTE ******** 8 | # We have attempted to detect the languages in your repository. Please check 9 | # the `language` matrix defined below to confirm you have the correct set of 10 | # supported CodeQL languages. 11 | # 12 | name: "CodeQL" 13 | 14 | on: 15 | push: 16 | branches: [ main , manifest-v3 ] 17 | pull_request: 18 | # The branches below must be a subset of the branches above 19 | branches: [ main , manifest-v3 ] 20 | schedule: 21 | - cron: '39 5 * * 5' 22 | 23 | jobs: 24 | analyze: 25 | name: Analyze 26 | runs-on: ubuntu-latest 27 | permissions: 28 | actions: read 29 | contents: read 30 | security-events: write 31 | 32 | strategy: 33 | fail-fast: false 34 | matrix: 35 | language: [ 'javascript' ] 36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] 37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support 38 | 39 | steps: 40 | - name: Checkout repository 41 | uses: actions/checkout@v3 42 | 43 | # Initializes the CodeQL tools for scanning. 44 | - name: Initialize CodeQL 45 | uses: github/codeql-action/init@v2 46 | with: 47 | languages: ${{ matrix.language }} 48 | # If you wish to specify custom queries, you can do so here or in a config file. 49 | # By default, queries listed here will override any specified in a config file. 50 | # Prefix the list here with "+" to use these queries and those in the config file. 51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main 52 | 53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). 54 | # If this step fails, then you should remove it and run the build manually (see below) 55 | - name: Autobuild 56 | uses: github/codeql-action/autobuild@v2 57 | 58 | # ℹ️ Command-line programs to run using the OS shell. 59 | # 📚 https://git.io/JvXDl 60 | 61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines 62 | # and modify them (or add more) to build your code if your project 63 | # uses a compiled language 64 | 65 | #- run: | 66 | # make bootstrap 67 | # make release 68 | 69 | - name: Perform CodeQL Analysis 70 | uses: github/codeql-action/analyze@v2 71 | -------------------------------------------------------------------------------- /.github/workflows/issues.yml: -------------------------------------------------------------------------------- 1 | name: Close inactive issues 2 | on: 3 | schedule: 4 | - cron: "0 0 1 * *" 5 | workflow_dispatch: 6 | 7 | jobs: 8 | close-issues: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | issues: write 12 | pull-requests: write 13 | steps: 14 | - uses: actions/stale@v5 15 | with: 16 | days-before-issue-stale: 1 17 | days-before-issue-close: 2 18 | operations-per-run: 900 19 | stale-issue-label: "stale" 20 | exempt-issue-labels: "no stale" 21 | stale-issue-message: "This issue will be closed soon, please see https://github.com/FastForwardTeam/FastForward/issues/1504" 22 | close-issue-message: "FastForward is no longer being actively maintained, see https://github.com/FastForwardTeam/FastForward/issues/1504 for more information." 23 | days-before-pr-stale: 30 24 | days-before-pr-close: 60 25 | repo-token: ${{ secrets.GITHUB_TOKEN }} 26 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Package 2 | 3 | on: 4 | push: 5 | branches: [main, manifest-v3] 6 | 7 | workflow_dispatch: 8 | 9 | jobs: 10 | Chromium: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | with: 16 | # pulls all commits (needed for commits to version) 17 | fetch-depth: 0 18 | 19 | - uses: actions/setup-node@v3 20 | with: 21 | node-version: 'lts/*' 22 | cache: 'npm' 23 | 24 | - name: Install dependencies 25 | run: npm ci 26 | 27 | - name: Make package 28 | run: node ./scripts/build.js chromium nover 29 | 30 | - name: Upload Package Artifact 31 | uses: actions/upload-artifact@v3 32 | with: 33 | name: FastForward_chromium 34 | path: build/dist 35 | if-no-files-found: error 36 | 37 | Firefox: 38 | runs-on: ubuntu-latest 39 | 40 | steps: 41 | - uses: actions/checkout@v3 42 | with: 43 | fetch-depth: 0 44 | 45 | - uses: actions/setup-node@v3 46 | with: 47 | node-version: 'lts/*' 48 | cache: 'npm' 49 | 50 | - name: Install dependencies 51 | run: npm ci 52 | 53 | - name: Make package 54 | run: node ./scripts/build.js firefox nover 55 | 56 | - name: Upload Package Artifact 57 | uses: actions/upload-artifact@v3 58 | with: 59 | name: FastForward_firefox 60 | path: build/dist 61 | if-no-files-found: error 62 | -------------------------------------------------------------------------------- /.github/workflows/pull.yml: -------------------------------------------------------------------------------- 1 | name: Pull_req 2 | 3 | on: pull_request 4 | 5 | jobs: 6 | Chromium: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v3 11 | with: 12 | # pulls all commits (needed for commits to version) 13 | fetch-depth: 0 14 | 15 | - uses: actions/setup-node@v3 16 | with: 17 | node-version: 'lts/*' 18 | cache: 'npm' 19 | 20 | - name: Install dependencies 21 | run: npm ci 22 | 23 | - name: Make package 24 | run: node ./scripts/build.js chromium nover 25 | 26 | - name: Upload Package Artifact 27 | uses: actions/upload-artifact@v3 28 | with: 29 | name: FastForward_chromium 30 | path: build/dist 31 | if-no-files-found: error 32 | 33 | Firefox: 34 | runs-on: ubuntu-latest 35 | 36 | steps: 37 | - uses: actions/checkout@v3 38 | with: 39 | fetch-depth: 0 40 | 41 | - uses: actions/setup-node@v3 42 | with: 43 | node-version: 'lts/*' 44 | cache: 'npm' 45 | 46 | - name: Install dependencies 47 | run: npm ci 48 | 49 | - name: Make package 50 | run: node ./scripts/build.js firefox nover 51 | 52 | - name: Upload Package Artifact 53 | uses: actions/upload-artifact@v3 54 | with: 55 | name: FastForward_firefox 56 | path: build/dist 57 | if-no-files-found: error 58 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .next_build_id.txt 2 | build/ 3 | node_modules 4 | injection_script.js 5 | .DS_Store -------------------------------------------------------------------------------- /.ip_logger_patterns.php: -------------------------------------------------------------------------------- 1 | open("FastForward (translations).zip") or die("Failed to open FastForward (translations).zip\n"); 27 | rename("_locales/en/messages.json", "messages.json"); 28 | recursivelyDelete("_locales"); 29 | $zip->extractTo("_locales"); 30 | foreach(scandir("_locales") as $locale) 31 | { 32 | if(in_array($locale, [".", ".."])) 33 | { 34 | continue; 35 | } 36 | unlink("_locales/{$locale}/marketing.json"); 37 | $cont = file_get_contents("_locales/{$locale}/messages.json"); 38 | if(rtrim($cont) == "{}") 39 | { 40 | recursivelyDelete("_locales/{$locale}"); 41 | continue; 42 | } 43 | $json = json_decode($cont, true); 44 | foreach($json as $key => $data) 45 | { 46 | if(in_array($key, ["bypassCounter", "optionsNavigationDelay", "optionsCrowdAutoOpen", "optionsCrowdAutoClose", "beforeNavigateDestination", "beforeNavigateTimer", "beforeNavigateUnsafeTimer", "beforeNavigateInstant", "crowdBypassedInfo", "crowdBypassedTimer", "crowdCloseTimer"])) 47 | { 48 | if(strpos($data["message"], "$1") === false) 49 | { 50 | echo "$key in $locale is missing $1\n"; 51 | } 52 | } 53 | else 54 | { 55 | if(strpos($data["message"], "$1") !== false) 56 | { 57 | echo "$key in $locale has a superfluous $1\n"; 58 | } 59 | } 60 | if(in_array($key, ["infoLinkvertise","infoFileHoster","infoOutdated","crowdWait","crowdDisabled"])) 61 | { 62 | if(strpos($data["message"], "\n") !== false) 63 | { 64 | echo "$key in $locale has a new line character\n"; 65 | } 66 | } 67 | } 68 | if(in_array($locale, ["es-ES", "br-FR"])) 69 | { 70 | rename("_locales/{$locale}", "_locales/".substr($locale, 0, 2)); 71 | } 72 | } 73 | $zip->close(); 74 | unlink("FastForward (translations).zip"); 75 | mkdir("_locales/en"); 76 | rename("messages.json", "_locales/en/messages.json"); 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

FastForward

4 |

Don't waste your time with compliance. FastForward automatically skips annoying link shorteners.

5 | 6 | 7 | 8 | [](https://github.com/FastForwardTeam/FastForward/blob/main/.github/workflows/main.yml) 9 | Discord 10 |

11 | Get FastForward on Chromium based browsers 12 | Get FastForward on Microsoft Edge 13 | Get FastForward for Firefox 14 |
15 | 16 | # Contributing to FastForward 17 | Thanks for taking the time to contribute to FastForward, it is volunteers like you who make this project possible. 18 | 19 | ## Contributing bypasses 20 | 21 | ### Making the bypass 22 | Initially, you may use the custom bypasses section on the extension's settings page to test out and formulate your bypass, but after that we recommend using a code editor like [VSCode](https://code.visualstudio.com/download)/[Codium](https://vscodium.com/#install). 23 | 24 | ### Submitting a Pull Request 25 | 26 | When submitting a pull please take care that: 27 | - Your code follows [the code style](docs/CODE_STYLE.md#code-style) 28 | - Commit messages should be descriptive 29 | - If it's a small change [squash all your commits](docs/Git_CLI.md#squashing-commits) 30 | - Follow the pull request template 31 | 32 | Consider joining the [Discord](https://discord.gg/RSAf7b5njt) so that we can discuss the PR in real time. 33 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

FastForward

4 |

Don't waste your time with compliance. FastForward automatically skips annoying link shorteners.

5 | 6 | 7 | 8 | [](https://github.com/FastForwardTeam/FastForward/blob/main/.github/workflows/main.yml) 9 | Discord 10 |

11 | Get FastForward on Chromium based browsers 12 | Get FastForward on Microsoft Edge 13 | Get FastForward for Firefox 14 |
15 | 16 | # FastForward Contributors 17 | 18 | Thanks to everyone who helps make FastForward: 19 | 20 | - The [code contributors](https://github.com/FastForwardTeam/FastForward/graphs/contributors) right here at Github 21 | - The [website devs](https://github.com/FastForwardTeam/Website/graphs/contributors) 22 | - The translators over at [Crowdin](https://crowdin.com/project/fastforward) 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /PRIVACY.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

FastForward

4 |

Don't waste your time with compliance. FastForward automatically skips annoying link shorteners.

5 | 6 | 7 | 8 | [](https://github.com/FastForwardTeam/FastForward/blob/main/.github/workflows/main.yml) 9 | Discord 10 |

11 | Get FastForward on Chromium based browsers 12 | Get FastForward on Microsoft Edge 13 | Get FastForward for Firefox 14 |
15 | 16 | # FastForward Privacy Policy 17 | 18 | ## What We Collect 19 | FastForward does not collect any personally identifiable information on its users. The only information collected is what is described below, in the Auto updating and Crowd Bypass sections. 20 | 21 | 22 | ## Auto-updating 23 | _This section does not apply to Firefox._ 24 | 25 | In order to provide up-to-date bypasses, FastForward sends a request to Github every hour, and if a new commit is found, it will download the latest "injection script." 26 | 27 | 28 | For this, [Github's privacy policy](https://help.github.com/en/github/site-policy/github-privacy-statement) applies. 29 | 30 | ## Crowd Bypass 31 | 32 | When Crowd Bypass (Options > "Give and take the destinations of unbypassable shorteners.") is enabled, occasionally the extension will send requests to our server. 33 | 34 | When you visit a known unbypassable shortener website, the URL is sent so it can check against the database if someone else has already reported its destination. 35 | When you complete your visit on such a website, the URL and destination URL are sent so it can be recorded for future visitors. We store a hashed version of your IP address along with the destination to prevent spam. We may record your user-agent and other headers to analyse errors on our server. Access to this database is restricted to only those developers and administrators who require it for the purpose of maintenance. We never share this data with anyone else. We use Cloudflare to protect and improve the performance of our server. Their [privacy policy](https://www.cloudflare.com/privacypolicy/) applies to you as an "End User". 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | > [!IMPORTANT] 2 | > FastForward is no longer being actively maintained.
3 | > You can fork this project and continue the development if you wish, or contact @undeadjess to take over this repo.
4 | > We are still accepting some pull requests!

5 | > If you're looking for an alternative, we recommend: [bypass-all-shortlinks debloated (userscript)](https://codeberg.org/Amm0ni4/bypass-all-shortlinks-debloated) or [ads-bypasser (userscript)](https://adsbypasser.github.io).
6 | > If you have an adblocker on your browser, these filter lists can help: [yokoffing's filterlists](https://github.com/yokoffing/filterlists) | [Actually Legitimate URL Shortener Tool](https://github.com/DandelionSprout/adfilt/blob/master/LegitimateURLShortener.txt).

7 | > The Crowd-Bypass server is still running, you can see the api documentation [here](https://github.com/FastForwardTeam/Server/wiki), and anyone is free to use it.

8 | > Maybe give the devs a hug, they all deserve one: 9 | > - [0xc60f](https://github.com/0xc60f) 10 | > - [AliahX](https://github.com/AliahX) 11 | > - [driedpampas](https://github.com/driedpampas) 12 | > - [jess <3](https://github.com/undeadjess) 13 | > - [lem6ns](https://github.com/lem6ns) 14 | > - [lostdusty](https://github.com/lostdusty) 15 | > - [NotAProton](https://github.com/NotAProton) 16 | > - [reashetyrr](https://github.com/reashetyrr)

17 | > 18 | > Thanks for your support over the years!
19 | > The FastForward Team <3 20 | 21 | --- 22 | 23 |
24 |

25 |

Don't waste your time with compliance. FastForward automatically skips annoying link shorteners.

26 | 27 | Builds 28 | Discord 29 | 30 | 31 | Get FastForward on Chromium based browsers 32 | Get FastForward on Microsoft Edge 33 | Get FastForward for Firefox 34 |
35 | 36 | > **We need developers to work on bypasses! If you're interested, [join our Discord](https://discord.gg/RSAf7b5njt).** 37 | 38 | ____ 39 | 40 | ## Installing the Extension 41 | Please refer to our [installation guide](./docs/INSTALLING.md). 42 | 43 | ## Supported websites 44 | Refer to our [bypassed list](./docs/Bypassed.md). 45 | 46 | ## About 47 | ### What is FastForward? 48 | FastForward is the successor of Universal Bypass (see below), a browser extension that can bypass annoying link shorteners, so you don't need to waste your time _trying_ to get to the final link. You can see the extension in action on [our official website](https://fastforward.team/example-links). 49 | 50 | ### What happened to Universal Bypass? 51 | As you may know, [Universal Bypass](https://github.com/Sainan/Universal-Bypass) is no longer maintained by its original developer, [Sainan](https://github.com/Sainan), who had worked on it for so long. 52 | 53 | ### Does FastForward have a Discord server? 54 | Yes! If you are interested in assisting the development, need help, or just wanna hang out, you can [click here to join](https://discord.gg/RSAf7b5njt) our server. 55 | -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | files: 2 | - source: src/_locales/en/messages.json 3 | translation: src/_locales/%two_letters_code%/messages.json 4 | -------------------------------------------------------------------------------- /docs/CODE_STYLE.md: -------------------------------------------------------------------------------- 1 | ### Code style: 2 | - [Standard JS](https://standardjs.com/rules.html) + [Prettier](https://prettier.io/) 3 | - Unix EOL (LF) 4 | - Newline at end of file 5 | 6 | ### How to set this up on VScode/Codium: 7 | - Extension: [VSCode marketplace](https://marketplace.visualstudio.com/items?itemName=numso.prettier-standard-vscode) 8 | - Newline at end of file: [stackoverflow.com/a/44704969](https://stackoverflow.com/a/44704969) 9 | -------------------------------------------------------------------------------- /docs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to FastForward 2 | Thanks for taking the time to contribute to FastForward, it is volunteers like you who make this project possible. 3 | 4 | ## Contibuting bypasses 5 | 6 | ### Making the bypass 7 | Initially, you may use the custom bypasses section on the extension's settings page to test out and formulate your bypass, but after that we reccomend using a code editor like [VSCode](https://code.visualstudio.com/download)/[Codium](https://vscodium.com/#install). 8 | 9 | ### Submitting a Pull Request 10 | 11 | When submitting a pull please take care that: 12 | - Your code follows [the code style](CODE_STYLE.md#code-style) 13 | - Commit messages should be descriptive 14 | - If its a small change [squash all your commits](Git_CLI.md#squashing-commits) 15 | - Follow the pull request template 16 | 17 | Consider joining the [Discord](https://discord.gg/RSAf7b5njt) so that we can discuss the PR in real time. 18 | -------------------------------------------------------------------------------- /docs/CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | # FastForward Contributors 2 | 3 | Thanks to everyone who helps make FastForward: 4 | 5 | - The [code contributors](https://github.com/FastForwardTeam/FastForward/graphs/contributors) right here at Github. 6 | - The [website devs](https://github.com/FastForwardTeam/Website/graphs/contributors). 7 | - The translators over at [Crowdin](https://crowdin.com/project/fastforward). 8 | 9 | ## Libraries used by FastForward 10 | 11 | - FastForward uses [UIkit](https://getuikit.com/) for its design. 12 | - The custom bypass editor is powered by [Ace](https://ace.c9.io/). 13 | -------------------------------------------------------------------------------- /docs/Git_CLI.md: -------------------------------------------------------------------------------- 1 | Install git before using the any of the commands. https://git-scm.com/downloads 2 | 3 | --- 4 | ### Squashing commits 5 | to make this: 6 | 7 | >• Update readme.md 8 | > 9 | >• Update readme.md 10 | > 11 | >• Update readme.md 12 | > 13 | >• Update readme.md 14 | 15 | Into this: 16 | 17 | > • Fix link in README 18 | 19 | 20 | Open the terminal and run the following commands. 21 | NOTE: Remember to substitue all `` 22 | ``` 23 | git clone https://github.com//FastForward 24 | ``` 25 | ``` 26 | cd FastForward 27 | ``` 28 | 29 |
30 | If you didn't make the changes on main- 
31 |   git checkout <YOUR BRANCH NAME>
32 | 
33 | 34 | ``` 35 | git reset --soft HEAD~ 36 | ``` 37 | ``` 38 | git commit -m "" 39 | ``` 40 | NOTE: When git asks for your password use a [PAT](https://github.com/settings/tokens). 41 | ``` 42 | git push --force 43 | ``` 44 | --- 45 | ### Fixing a messed up main branch 46 | NOTE: If you have made any changes on your main brainch they **will be lost.** 47 | 48 | Open the terminal and run the following commands. 49 | NOTE: Remember to substitue all `` 50 | ``` 51 | git clone https://github.com//FastForward 52 | ``` 53 | ``` 54 | cd FastForward 55 | git remote add upstream https://github.com/FastForwardteam/FastForward 56 | git fetch upstream 57 | git checkout main 58 | git reset --hard upstream/main 59 | 60 | ``` 61 | 62 | NOTE: When git asks for your password use a [PAT](https://github.com/settings/tokens). 63 | ``` 64 | git push origin main --force 65 | ``` 66 | -------------------------------------------------------------------------------- /docs/PRIVACY.md: -------------------------------------------------------------------------------- 1 | # FastForward Privacy Policy 2 | 3 | ## Crowd Bypass 4 | 5 | When Crowd Bypass (Options > "Give and take the destinations of unbypassable shorteners.") is enabled, ocassionally the extension will send requests to our server: 6 | 7 | - When you visit a known unbypassable shortener website, the URL is sent so it can check against the database if someone else has already reported its destination. 8 | - When you complete your visit on such a website, the URL and destination URL are sent so it can be recorded for future visitors. 9 | 10 | To prevent abuse, we log a hashed version of your IP address in our database when you submit a link. Only the developers have access to the database. 11 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "devDependencies": { 4 | "ejs": "^3.1.9", 5 | "eslint": "^8.37.0", 6 | "eslint-config-prettier": "^8.8.0", 7 | "fs-extra": "^11.1.1", 8 | "prettier": "^2.8.7", 9 | "web-ext": "^7.6.2" 10 | }, 11 | "scripts": { 12 | "lint": "eslint", 13 | "build": "node ./scripts/build.js" 14 | } 15 | } -------------------------------------------------------------------------------- /platform_spec/chromium/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | "icons": { 4 | "48": "icon/48.png", 5 | "128": "icon/128.png", 6 | "150": "icon/150.png", 7 | "176": "icon/176.png", 8 | "512": "icon/512.png" 9 | }, 10 | "default_locale": "en", 11 | "name": "FastForward", 12 | "description": "__MSG_appDesc__", 13 | "homepage_url": "https://fastforward.team", 14 | "version": "13.15.2", 15 | "author": "FastForward Team", 16 | "incognito": "split", 17 | "permissions": [ 18 | "alarms", 19 | "storage", 20 | "tabs", 21 | "declarativeNetRequestWithHostAccess" 22 | ], 23 | "host_permissions": [ 24 | "" 25 | ], 26 | "options_ui": { 27 | "page": "html/options.html", 28 | "open_in_tab": true 29 | }, 30 | "background": { 31 | "service_worker": "background.js", 32 | "type": "module" 33 | }, 34 | "action": { 35 | "default_popup": "html/popup.html" 36 | }, 37 | "content_scripts": [ 38 | { 39 | "matches": [ 40 | "" 41 | ], 42 | "js": [ 43 | "content_script.js" 44 | ], 45 | "run_at": "document_start" 46 | } 47 | ], 48 | "web_accessible_resources": [{ 49 | "resources": [ 50 | "html/before-navigate.html", 51 | "html/blocked.html", 52 | "html/crowd-bypassed.html", 53 | "html/tracker-bypass.html", 54 | "html/options.html", 55 | "icon/48.png", 56 | "injection_script.js", 57 | "bypasses/*", 58 | "helpers/*"], 59 | "matches": [""] 60 | }], 61 | 62 | "declarative_net_request": { 63 | "rule_resources": [{ 64 | "id": "ipLoggerRuleset", 65 | "enabled": true, 66 | "path": "ip_logger_blocker.json" 67 | }, 68 | { 69 | "id": "trackerRuleset", 70 | "enabled": false, 71 | "path": "tracker_bypass.json" 72 | }] 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /platform_spec/firefox/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 3, 3 | "icons": { 4 | "48": "icon/48.png", 5 | "128": "icon/128.png", 6 | "150": "icon/150.png", 7 | "176": "icon/176.png", 8 | "512": "icon/512.png" 9 | }, 10 | "default_locale": "en", 11 | "name": "FastForward", 12 | "description": "__MSG_appDesc__", 13 | "homepage_url": "https://fastforward.team", 14 | "version": "13.15.2", 15 | "author": "FastForward Team", 16 | "browser_specific_settings": { 17 | "gecko": { 18 | "id": "addon@fastforward.team", 19 | "strict_min_version": "113.0" 20 | } 21 | }, 22 | "permissions": [ 23 | "alarms", 24 | "storage", 25 | "webNavigation", 26 | "tabs", 27 | "declarativeNetRequestWithHostAccess" 28 | ], 29 | "host_permissions": [ 30 | "" 31 | ], 32 | "options_ui": { 33 | "page": "html/options.html", 34 | "open_in_tab": true 35 | }, 36 | "background": { 37 | "scripts": ["background.js"], 38 | "type": "module" 39 | }, 40 | "action": { 41 | "default_popup": "html/popup.html" 42 | }, 43 | "content_scripts": [ 44 | { 45 | "matches": [ 46 | "" 47 | ], 48 | "js": [ 49 | "content_script.js" 50 | ], 51 | "run_at": "document_start" 52 | } 53 | ], 54 | "web_accessible_resources": [{ 55 | "resources": [ 56 | "html/before-navigate.html", 57 | "html/blocked.html", 58 | "html/crowd-bypassed.html", 59 | "html/tracker-bypass.html", 60 | "html/options.html", 61 | "icon/48.png", 62 | "injection_script.js", 63 | "bypasses/*", 64 | "helpers/*", 65 | "rules.json" 66 | ], 67 | "matches": [""] 68 | }], 69 | "declarative_net_request": { 70 | "rule_resources": [{ 71 | "id": "ipLoggerRuleset", 72 | "enabled": true, 73 | "path": "ip_logger_blocker.json" 74 | }, 75 | { 76 | "id": "trackerRuleset", 77 | "enabled": false, 78 | "path": "tracker_bypass.json" 79 | }] 80 | 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /scripts/build_js/injection_script_template.js: -------------------------------------------------------------------------------- 1 | const bypasses = [/- bypasses -/]; 2 | const script_src = new URL(document.currentScript.src); 3 | const ext_base_URL = script_src.searchParams.get('ext_base_URL'); 4 | 5 | function matchingBypass(bypasses) { 6 | for (const [key] of Object.entries(bypasses)) { 7 | if (key.charAt(0) === '/' && key.charAt(key.length - 1) === '/') { 8 | let pattern = new RegExp(key.substring(1, key.length - 1)); 9 | if (pattern.test(location.href)) { 10 | return key; 11 | } 12 | } else if (key === location.host) { 13 | return key; 14 | } 15 | } 16 | return null; 17 | } 18 | 19 | if (matchingBypass(bypasses)) { 20 | const bypass_url = bypasses[matchingBypass(bypasses)]; 21 | 22 | import(ext_base_URL.concat(bypass_url)).then(({ default: bypass }) => { 23 | import(ext_base_URL.concat('helpers/dom.js')).then( 24 | ({ default: helpers }) => { 25 | const bps = new bypass(); 26 | bps.set_helpers(helpers); 27 | console.log(`ensure_dom: ${bps.ensure_dom}`); 28 | if (bps.ensure_dom) { 29 | let executed = false; 30 | document.addEventListener('readystatechange', () => { 31 | if ( 32 | ['interactive', 'complete'].includes(document.readyState) && 33 | !executed 34 | ) { 35 | executed = true; 36 | bps.execute(); 37 | } 38 | }); 39 | document.addEventListener('DOMContentLoaded', () => { 40 | if (!executed) { 41 | executed = true; 42 | bps.execute(); 43 | } 44 | }); 45 | } else { 46 | bps.execute(); 47 | } 48 | } 49 | ); 50 | }); 51 | } 52 | -------------------------------------------------------------------------------- /src/_locales/am/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "በማክበር ጊዜዎን አያባክን። ሁለንተናዊ አቋራጭ የሚረብሹ አገናኝ አቋራጮችን ይገድባል።" 4 | }, 5 | "firstrunTitle": { 6 | "message": "ዩኒቨርሳል Bypass ን ስለጫኑ እናመሰግናለን!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "ሆኖም ኖቭስክሪፕትን ወይም ተመሳሳይን የሚጠቀሙ ፣ ዩኒቨርሳል ኦንቨርንቨር ከ ጋር የማይጣጣም ይመስላል።" 10 | }, 11 | "version": { 12 | "message": "ሥሪት" 13 | }, 14 | "definitionsVersion": { 15 | "message": "ትርጓሜዎችን ማለፍ" 16 | }, 17 | "changelog": { 18 | "message": "መለወጫ" 19 | }, 20 | "update": { 21 | "message": "ዝማኔዎችን ይመልከቱ" 22 | }, 23 | "updating": { 24 | "message": "የትርጉም ፍችዎችን በማውረድ ላይ ..." 25 | }, 26 | "updateYes": { 27 | "message": "የትርጉም ፍችዎችን በማውረድ ላይ ..." 28 | }, 29 | "updateNo": { 30 | "message": "የማለፍ ትርጓሜዎች ወቅታዊ ናቸው።" 31 | }, 32 | "faq": { 33 | "message": "ተዘውትረው የሚጠየቁ ጥያቄዎች (ተዘውትረው)" 34 | }, 35 | "bypassCounter": { 36 | "message": "ሁለንተናዊ ማለፍ ቀድሞውንም ጣቢያዎችን$1 አል sitesል" 37 | }, 38 | "support": { 39 | "message": "ወደ ሁለንተናዊ ማቋረጫ ያበርክቱ።" 40 | }, 41 | "options": { 42 | "message": "አማራጮች" 43 | }, 44 | "optionsLink": { 45 | "message": "ሁለንተናዊ አቋራጭ አማራጮችን ቀይር።" 46 | }, 47 | "optionsEnabled": { 48 | "message": "የድርጣቢያ ማለፍን ያንቁ።" 49 | }, 50 | "optionsNavigationDelay": { 51 | "message": "ከ$1 ሰከንድ (ሰ) በኋላ ወደ መድረሻዎች ውሰደኝ ፡፡" 52 | }, 53 | "optionsTrackerBypass": { 54 | "message": "Apimon.de ን በመጠቀም ትራኮችን (ለምሳሌ bit.ly እና t.co ን) በመጠቀም ያቋርጣሉ ፡፡" 55 | }, 56 | "optionsInstantNavigationTrackers": { 57 | "message": "በፍጥነት ወደ ትራካckers መድረሻዎች ውሰደኝ ፡፡" 58 | }, 59 | "optionsBlockIPLoggers": { 60 | "message": "የአይ.ፒ ሎጊዎችን ማለፍ ካልቻሉ አግድ።" 61 | }, 62 | "optionsCrowdBypass": { 63 | "message": "የተጨናነቀ አቋራጭ የማይተላለፍ አቋራጭ ያላቸውን መድረሻ ይስጡ እና ይውሰዱ ፡፡" 64 | }, 65 | "optionsCrowdAutoOpen": { 66 | "message": "ከ$1 ሰከንድ (ቶች) በኋላ በህዝብ የተመረጡ መድረሻዎችን በአዲስ ትር ክፈት" 67 | }, 68 | "optionsCrowdAutoClose": { 69 | "message": "ከጎበኙ በኋላ ከ$1 ሰከንድ (ሰት) በኋላ በሕዝብ የተፈጠረ መድረሻን የያዘ ትር ይዝጉ" 70 | }, 71 | "privacyPolicy": { 72 | "message": "የ ግል የሆነ" 73 | }, 74 | "contributors": { 75 | "message": "አስተዋፅutors አበርካቾች" 76 | }, 77 | "optionsUserscripts": { 78 | "message": "ብጁ መተላለፊያዎች" 79 | }, 80 | "optionsUserscriptsDescription": { 81 | "message": "ጣቢያዎችን ለማለፍ የራሳቸውን ስክሪፕቶች ለመፍጠር ለገንቢዎች ይህ የላቀ ባህሪ ነው። አንዴ ከተጠናቀቁ በኋላ ወደ ዩኒቨርሳል ማለፍ እንዲታከሉ በ GitHub ላይ ሊገቡ ይችላሉ ፣ ስለሆነም ለሁሉም ሰው ይገኛሉ ፡፡" 82 | }, 83 | "beforeNavigate": { 84 | "message": "መድረሻዎ ላይ ደርሰዋል።" 85 | }, 86 | "beforeNavigateDestination": { 87 | "message": "መድረሻዎ$1 ነው" 88 | }, 89 | "beforeNavigateUnsafe": { 90 | "message": "ሆኖም ግን ፣ አሁን ከዳሰሱ ዩኒቨርሳል ኦንቨርንሌይትን ይገነዘባሉ።" 91 | }, 92 | "beforeNavigateUnsafeTimer": { 93 | "message": "በ$1 ሰከንዶች ውስጥ ከእንግዲህ አይገኙም" 94 | }, 95 | "beforeNavigateUnsafeTimerSingular": { 96 | "message": "በ 1 ሰከንድ ውስጥ ከእንግዲህ ወዲህ አይገኙም።" 97 | }, 98 | "beforeNavigateTimer": { 99 | "message": "በ$1 ሰከንዶች ውስጥ በራስ-ሰር ይዛወራሉ።" 100 | }, 101 | "beforeNavigateTimerSingular": { 102 | "message": "በ 1 ሴኮንድ ውስጥ በራስ-ሰር ይዛወራሉ።" 103 | }, 104 | "beforeNavigateOptions": { 105 | "message": "በቅጽበት ወይም በ x ሰከንዶች ውስጥ አቅጣጫዎን መለወጥ ይፈልጋሉ?" 106 | }, 107 | "beforeNavigateInstant": { 108 | "message": "ወደ$1 እየተጓዙ ነው" 109 | }, 110 | "infoFileHoster": { 111 | "message": "እንደ አለመታደል ሆኖ የወረደው አገልጋይ ፋይሉን ለማውረድ ከመፍቀድዎ በፊት መጠበቅዎን ያረጋግጣል።" 112 | }, 113 | "infoOutdated": { 114 | "message": "ይህ ድርጣቢያ በአዲሱ ኦቨርቨር ኦቨር ኦቨር ኦቨር ኦቨር ኦፕሬሽን (ስሪት) ተላል isል።" 115 | }, 116 | "crowdWait": { 117 | "message": "እንደ አለመታደል ሆኖ ይህንን አገናኝ ያጋጠሙዎት እርስዎ የመጀመሪያ ነዎት ፣ ግን ከጠበቁ በኋላ ሌሎች ሁለንተናዊ የመንገድ ተጠቃሚዎች ከእንግዲህ አያስፈልጉም ፡፡" 118 | }, 119 | "crowdDisabled": { 120 | "message": "ይህ ድርጣቢያ በአጋጣሚዎች ውስጥ ማንቃት በሚችሉት የሰዎች ማለፍ ተላልpassል።" 121 | }, 122 | "crowdBypassed": { 123 | "message": "መጠበቅ የለብዎትም!" 124 | }, 125 | "crowdBypassedInfo": { 126 | "message": "ሌሎች ሁለንተናዊ አቋራጭ ተጠቃሚዎች እርስዎን ይጠባበቁ እና ይህ ወደ$1 እንደሚወስድ ዘግቧል።" 127 | }, 128 | "crowdBypassedTimer": { 129 | "message": "ይህ በ$1 ሰከንዶች ውስጥ በአዲስ ትር ውስጥ ይከፈታል።" 130 | }, 131 | "crowdBypassedTimerSingular": { 132 | "message": "ይህ በ 1 ሴኮንድ ውስጥ በአዲስ ትር ውስጥ ይከፈታል" 133 | }, 134 | "crowdCloseTimer": { 135 | "message": "ይህ ትር በ$1 ሰከንዶች ውስጥ ይዘጋል።" 136 | }, 137 | "crowdCloseTimerSingular": { 138 | "message": "ይህ ትር በ 1 ሴኮንድ ውስጥ ይዘጋል።" 139 | }, 140 | "cancel": { 141 | "message": "ይቅር።" 142 | }, 143 | "crowdBypassedIgnore": { 144 | "message": "ይህ ትክክል አልነበረም?" 145 | }, 146 | "crowdBypassedOptions": { 147 | "message": "ይህ በአዲሱ ትር ውስጥ ወዲያውኑ ወይም በ x ሰከንዶች ውስጥ እንዲከፈት ይፈልጋሉ?" 148 | }, 149 | "blockedTitle": { 150 | "message": "ሁለንተናዊ መተላለፊያ የእርስዎ አይፒ እንዳይመዘገብ አግዶታል ፡፡" 151 | }, 152 | "blockedSubtitle": { 153 | "message": "መጥፎ ተዋንያን የእርስዎን አይፒ (IP) እንዳያገኙ ለመከላከል ሁለንተናዊ ማለፍ ይፈልጋሉ?" 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/_locales/an/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": { 3 | "message": "Versión" 4 | }, 5 | "definitionsVersion": { 6 | "message": "Omitir definiziónes" 7 | }, 8 | "changelog": { 9 | "message": "Rechistro de cambio." 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/_locales/az/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "Vaxtınızı uyğunlaşdırmaya xərcləməyin. FastForward, zəhlətökən bağlantı qısaldıcılarını ötürür." 4 | }, 5 | "firstrunTitle": { 6 | "message": "FastForward quraşdırdığınız üçün təşəkkürlər!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "Buna baxmayaraq, FastForward ilə uyğunlaşmayan NoScript və ya oxşarını istifadə edirsiniz." 10 | }, 11 | "version": { 12 | "message": "Versiya" 13 | }, 14 | "definitionsVersion": { 15 | "message": "Bypass tərifləri" 16 | }, 17 | "changelog": { 18 | "message": "Dəyişiklik qeydi" 19 | }, 20 | "update": { 21 | "message": "Yeniləmələri yoxla" 22 | }, 23 | "faq": { 24 | "message": "Tez-tez Soruşulan Suallar (FAQ)" 25 | }, 26 | "support": { 27 | "message": "FastForward-ı Dəstəkləyin." 28 | }, 29 | "options": { 30 | "message": "Seçimlər" 31 | }, 32 | "optionsLink": { 33 | "message": "FastForward seçimlərini dəyişdirin." 34 | }, 35 | "optionsEnabled": { 36 | "message": "Veb saytlarının ötürülməsini fəallaşdır." 37 | }, 38 | "optionsBlockIPLoggers": { 39 | "message": "Ötürə bilməsə, IP qeydlərini əngəllə." 40 | }, 41 | "optionsCrowdBypass": { 42 | "message": "Ötürülə bilməyən qısaldıcıların yerlərini verin və aparın." 43 | }, 44 | "privacyPolicy": { 45 | "message": "Gizlilik Siyasəti" 46 | }, 47 | "optionsUserscripts": { 48 | "message": "Özəl Bypass-lar" 49 | }, 50 | "beforeNavigate": { 51 | "message": "Demək olar ki, təyinat yerindəsiniz." 52 | }, 53 | "beforeNavigateDestination": { 54 | "message": "Təyinat yeri $1" 55 | }, 56 | "beforeNavigateTimer": { 57 | "message": "$1 saniyə ərzində avtomatik yönləndiriləcəksiniz." 58 | }, 59 | "beforeNavigateTimerSingular": { 60 | "message": "1 saniyə ərzində avtomatik yönləndiriləcəksiniz." 61 | }, 62 | "crowdWait": { 63 | "message": "Təəssüf ki, bu bağlantı ilə qarşılaşan ilk sizsiniz, ancaq siz gözlədikdən sonra, digər FastForward istifadəçilərinin buna ehtiyacı olmayacaq." 64 | }, 65 | "crowdBypassed": { 66 | "message": "Gözləməyinizə ehtiyac yoxdur!" 67 | }, 68 | "crowdBypassedInfo": { 69 | "message": "Digər FastForward istifadəçiləri artıq sizi gözlədilər və bunun $1 a çatdığı bildirildi" 70 | }, 71 | "crowdBypassedTimer": { 72 | "message": "Bu, $1 saniyə ərzində yeni bir vərəqdə açılacaq." 73 | }, 74 | "crowdBypassedTimerSingular": { 75 | "message": "Bu, 1 saniyə ərzində yeni bir vərəq açılacaq." 76 | }, 77 | "crowdBypassedIgnore": { 78 | "message": "Bu doğru deyil?" 79 | }, 80 | "crowdBypassedOptions": { 81 | "message": "Bunun indi ya x saniyə sonra yeni bir vərəqdə açılmasını istəyirsiniz?" 82 | }, 83 | "blockedTitle": { 84 | "message": "FastForward, IP ünvanların qeydlərə əlavə edilməsinin qarşısı aldı." 85 | }, 86 | "blockedSubtitle": { 87 | "message": "FastForward-ın, pisniyyətli insanların IP ünvanınızı oğurlamasının qarşısını almasını istəmirsiniz?" 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/_locales/br/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstrunTitle": { 3 | "message": "Trugarez evit ho staliañ FastForward!" 4 | }, 5 | "version": { 6 | "message": "Handelv" 7 | }, 8 | "changelog": { 9 | "message": "Renabl ar c'hemmoù" 10 | }, 11 | "update": { 12 | "message": "Gwiriañ an hizivadurioù" 13 | }, 14 | "faq": { 15 | "message": "Foar ar Goulennoù (FAG)" 16 | }, 17 | "bypassCounter": { 18 | "message": "Bet oc'h e-biou da $1s lec'hienn a-drugarez da FastForward." 19 | }, 20 | "support": { 21 | "message": "Kenoberiañ da FastForward." 22 | }, 23 | "options": { 24 | "message": "Dibarzhioù" 25 | }, 26 | "optionsLink": { 27 | "message": "Kemmañ dibarzhioù FastForward." 28 | }, 29 | "optionsEnabled": { 30 | "message": "Gweredekaat an tremen e-biou d'al lec'hiennoù." 31 | }, 32 | "privacyPolicy": { 33 | "message": "Reolenn a-fet buhez prevez" 34 | }, 35 | "contributors": { 36 | "message": "Perzhidi" 37 | }, 38 | "optionsUserscripts": { 39 | "message": "Tremenadennoù e-biou personelaet" 40 | }, 41 | "beforeNavigate": { 42 | "message": "Tost erru oc'h da benn hoc'h hent." 43 | }, 44 | "beforeNavigateDestination": { 45 | "message": "$1 eo hoc'h arvoned" 46 | }, 47 | "beforeNavigateTimer": { 48 | "message": "Adheñchet e vezoc'h bet ent emgefreek a-benn $1 eilenn." 49 | }, 50 | "beforeNavigateTimerSingular": { 51 | "message": "Adheñchet e vezoc'h bet ent emgefreek a-benn 1 eilenn." 52 | }, 53 | "cancel": { 54 | "message": "Nullañ." 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/_locales/ckb/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "کاتی خۆت بە فیڕۆ مەدە بە ڕەزای بوون، ئەم تێپەڕ گشتیە هەموو بەستەرە بێزارکەرەکان لادەبات." 4 | }, 5 | "firstrunTitle": { 6 | "message": "سوپاس بۆ دامەزراندنی FastForward!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "وا دیارە، تۆ زیادکراوی NoScript بەکار دەهێنیت یان هەر یەک لەو زیادکراوانە. کە ئەم زیادکراوەی ئێمە ناگونجێت لەگەڵیدا." 10 | }, 11 | "version": { 12 | "message": "نوسخە" 13 | }, 14 | "definitionsVersion": { 15 | "message": "ماناکانی تێپەڕەکە" 16 | }, 17 | "changelog": { 18 | "message": "تۆماری گۆڕانەکان" 19 | }, 20 | "update": { 21 | "message": "پشکنین بۆ نوسخە نوێکان" 22 | }, 23 | "updating": { 24 | "message": "داگرتنی ماناکانی تێپەڕەکە..." 25 | }, 26 | "updateYes": { 27 | "message": "داگرتنی ماناکانی تێپەڕەکە سەرکەوتوو بو" 28 | }, 29 | "updateNo": { 30 | "message": "پێناسەکانی تێپەڕەکە نوێە" 31 | }, 32 | "faq": { 33 | "message": "پرسیارە زۆر دووبارە کراوەکان" 34 | }, 35 | "bypassCounter": { 36 | "message": "ئەم تێپەڕە گشتیە هەتا ئێستا $1 پەڕەی بۆ تێپەڕاندوویت" 37 | }, 38 | "support": { 39 | "message": "یارمەتی تێپەڕەکە بدە." 40 | }, 41 | "options": { 42 | "message": "هەڵبژاردنەکان" 43 | }, 44 | "optionsLink": { 45 | "message": "بژاردەکانی تێپەڕەکە بگۆڕە" 46 | }, 47 | "optionsEnabled": { 48 | "message": "بەکارخستنی رێگاگرتنی وێبسایت." 49 | }, 50 | "optionsNavigationDelay": { 51 | "message": "بمبە شوێنی مەبەست دوای $1 چرکە" 52 | }, 53 | "optionsTrackerBypass": { 54 | "message": "بیپەڕێنە سایتەکە سیخوڕیەکان (وەک bit.ly و t.co) بە بەکارهێنانی Apimon.de. " 55 | }, 56 | "optionsInstantNavigationTrackers": { 57 | "message": "دەستبەجی بمبە بۆ شوێنی چوون." 58 | }, 59 | "optionsBlockIPLoggers": { 60 | "message": "ڕایبگرە ئایپی دزە پێکەرەکان ئەگەر نەتوانی پەڕەکە تێ بپەڕێنیت" 61 | }, 62 | "optionsCrowdAutoOpen": { 63 | "message": "لینکی کۆتایم پێ بدە لە دوای $1 چرکەدا" 64 | }, 65 | "optionsUserscripts": { 66 | "message": "دەربازبوونی نەریتی" 67 | }, 68 | "beforeNavigateDestination": { 69 | "message": "ئەو شوێنەی کە ذەچیت: $1" 70 | }, 71 | "crowdBypassed": { 72 | "message": "لەوانەیە پێویست نەکات بوەستیت!" 73 | }, 74 | "cancel": { 75 | "message": "لابردن" 76 | }, 77 | "crowdBypassedIgnore": { 78 | "message": "ئایە ئەمە ڕاست نەبوو؟" 79 | }, 80 | "crowdBypassedOptions": { 81 | "message": "ئایا تۆ دەتەوێت ئەمە بکرێتەوە لە پەڕیەکی نوێدا ڕاستەوخۆ یان دوای چەند چرکەیەک ؟" 82 | }, 83 | "blockedTitle": { 84 | "message": "ئەم تێپەڕە نەیهێشت ئایپی ئەدرێسەکەت تۆمار بکرێت" 85 | }, 86 | "blockedSubtitle": { 87 | "message": "ئایا تۆ ناتەوێت ئەم تێپەڕە ڕێگری بکات لە خەڵکانی خراپ لە بردنی IP تایبەت بە تۆ ؟" 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/_locales/eo/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "firstrunNoScript": { 3 | "message": "Vi ŝajne uzas NoScript, aŭ aferoj same. FastForward bedaŭrinde ne povas kunfari kun tioj." 4 | }, 5 | "version": { 6 | "message": "versio" 7 | }, 8 | "definitionsVersion": { 9 | "message": "transiranta difinoj" 10 | }, 11 | "updating": { 12 | "message": "Elŝutanta preterpasa difiniojn" 13 | }, 14 | "faq": { 15 | "message": "Ofta demandoj" 16 | }, 17 | "bypassCounter": { 18 | "message": "FastForward preterpasinta $1 retpaĝojn. " 19 | }, 20 | "options": { 21 | "message": "agordoj" 22 | }, 23 | "beforeNavigateInstant": { 24 | "message": "Vi estas navigita al $1" 25 | }, 26 | "infoOutdated": { 27 | "message": "Ĉi tio retpaĝo estas uzanta pli nova versio de FastForward" 28 | }, 29 | "crowdWait": { 30 | "message": "Bedaŭrinde, vi estas la unua vizitanto sur ĉi retpaĝo. Sed, se vi atendas, la aliaj uzantoj ne atendos." 31 | }, 32 | "crowdBypassedTimerSingular": { 33 | "message": "Nova langeto estos malfermita en 1 sekundo." 34 | }, 35 | "crowdCloseTimer": { 36 | "message": "La langeto estos fermita en $1 sekundoj" 37 | }, 38 | "crowdCloseTimerSingular": { 39 | "message": "La langeto estos fermita en 1 sekundo" 40 | }, 41 | "cancel": { 42 | "message": "Nuligi." 43 | }, 44 | "crowdBypassedOptions": { 45 | "message": "Ĉu vi volas aperi tion instante, sur nova tabo?" 46 | }, 47 | "blockedTitle": { 48 | "message": "FastForward haltis via IP adreso registrita." 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/_locales/ga-IE/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "Ná drámhail do am lé comhlíonadh. Seachnaíonn Seachbhóthar Uilíoch go huathoibríoch gearrshaolaithe naisc atá annamh." 4 | }, 5 | "firstrunTitle": { 6 | "message": "Go raibh maith agat chun FastForward a shuiteáil!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "Ach, Tá tú ag usaíd NoScript ná rúd againn éile agus ní feidir le FastForward in an obair lé sin." 10 | }, 11 | "faq": { 12 | "message": "Ceisteanna Coitianta (CC)" 13 | }, 14 | "support": { 15 | "message": "Taspann do tachíocht le haghaidh FastForward" 16 | }, 17 | "options": { 18 | "message": "Roghnna" 19 | }, 20 | "optionsLink": { 21 | "message": "Athrú ná roghnna de FastForward." 22 | }, 23 | "optionsEnabled": { 24 | "message": "Cumasaigh seachbhóithre láithreán gréasáin." 25 | }, 26 | "optionsNavigationDelay": { 27 | "message": "Tuair me go cinn scríbe tar éis$1 an dara ceann. (Bain úsáid as 0 le nascleanúint a dhéanamh láithreach.)" 28 | }, 29 | "optionsInstantNavigationTrackers": { 30 | "message": "Tóg mé chuig ceann scríbe na lorgairí láithreach." 31 | }, 32 | "optionsBlockIPLoggers": { 33 | "message": "Bloc logálaithe IP mura féidir iad a sheachaint." 34 | }, 35 | "optionsCrowdBypass": { 36 | "message": "Tuair agus tóg na cinn scríbe na ngiorraitheoirí nach féidir a phasáil." 37 | }, 38 | "privacyPolicy": { 39 | "message": "Beartas Príobháideachais" 40 | }, 41 | "optionsUserscripts": { 42 | "message": "Seachbhóithre saincheaptha" 43 | }, 44 | "optionsUserscriptsDescription": { 45 | "message": "Is gné ard é seo do fhorbróirí chun a gcuid scripteanna féin a chruthú chun suíomhanna a sheachbhóthar. Nuair a bheidh siad foirfe, is féidir iad a chur isteach ansin ar GitHub le bheith curtha le Seachbhóthar Uilíoch, agus mar sin tá siad ar fáil do gach duine." 46 | }, 47 | "beforeNavigate": { 48 | "message": "Ta tú beagnach ansín" 49 | }, 50 | "beforeNavigateDestination": { 51 | "message": "Tá do ceann scríbe $1" 52 | }, 53 | "beforeNavigateTimer": { 54 | "message": "Déanfar tú a atreorú go huathoibríoch i$1 soicind." 55 | }, 56 | "beforeNavigateTimerSingular": { 57 | "message": "Déanfar tú a atreorú go huathoibríoch i 1 soicind." 58 | }, 59 | "beforeNavigateOptions": { 60 | "message": "Ar mhaith leat a bheith atreoraithe láithreach nó i x soicind?" 61 | }, 62 | "crowdBypassed": { 63 | "message": "B'fhéidir nach mbeidh ort fanacht!" 64 | }, 65 | "crowdBypassedInfo": { 66 | "message": "Tá úsáideoirí eile Seachbhóthar Uilíoch tar éis fanacht leat cheana féin agus thuairiscigh siad go dtiocfaidh $1" 67 | }, 68 | "crowdBypassedIgnore": { 69 | "message": "Nach raibh sé séo i gceart?" 70 | }, 71 | "blockedTitle": { 72 | "message": "Chuir Seachbhóthar Uilíoch cosc ar do IP a bheith logáilte isteach." 73 | }, 74 | "blockedSubtitle": { 75 | "message": "Ná bí ag iarraidh Seachbhóthar Uilíoch chun droch-ghníomhaithe a chosc ar do IP a fháil?" 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/_locales/he/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "אל תבזבז את הזמן שלך! FastForward מדלג אוטומטית על מקצרי לינקים מעצבנים." 4 | }, 5 | "firstrunTitle": { 6 | "message": "תודה לך על כך שהתקנת את FastForward!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "ככול הנראה אתה עושה שימוש ב-NoScript ודומיו, מה שלא מאפשר את פעולת FastForward." 10 | }, 11 | "version": { 12 | "message": "גרסה" 13 | }, 14 | "definitionsVersion": { 15 | "message": "הגדרות מעקף" 16 | }, 17 | "changelog": { 18 | "message": "רשימת שינויים" 19 | }, 20 | "update": { 21 | "message": "בדוק עדכונים" 22 | }, 23 | "updating": { 24 | "message": "מוריד הגדרות עקיפה ..." 25 | }, 26 | "updateYes": { 27 | "message": "הגדרות עקיפה הורדו בהצלחה." 28 | }, 29 | "updateNo": { 30 | "message": "הגדרות עקיפה אותרו כעדכניות." 31 | }, 32 | "faq": { 33 | "message": "שאלות נפוצות (FAQ)" 34 | }, 35 | "bypassCounter": { 36 | "message": "מעקף אוניברסלי כבר עקף $1 אתרים בשבילך." 37 | }, 38 | "support": { 39 | "message": "תמוך ב-FastForward" 40 | }, 41 | "options": { 42 | "message": "הגדרות" 43 | }, 44 | "optionsLink": { 45 | "message": "הגדר את FastForward." 46 | }, 47 | "optionsEnabled": { 48 | "message": "הפעל מעקף לאתר." 49 | }, 50 | "optionsNavigationDelay": { 51 | "message": "קח אותי ליעד אחרי $1 שני(ות). (השתמש ב0 על מנת לנווט במיידי)" 52 | }, 53 | "optionsTrackerBypass": { 54 | "message": "תעקוף טראקרים (כמו bit.ly ו - t.co) באמצעות Apimon.de." 55 | }, 56 | "optionsInstantNavigationTrackers": { 57 | "message": "העבר אותי למקור אוטומטית." 58 | }, 59 | "optionsBlockIPLoggers": { 60 | "message": "חסום אוספי IP אם אי אפשר לעקוף אותם." 61 | }, 62 | "optionsCrowdAutoOpen": { 63 | "message": "תפתח מקורות שנוצרו בעזרת הקהל בכרטיסייה חדשה אחרי $1 שניות." 64 | }, 65 | "privacyPolicy": { 66 | "message": "מדיניות פרטיות" 67 | }, 68 | "contributors": { 69 | "message": "תורמים" 70 | }, 71 | "optionsUserscripts": { 72 | "message": "מעקפים מותאמים אישית" 73 | }, 74 | "beforeNavigate": { 75 | "message": "כמעט ביעד שלך." 76 | }, 77 | "beforeNavigateDestination": { 78 | "message": "כתובת היעד שלך היא $1" 79 | }, 80 | "beforeNavigateUnsafe": { 81 | "message": "אם תנווט כעת, הם יזהו את תוספת זאת." 82 | }, 83 | "beforeNavigateUnsafeTimer": { 84 | "message": "אתה לא תהיה גלוי בעוד $1 שניות" 85 | }, 86 | "beforeNavigateUnsafeTimerSingular": { 87 | "message": "אתה לא תהיה גלוי בעוד שנייה." 88 | }, 89 | "beforeNavigateTimer": { 90 | "message": "תועבר אוטומטית עוד $1 שניות." 91 | }, 92 | "beforeNavigateTimerSingular": { 93 | "message": "תועבר אוטומטית בעוד שנייה." 94 | }, 95 | "beforeNavigateOptions": { 96 | "message": "האם ברצונך להיות מכוון מחדש מיידית או בעוד x שניות?" 97 | }, 98 | "beforeNavigateInstant": { 99 | "message": "מנווט ל $1" 100 | }, 101 | "infoOutdated": { 102 | "message": "האתר הזה יכול להיעקף בעזרת גרסה חדשה יותר של FastForward." 103 | }, 104 | "crowdWait": { 105 | "message": "לצערי, אתה הראשון שנתקל בקישור הזה, אבל אחרי שחיכית, משתמשי FastForward אחרים לא יצטרכו לחכות יותר." 106 | }, 107 | "crowdDisabled": { 108 | "message": "אתר זה עוקף על ידי crowd bypass, אפשר לכבות אופציה זו בהגדרות." 109 | }, 110 | "crowdBypassed": { 111 | "message": "יתכן ואתה לא צריך להמתין בכלל!" 112 | }, 113 | "crowdBypassedInfo": { 114 | "message": "משתמשים נוספים כבר המתינו, ודיווחו שהקישור מוביל ל- $1" 115 | }, 116 | "crowdBypassedTimer": { 117 | "message": "תוכן זה יפתח בחלון חדש בעוד $1 שניות." 118 | }, 119 | "crowdBypassedTimerSingular": { 120 | "message": "תוכן זה יפתח בחלון חדש בעוד כשניה." 121 | }, 122 | "crowdCloseTimer": { 123 | "message": "חלון זה ייסגר בעוד $1 שניות." 124 | }, 125 | "crowdCloseTimerSingular": { 126 | "message": "חלון זה ייסגר בעוד שניה." 127 | }, 128 | "cancel": { 129 | "message": "ביטול." 130 | }, 131 | "crowdBypassedIgnore": { 132 | "message": "האם נתיב זה שגוי?" 133 | }, 134 | "crowdBypassedOptions": { 135 | "message": "האם ברצונך לפתוח חלון זה באופן מיידי או תוך x שניות?" 136 | }, 137 | "blockedTitle": { 138 | "message": "עקיפה אוניברסלית מנעה את רישום ה- IP שלך." 139 | }, 140 | "blockedSubtitle": { 141 | "message": "לא רוצה שFastForward ימנע ממקורות רעים לקבל גישה לכתובת הIP שלך?" 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/_locales/hmn/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "不要浪費時間遵守法規。通用旁路繞過了惱人的鏈接縮短器。" 4 | }, 5 | "firstrunTitle": { 6 | "message": "感謝您安裝通用旁路!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "但是,您似乎正在使用與FastForward不兼容的NoScript或類似腳本。" 10 | }, 11 | "version": { 12 | "message": "版" 13 | }, 14 | "definitionsVersion": { 15 | "message": "繞過定義" 16 | }, 17 | "changelog": { 18 | "message": "變更日誌" 19 | }, 20 | "update": { 21 | "message": "檢查更新" 22 | }, 23 | "updating": { 24 | "message": "正在下載旁路定義..." 25 | }, 26 | "updateYes": { 27 | "message": "成功下載旁路定義。" 28 | }, 29 | "updateNo": { 30 | "message": "旁路定義是最新的。" 31 | }, 32 | "faq": { 33 | "message": "常見問題解答 (FAQ)" 34 | }, 35 | "bypassCounter": { 36 | "message": "FastForward $1 已經為您繞過了站點。" 37 | }, 38 | "support": { 39 | "message": "為通用旁路做貢獻。" 40 | }, 41 | "options": { 42 | "message": "選件" 43 | }, 44 | "optionsLink": { 45 | "message": "更改通用繞過選項。" 46 | }, 47 | "optionsEnabled": { 48 | "message": "啟用網站繞過。" 49 | }, 50 | "optionsTrackerBypass": { 51 | "message": "使用Apimon.de繞過跟踪器(例如bit.ly和t.co)。" 52 | }, 53 | "optionsInstantNavigationTrackers": { 54 | "message": "立即將我帶到追踪器的目的地。" 55 | }, 56 | "optionsBlockIPLoggers": { 57 | "message": "如果無法繞過IP記錄器,則將其阻止。" 58 | }, 59 | "optionsCrowdBypass": { 60 | "message": "給予和繞過不可逾越的起酥油的目的地。" 61 | }, 62 | "privacyPolicy": { 63 | "message": "隱私政策" 64 | }, 65 | "contributors": { 66 | "message": "貢獻者" 67 | }, 68 | "optionsUserscripts": { 69 | "message": "自定義繞過\n" 70 | }, 71 | "optionsUserscriptsDescription": { 72 | "message": "這是開發人員可以創建自己的腳本來繞過站點的高級功能。完善後,可以將它們提交到GitHub上以添加到FastForward,因此每個人都可以使用。" 73 | }, 74 | "beforeNavigate": { 75 | "message": "您快要到目的地了。" 76 | }, 77 | "beforeNavigateDestination": { 78 | "message": "您的目的地是 $1" 79 | }, 80 | "beforeNavigateUnsafe": { 81 | "message": "但是,如果您現在導航,他們將檢測到通用旁路。" 82 | }, 83 | "beforeNavigateTimer": { 84 | "message": "您將在幾秒鐘內自動重定向 $1。" 85 | }, 86 | "beforeNavigateTimerSingular": { 87 | "message": "您將在1秒內自動重定向。" 88 | }, 89 | "beforeNavigateOptions": { 90 | "message": "您要立即重定向還是在x秒內重定向?" 91 | }, 92 | "beforeNavigateInstant": { 93 | "message": "您正在導航到 $1" 94 | }, 95 | "infoFileHoster": { 96 | "message": "不幸的是,下載服務器將確保您等待之後才允許下載文件。" 97 | }, 98 | "infoOutdated": { 99 | "message": "較新版本的FastForward繞過了該網站。" 100 | }, 101 | "crowdWait": { 102 | "message": "不幸的是,您是第一個遇到此鏈接的人,但是在等待之後,其他通用繞過用戶將不再需要。" 103 | }, 104 | "crowdDisabled": { 105 | "message": "您已在選項中禁用了人群旁路,從而繞過了該網站。" 106 | }, 107 | "crowdBypassed": { 108 | "message": "您可能不必等待!" 109 | }, 110 | "crowdBypassedInfo": { 111 | "message": "其他通用繞過用戶已經在等您,並報告這導致 $1" 112 | }, 113 | "crowdBypassedTimer": { 114 | "message": "這將在幾秒鐘內在新標籤頁中打開 $1。" 115 | }, 116 | "crowdBypassedTimerSingular": { 117 | "message": "這將在1秒鐘內在新標籤頁中打開。" 118 | }, 119 | "crowdCloseTimer": { 120 | "message": "此標籤將在幾秒鐘內關閉 $1。" 121 | }, 122 | "crowdCloseTimerSingular": { 123 | "message": "此標籤將在1秒鐘內關閉。" 124 | }, 125 | "cancel": { 126 | "message": "取消。" 127 | }, 128 | "crowdBypassedIgnore": { 129 | "message": "這不正確嗎?" 130 | }, 131 | "crowdBypassedOptions": { 132 | "message": "您是否要立即或在x秒內在新標籤頁中打開它?" 133 | }, 134 | "blockedTitle": { 135 | "message": "通用旁路阻止您的IP被記錄。" 136 | }, 137 | "blockedSubtitle": { 138 | "message": "不想讓FastForward阻止不良行為者獲取您的IP嗎?" 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/_locales/hy-AM/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "Ne perdez pas votre temps avec la conformité. Le bypass universel évite les raccourcisseurs de liens gênants." 4 | }, 5 | "firstrunTitle": { 6 | "message": "Merci d'avoir installé FastForward!" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/_locales/ja/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "FastForwardは、迷惑な短縮リンクを回避します。コンプライアンスで時間を無駄にしないでください。" 4 | }, 5 | "firstrunTitle": { 6 | "message": "FastForwardをインストールしていただき、ありがとうございます!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "NoScriptなどを使用しているようですが、FastForwardとは互換性がありません。" 10 | }, 11 | "version": { 12 | "message": "バージョン" 13 | }, 14 | "definitionsVersion": { 15 | "message": "バイパス定義" 16 | }, 17 | "changelog": { 18 | "message": "変更履歴" 19 | }, 20 | "update": { 21 | "message": "アップデートを確認する" 22 | }, 23 | "updating": { 24 | "message": "バイパス定義をダウンロードしています..." 25 | }, 26 | "updateYes": { 27 | "message": "バイパス定義は正常にダウンロードされました。" 28 | }, 29 | "updateNo": { 30 | "message": "バイパス定義は最新です。" 31 | }, 32 | "faq": { 33 | "message": "よくある質問と回答(FAQ)" 34 | }, 35 | "bypassCounter": { 36 | "message": "FastForwardは、いままでに$1件のサイトをバイパスしました。" 37 | }, 38 | "support": { 39 | "message": "FastForwardに貢献する" 40 | }, 41 | "options": { 42 | "message": "オプション" 43 | }, 44 | "optionsLink": { 45 | "message": "オプションから変更できます。" 46 | }, 47 | "optionsEnabled": { 48 | "message": "ウェブサイトのバイパスを有効にする" 49 | }, 50 | "optionsNavigationDelay": { 51 | "message": "$1秒後にリンク先へ移動する" 52 | }, 53 | "optionsTrackerBypass": { 54 | "message": "Apimon.deを使ってトラッカー (bit.ly や t.coなど) をバイパスする" 55 | }, 56 | "optionsInstantNavigationTrackers": { 57 | "message": "すぐにトラッカーのリンク先へ移動する" 58 | }, 59 | "optionsBlockIPLoggers": { 60 | "message": "バイパスされなかった場合はIPアドレスがログされないように阻止する" 61 | }, 62 | "optionsCrowdBypass": { 63 | "message": "Crowd Bypass: バイパスできない短縮リンクの行き先を取得したり提供したりする" 64 | }, 65 | "optionsCrowdAutoOpen": { 66 | "message": "$1秒後に新しいタブでクラウドソーシング先を開く" 67 | }, 68 | "optionsCrowdAutoClose": { 69 | "message": "$1秒後にクラウドソーシング先を含むタブを閉じる" 70 | }, 71 | "privacyPolicy": { 72 | "message": "プライバシーポリシー" 73 | }, 74 | "contributors": { 75 | "message": "貢献者" 76 | }, 77 | "optionsUserscripts": { 78 | "message": "カスタムバイパス" 79 | }, 80 | "optionsUserscriptsDescription": { 81 | "message": "これは、開発者が独自のスクリプトを作成してサイトをバイパスするための高度な機能です。完成後、誰でも使えるように、GitHubに投稿してFastForwardに追加することもできます。" 82 | }, 83 | "beforeNavigate": { 84 | "message": "リンク先まであと少しです。" 85 | }, 86 | "beforeNavigateDestination": { 87 | "message": "リンク先は$1" 88 | }, 89 | "beforeNavigateUnsafe": { 90 | "message": "ただし、いま移動すると、サイトはFastForwardを検出してしまいます。" 91 | }, 92 | "beforeNavigateUnsafeTimer": { 93 | "message": "あと$1秒で検出されなくなります。" 94 | }, 95 | "beforeNavigateUnsafeTimerSingular": { 96 | "message": "あと1秒で検出されなくなります。" 97 | }, 98 | "beforeNavigateTimer": { 99 | "message": "$1秒後に自動的にリダイレクトされます。" 100 | }, 101 | "beforeNavigateTimerSingular": { 102 | "message": "1秒後に自動的にリダイレクトされます。" 103 | }, 104 | "beforeNavigateOptions": { 105 | "message": "すぐに、または数秒後にリダイレクトされるようにしたいですか?" 106 | }, 107 | "beforeNavigateInstant": { 108 | "message": "$1に移動しています" 109 | }, 110 | "infoLinkvertise": { 111 | "message": "このサイトのバイパスは許可されていませんが、私たちはこのサイトのもっとも迷惑な手順を除去するように交渉しました。" 112 | }, 113 | "infoFileHoster": { 114 | "message": "残念ながら、ダウンロードサーバーはファイルのダウンロードが許可される前に待機していることを確認します。" 115 | }, 116 | "infoOutdated": { 117 | "message": "このサイトは、FastForwardの新しいバージョンでバイパスされます。" 118 | }, 119 | "crowdWait": { 120 | "message": "残念ながら、あなたはこのリンクの最初のアクセス者です。しばらくすれば、他のFastForwardユーザーが待つ必要はなくなります。" 121 | }, 122 | "crowdDisabled": { 123 | "message": "このサイトは、Crowd Bypassを有効にしているときのみバイパスできます。オプションからこの設定をオンにすることができます。" 124 | }, 125 | "crowdBypassed": { 126 | "message": "もう待つ必要はありません!" 127 | }, 128 | "crowdBypassedInfo": { 129 | "message": "他のFastForwardユーザーがこのページを訪れたことがあり、$1に移動することを報告しています。" 130 | }, 131 | "crowdBypassedTimer": { 132 | "message": "$1秒後に新しいタブで開きます。" 133 | }, 134 | "crowdBypassedTimerSingular": { 135 | "message": "1秒後に新しいタブで開きます。" 136 | }, 137 | "crowdCloseTimer": { 138 | "message": "このタブは$1秒後に閉じられます。" 139 | }, 140 | "crowdCloseTimerSingular": { 141 | "message": "このタブは1秒後に閉じられます。" 142 | }, 143 | "cancel": { 144 | "message": "キャンセルする" 145 | }, 146 | "crowdBypassedIgnore": { 147 | "message": "正しくありませんか?" 148 | }, 149 | "crowdBypassedOptions": { 150 | "message": "すぐに、または数秒後に新しいタブで開かれるようにしたいですか?" 151 | }, 152 | "blockedTitle": { 153 | "message": "FastForwardは、あなたのIPアドレスがログされないように阻止しました。" 154 | }, 155 | "blockedSubtitle": { 156 | "message": "悪意のある人があなたのIPアドレスをログできないようにする機能をオフにしたいですか?" 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/_locales/ka/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "ნუ დაკარგავთ დროს. FastForward გამოტოვებს მომაბეზრებელ ბმულის შემამოკლებლებს." 4 | }, 5 | "firstrunTitle": { 6 | "message": "მადლობა FastForward დაყენებისთვის!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "შესაძლოა თქვენ იყენებთ NoScript ან სხვა მასგავს გაფართოებას, რომელიც არ არის თავსებადი FastForward-თან" 10 | }, 11 | "version": { 12 | "message": "ვერსია" 13 | }, 14 | "definitionsVersion": { 15 | "message": "გამოტოვების წესები" 16 | }, 17 | "changelog": { 18 | "message": "ცვლილებელის ისტორია" 19 | }, 20 | "update": { 21 | "message": "განახლების შემოწმება" 22 | }, 23 | "updating": { 24 | "message": "გამოტოვების წესები ითვირთება..." 25 | }, 26 | "updateYes": { 27 | "message": "გამოტოვების წესები წარმატებით ჩამოიტვირთა." 28 | }, 29 | "updateNo": { 30 | "message": "გამოტოვების წესები განახლებულია." 31 | }, 32 | "faq": { 33 | "message": "ხშირად დასმული კითხვები" 34 | }, 35 | "bypassCounter": { 36 | "message": "FastForward-მა გამოტოვა $1 გვერდი თქვენთვის." 37 | }, 38 | "support": { 39 | "message": "შეიტანეთ თქვენი წვლილი." 40 | }, 41 | "options": { 42 | "message": "პარამეტრები" 43 | }, 44 | "optionsLink": { 45 | "message": "შეცვალეთ პარამეტრები." 46 | }, 47 | "optionsEnabled": { 48 | "message": "ok" 49 | }, 50 | "optionsNavigationDelay": { 51 | "message": "ავტომატური გადასვლა $1 წამში" 52 | }, 53 | "optionsBlockIPLoggers": { 54 | "message": "დაბლოკე იპ ლოგერები თუ შემოვლა არ მუშაობს" 55 | }, 56 | "privacyPolicy": { 57 | "message": "კონფიდენციალურობის პოლიტიკა" 58 | }, 59 | "contributors": { 60 | "message": "წვლილის შემტანები" 61 | }, 62 | "optionsUserscripts": { 63 | "message": "არაოფიციალური შემოსავლები" 64 | }, 65 | "beforeNavigate": { 66 | "message": "თითქმით მისული ხარტ თქვენ ვებსაიტზე" 67 | }, 68 | "beforeNavigateDestination": { 69 | "message": "დანიშნულების მისამართი $1" 70 | }, 71 | "beforeNavigateUnsafe": { 72 | "message": "თუ ეხლა გადახვალთ საიტზე ისინი დააფიქსირებენ FastForward." 73 | }, 74 | "beforeNavigateUnsafeTimer": { 75 | "message": "თქვენ არ იქნებით დაფიქსირებული $1 წამში" 76 | }, 77 | "beforeNavigateUnsafeTimerSingular": { 78 | "message": "თქვენ არ იქნებით დაფიქსირებული 1 წამში" 79 | }, 80 | "beforeNavigateTimer": { 81 | "message": "თქვენ გადამისამართდებით ავტომატურად $1 წამში" 82 | }, 83 | "beforeNavigateTimerSingular": { 84 | "message": "თქვენ გადამისამართდებით ავტომატურად 1 წამში" 85 | }, 86 | "beforeNavigateOptions": { 87 | "message": "გსურთ გადამისამართება მომენტალურად ან x წამში?" 88 | }, 89 | "beforeNavigateInstant": { 90 | "message": "FastForward-ერი ეხლა წაგიყვანთ $1" 91 | }, 92 | "infoFileHoster": { 93 | "message": "სამწუხაროდ, გადმოწერის სერვერი ამოწმებს დაელოდეთ თუ არა შესაბამისი დრო ფაილის გადმოსაწერად." 94 | }, 95 | "infoOutdated": { 96 | "message": "ამ ვებსაიტის შემოვლა შესაძლებელია მხოლოდ FastForward-ის ახალი ვერსიით" 97 | }, 98 | "crowdWait": { 99 | "message": "სამწუხაროდ, თქვენ ხართ პირველი მომხმარებელი, ვინც გახსნა ეს ბმული. სხვა მომხმარებლებს თქვენს შემდეგ აღარ მოუწევთ ლოდინი." 100 | }, 101 | "crowdBypassed": { 102 | "message": "თქვენ არ გჭირდებათ ლოდინი" 103 | }, 104 | "crowdBypassedInfo": { 105 | "message": "FastForward-ის სხვა მომხმარებლები დაელოდნენ თქვენს მაგივრად და შეგვატყობინეს რომ ეს მისამართი გადამისამართდება $1 -ზე." 106 | }, 107 | "crowdBypassedTimer": { 108 | "message": "და ის გაიხსნება $1 წამში." 109 | }, 110 | "crowdBypassedTimerSingular": { 111 | "message": "და ის გაიხსნება 1 წამში." 112 | }, 113 | "crowdCloseTimer": { 114 | "message": "ეს ჩანართი დაიხურება $1 წამში." 115 | }, 116 | "crowdCloseTimerSingular": { 117 | "message": "ეს ჩანართი დაიხურება 1 წამში." 118 | }, 119 | "cancel": { 120 | "message": "გაუქმება" 121 | }, 122 | "crowdBypassedIgnore": { 123 | "message": "ეს არასწორია?" 124 | }, 125 | "crowdBypassedOptions": { 126 | "message": "გსურთ გახსნა მომენტალურად ან x წამში?" 127 | }, 128 | "blockedTitle": { 129 | "message": "FastForward-მა დაგიცვათ თქვენი IP-ს დამახსოვრებისგან.\n" 130 | }, 131 | "blockedSubtitle": { 132 | "message": "არ გინდათ FastForwarder-მა რო დაგიცვას ცუდი ადამიანებისგან თქვენი მდებარეობა რო არ გაიგონ?" 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/_locales/ko/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "시간을 낭비하지 마세요. FastForward로 성가신 링크 단축 서비스를 자동 생략하세요." 4 | }, 5 | "firstrunTitle": { 6 | "message": "FastForward를 설치해 주셔서 감사합니다!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "흠, NoScript나 비슷한 걸 쓰는 것 같지만, FastForward는 그런 것들과 호환되지 않습니다." 10 | }, 11 | "version": { 12 | "message": "버전" 13 | }, 14 | "definitionsVersion": { 15 | "message": "우회 정의" 16 | }, 17 | "changelog": { 18 | "message": "변경 사항" 19 | }, 20 | "update": { 21 | "message": "업데이트 확인" 22 | }, 23 | "updating": { 24 | "message": "바이 패스 정의 다운로드 중 ..." 25 | }, 26 | "updateYes": { 27 | "message": "인젝션 스크립트를 업데이트하는데 성공했습니다!" 28 | }, 29 | "updateNo": { 30 | "message": "인젝션 스크립트가 이미 최신입니다." 31 | }, 32 | "faq": { 33 | "message": "자주 묻는 질문" 34 | }, 35 | "bypassCounter": { 36 | "message": "FastForward는 당신을 위해 $1개의 사이트를 우회했어요." 37 | }, 38 | "support": { 39 | "message": "FastForward 돕기" 40 | }, 41 | "options": { 42 | "message": "설정" 43 | }, 44 | "optionsLink": { 45 | "message": "FastForward의 설정을 바꾸기" 46 | }, 47 | "optionsEnabled": { 48 | "message": "웹사이트 우회 켜기" 49 | }, 50 | "optionsNavigationDelay": { 51 | "message": "목적지로 $1초 뒤에 이동하기 (0을 쓰면 즉시 이동)" 52 | }, 53 | "optionsTrackerBypass": { 54 | "message": "Apimon.de를 사용하여 트래커 (예 : bit.ly 및 t.co)를 무시하십시오." 55 | }, 56 | "optionsInstantNavigationTrackers": { 57 | "message": "즉시 추적기의 목적지로 보내기" 58 | }, 59 | "optionsBlockIPLoggers": { 60 | "message": "우회할 수 없는 사이트의 IP 기록 차단하기." 61 | }, 62 | "optionsCrowdBypass": { 63 | "message": "우회할 수 없는 URL 단축 사이트 목적지 주고 받기." 64 | }, 65 | "optionsCrowdAutoOpen": { 66 | "message": "$1초 후 새 탭에서 크라우드 소싱 대상 열기 (0 = 즉시)" 67 | }, 68 | "optionsCrowdAutoClose": { 69 | "message": "크라우드소싱 대상 방문 $1초 후 해당 탭 닫기." 70 | }, 71 | "privacyPolicy": { 72 | "message": "개인정보 취급방침" 73 | }, 74 | "contributors": { 75 | "message": "도와주신 분들" 76 | }, 77 | "optionsUserscripts": { 78 | "message": "사용자 지정 우회책" 79 | }, 80 | "optionsUserscriptsDescription": { 81 | "message": "개발자를 위한 고급 기능으로 자체 우회책을 만들 수 있습니다. 완벽하게 만들어졌다면, GitHub에 제안해 FastForward에 추가되고 모두가 쓸 수 있게 됩니다." 82 | }, 83 | "beforeNavigate": { 84 | "message": "거의 다 왔습니다." 85 | }, 86 | "beforeNavigateDestination": { 87 | "message": "목적지는 $1 입니다." 88 | }, 89 | "beforeNavigateUnsafe": { 90 | "message": "잠깐!, 지금 바로 간다면 FastForward가 들통날 거에요." 91 | }, 92 | "beforeNavigateUnsafeTimer": { 93 | "message": "$1초 후에 감지되지 않게 됩니다." 94 | }, 95 | "beforeNavigateUnsafeTimerSingular": { 96 | "message": "1초 후에 감지되지 않게 됩니다." 97 | }, 98 | "beforeNavigateTimer": { 99 | "message": "페이지로 $1초 안에 이동합니다." 100 | }, 101 | "beforeNavigateTimerSingular": { 102 | "message": "페이지로 1초 안에 이동합니다." 103 | }, 104 | "beforeNavigateOptions": { 105 | "message": "자동으로 리다이렉트하고 싶나요?" 106 | }, 107 | "beforeNavigateInstant": { 108 | "message": "$1 (으)로 이동 중입니다" 109 | }, 110 | "infoLinkvertise": { 111 | "message": "우리는 이 웹 사이트를 우회 할 수는 없지만, 가장 귀찮은 단계를 제거하기로 협상했습니다." 112 | }, 113 | "infoFileHoster": { 114 | "message": "불행히도, 다운로드 서버가 당신이 실제로 파일을 받기 위해 기다렸는지 확인하기 때문에 건너뛸 수 없습니다." 115 | }, 116 | "infoOutdated": { 117 | "message": "이 사이트는 FastForward를 업데이트 해야 건너뛸 수 있습니다." 118 | }, 119 | "crowdWait": { 120 | "message": "안타깝게도 이 링크의 첫 발견자신 것 같군요. 기다려주신다면 다른 사용자 분들은 기다리지 않으실 수 있어요." 121 | }, 122 | "crowdDisabled": { 123 | "message": "이 사이트는 crowd bypass에 의해서만 통과할 수 있습니다. 설정에서 이 옵션을 켤 수 있습니다." 124 | }, 125 | "crowdBypassed": { 126 | "message": "이제 기다릴 필요 없어요!" 127 | }, 128 | "crowdBypassedInfo": { 129 | "message": "다른 FastForward 사용자가 이 페이지를 방문한 적이 있으며, $1 로 이동하는걸로 알아냈습니다." 130 | }, 131 | "crowdBypassedTimer": { 132 | "message": "페이지가 새 탭에 $1초 안에 열립니다." 133 | }, 134 | "crowdBypassedTimerSingular": { 135 | "message": "페이지가 새 탭에 1초 안에 열립니다." 136 | }, 137 | "crowdCloseTimer": { 138 | "message": "이 탭은 $1초 후 닫힙니다." 139 | }, 140 | "crowdCloseTimerSingular": { 141 | "message": "이 탭은 1초 후 닫힙니다." 142 | }, 143 | "cancel": { 144 | "message": "취소" 145 | }, 146 | "crowdBypassedIgnore": { 147 | "message": "올바르지 않나요?" 148 | }, 149 | "crowdBypassedOptions": { 150 | "message": "자동으로 이동하고 싶나요?" 151 | }, 152 | "blockedTitle": { 153 | "message": "FastForward가 당신의 IP를 기록하지 못하게 막았습니다." 154 | }, 155 | "blockedSubtitle": { 156 | "message": "FastForward가 악성 사이트에서 IP를 가져가는것을 막기를 원하나요?" 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/_locales/lo/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "ຢ່າເສຍເວລາຂອງທ່ານດ້ວຍການປະຕິບັດຕາມ. FastForward ຫລີກລ້ຽງການເຊື່ອມຕໍ່ສັ້ນທີ່ ໜ້າ ຮໍາຄານ" 4 | }, 5 | "firstrunTitle": { 6 | "message": "ຂອບໃຈ ສຳ ລັບຕິດຕັ້ງ FastForward!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "ເຖິງຢ່າງໃດກໍ່ຕາມ, ທ່ານເບິ່ງຄືວ່າ ກຳ ລັງໃຊ້ NoScript ຫຼືຄ້າຍຄືກັນ, ເຊິ່ງ FastForward ບໍ່ເຂົ້າກັນ." 10 | }, 11 | "version": { 12 | "message": "ຮຸ່ນ" 13 | }, 14 | "definitionsVersion": { 15 | "message": "ຄຳ ນິຍາມບິດເບືອນ" 16 | }, 17 | "changelog": { 18 | "message": "Changelog" 19 | }, 20 | "update": { 21 | "message": "ກວດເບິ່ງການປັບປຸງ..." 22 | }, 23 | "updating": { 24 | "message": "ກຳ ລັງດາວໂຫລດ ຄຳ ນິຍາມ bypass ..." 25 | }, 26 | "updateYes": { 27 | "message": "ການດາວໂຫລດ ຄຳ ນິຍາມ bypass ສຳ ເລັດແລ້ວ." 28 | }, 29 | "updateNo": { 30 | "message": "ນິຍາມ Bypass ແມ່ນທັນສະ ໄໝ." 31 | }, 32 | "faq": { 33 | "message": "ຄໍາ​ຖາມ​ທີ່​ຖືກ​ຖາມ​ເລື້ອຍໆ" 34 | }, 35 | "support": { 36 | "message": "ປະກອບສ່ວນໃຫ້ FastForward." 37 | }, 38 | "options": { 39 | "message": "ທາງເລືອກ" 40 | }, 41 | "optionsLink": { 42 | "message": "ປ່ຽນຕົວເລືອກ FastForward." 43 | }, 44 | "optionsEnabled": { 45 | "message": "ເປີດ ນຳ ໃຊ້ເວັບໄຊທ໌ຂ້າມຜ່ານ." 46 | }, 47 | "optionsNavigationDelay": { 48 | "message": "ພາຂ້ອຍໄປທີ່ຈຸດ ໝາຍ ປາຍທາງຫຼັງຈາກ $1 ວິນາທີ." 49 | }, 50 | "optionsTrackerBypass": { 51 | "message": "ຜູ້ຕິດຕາມ Bypass (ເຊັ່ນ: bit.ly ແລະ t.co) ໂດຍໃຊ້ Apimon.de" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/_locales/mi/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "optionsUserscripts": { 3 | "message": "Custom Bypasses" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/_locales/no/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "Ikke kast bort tiden din på å følge krav. FastForward hopper automatisk over irriterende lenkeforkortere." 4 | }, 5 | "firstrunTitle": { 6 | "message": "Takk for at du har installert FastForward!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "Men du ser ut til å bruke NoScript eller noe lignende, som FastForward ikke er kompatibel med." 10 | }, 11 | "version": { 12 | "message": "Versjon" 13 | }, 14 | "definitionsVersion": { 15 | "message": "Bypass definisjoner" 16 | }, 17 | "changelog": { 18 | "message": "Endringslogg" 19 | }, 20 | "update": { 21 | "message": "Se etter oppdateringer" 22 | }, 23 | "updating": { 24 | "message": "Laster ned bypass-definisjoner..." 25 | }, 26 | "updateYes": { 27 | "message": "Oppdateringsskriptet ble oppdatert!" 28 | }, 29 | "updateNo": { 30 | "message": "Forbigående definisjoner er oppdatert." 31 | }, 32 | "faq": { 33 | "message": "Ofte Stilte Spørsmål (FAQ)" 34 | }, 35 | "bypassCounter": { 36 | "message": "FastForward har allerede forbigått $1 nettsteder for deg." 37 | }, 38 | "support": { 39 | "message": "Støtt FastForward." 40 | }, 41 | "options": { 42 | "message": "Innstillinger" 43 | }, 44 | "optionsLink": { 45 | "message": "Endre FastForward sine innstillinger." 46 | }, 47 | "optionsEnabled": { 48 | "message": "Slå på nettside bypass." 49 | }, 50 | "optionsNavigationDelay": { 51 | "message": "Ta meg til destinasjoner etter $1 sekund(er). (Bruk 0 for å navigere øyeblikkelig.)" 52 | }, 53 | "optionsTrackerBypass": { 54 | "message": "Omgå for trackere (for eksempel bit.ly og t.co) ved å bruke Apimon.de." 55 | }, 56 | "optionsInstantNavigationTrackers": { 57 | "message": "Ta meg til destinasjoner av trackere med en gang." 58 | }, 59 | "optionsBlockIPLoggers": { 60 | "message": "Blokker IP-loggførere dersom de ikke kan bli hoppet forbi." 61 | }, 62 | "optionsCrowdBypass": { 63 | "message": "Gi og ta ankomstpunktene til upasserbare forkortere." 64 | }, 65 | "optionsCrowdAutoOpen": { 66 | "message": "Åpne publikumsdestinasjoner i en ny fane etter $1 sekund(er). (0 = øyeblikkelig.)" 67 | }, 68 | "privacyPolicy": { 69 | "message": "Privatlivsretningslinjer" 70 | }, 71 | "optionsUserscripts": { 72 | "message": "Tilpassede forbipasserere" 73 | }, 74 | "optionsUserscriptsDescription": { 75 | "message": "Dette er en avansert funksjon for utviklere å lage sine egne skript for å omgå nettsteder. Når de er perfeksjonert, kan de deretter sendes inn på GitHub for å bli lagt til FastForward, slik at de er tilgjengelige for alle." 76 | }, 77 | "beforeNavigate": { 78 | "message": "Du er nesten i destinasjonen din." 79 | }, 80 | "beforeNavigateDestination": { 81 | "message": "Destinasjonen din er $1" 82 | }, 83 | "beforeNavigateTimer": { 84 | "message": "Du blir omdirigert automatisk om $1 sekunder." 85 | }, 86 | "beforeNavigateTimerSingular": { 87 | "message": "Du blir omdirigert automatisk i løpet av 1 sekund." 88 | }, 89 | "beforeNavigateOptions": { 90 | "message": "Vil du bli omdirigert øyeblikkelig eller om x sekunder?" 91 | }, 92 | "crowdWait": { 93 | "message": "Dessverre er du den første som møter denne lenken, men etter at du har ventet, vil andre brukere av FastForward ikke lenger behøve å gjøre det." 94 | }, 95 | "crowdDisabled": { 96 | "message": "Dette nettstedet omgås av publikumsomgang, som du har deaktivert under alternativene." 97 | }, 98 | "crowdBypassed": { 99 | "message": "Du vil kanskje ikke måtte vente!" 100 | }, 101 | "crowdBypassedInfo": { 102 | "message": "Andre FastForward-brukere har allerede ventet på deg, og har meldt ifra om at dette fører til $1" 103 | }, 104 | "crowdBypassedTimer": { 105 | "message": "Dette åpnes i en ny fane om $1 sekunder." 106 | }, 107 | "crowdBypassedTimerSingular": { 108 | "message": "Dette åpnes i en ny fane om 1 sekund." 109 | }, 110 | "cancel": { 111 | "message": "Avbryt." 112 | }, 113 | "crowdBypassedIgnore": { 114 | "message": "Var ikke dette korrekt?" 115 | }, 116 | "crowdBypassedOptions": { 117 | "message": "Vil du at dette skal åpnes i en ny fane øyeblikkelig eller om x sekunder?" 118 | }, 119 | "blockedTitle": { 120 | "message": "FastForward hindret IP-adressen din fra å bli loggført." 121 | }, 122 | "blockedSubtitle": { 123 | "message": "Vil du at FastForward skal stoppe dårlige folk fra å få IPen din?" 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/_locales/sh/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "Ne gubite vreme na komplikacije. FastForward zaobilazi dosadne link shortenere." 4 | }, 5 | "firstrunTitle": { 6 | "message": "Hvala vam za instaliranje FastForward!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "Međutim, izgleda da koristite NoScript ili slično, s čime FastForward nije kompatibilan." 10 | }, 11 | "version": { 12 | "message": "Verzija" 13 | }, 14 | "definitionsVersion": { 15 | "message": "Definicija bypassera" 16 | }, 17 | "changelog": { 18 | "message": "Promene" 19 | }, 20 | "update": { 21 | "message": "Proveri ima li ažuriranja" 22 | }, 23 | "updating": { 24 | "message": "Preuzimanje definicije bypassera..." 25 | }, 26 | "updateYes": { 27 | "message": "Uspešno instaliran bypass" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/_locales/sl/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "Ne zapravljajte časa s skladnostjo. Univerzalni bypass obide nadležne krajšave povezav." 4 | }, 5 | "firstrunTitle": { 6 | "message": "Hvala, ker ste namestili FastForward!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "Vendar se zdi, da uporabljate NoScript ali podobno, s čimer FastForward ni združljiv." 10 | }, 11 | "version": { 12 | "message": "Različica" 13 | }, 14 | "definitionsVersion": { 15 | "message": "Opredelitve definicij" 16 | }, 17 | "changelog": { 18 | "message": "Dnevnik sprememb" 19 | }, 20 | "update": { 21 | "message": "Preveri za posodobitve" 22 | }, 23 | "updating": { 24 | "message": "Prenos definicij bypass ..." 25 | }, 26 | "updateYes": { 27 | "message": "Definicije bypass so uspešno prenesene." 28 | }, 29 | "updateNo": { 30 | "message": "Definicije bypass so posodobljene." 31 | }, 32 | "faq": { 33 | "message": "Pogosta vprašanja (FAQ)" 34 | }, 35 | "bypassCounter": { 36 | "message": "FastForward je že zaobšel$1 spletnih mest za vas." 37 | }, 38 | "support": { 39 | "message": "Prispevajte k Univerzalni obvoznici." 40 | }, 41 | "options": { 42 | "message": "Opcije" 43 | }, 44 | "optionsLink": { 45 | "message": "Spremeni možnosti FastForward '." 46 | }, 47 | "optionsEnabled": { 48 | "message": "Omogoči obhode spletnih strani" 49 | }, 50 | "optionsNavigationDelay": { 51 | "message": "Odpeljite me do cilja po$1 sekundah." 52 | }, 53 | "optionsTrackerBypass": { 54 | "message": "S storitvijo Apimon.de obiščite sledilnike (na primer bit.ly in t.co)." 55 | }, 56 | "optionsInstantNavigationTrackers": { 57 | "message": "Takoj me popeljejo na destinacije sledilcev." 58 | }, 59 | "optionsBlockIPLoggers": { 60 | "message": "Blokirajte zapisovalnike IP, če jih ni mogoče zaobiti." 61 | }, 62 | "optionsCrowdBypass": { 63 | "message": "Množični obvoz: Določite in izkoristite cilje neprimerljivih skrajševalcev." 64 | }, 65 | "optionsCrowdAutoOpen": { 66 | "message": "Po$1 sekundah odprite nove cilje na novem zavihku na novem zavihku." 67 | }, 68 | "optionsCrowdAutoClose": { 69 | "message": "Zaprite zavihek, ki vsebuje destinacijo z množico ljudi po$1 sekunde obiska." 70 | }, 71 | "privacyPolicy": { 72 | "message": "Politika zasebnosti" 73 | }, 74 | "contributors": { 75 | "message": "Sodelujoči" 76 | }, 77 | "optionsUserscripts": { 78 | "message": "Obvoznice po meri" 79 | }, 80 | "optionsUserscriptsDescription": { 81 | "message": "To je napredna funkcija za razvijalce, da ustvarijo svoje skripte za obhod spletnih mest. Ko bodo izpopolnjeni, jih je mogoče nato poslati na GitHub in jih dodati FastForward, tako da so na voljo vsem." 82 | }, 83 | "beforeNavigate": { 84 | "message": "Skoraj že ste na svojem cilju." 85 | }, 86 | "beforeNavigateDestination": { 87 | "message": "Vaš cilj je$1" 88 | }, 89 | "beforeNavigateUnsafe": { 90 | "message": "Če pa greste zdaj, bodo zaznali FastForward." 91 | }, 92 | "beforeNavigateUnsafeTimer": { 93 | "message": "V$1 sekundah ne boste več zaznani." 94 | }, 95 | "beforeNavigateUnsafeTimerSingular": { 96 | "message": "V 1 sekundi ne boste več zaznani." 97 | }, 98 | "beforeNavigateTimer": { 99 | "message": "Preusmerjeni boste samodejno v$1 sekundah." 100 | }, 101 | "beforeNavigateTimerSingular": { 102 | "message": "V 1 sekundi boste samodejno preusmerjeni." 103 | }, 104 | "beforeNavigateOptions": { 105 | "message": "Ali želite biti preusmerjeni takoj ali v x sekundah?" 106 | }, 107 | "beforeNavigateInstant": { 108 | "message": "Navigirate do$1" 109 | }, 110 | "infoFileHoster": { 111 | "message": "Na žalost bo strežnik za prenos poskrbel, da ste čakali, preden boste dovolili prenos datoteke." 112 | }, 113 | "infoOutdated": { 114 | "message": "To spletno mesto obide novejša različica FastForward." 115 | }, 116 | "crowdWait": { 117 | "message": "Na žalost ste prvič naleteli na to povezavo, vendar po tem, ko ste čakali, drugim uporabnikom FastForward-a ne bo več treba." 118 | }, 119 | "crowdDisabled": { 120 | "message": "To spletno mesto obide množica bypass, kar lahko omogočite v možnostih." 121 | }, 122 | "crowdBypassed": { 123 | "message": "Morda ne bo treba čakati!" 124 | }, 125 | "crowdBypassedInfo": { 126 | "message": "Drugi uporabniki FastForward-a so vas že čakali in sporočili, da to vodi do$1" 127 | }, 128 | "crowdBypassedTimer": { 129 | "message": "To se odpre v novem zavihku v$1 sekundah." 130 | }, 131 | "crowdBypassedTimerSingular": { 132 | "message": "To se odpre v novem zavihku v 1 sekundi." 133 | }, 134 | "crowdCloseTimer": { 135 | "message": "Ta zavihek se zapre v$1 sekundah." 136 | }, 137 | "crowdCloseTimerSingular": { 138 | "message": "Ta zavihek se zapre v 1 sekundi." 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/_locales/su/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "Ulah nyia-nyia keun waktos nurut kana aturan. FastForward bakal otomatis ngalangkungan alamat nu matak ngagganggu. " 4 | }, 5 | "firstrunTitle": { 6 | "message": "Hatur nuhun parantos masang FastForward!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "Nanging, anjeun sigana nganggo ekstensi NoScript atawa nu sajabana, nyebabkeun FastForward teu jalan." 10 | }, 11 | "version": { 12 | "message": "Vérsi" 13 | }, 14 | "definitionsVersion": { 15 | "message": "Pangertian Bypass" 16 | }, 17 | "changelog": { 18 | "message": "Catetan parobahan" 19 | }, 20 | "update": { 21 | "message": "Marios pambaharuan" 22 | }, 23 | "updating": { 24 | "message": "Ngunduh definisi bypass..." 25 | }, 26 | "updateYes": { 27 | "message": "Rengse ngunduh definisi bypass." 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/_locales/uz/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "Vaqtingizni moslashtirish uchun bekorga ketkazmang. FastForward sizga veb manzillarni qisqartirishda ko'mak beradi." 4 | }, 5 | "firstrunTitle": { 6 | "message": "FastForwardni o'rnatganingiz uchun rahmat!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "Siz FastForwardga mos bo'lmagan NoScript yoki shunga o'xshash dasturdan foydalanayotgangan o'xshaysiz." 10 | }, 11 | "version": { 12 | "message": "Versiya" 13 | }, 14 | "definitionsVersion": { 15 | "message": "Bypass ta'riflari" 16 | }, 17 | "changelog": { 18 | "message": "Holati" 19 | }, 20 | "update": { 21 | "message": "Yangilanishlar uchun tekshirish" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/_locales/zh-CN/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "不要费时等待,FastForward 可以帮你规避烦人的短链接。" 4 | }, 5 | "firstrunTitle": { 6 | "message": "感谢您安装 FastForward!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "看起来您正在使用 NoScript 或类似工具,FastForward 暂不与之兼容。" 10 | }, 11 | "version": { 12 | "message": "版本" 13 | }, 14 | "definitionsVersion": { 15 | "message": "Bypass的定义" 16 | }, 17 | "changelog": { 18 | "message": "更新记录" 19 | }, 20 | "update": { 21 | "message": "检查更新" 22 | }, 23 | "updating": { 24 | "message": "正在下载Bypass 的定义..." 25 | }, 26 | "updateYes": { 27 | "message": "Bypass的定义下载成功。" 28 | }, 29 | "updateNo": { 30 | "message": "Bypass的定义已是最新版本。" 31 | }, 32 | "faq": { 33 | "message": "常见问题(FAQ)" 34 | }, 35 | "bypassCounter": { 36 | "message": "FastForward已经帮你跳过了$1的网站" 37 | }, 38 | "support": { 39 | "message": "支持FastForward." 40 | }, 41 | "options": { 42 | "message": "选项" 43 | }, 44 | "optionsLink": { 45 | "message": "更改FastForward的选项" 46 | }, 47 | "optionsEnabled": { 48 | "message": "启用网站跳过功能" 49 | }, 50 | "optionsNavigationDelay": { 51 | "message": "在$1秒后跳到目标网站.(0 为立刻跳转.)" 52 | }, 53 | "optionsTrackerBypass": { 54 | "message": "跳过使用Apimon.de的追踪器(比如bit.ly和t.co)。" 55 | }, 56 | "optionsInstantNavigationTrackers": { 57 | "message": "立即将我带到追踪器的目的网址。" 58 | }, 59 | "optionsBlockIPLoggers": { 60 | "message": "如果无法绕过IP记录器,则将其屏蔽。\n" 61 | }, 62 | "optionsCrowdBypass": { 63 | "message": "分享/获取无法跳过的短地址提供商的目的网址。" 64 | }, 65 | "optionsCrowdAutoOpen": { 66 | "message": "$1秒后在新标签页打开人们分享的目的网址。" 67 | }, 68 | "optionsCrowdAutoClose": { 69 | "message": "访问人们分享的目的网址$1秒后将其标签页关闭。" 70 | }, 71 | "privacyPolicy": { 72 | "message": "隐私政策" 73 | }, 74 | "contributors": { 75 | "message": "贡献者" 76 | }, 77 | "optionsUserscripts": { 78 | "message": "自定义跳过" 79 | }, 80 | "optionsUserscriptsDescription": { 81 | "message": "此高级功能供开发者创建自己的绕过脚本。完善以后,这些脚本可以提交到GitHub上,再添加到FastForward中,让所有人都能使用。" 82 | }, 83 | "beforeNavigate": { 84 | "message": "您即将到达目的网址。" 85 | }, 86 | "beforeNavigateDestination": { 87 | "message": "您的目的网址为$1" 88 | }, 89 | "beforeNavigateUnsafe": { 90 | "message": "如果您马上跳转,他们将会检测到FastForward。" 91 | }, 92 | "beforeNavigateUnsafeTimer": { 93 | "message": "$1秒后,您将不再被检测到。" 94 | }, 95 | "beforeNavigateUnsafeTimerSingular": { 96 | "message": "1秒后,您将在不再被检测到。" 97 | }, 98 | "beforeNavigateTimer": { 99 | "message": "$1秒后,您将被自动导航到目的网站。" 100 | }, 101 | "beforeNavigateTimerSingular": { 102 | "message": "1秒后,您将被自动导航到目的网站。" 103 | }, 104 | "beforeNavigateOptions": { 105 | "message": "您想立刻导航到目的网站还是在x秒后?" 106 | }, 107 | "beforeNavigateInstant": { 108 | "message": "您正在导航到$1" 109 | }, 110 | "infoLinkvertise": { 111 | "message": "我们不允许绕过这个网站,但我们已经通过谈判取消了他们最烦人的步骤。" 112 | }, 113 | "infoFileHoster": { 114 | "message": "很不辛的是,下载服务器会确保您已经等待,然后才允许您下载文件。" 115 | }, 116 | "infoOutdated": { 117 | "message": "该网站已被新版本的FastForward跳转。" 118 | }, 119 | "crowdWait": { 120 | "message": "很抱歉您是第一个点击此链接的人,过一段时间以后,其他FastForward用户将不再需要等待。" 121 | }, 122 | "crowdDisabled": { 123 | "message": "该网站需使用群众分享跳过功能,但您已禁用此功能。" 124 | }, 125 | "crowdBypassed": { 126 | "message": "您或许不必等待!" 127 | }, 128 | "crowdBypassedInfo": { 129 | "message": "其他FastForward用户已经帮您导航,并报告该链接的目的网址为$1" 130 | }, 131 | "crowdBypassedTimer": { 132 | "message": "$1秒后将会在新标签页打开。" 133 | }, 134 | "crowdBypassedTimerSingular": { 135 | "message": "1秒后将会在新标签页打开。" 136 | }, 137 | "crowdCloseTimer": { 138 | "message": "此选项卡将在$1秒后关闭。" 139 | }, 140 | "crowdCloseTimerSingular": { 141 | "message": "此选项卡将在1秒后关闭。" 142 | }, 143 | "cancel": { 144 | "message": "取消" 145 | }, 146 | "crowdBypassedIgnore": { 147 | "message": "该信息不正确?" 148 | }, 149 | "crowdBypassedOptions": { 150 | "message": "您想在新标签页中立刻打开还是在x秒后?" 151 | }, 152 | "blockedTitle": { 153 | "message": "FastForward阻止了您的IP地址被记录" 154 | }, 155 | "blockedSubtitle": { 156 | "message": "不想要FastForward阻止不良分子获取您的IP地址?" 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/_locales/zh-TW/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "appDesc": { 3 | "message": "別浪費時間在等待上!FastForward 能夠全自動地繞過煩人的短連結!" 4 | }, 5 | "firstrunTitle": { 6 | "message": "感謝您安裝 FastForward!" 7 | }, 8 | "firstrunNoScript": { 9 | "message": "然而,您似乎安裝了 NoScript 或類似的插件,導致與 FastForward 造成衝突。" 10 | }, 11 | "version": { 12 | "message": "版本" 13 | }, 14 | "definitionsVersion": { 15 | "message": "繞過規則定義" 16 | }, 17 | "changelog": { 18 | "message": "更新紀錄" 19 | }, 20 | "update": { 21 | "message": "檢查更新" 22 | }, 23 | "updating": { 24 | "message": "下載規則定義" 25 | }, 26 | "updateYes": { 27 | "message": "成功更新注入腳本!" 28 | }, 29 | "updateNo": { 30 | "message": "繞過規則定義已是最新版本。" 31 | }, 32 | "faq": { 33 | "message": "常見問答 (FAQ)" 34 | }, 35 | "bypassCounter": { 36 | "message": "FastForward 已幫您繞過$1個網站。" 37 | }, 38 | "support": { 39 | "message": "幫助 FastForward" 40 | }, 41 | "options": { 42 | "message": "選項" 43 | }, 44 | "optionsLink": { 45 | "message": "設定 FastForward 的選項" 46 | }, 47 | "optionsEnabled": { 48 | "message": "啟用網站繞過功能" 49 | }, 50 | "optionsNavigationDelay": { 51 | "message": "在$1秒後轉移到目標連結。 (輸入0可以瞬間轉移)" 52 | }, 53 | "optionsTrackerBypass": { 54 | "message": "繞過使用Apimon.de的追踪器(比如bit.ly和t.co)。" 55 | }, 56 | "optionsInstantNavigationTrackers": { 57 | "message": "跳過追蹤紀錄器,直接帶我到目的地。" 58 | }, 59 | "optionsBlockIPLoggers": { 60 | "message": "若實在無法繞過,直接禁止瀏覽器訪問IP記錄網站。" 61 | }, 62 | "optionsCrowdBypass": { 63 | "message": "對於無法繞過的短連結,直接帶我到短連結頁面。" 64 | }, 65 | "optionsCrowdAutoOpen": { 66 | "message": "在$1秒後轉移到用戶提供的連結。 (0=立刻轉移)" 67 | }, 68 | "optionsCrowdAutoClose": { 69 | "message": "訪問人們分享的目的網址$1秒後將其標籤頁關閉。" 70 | }, 71 | "privacyPolicy": { 72 | "message": "隱私權政策" 73 | }, 74 | "contributors": { 75 | "message": "貢獻者" 76 | }, 77 | "optionsUserscripts": { 78 | "message": "自定義繞過規則" 79 | }, 80 | "optionsUserscriptsDescription": { 81 | "message": "這是讓開發者自己編寫程式繞過網站的進階功能。當修改至功能完好後,可以提交到 Github,以新增至 FastForward 讓大家使用。" 82 | }, 83 | "beforeNavigate": { 84 | "message": "您與目的地觸手可及。" 85 | }, 86 | "beforeNavigateDestination": { 87 | "message": "您的目的地是 $1" 88 | }, 89 | "beforeNavigateUnsafe": { 90 | "message": "但若您馬上跳轉,他們將會檢測到FastForward。" 91 | }, 92 | "beforeNavigateUnsafeTimer": { 93 | "message": "$1秒後,您將不再被檢測到。" 94 | }, 95 | "beforeNavigateUnsafeTimerSingular": { 96 | "message": "1秒後,您將不再被檢測到。" 97 | }, 98 | "beforeNavigateTimer": { 99 | "message": "您將在$1秒後被重新導向。" 100 | }, 101 | "beforeNavigateTimerSingular": { 102 | "message": "您將在1秒後被自動重新導向" 103 | }, 104 | "beforeNavigateOptions": { 105 | "message": "您希望立刻或是x秒後被重新導向嗎?" 106 | }, 107 | "beforeNavigateInstant": { 108 | "message": "您正在導航到$1" 109 | }, 110 | "infoLinkvertise": { 111 | "message": "我們不受允許直接繞過這個網頁,不過我們已通過談判能夠移除這個網頁最麻煩的步驟了。" 112 | }, 113 | "infoFileHoster": { 114 | "message": "很不幸,下載伺服器需要確保您在下載檔案前已等候" 115 | }, 116 | "infoOutdated": { 117 | "message": "此網站被更新版本的 FastForward 繞過了。" 118 | }, 119 | "crowdWait": { 120 | "message": "很遺憾地,您是第一個遇到這個連結的人,但在您等候了以後,其他 FastForward 的用戶就不用受苦了。" 121 | }, 122 | "crowdDisabled": { 123 | "message": "這個網站是以用戶提供的連結繞過,而此功能已被您在設定中關閉。" 124 | }, 125 | "crowdBypassed": { 126 | "message": "或許您可以不用再等待了。" 127 | }, 128 | "crowdBypassedInfo": { 129 | "message": "其他的 FastForward 用戶已經替您省下寶貴的時間,並回報該短連結重導向 $1" 130 | }, 131 | "crowdBypassedTimer": { 132 | "message": "將在$1秒後以新分頁開啟。" 133 | }, 134 | "crowdBypassedTimerSingular": { 135 | "message": "將在1秒後以新分頁開啟。" 136 | }, 137 | "crowdCloseTimer": { 138 | "message": "此分頁會在$1秒後關閉" 139 | }, 140 | "crowdCloseTimerSingular": { 141 | "message": "此分頁會在1秒後關閉" 142 | }, 143 | "cancel": { 144 | "message": "取消" 145 | }, 146 | "crowdBypassedIgnore": { 147 | "message": "該資訊有誤嗎?" 148 | }, 149 | "crowdBypassedOptions": { 150 | "message": "您希望立刻或是幾秒後以新分頁開啟嗎?" 151 | }, 152 | "blockedTitle": { 153 | "message": "FastForward 防止您的IP被記錄。" 154 | }, 155 | "blockedSubtitle": { 156 | "message": "不希望FastForward自動防止不法者獲取您的IP嗎?" 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/bypasses/1link.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class ONELink extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | this.helpers.safelyNavigate(document.querySelector('a#download').href); 11 | } 12 | } 13 | 14 | export const matches = ['1link.club'] -------------------------------------------------------------------------------- /src/bypasses/1shortlink.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class ONEShortlink extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | this.helpers.awaitElement('#redirect-link', e => { 11 | this.helpers.safelyNavigate(e.href); 12 | }) 13 | } 14 | } 15 | 16 | export const matches = ['1shortlink.com'] -------------------------------------------------------------------------------- /src/bypasses/BypassDefinition.js: -------------------------------------------------------------------------------- 1 | const IMPLEMENTATION_ERROR = function_name => { 2 | throw new Error(`${function_name} must be implemented`) 3 | } 4 | 5 | export default class BypassDefinition { 6 | constructor() { 7 | this.ensure_dom = false 8 | } 9 | 10 | set_helpers(helpers) { 11 | this.helpers = helpers 12 | } 13 | 14 | execute() { 15 | IMPLEMENTATION_ERROR() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/bypasses/acortalink.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Acortalink extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | function rot13(str) { 11 | const input = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; 12 | const output = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'; 13 | let index = x => input.indexOf(x); 14 | let translate = x => index(x) > -1 ? output[index(x)] : x; 15 | return str.split('').map(translate).join(''); 16 | } 17 | // Triggered on example.com and subdomains (e.g. www.example.com) 18 | this.helpers.ensureDomLoaded(() => { 19 | // Triggered as soon as the DOM is ready 20 | window.open = (linkacorta) => { 21 | this.helpers.safelyNavigate(rot13(atob(linkacorta.substring(30)))); 22 | }; 23 | GetLink(); 24 | }) 25 | } 26 | } 27 | 28 | export const matches = ['acortalink.me'] 29 | -------------------------------------------------------------------------------- /src/bypasses/admaven.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Admaven extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | //Execute only if the regex matches /.*\/s\?[A-Za-z]{3}/ 11 | if (window.location.pathname.match(/.*\/s\?[A-Za-z0-9]{3}/)) { 12 | this.helpers.safelyNavigate(document.scripts[0].textContent.split("link: '")[1].split("'")[0]) 13 | } 14 | } 15 | } 16 | 17 | export const matches = ["mega-guy.com", "ofpacksmega.com", "depravityweb.co", "secretpack-links.com", "secret-links.com", "tavernleaks.com", "free-leaks.com", "hotstars-leaks.com", "thepremium.online", "admiregirls-byme.com", "all-fans.online", "pnp-drops.me", "megadropz.com", "goldmega.online", "badgirlsdrop.com", "rareofhub.com", "only-fun.xyz", "megadumpz.com", "leakutopia.site", "xprmpacks.com", "onlymega.co", "tomxcontent.com", "newsociety0.co", "cemendemons.com", "fansmega.com", "premiumstashdrop.com"] 18 | -------------------------------------------------------------------------------- /src/bypasses/adtival.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Adtival extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | this.ensure_dom = true; 7 | } 8 | 9 | execute() { 10 | console.log('Adtival found!'); 11 | 12 | const executor = async () => { 13 | const El = window.livewire.components.components()[0]; 14 | 15 | const payload = { 16 | fingerprint: El.fingerprint, 17 | serverMemo: El.serverMemo, 18 | updates: [ 19 | { 20 | payload: { 21 | event: 'getData', 22 | id: 'whathappen', 23 | params: [], 24 | }, 25 | type: 'fireEvent', 26 | }, 27 | ], 28 | }; 29 | 30 | const response = await fetch( 31 | location.origin + '/livewire/message/pages.show', 32 | { 33 | headers: { 34 | 'Content-Type': 'application/json', 35 | 'X-Livewire': 'true', 36 | 'X-CSRF-TOKEN': window.livewire_token, 37 | }, 38 | method: 'POST', 39 | body: JSON.stringify(payload), 40 | } 41 | ); 42 | 43 | const json = await response.json(); 44 | 45 | // ensure URL 46 | const url = new URL(json.effects.emits[0].params[0]); 47 | 48 | this.helpers.safelyAssign(url.href); 49 | // this.helpers.unsafelyNavigate(url.href, location.href) 50 | }; 51 | 52 | // special case for sekilastekno. modbaca(?) 53 | if (RegExp(/(modebaca|sekilastekno)\.com/).exec(location.host)) { 54 | this.helpers.ifElement("form[method='post']", (a) => { 55 | console.log('addRecord...'); 56 | 57 | const input = document.createElement('input'); 58 | input.value = window.livewire_token; 59 | input.name = '_token'; 60 | input.hidden = true; 61 | a.appendChild(input); 62 | a.submit(); 63 | }); 64 | 65 | // ...same step as miuiku and vebma 66 | this.helpers.ifElement('button[x-text]', async () => { 67 | console.log('getLink..'); 68 | executor(); 69 | }); 70 | 71 | return; 72 | } 73 | 74 | // adtival getLink on miuiku 75 | this.helpers.ifElement("div[class='max-w-5xl mx-auto']", async () => { 76 | console.log('Executing..'); 77 | executor(); 78 | }); 79 | 80 | // adtival b64UrlLastPage 81 | this.helpers.ifElement("button[id='copyVideoURL']", () => { 82 | const shortID = new URLSearchParams(window.location.search).get( 83 | 'shortid' 84 | ); 85 | 86 | this.helpers.safelyAssign(atob(shortID)); 87 | }); 88 | } 89 | } 90 | 91 | export const matches = [ 92 | /movienear\.me|lewat\.club|tautan\.pro|(droidtamvan|gubukbisnis|onlinecorp)\.me|(liveshootv|modebaca|haipedia|sekilastekno|miuiku|vebma)\.com|shrink\.world|link\.mymastah\.xyz|(sportif|cararoot)\.id|healthinsider\.online/, 93 | 'www.adtival.network', 94 | ]; 95 | -------------------------------------------------------------------------------- /src/bypasses/akoam.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Akoam extends BypassDefinition { 4 | constructor() { 5 | super() 6 | } 7 | 8 | execute() { 9 | this.helpers.ODP(window, 'timer', { 10 | value: 0, 11 | writable: false 12 | }) 13 | this.helpers.awaitElement('.download_button[href]', a => { 14 | this.helpers.safelyNavigate(a.href) 15 | }) 16 | } 17 | } 18 | 19 | export const matches = ['akoam.to'] 20 | -------------------------------------------------------------------------------- /src/bypasses/akwam.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Akwam extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | window.setInterval = f => setInterval(f, 1) 11 | this.helpers.awaitElement("a.download_button[href]", a => {this.helpers.safelyNavigate(a.href)}) 12 | } 13 | } 14 | 15 | export const matches = ['akwam.org', 'akw.to'] 16 | -------------------------------------------------------------------------------- /src/bypasses/an1.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class An1 extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | window.setTimeout = f => setTimeout(f, 1) 11 | this.helpers.awaitElement("#waiting > a", a => a.click()) 12 | } 13 | } 14 | 15 | export const matches = ['an1.com'] 16 | -------------------------------------------------------------------------------- /src/bypasses/androidtop.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Androidtop extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | // If the variable downloadTimer is defined, then use clearInterval to stop the timer. 11 | document.querySelector('.counterhide').setAttribute('style', 'opacity: 0; visibility: hidden; height: 0px;'); 12 | document.querySelector('.download-result').setAttribute('style', 'opacity: 1; visibility: visible;'); 13 | } 14 | } 15 | 16 | export const matches = ['androidtop.net']; 17 | -------------------------------------------------------------------------------- /src/bypasses/anonym.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Anonym extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.ensureDomLoaded(() => { 11 | const a = window.location.href.split('/').slice(-1)[0] 12 | this.helpers.safelyNavigate(`https://anonym.ninja/download/file/request/${a}`) 13 | }) 14 | } 15 | } 16 | 17 | export const matches = ['anonym.ninja'] 18 | -------------------------------------------------------------------------------- /src/bypasses/apkhubs.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Apkhubs extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.ifElement("a#downloadbtn", a => { 11 | this.helpers.safelyNavigate(a.href) 12 | }) 13 | } 14 | } 15 | 16 | export const matches = ['apkhubs.com']; 17 | -------------------------------------------------------------------------------- /src/bypasses/blitly.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Blitly extends BypassDefinition { 4 | constructor() { 5 | super() 6 | } 7 | 8 | execute() { 9 | const target_url = new URLSearchParams(window.location.search).get('url') 10 | this.helpers.safelyNavigate(target_url) 11 | } 12 | } 13 | 14 | export const matches = ['blitly.io'] 15 | -------------------------------------------------------------------------------- /src/bypasses/blogtech.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class BlogTechh extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | } 7 | 8 | execute() { 9 | this.helpers.awaitElement("button#getlink", button => { 10 | button.click() 11 | }) 12 | } 13 | } 14 | 15 | export const matches = ['blogtechh.com', 'oko.sh']; 16 | -------------------------------------------------------------------------------- /src/bypasses/bluemediafile.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Bluemediafile extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | this.ensure_dom = true; 7 | } 8 | 9 | execute() { 10 | if (location.href.match(/\/url-generator(-\d+)?\.php\?url=/) === null) 11 | return; 12 | 13 | window.Time_Start -= 5000; 14 | window.i = 0; 15 | this.helpers.awaitElement('input#nut[src]', (i) => i.parentNode.submit()); 16 | } 17 | } 18 | 19 | export const matches = [ 20 | 'bluemediafiles.com', 21 | 'bluemediafile.sbs', 22 | 'bluemediafile.site', 23 | ]; 24 | -------------------------------------------------------------------------------- /src/bypasses/boost.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Boost extends BypassDefinition { 4 | constructor() { 5 | super() 6 | } 7 | 8 | execute() { 9 | // Based off of bloggerpemula's bypass: https://greasyfork.org/en/scripts/431691-bypass-all-shortlinks/code 10 | fetch(location.href).then(bo => bo.text()).then(html => this.helpers.safelyNavigate(atob(html.split('bufpsvdhmjybvgfncqfa="')[1].split('"')[0]))) 11 | } 12 | } 13 | 14 | export const matches = ['boost.ink'] 15 | -------------------------------------------------------------------------------- /src/bypasses/brpaper.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Brpaper extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.ensureDomLoaded(() => { 11 | const loc = location.href.replace("downloads", "downloader") 12 | this.helpers.safelyNavigate(loc) 13 | }) 14 | } 15 | } 16 | 17 | export const matches = ['brpaper.com'] 18 | -------------------------------------------------------------------------------- /src/bypasses/bstlar.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Bstlar extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | } 7 | 8 | execute() { 9 | this.helpers.bypassRequests(async data => { 10 | if (data.currentTarget?.responseText?.includes('tasks')) { 11 | const response = JSON.parse(data.currentTarget.responseText); 12 | const userAgent = navigator.userAgent; 13 | const XSRF_TOKEN = this.getCookie('XSRF-TOKEN'); 14 | const boostellar_session = this.getCookie('boostellar_session') 15 | const PfufeQwMeP6og9Poi7DmjbGJCcYhyXKQhlPnQ4Ud = this.getCookie('PfufeQwMeP6og9Poi7DmjbGJCcYhyXKQhlPnQ4Ud') 16 | const cf_clearance = this.getCookie('cf_clearance') 17 | const task_request = await fetch('https://bstlar.com/api/link-completed', { 18 | method: 'POST', 19 | headers: { 20 | accept: 'application/json, text/plain, */*', 21 | authorization: 'null', 22 | cookie: `XSRF-TOKEN=${XSRF_TOKEN}; boostellar_session=${boostellar_session}; PfufeQwMeP6og9Poi7DmjbGJCcYhyXKQhlPnQ4Ud=${PfufeQwMeP6og9Poi7DmjbGJCcYhyXKQhlPnQ4Ud}; cf_clearance=${cf_clearance}`, 23 | origin: 'https://bstlar.com', 24 | pragma: 'no-cache', 25 | priority: 'u=1, i', 26 | referer: 'https://bstlar.com/hV/krampus', 27 | 'user-agent': userAgent, 28 | 'x-xsrf-token': XSRF_TOKEN, 29 | 'Content-Type': 'application/json' 30 | }, 31 | body: JSON.stringify({ 32 | link_id: response['link']['id'] 33 | }) 34 | }) 35 | if (task_request.status !== 200) return; 36 | const task_response = await task_request.text(); 37 | this.helpers.safelyNavigate(task_response) 38 | } 39 | }); 40 | } 41 | 42 | getCookie(name) { 43 | let value = '; ' + document.cookie; 44 | let parts = value.split('; ' + name + '='); 45 | if (parts.length === 2) return parts.pop().split(';').shift(); 46 | } 47 | } 48 | 49 | export const matches = ['bstlar.com']; 50 | -------------------------------------------------------------------------------- /src/bypasses/cbrun.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Cbrun extends BypassDefinition { 4 | constructor() { 5 | super() 6 | } 7 | execute() { 8 | const a = document.querySelector('a.btn') 9 | if (a) { 10 | this.helpers.safelyNavigate(a.href) 11 | } 12 | } 13 | } 14 | 15 | export const matches = ['cb.run', 'cb.click'] 16 | -------------------------------------------------------------------------------- /src/bypasses/cheatsquad.js: -------------------------------------------------------------------------------- 1 | 2 | import BypassDefinition from './BypassDefinition.js' 3 | 4 | export default class Cheatsquad extends BypassDefinition { 5 | constructor() { 6 | super() 7 | // custom bypass required bases can be set here 8 | } 9 | 10 | execute() { 11 | this.helpers.ODP(window, "steps", { 12 | get: () => [true] 13 | }) 14 | this.helpers.ODP(window, "youtube", { 15 | get: () => 1 16 | }) 17 | this.helpers.ensureDomLoaded(() => document.querySelectorAll("div.loader").forEach(d => d.className = "check_loader")) 18 | } 19 | } 20 | 21 | export const matches = ['cheatsquad.gg'] 22 | -------------------------------------------------------------------------------- /src/bypasses/clictune.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Clictune extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | seconde = 0; 11 | Compteur(); 12 | 13 | this.helpers.awaitElement('#compteur2 a[href]', a => { 14 | this.helpers.safelyNavigate(new URL(a.href).searchParams.get("url")) 15 | }) 16 | } 17 | } 18 | 19 | export const matches = ['www.dlink2.net', 'www.dlink2.com', 'www.clictune.com', 'www.dlink4.com'] 20 | -------------------------------------------------------------------------------- /src/bypasses/complete2unlock.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Complete2unlock extends BypassDefinition { 4 | constructor() { 5 | super() 6 | } 7 | 8 | execute() { 9 | const timer = setInterval(() => { 10 | const link_success_button = document.getElementById('link-success-button') 11 | if (!link_success_button) return 12 | 13 | const unlock_panels = document.querySelectorAll('.unlockpanel') 14 | 15 | if (0 === unlock_panels.length) return 16 | 17 | clearInterval(timer) 18 | // override the window open method, no more annoying popups 19 | window.open = () => { } 20 | 21 | unlock_panels.forEach(panel => panel.click()) 22 | 23 | const is_button_enabled_timer = setInterval(() => { 24 | if (link_success_button.hasAttribute('disabled')) return 25 | 26 | clearInterval(is_button_enabled_timer) 27 | link_success_button.click() 28 | }, 100) 29 | }, 300) 30 | 31 | setInterval(() => clearInterval(timer), 30000) 32 | } 33 | } 34 | 35 | export const matches = ['complete2unlock.com'] 36 | -------------------------------------------------------------------------------- /src/bypasses/cpmlink.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Cpmlink extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | this.helpers.ifElement('a#btn-main', a =>{ 11 | this.helpers.crowdPath(location.pathname.substring(4)) 12 | this.helpers.contributeAndNavigate(a.href) 13 | },() => this.helpers.crowdBypass()) 14 | } 15 | } 16 | 17 | export const matches = ['cpmlink.net'] 18 | -------------------------------------------------------------------------------- /src/bypasses/crackedappsstore.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Crackedappsstore extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | // Find the div with the class name "show_download_links" and remove the 'display: none' style 11 | const ulElement = document.querySelector('#list-downloadlinks'); 12 | let href; 13 | 14 | if (ulElement) { 15 | const liElements = ulElement.querySelectorAll('li'); 16 | if (liElements.length > 1) { 17 | href = liElements[1].querySelector('a').href; 18 | } else if (liElements.length === 1) { 19 | href = liElements[0].querySelector('a').href; 20 | } 21 | } 22 | 23 | this.helpers.safelyNavigate(href); 24 | 25 | // Find the ul with the id list-downloadlinks, find the li in it, and pull the link from the first a tag 26 | const link2 = document.querySelector('#list-downloadlinks li:first-child a'); 27 | this.helpers.safelyNavigate(link2); 28 | } 29 | } 30 | 31 | export const matches = ['crackedappsstore.com']; 32 | -------------------------------------------------------------------------------- /src/bypasses/curseforge.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Curseforge extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | window.setInterval = f => setInterval(f, 100) 11 | } 12 | } 13 | 14 | export const matches = ['curseforge.com']; 15 | -------------------------------------------------------------------------------- /src/bypasses/daominhha.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Daominhha extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | let str = (new URL(location.href)).searchParams.get('url') 11 | str = str.split("").reverse().join("") 12 | str = str.replaceAll("-", "+") 13 | str = str.replaceAll(".", "/") 14 | str = str.replaceAll(",", "=") 15 | this.helpers.safelyAssign(atob(str)) 16 | } 17 | } 18 | 19 | export const matches = ['daominhha.com/download'] 20 | -------------------------------------------------------------------------------- /src/bypasses/earnme.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Earnme extends BypassDefinition { 4 | constructor() { 5 | super() 6 | } 7 | 8 | execute() { 9 | this.helpers.awaitElement('#tp-snp2', a => { 10 | a.click() 11 | }) 12 | } 13 | } 14 | 15 | export const matches = ['earnme.club', 'usanewstoday.club'] 16 | -------------------------------------------------------------------------------- /src/bypasses/enlacito.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Enlacito extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | this.helpers.safelyNavigate(window.DYykkzwP) 11 | } 12 | } 13 | 14 | // This is a link protecor that I've seen in many domains, so this script probably works in many of them 15 | // If you find another domain that uses this script, please add it to the array below 16 | export const matches = ['enlacito.com'] 17 | -------------------------------------------------------------------------------- /src/bypasses/favpng.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Favpng extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | this.ensure_dom = true; 7 | } 8 | 9 | execute() { 10 | const scripts = document.getElementsByTagName('script'); 11 | for (let i = 0; i < scripts.length; i++) { 12 | let script = scripts[i]; 13 | if (script.textContent.includes('https://download.favpng.com/api_download.php?')) { 14 | let startIndex = script.textContent.indexOf('https://download.favpng.com/api_download.php?'); 15 | let endIndex = script.textContent.indexOf('"', startIndex); 16 | this.helpers.safelyNavigate(script.textContent.substring(startIndex, endIndex)); 17 | } 18 | } 19 | } 20 | } 21 | 22 | export const matches = ['favpng.com']; 23 | -------------------------------------------------------------------------------- /src/bypasses/fclc.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Fclc extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.ensureDomLoaded(() => { 11 | this.helpers.crowdBypass() 12 | }) 13 | } 14 | } 15 | 16 | export const matches = ['fc-lc.com'] 17 | -------------------------------------------------------------------------------- /src/bypasses/filedm.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Filedm extends BypassDefinition { 4 | constructor() { 5 | super() 6 | } 7 | 8 | execute() { 9 | this.helpers.awaitElement('a#d1button', address => { 10 | this.helpers.safelyNavigate("http://cdn.directdl.xyz/getfile?id=" + address.href.split("_")[1]) 11 | }) 12 | } 13 | } 14 | 15 | export const matches = ['filedm.com'] 16 | -------------------------------------------------------------------------------- /src/bypasses/filefactory.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Filefactory extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.insertInfoBox("Unfortunately, the download server will ensure that you have waited before allowing you to download the file.") 11 | } 12 | } 13 | 14 | export const matches = ['https://filefactory.com', 'https://file-upload.com', 'https://asdfiles.com', 'https://mega4up.com', ' https://up-load.io', 'https://cosmobox.org', 'https://devdrive.cloud']; 15 | -------------------------------------------------------------------------------- /src/bypasses/filehorse.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Filehorse extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.ensureDomLoaded(() => { 11 | this.helpers.ifElement("a#download_url[href]", addr => { 12 | if (typeof timerx == "number"){ 13 | clearTimeout(timerx) 14 | } 15 | this.helpers.safelyAssign(addr.href) 16 | }) 17 | }) 18 | } 19 | } 20 | 21 | export const matches = ['filehorse.com'] 22 | -------------------------------------------------------------------------------- /src/bypasses/filepuma.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Filepuma extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | // Find the last script in the page 11 | let scripts = document.getElementsByTagName('script'); 12 | let lastScript = scripts[scripts.length - 1]; 13 | // Get the script's source 14 | let scriptSrc = lastScript.innerHTML; 15 | // Find the first location.href in the script and get the value of location.href 16 | let url = scriptSrc.split('location.href = "')[1].split('"')[0]; 17 | alert(url) 18 | 19 | } 20 | } 21 | 22 | export const matches = ['filepuma.com']; 23 | -------------------------------------------------------------------------------- /src/bypasses/firefaucet.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Firefaucet extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | window.setInterval = f => setInterval(f, 1); 11 | 12 | } 13 | } 14 | 15 | export const matches = ['firefaucet.win', 'sfirmware.com', 'emulator.games']; 16 | -------------------------------------------------------------------------------- /src/bypasses/fiveplay.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Fiveplay extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | } 7 | 8 | execute() { 9 | // Find the div with the class "download_btn", find the a tag within the div, and return the href attribute 10 | let downloadBtnGroup = document.querySelector('.download-btn-group'); 11 | if (downloadBtnGroup) { 12 | let anchorElement = downloadBtnGroup.querySelector('a'); 13 | if (anchorElement) { 14 | this.helpers.safelyAssign(anchorElement.getAttribute('href')); 15 | } 16 | } 17 | } 18 | } 19 | 20 | export const matches = ['5play.ru']; 21 | -------------------------------------------------------------------------------- /src/bypasses/forex1pro.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Forex1pro extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.ensureDomLoaded(() => { 11 | this.helpers.safelyAssign(`https://fx4vip.com${location.pathname}`) 12 | }) 13 | } 14 | } 15 | 16 | export const matches = ['forex1pro.com'] 17 | -------------------------------------------------------------------------------- /src/bypasses/fourshared.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Fourshared extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | if (document.cookie.indexOf("exUserId=") === -1){ 11 | document.cookie = "exUserId=0; domain=.4shared.com; path=/" 12 | } 13 | } 14 | } 15 | 16 | export const matches = ['4shared.com'] 17 | -------------------------------------------------------------------------------- /src/bypasses/fssquad.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Fssquad extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | this.helpers.ifElement("div#wpsafe-link", d => { 11 | this.helpers.safelyNavigate(d.getElementsByTagName("a")[0].onclick()) 12 | }) 13 | } 14 | } 15 | 16 | export const matches = ['fssquad.com'] 17 | -------------------------------------------------------------------------------- /src/bypasses/gamesmega.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Gamesmega extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.ODP(window, "hash", { 11 | get: () => "", 12 | set: _ => this.helpers.safelyNavigate(decodeURIComponent(atob(_))) 13 | }) 14 | } 15 | } 16 | 17 | export const matches = ['gamesmega.net'] 18 | -------------------------------------------------------------------------------- /src/bypasses/get2clickblogspot.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Get2clickblogspot extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | } 7 | 8 | execute() { 9 | // Find the div with the class "hidden btn waves-effect waves-light blue darken-2 white-text" and change it to "btn waves-effect waves-light blue darken-2 white-text" 10 | document.querySelector('.hidden.btn.waves-effect.waves-light.blue.darken-2.white-text').className = 'btn.waves-effect.waves-light.blue.darken-2.white-text'; 11 | 12 | //Find the div with the class btn blue darken-2 waves-effect waves-light white-text hidden and make it btn blue darken-2 waves-effect waves-light white-text 13 | document.querySelector('.btn.blue.darken-2.waves-effect.waves-light.white-text.hidden').className = 'btn.blue.darken-2.waves-effect.waves-light.white-text'; 14 | //Remove the disabled attribute from the div element above 15 | document.querySelector('.btn.blue.darken-2.waves-effect.waves-light.white-text').removeAttribute('disabled'); 16 | //Wait until the page is changed 17 | window.addEventListener('load', () => { 18 | //The url will look like this https://get-click2.blogspot.com/2019/01/0xc60f.live?m=1 19 | //return the part of the url that is after the date, in this case it is 0xc60f.live?m=1 20 | let url = location.href.replace(/.*\/\d+\/(.*)/, '$1'); 21 | this.helpers.safelyNavigate(url); 22 | }); 23 | } 24 | } 25 | 26 | export const matches = ['get-click2.blogspot.com/']; 27 | -------------------------------------------------------------------------------- /src/bypasses/getwallpapers.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Getwallpapers extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | window.setInterval = f => setInterval(f, 1) 11 | } 12 | } 13 | 14 | export const matches = ['getwallpapers.com', 'https://sammobile.com', "https://ydfile.com", "https://mobilemodsapk.com", "https://dlandroid.com", "https://download.modsofapk.com", "https://zedge.net ", "https://fex.net", "https://k2s.cc", " https://u.to"]; 15 | -------------------------------------------------------------------------------- /src/bypasses/gixen.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Gixen extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | const sid = document.cookie.match(/sessionid=(\d+)/)[1] 11 | if (sid){ 12 | let f = document.createElement('form') 13 | f.method = 'POST' 14 | f.action = "home_2.php?sessionid=" + sid 15 | f.innerHTML = '' 16 | document.documentElement.appendChild(f) 17 | this.helpers.countIt(() => f.submit()) 18 | } 19 | } 20 | } 21 | 22 | export const matches = ['gixen.com/home_1.php'] 23 | -------------------------------------------------------------------------------- /src/bypasses/idnation.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Idnation extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.ifElement("#linko[href]", b => this.helpers.safelyNavigate(b.href)) 11 | } 12 | } 13 | 14 | export const matches = ['idnation.net']; 15 | -------------------------------------------------------------------------------- /src/bypasses/indishare.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Indishare extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | window.setTimeout = f => setTimeout(f, 1) 11 | } 12 | } 13 | 14 | export const matches = ['indishare.org', 'solvetube.site']; 15 | -------------------------------------------------------------------------------- /src/bypasses/leitup.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Leitup extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | this.helpers.ifElement('input.form-control[type="text"]', (input) => { 11 | let destination = input.attributes.placeholder.value 12 | this.helpers.safelyNavigate(destination) 13 | }) 14 | } 15 | } 16 | 17 | export const matches = ['leitup.com'] 18 | -------------------------------------------------------------------------------- /src/bypasses/letsboost.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Letsboost extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | this.ensure_dom = true; 7 | } 8 | 9 | execute() { 10 | alert("FastForward: If nothing happens in a few seconds, the bypass couldn't be executed. Please disable your ad blocker and refresh the page. Press OK to continue."); 11 | this.helpers.insertInfoBox("If nothing happens in a few seconds, the bypass couldn't be executed. Please disable your ad blocker and refresh the page."); 12 | this.helpers.awaitElement("script:last-of-type:not([src])", () => { 13 | const lastScript = document.getElementsByTagName('script')[document.getElementsByTagName('script').length - 1]; 14 | const scriptContent = lastScript.innerHTML; 15 | const jsonDat = JSON.parse(scriptContent.match(/stepDat = '(.*)';/)[1]); 16 | const url = jsonDat[jsonDat.length-1]["url"]; 17 | this.helpers.safelyNavigate(url); 18 | }); 19 | } 20 | } 21 | 22 | 23 | export const matches = ['letsboost.net']; -------------------------------------------------------------------------------- /src/bypasses/liblink.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Liblink extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | this.helpers.ifElement("body > div > h1 > span", addr => { 11 | this.helpers.safelyNavigate(addr.innerHTML) 12 | }) 13 | } 14 | } 15 | 16 | export const matches = ['liblink.pl'] 17 | -------------------------------------------------------------------------------- /src/bypasses/linegee.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Linegee extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | } 7 | 8 | execute() { 9 | const continueLink = Array.from(document.getElementsByTagName('a')).find(a => a.textContent.trim() === 'Continue'); 10 | const href = continueLink.getAttribute('href'); 11 | this.helpers.safelyNavigate(href); 12 | 13 | 14 | } 15 | } 16 | 17 | export const matches = ['linegee.net']; 18 | -------------------------------------------------------------------------------- /src/bypasses/linksht.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Linksht extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | const getUrl = document.URL; 11 | const urlSplit = getUrl.split("/"); 12 | $.post("/Links/Getlink", {id: urlSplit[urlSplit.length - 1]}, function (destination) { 13 | if(destination!="") { 14 | location.assign(destination); 15 | } 16 | }); 17 | } 18 | } 19 | 20 | export const matches = ['linksht.com'] -------------------------------------------------------------------------------- /src/bypasses/linkspy.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Linkspy extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | const url = document.getElementsByClassName("skipButton")[0].getAttribute("href") 11 | this.helpers.safelyNavigate(url) 12 | } 13 | } 14 | 15 | export const matches = ['linkspy.cc'] 16 | -------------------------------------------------------------------------------- /src/bypasses/lkc21.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Lkc21 extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | window.setTimeout = f => setTimeout(f, 100) 11 | } 12 | } 13 | 14 | export const matches = ['lkc21.net']; 15 | -------------------------------------------------------------------------------- /src/bypasses/lnk.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Lnk extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | if (!window.location.href.includes('/go/')) { 11 | //Insert /go/ inbetween the domain and the rest of the url 12 | this.helpers.safelyNavigate(window.location.href.replace(/(https?:\/\/[^/]+)(\/.*)/, '$1/go$2')); 13 | } 14 | document.getElementById('get_link_btn').click(); 15 | } 16 | } 17 | 18 | export const matches = ['lnk.parts', 'icerik.site']; 19 | 20 | -------------------------------------------------------------------------------- /src/bypasses/lnk2.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Lnk2 extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | this.ensure_dom = true; 7 | } 8 | 9 | execute() { 10 | //If the url doesn't contain /go/, use the insertInfoBox 11 | if (window.location.href.includes('/go/')) { 12 | document.getElementById('getLink').removeAttribute('disabled'); 13 | document.getElementById('getLink').click(); 14 | } else { 15 | this.helpers.insertInfoBox('Please complete the captcha, then we can bypass you'); 16 | } 17 | } 18 | } 19 | 20 | export const matches = ['lnk2.cc']; 21 | -------------------------------------------------------------------------------- /src/bypasses/lnk2cc.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Lnk2cc extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | //Replace substr(0,4) with substring 11 | 12 | if (location.pathname.substring(0,5) === "/go/"){ 13 | document.querySelector("form").submit() 14 | } 15 | else{ 16 | this.helpers.crowdBypass() 17 | } 18 | } 19 | } 20 | 21 | export const matches = ['lnk2.cc'] 22 | -------------------------------------------------------------------------------- /src/bypasses/longfiles.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Longfiles extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | window.setTimeout = f => this.helpers.setTimeout(f, 1) 11 | } 12 | } 13 | 14 | export const matches = ['longfiles.com', 'filepuma.com', 'portableapps.com', 'indishare.org', 'solvetube.site'] 15 | -------------------------------------------------------------------------------- /src/bypasses/lootlink.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class LootLink extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | if (/[?&]r=/.test(window.location.href.toString())) { // https://loot-link.com/s?fJjn&r= 11 | const urlParams = new URLSearchParams(window.location.search) 12 | const r = urlParams.get('r') 13 | const finalURL = decodeURIComponent(escape(atob(r))) 14 | this.helpers.safelyNavigate(finalURL) 15 | } else { // https://loot-link.com/s?fJjn 16 | const originalFetch = window.fetch 17 | window.fetch = (url, config) => this.customFetch(url, config, originalFetch) 18 | } 19 | } 20 | 21 | customFetch(url, config, originalFetch) { 22 | if (url.includes(`${INCENTIVE_SYNCER_DOMAIN}/tc`)) { 23 | return originalFetch(url, config).then(response => { 24 | if (!response.ok) return response.json() 25 | return this.handleResponse(response) 26 | }); 27 | } 28 | return originalFetch(url, config) 29 | } 30 | 31 | handleResponse(response) { 32 | return response.clone().json().then(data => { 33 | this.helpers.insertInfoBox( 34 | 'Please wait a moment while we search for the destination link.' 35 | ); 36 | let urid = "" 37 | let action_pixel_url = "" 38 | data.forEach(item => { 39 | urid = item.urid 40 | action_pixel_url = item.action_pixel_url 41 | }); 42 | 43 | const task_id = 54; // magic number 44 | 45 | this.setupWebSocket(urid, task_id) 46 | navigator.sendBeacon(`https://${urid.substr(-5) % 3}.${INCENTIVE_SERVER_DOMAIN}/st?uid=${urid}&cat=${task_id}`) 47 | fetch(`https://${INCENTIVE_SYNCER_DOMAIN}/td?ac=1&urid=${urid}&&cat=${task_id}&tid=${TID}`) 48 | fetch(action_pixel_url) 49 | 50 | return new Response(JSON.stringify(data), { 51 | status: response.status, 52 | statusText: response.statusText, 53 | headers: response.headers 54 | }) 55 | }) 56 | } 57 | 58 | setupWebSocket(urid, task_id) { 59 | const ws = new WebSocket(`wss://${urid.substr(-5) % 3}.${INCENTIVE_SERVER_DOMAIN}/c?uid=${urid}&cat=${task_id}&key=${KEY}`) 60 | 61 | ws.onopen = () => setInterval(() => ws.send('0'), 1000) 62 | ws.onmessage = event => { 63 | if (event.data.includes('r:')) { 64 | this.helpers.safelyNavigate(this.decryptData(event.data.replace('r:', ''))) 65 | } 66 | } 67 | } 68 | 69 | decryptData(encodedData) { 70 | let final = "" 71 | let combinationLink = atob(encodedData) 72 | let key = combinationLink.substring(0, 5) 73 | let enc_link = combinationLink.substring(5) 74 | for (let i = 0; i < enc_link.length; i++) { 75 | let enc_char = enc_link.charCodeAt(i) 76 | let keyAtOffset = key.charCodeAt(i % key.length) 77 | let charcode = enc_char ^ keyAtOffset 78 | final += String.fromCharCode(charcode) 79 | } 80 | 81 | return final 82 | } 83 | } 84 | 85 | export const matches = ['lootlinks.co', 'loot-links.com', 'loot-link.com', "linksloot.net", "lootdest.com", "lootlink.org", "lootdest.info", "lootdest.org", "links-loot.com"] 86 | -------------------------------------------------------------------------------- /src/bypasses/mangalist.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Mangalist extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | this.helpers.awaitElement("#btt > button.btn.btn-primary.text-center[onclick^='window.location.assign(']", b => { 11 | let o = b.getAttribute('onclick') 12 | this.helpers.safelyNavigate(o.substring(24, o.length - 3)) 13 | }) 14 | } 15 | } 16 | 17 | export const matches = ['mangalist.org'] 18 | -------------------------------------------------------------------------------- /src/bypasses/manualsbooks.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Manualsbooks extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | } 7 | 8 | execute() { 9 | // Wait for 2 seconds 10 | 11 | newElement.parentNode.replaceChild(downloadButton, newElement), clearInterval(id); 12 | this.helpers.safelyNavigate(this.helpers.parseTarget(document.getElementById("download"))) 13 | 14 | } 15 | } 16 | 17 | export const matches = ['manualsbooks.com'] 18 | -------------------------------------------------------------------------------- /src/bypasses/mobi2c.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Mobi2c extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | // /mobi2c.com|newforex.online|healthy4pepole.com|world-trips.net|forex-gold.net|healdad.com|world2our.com|gamalk-sehetk.com|mobitaak.com|forexit.online|shopforex.online|bluetechno.net/, function() {ClickIfExists('.submitBtn', 3);ClickIfExists('#go_d', 3, 'setInterval');}); 11 | //Click the element .submitBtn after a delay of 3 seconds 12 | this.helpers.setTimeout(() => { 13 | document.getElementsByClassName('.submitBtn')[0].click(); 14 | }, 3000); 15 | //Click the element #go_d every 3 seconds until it is clicked 16 | this.helpers.setInterval(() => { 17 | document.getElementById('#go_d')[0].click(); 18 | }, 3000); 19 | } 20 | } 21 | 22 | export const matches = ['mobi2c.com', 'newforex.online', 'healthy4pepole.com', 'world-trips.net', 'forex-gold.net', 'healdad.com', 'world2our.com', 'gamalk-sehetk.com', 'mobitaak.com', 'forexit.online', 'shopforex.online', 'bluetechno.net'] 23 | -------------------------------------------------------------------------------- /src/bypasses/mydramalist.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Mydramalist extends BypassDefinition { 4 | constructor () { 5 | super() 6 | } 7 | 8 | execute () { 9 | const search_params = location.search 10 | const decoded_search_params = decodeURIComponent(search_params) 11 | const full_url = decoded_search_params.replace('?q=', '') 12 | this.helpers.safelyNavigate(full_url) 13 | } 14 | } 15 | 16 | export const matches = ['mydramalist.com'] 17 | -------------------------------------------------------------------------------- /src/bypasses/oko.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Oko extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | // todo: make execute function 11 | } 12 | } 13 | 14 | export const matches = ['oko.sh'] 15 | -------------------------------------------------------------------------------- /src/bypasses/onelink.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Onelink extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | this.ensure_dom = true; 7 | } 8 | 9 | execute() { 10 | window.setInterval = f => setInterval(f, 1); 11 | let b = document.getElementById('go_next'); 12 | if (b && this.helpers.isGoodLink(b.href)) { 13 | this.helpers.safelyAssign(b.href); 14 | } else { 15 | this.helpers.ifElement('#download', b => this.helpers.safelyNavigate(b.href)); 16 | } 17 | } 18 | } 19 | 20 | export const matches = ['1link.club']; 21 | -------------------------------------------------------------------------------- /src/bypasses/onepieceex.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Onepieceex extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.ensureDomLoaded(() => { 11 | this.helpers.ifElement("noscript", n => this.helpers.safelyNavigate(n.textContent)) 12 | }) 13 | } 14 | } 15 | 16 | export const matches = ['onepieceex.net'] 17 | -------------------------------------------------------------------------------- /src/bypasses/onlinefix.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Onelinefix extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | window.setTimeout = f => setTimeout(f,1) 11 | this.helpers.awaitElement("#res > center > button.btn[onclick]", but => but.onclick()) 12 | } 13 | } 14 | 15 | export const matches = ['online-fix.me/ext/'] 16 | -------------------------------------------------------------------------------- /src/bypasses/oracle.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Oracle extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | document.querySelectorAll("[data-file]").forEach(e => { 11 | let link = e.getAttribute("data-file"), 12 | jre8 = RegExp("download.oracle.com/otn/java/jdk/8u([0-9]*)-b([0-9]*)/([a-z0-9]{32})/(.*)$", "g").exec(link) 13 | if (jre8 && jre8[3]){ 14 | os_type = RegExp("8u[0-9]*-([^-]*)-").exec(jre8[4])[1] 15 | os_type = (os_type == "macosx") ? "unix" : os_type 16 | e.onclick = () => this.helpers.safelyNavigate("https://javadl.oracle.com/webapps/download/GetFile/1.8.0_" + jre8[1] + "-b" + jre8[2] + "/" + jre8[3] + "/" + os_type + "-i586/" + jre8[4]) 17 | } 18 | }) 19 | } 20 | } 21 | 22 | export const matches = ['oracle.com'] 23 | -------------------------------------------------------------------------------- /src/bypasses/ouo.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from "./BypassDefinition.js" 2 | 3 | export default class Ouo extends BypassDefinition { 4 | constructor() { 5 | super() 6 | } 7 | execute() { 8 | if (location.pathname !== '/') { 9 | if (/(go|fbc)/.test(location.pathname.split("/")[1])) { 10 | document.querySelector("form").submit() 11 | } 12 | else { 13 | if (document.querySelector("form#form-captcha")) { 14 | document.querySelector("form#form-captcha").action = `/xreallcygo${location.pathname}` 15 | document.querySelector("form#form-captcha").submit() 16 | } 17 | else { 18 | //this.helpers.crowdBypass() 19 | } 20 | } 21 | } 22 | } 23 | } 24 | export const matches = ['ouo.press', 'ouo.io'] 25 | -------------------------------------------------------------------------------- /src/bypasses/oxy.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Oxy extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | this.helpers.ifElement("button#download[disabled]", d => { 11 | this.helpers.awaitElement("button#download:not([disabled])", d => { 12 | d.click() 13 | }) 14 | }) 15 | } 16 | } 17 | 18 | export const matches = ['oxy.cloud'] 19 | -------------------------------------------------------------------------------- /src/bypasses/pcgamestorrents.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Pcgamestorrents extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | window.setInterval = f => setInterval(f, 1) 11 | this.helpers.transparentProperty("Time_Start", t => t - 5000) 12 | this.helpers.awaitElement("input#nut[src]", i => i.parentNode.submit()) 13 | 14 | } 15 | } 16 | 17 | export const matches = ['dl.pcgamestorrents.org']; 18 | -------------------------------------------------------------------------------- /src/bypasses/pirateproxy.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Pirateproxy extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | let search = location.search.replace("?", "") 11 | if (search) { 12 | this.helpers.safelyNavigate(`https://${search}`) 13 | } 14 | } 15 | } 16 | 17 | export const matches = ['pirateproxy.wtf'] 18 | -------------------------------------------------------------------------------- /src/bypasses/portableapps.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Portableapps extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | //Check if the url contains "/downloading" 11 | if (window.location.href.indexOf('/downloading') > -1) { 12 | let url = window.location.href; 13 | let urlSplit = url.split('&f='); 14 | let urlSplit2 = urlSplit[1].split('&'); 15 | let finalUrl = "https://download2.portableapps.com/portableapps/PortableApps.comPlatform/" + urlSplit2 16 | //Open finalUrl in a new tab 17 | window.open(finalUrl, '_blank'); 18 | } 19 | } 20 | } 21 | 22 | export const matches = ['portableapps.com']; 23 | -------------------------------------------------------------------------------- /src/bypasses/ps4linux.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class PS4Linux extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | const targetURL = document.querySelector('#skipaft > a:nth-child(1)')?.href 11 | if (targetURL) { 12 | this.helpers.safelyNavigate(targetURL) 13 | } 14 | } 15 | } 16 | 17 | export const matches = ['ps4linux.com'] 18 | -------------------------------------------------------------------------------- /src/bypasses/rekonise.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Rekonise extends BypassDefinition { 4 | constructor() { 5 | super() 6 | } 7 | 8 | execute() { 9 | let xhr = new XMLHttpRequest() 10 | xhr.onload = () => { 11 | let data = JSON.parse(xhr.responseText) 12 | this.helpers.safelyNavigate(data.url) 13 | } 14 | xhr.open( 15 | 'GET', 16 | `https://api.rekonise.com/social-unlocks${location.pathname}`, 17 | true 18 | ) 19 | xhr.send() 20 | } 21 | } 22 | export const matches = ['rekonise.com'] 23 | -------------------------------------------------------------------------------- /src/bypasses/ryn.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Ryn extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | if (typeof countdown == 'function') { 11 | document.write(''); 12 | countdown(); 13 | this.helpers.safelyNavigate(document.querySelector('#link > a').href); 14 | } 15 | } 16 | } 17 | 18 | export const matches = ['ryn.cc']; 19 | -------------------------------------------------------------------------------- /src/bypasses/sfile.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Sfile extends BypassDefinition { 4 | constructor() { 5 | super() 6 | } 7 | 8 | execute() { 9 | this.helpers.ODP(window, 'downloadButton', { 10 | set: a => { 11 | if (a?.href) { 12 | this.helpers.safelyAssign(a.href) 13 | } 14 | } 15 | }) 16 | } 17 | } 18 | 19 | export const matches = ['sfile.mobi', 'sfile.xyz', 'apkmos.com'] 20 | -------------------------------------------------------------------------------- /src/bypasses/shortenbuddy.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Shortenbuddy extends BypassDefinition { 4 | constructor () { 5 | super() 6 | } 7 | execute () { 8 | let url = location.href.replace('links.', '') 9 | this.helpers.safelyAssign(url) 10 | } 11 | } 12 | 13 | export const matches = ['links.shortenbuddy.com'] 14 | -------------------------------------------------------------------------------- /src/bypasses/shortly.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Shortly extends BypassDefinition { 4 | constructor() { 5 | super() 6 | } 7 | 8 | execute() { 9 | if (location.pathname.substr(0, 3) === "/r/") { 10 | document.getElementById = () => ({ 11 | submit: () => { 12 | let f = document.querySelector("form") 13 | f.action = "/link#" + document.querySelector("input[name='id']").value 14 | f.submit() 15 | } 16 | }) 17 | } 18 | else if (location.pathname === "/link") { 19 | let xhr = new XMLHttpRequest() 20 | xhr.onload = () => this.helpers.safelyNavigate(xhr.responseText) 21 | xhr.open("POST", "https://www.shortly.xyz/getlink.php", true) 22 | xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded") 23 | xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest") 24 | xhr.send("id=" + location.hash.substr(1)) 25 | } 26 | } 27 | } 28 | 29 | export const matches = ['shortly.xyz'] 30 | -------------------------------------------------------------------------------- /src/bypasses/shortmoz.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Shortmoz extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | window.setInterval = f => setTimeout(f,1) 11 | this.helpers.awaitElement("a.btn.redirect[href^='http']", a => 12 | this.helpers.safelyNavigate(a.href)) 13 | } 14 | } 15 | 16 | export const matches = ['shortmoz.link'] 17 | -------------------------------------------------------------------------------- /src/bypasses/softpedia.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Softpedia extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.ifElement('meta[http-equiv=\'refresh\'][content]', m => { 11 | let c = m.content.replace('; url=', ';url='); 12 | if (c.indexOf(';url=') > -1) { 13 | this.helpers.safelyAssign(c.split(';url=')[1]); 14 | } 15 | }); 16 | } 17 | } 18 | 19 | export const matches = ['softpedia.com']; 20 | -------------------------------------------------------------------------------- /src/bypasses/sourceforge.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Sourceforge extends BypassDefinition { 4 | constructor() { 5 | super() 6 | } 7 | 8 | execute() { 9 | var button = document.createElement('button') 10 | var downloaded = false 11 | button.className = 'direct-download' 12 | button.style.display = 'none' 13 | document.documentElement.appendChild(button) 14 | this.helpers.ODP(window, 'log', { 15 | value: m => { 16 | console.log(m) 17 | if (m === 'triggering downloader:start') { 18 | downloaded = true 19 | } 20 | }, 21 | writable: false 22 | }) 23 | this.helpers.ensureDomLoaded(() => { 24 | let buttonTimer = setInterval(() => { 25 | if (downloaded) { 26 | button.click() 27 | clearInterval(buttonTimer) 28 | } 29 | }, 100) 30 | }) 31 | } 32 | } 33 | 34 | export const matches = ['/sourceforge.net/projects/.+/files/.+/download/'] 35 | -------------------------------------------------------------------------------- /src/bypasses/spaste.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Spaste extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.insertInfoBox('Please complete the captcha to continue'); 11 | const doTheThing = f => setTimeout(() => { 12 | let item = document.querySelector('#currentCapQue').textContent; 13 | document.querySelectorAll('.markAnswer').forEach(as => { 14 | if (as.querySelector('img').getAttribute('src').toLowerCase().indexOf(item) > -1) { 15 | as.click(); 16 | } 17 | }); 18 | f(); 19 | }, 200); 20 | document.querySelector('#captchaVerifiedStatus').click(); 21 | doTheThing(() => doTheThing(() => doTheThing(() => document.querySelector('#template-contactform-submit').click()))); 22 | } 23 | } 24 | 25 | export const matches = ['spaste.com/s', 'spaste.com/site']; 26 | -------------------------------------------------------------------------------- /src/bypasses/squidssh.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Squidssh extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | let p = atob((new URLSearchParams(location.search)).get('short')) 11 | crowdPath(p) 12 | crowdBypass(() => this.helpers.ifElement("form[action='/user/links']", f => f.action += "#" + p)) 13 | } 14 | } 15 | 16 | export const matches = ['squidssh.com/li/go.php', 'goodssh.com/li/go.php'] 17 | -------------------------------------------------------------------------------- /src/bypasses/srtam.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Srtam extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.ensureDomLoaded(() => { 11 | if (document.querySelector(".skip-container")) { 12 | let form = document.createElement("form") 13 | form.method = "POST" 14 | form.innerHTML = "" 15 | form = document.documentElement.appendChild(form) 16 | this.helpers.countIt(() => form.submit()) 17 | } 18 | }) 19 | } 20 | } 21 | 22 | export const matches = ['srt.am'] 23 | -------------------------------------------------------------------------------- /src/bypasses/sub2unlock.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Sub2unlock extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | const url = document.URL; 11 | let destination; 12 | 13 | if(url.includes("sub2unlock.com/link/unlock")) { 14 | destination = document.getElementById("link").getAttribute("href"); 15 | } else { 16 | const urlSplit = url.split("/"); 17 | destination = 'https://sub2unlock.com/link/unlock/' + urlSplit[urlSplit.length - 1]; 18 | } 19 | 20 | this.helpers.safelyNavigate(destination); 21 | } 22 | } 23 | 24 | export const matches = ['sub2unlock.com'] 25 | -------------------------------------------------------------------------------- /src/bypasses/sub4unlock.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Sub4unlock extends BypassDefinition { 4 | constructor() { 5 | super() 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | if (typeof fun2 == "function") { 11 | window.open = this.helpers.safelyNavigate 12 | fun2() 13 | } 14 | } 15 | } 16 | 17 | export const matches = ['sub4unlock.com'] 18 | -------------------------------------------------------------------------------- /src/bypasses/syosetu.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Syosetu extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | const [, second] = document.URL.match(/.*syosetu\.org\/\?mode=url_jump&url=(.+)/); 11 | this.helpers.safelyNavigate( 12 | decodeURIComponent(second) 13 | ) 14 | } 15 | } 16 | 17 | export const matches = ['syosetu.org'] 18 | -------------------------------------------------------------------------------- /src/bypasses/tii.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class TiiLa extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | this.ensure_dom = true; 7 | } 8 | 9 | execute() { 10 | const urlObj = new URL(window.location.href) 11 | this.helpers.crowdQuery('tii.la', urlObj.pathname.slice(1)).then((dest) => { 12 | this.helpers.crowdNavigate(dest) 13 | }); 14 | /*keep checking for the button*/ 15 | setInterval(() => { 16 | const button = document.querySelector("a.btn.btn-success.btn-lg.get-link"); 17 | if (button && button.href) { 18 | this.helpers.crowdContribute('tii.la', urlObj.pathname.slice(1), button.href) 19 | this.helpers.safelyNavigate(button.href) 20 | } 21 | }, 500); 22 | 23 | } 24 | } 25 | 26 | export const matches = ['tii.la']; 27 | -------------------------------------------------------------------------------- /src/bypasses/tiklat.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Tiklat extends BypassDefinition { 4 | constructor () { 5 | super() 6 | } 7 | 8 | execute () { 9 | window.setInterval = func => setInterval(func, 1) 10 | this.helpers.awaitElement('.skip > .wait > .skip > .btn > a[href]', a => { 11 | this.helpers.safelyNavigate(a.href) 12 | }) 13 | } 14 | } 15 | 16 | export const matches = ['tik.lat'] 17 | -------------------------------------------------------------------------------- /src/bypasses/tlgd.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Tlgd extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | this.helpers.safelyAssign("http://www.twitlonger.com/show" + location.pathname) 11 | } 12 | } 13 | 14 | export const matches = ['tl.gd']; 15 | -------------------------------------------------------------------------------- /src/bypasses/uiz.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Uiz extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | Object.freeze(location) 11 | this.helpers.ensureDomLoaded(() => { 12 | const regHere = /.*window\.location\.href = "(http[^"]+)";.*/ 13 | document.querySelectorAll("script").forEach(script => { 14 | let match = regHere.exec(script.textContent) 15 | if (match && match[1]){ 16 | this.helpers.crowdPath(bypassClipboard) 17 | this.helpers.contributeAndNavigate(match[1]) 18 | 19 | } 20 | }) 21 | }) 22 | } 23 | } 24 | 25 | export const matches = ['uiz.io', 'uiz.app', 'tlkm.id'] 26 | -------------------------------------------------------------------------------- /src/bypasses/uploadking.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Uploadking extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | this.ensure_dom = true 7 | } 8 | 9 | execute() { 10 | this.helpers.ifElement("form[name='F1']", f => this.helpers.countIt(() => f.submit())) 11 | } 12 | } 13 | 14 | export const matches = ['uploadking.net']; 15 | -------------------------------------------------------------------------------- /src/bypasses/uploadrar.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Uploadrar extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | document.querySelector('.mngez-free-download').click(); 11 | document.querySelector('#direct_link > a:nth-child(1)').click(); 12 | document.querySelector('#downloadbtn.downloadbtn').click(); 13 | } 14 | } 15 | 16 | export const matches = ['uploadrar.com', 'uploadrar.net', 'uptomega.me'] 17 | -------------------------------------------------------------------------------- /src/bypasses/ux9.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Ux9 extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.safelyAssign(window.ux_secure.fullUrl); 11 | } 12 | } 13 | 14 | export const matches = ['ux9.de']; 15 | -------------------------------------------------------------------------------- /src/bypasses/vk.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Vk extends BypassDefinition { 4 | constructor() { 5 | super() 6 | } 7 | 8 | execute() { 9 | this.helpers.safelyNavigate(decodeURIComponent(document.URL.match(/vk\.com\/away\.php\?to=([^&]+)/)[1])) 10 | } 11 | } 12 | 13 | export const matches = ['vk.com/away.php?to='] 14 | -------------------------------------------------------------------------------- /src/bypasses/wadooo.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Wadooo extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.crowdPath(location.hash.substring(1)) 11 | this.helpers.crowdBypass() 12 | } 13 | } 14 | 15 | export const matches = ['wadooo.com'] 16 | -------------------------------------------------------------------------------- /src/bypasses/workclick.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js'; 2 | 3 | export default class Workclick extends BypassDefinition { 4 | constructor() { 5 | super(); 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | async execute() { 10 | const uuid = new URLSearchParams(window.location.search).get('t'); 11 | this.helpers.insertInfoBox( 12 | 'You will need to wait for 10 seconds as the site is loading the destination URL. Please be patient.' 13 | ); 14 | fetch(`https://redirect-api.work.ink/externalPopups/${uuid}/pageOpened`); 15 | await new Promise((r) => setTimeout(r, 11 * 1000)); 16 | let { destination } = await fetch( 17 | `https://redirect-api.work.ink/externalPopups/${uuid}/destination` 18 | ).then((r) => r.json()); 19 | const url = new URL(destination); 20 | if (url.searchParams.has('duf')) { 21 | const finalUrl = window.atob( 22 | url.searchParams.get('duf').split('').reverse().join('') 23 | ); 24 | destination = finalUrl; 25 | } 26 | let path = await this.helpers.ffclipboard.get('workink'); 27 | this.helpers.ffclipboard.clear('workink'); 28 | this.helpers.followAndContribute('work.ink', path, destination); 29 | 30 | return this.helpers.safelyNavigate(destination); 31 | } 32 | } 33 | 34 | export const matches = ['workink.click']; 35 | -------------------------------------------------------------------------------- /src/bypasses/ytsubme.js: -------------------------------------------------------------------------------- 1 | import BypassDefinition from './BypassDefinition.js' 2 | 3 | export default class Ytsubme extends BypassDefinition { 4 | constructor() { 5 | super() 6 | // custom bypass required bases can be set here 7 | } 8 | 9 | execute() { 10 | this.helpers.ensureDomLoaded(() =>{ 11 | this.helpers.ifElement("a#link", addr => { 12 | this.helpers.safelyNavigate(addr.href) 13 | }) 14 | }) 15 | } 16 | } 17 | 18 | export const matches = ['ytsubme.com'] 19 | -------------------------------------------------------------------------------- /src/helpers/infobox.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Inserts an info box into the DOM. This is used to show the user information or to complete a specific step (do a captcha, for example). 3 | * @param {string} text - The text to show in the info box. 4 | */ 5 | export function insertInfoBox(text) { 6 | let infobox_container = document.querySelector('div#ffibv1'); 7 | 8 | if (!infobox_container) { 9 | infobox_container = document.createElement('div'); 10 | infobox_container.setAttribute('id', 'ffibv1'); 11 | infobox_container.setAttribute( 12 | 'style', 13 | ` 14 | z-index: 99999999; position: fixed; bottom: 0; line-height:normal; 15 | right: 0; padding: 20px; color:#111; font-size:21px; 16 | font-family:-apple-system,BlinkMacSystemFont,segoe ui,Roboto,helvetica neue,Arial,sans-serif,apple color emoji,segoe ui emoji,segoe ui symbol; 17 | max-width:500px; display: flex; flex-direction: column-reverse; 18 | ` 19 | ); 20 | 21 | document.body.appendChild(infobox_container); 22 | } 23 | const div = document.createElement('div'); 24 | div.style = 25 | 'margin-left:20px; margin-bottom: 20px;background:#eee;border-radius:10px;padding:20px;box-shadow:#111 0px 5px 40px;cursor:pointer'; 26 | div.innerHTML = ``; 27 | div.setAttribute('aria-hidden', 'true'); 28 | const span = div.querySelector('span'); 29 | span.textContent = text; 30 | div.onclick = () => infobox_container.removeChild(div); 31 | infobox_container.appendChild(div); 32 | setTimeout(() => infobox_container.removeChild(div), 7000); 33 | } 34 | 35 | export default insertInfoBox; 36 | -------------------------------------------------------------------------------- /src/html/base.js: -------------------------------------------------------------------------------- 1 | const brws = typeof browser == 'undefined' ? chrome : browser; 2 | document.documentElement.setAttribute( 3 | 'dir', 4 | brws.i18n.getMessage('@@bidi_dir') 5 | ); 6 | -------------------------------------------------------------------------------- /src/html/before-navigate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 18 |
19 |

20 |

21 |
22 |

23 |
24 | 31 |
32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/html/before-navigate.js: -------------------------------------------------------------------------------- 1 | /*global brws*/ 2 | const timerElement = document.getElementById('timer'); 3 | const timerText = timerElement.querySelector('p'); 4 | 5 | // Get target URL from search parameter 6 | const urlParams = new URLSearchParams(window.location.search); 7 | const targetUrl = urlParams.get('target'); 8 | 9 | function escapeHtml(unsafe) { 10 | if (!unsafe) return unsafe; //prevents null objects from throwing an error 11 | return unsafe 12 | .replaceAll('&', '&') 13 | .replaceAll('<', '<') 14 | .replaceAll('>', '>') 15 | .replaceAll('"', '"') 16 | .replaceAll("'", '''); 17 | } 18 | 19 | // Update destination message with target URL 20 | const destinationElement = document.querySelector('#destination'); 21 | destinationElement.innerHTML = brws.i18n.getMessage( 22 | 'beforeNavigateDestination', 23 | `
${escapeHtml(targetUrl)} ` 26 | ); 27 | 28 | brws.storage.local.get('options', (result) => { 29 | if (!result.options.navigationDelayToggle) { 30 | return; 31 | } 32 | const delay = result.options.navigationDelay; 33 | let timeLeft = delay; 34 | 35 | timerElement.classList.remove('uk-hidden'); 36 | timerText.textContent = brws.i18n.getMessage( 37 | timeLeft === 1 ? 'beforeNavigateTimerSingular' : 'beforeNavigateTimer', 38 | [timeLeft] 39 | ); 40 | 41 | const interval = setInterval(() => { 42 | timeLeft--; 43 | if (timeLeft <= 0) { 44 | clearInterval(interval); 45 | window.location.href = targetUrl; 46 | } else { 47 | timerText.textContent = brws.i18n.getMessage( 48 | timeLeft === 1 ? 'beforeNavigateTimerSingular' : 'beforeNavigateTimer', 49 | [timeLeft] 50 | ); 51 | } 52 | }, 1000); 53 | }); 54 | -------------------------------------------------------------------------------- /src/html/blocked.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 18 |
19 |

20 |

21 |
22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/html/consent.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | FastForward 5 | 6 | 7 | 8 | 9 | 41 | 42 | 43 | 48 |
49 |
50 |

Thank you for installing FastForward

51 |

52 | This extension collects the tab url when you choose to add a website to the whitelist, and temporarily processes the url of bypassed sites while navigating them. This data never leaves your device. 53 |

54 |

55 | Additionally, if the "Crowd Bypass" option is enabled, the extension may send some bypassed urls to our server to be processed and added to our database in accordance with our privacy policy. They are never shared. 56 |

57 |

58 | If you consent to this data collection hit "Agree" to continue and then allow the permission request. Otherwise hit "Refuse" and the extension will be uninstalled. 59 |

60 | 61 | 62 |
63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /src/html/consent.js: -------------------------------------------------------------------------------- 1 | // Function to save consent status 2 | async function saveConsentStatus(consentStatus) { 3 | return browser.storage.local.set({ consentStatus: consentStatus }); 4 | } 5 | 6 | // Function to get consent status 7 | async function getConsentStatus() { 8 | return new Promise((resolve) => { 9 | browser.storage.local.get('consentStatus').then((result) => { 10 | resolve(result.consentStatus); 11 | }); 12 | }); 13 | } 14 | 15 | // Event listener for "Agree" button 16 | document.querySelector('#agree').addEventListener('click', async function () { 17 | console.log("Agree button clicked."); 18 | const permissionsToRequest = { 19 | origins: [""], 20 | }; 21 | function onResponse(response) { 22 | if (response) { 23 | console.log("Permission was granted"); 24 | window.close(); // Close the window after permission is granted 25 | } else { 26 | console.log("Permission was refused"); 27 | browser.management.uninstallSelf(); 28 | } 29 | return browser.permissions.getAll(); 30 | } 31 | const response = await browser.permissions.request(permissionsToRequest); 32 | const currentPermissions = await onResponse(response); 33 | console.log(`Current permissions:`, currentPermissions); 34 | await saveConsentStatus('consent-granted'); 35 | }); 36 | 37 | // Event listener for "Refuse" button 38 | document.querySelector('#refuse').addEventListener('click', async function () { 39 | console.log("Uninstalling extension."); 40 | browser.management.uninstallSelf(); 41 | }); -------------------------------------------------------------------------------- /src/html/crowd-bypassed.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 |
17 |

18 |

19 | 22 |

23 | 26 |
27 | 34 | 35 |
36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /src/html/crowd-bypassed.js: -------------------------------------------------------------------------------- 1 | /*global brws*/ 2 | const timerElement = document.getElementById('timer'); 3 | const timerText = timerElement.querySelector('p'); 4 | const tempDisableCrowdButton = document.getElementById('temp-disable-crowd'); 5 | 6 | // Get target URL from search parameter 7 | const urlParams = new URLSearchParams(window.location.search); 8 | const targetUrl = urlParams.get('target'); 9 | 10 | function escapeHtml(unsafe) { 11 | if (!unsafe) return unsafe; //prevents null objects from throwing an error 12 | return unsafe 13 | .replaceAll('&', '&') 14 | .replaceAll('<', '<') 15 | .replaceAll('>', '>') 16 | .replaceAll('"', '"') 17 | .replaceAll("'", '''); 18 | } 19 | 20 | function updateDestinationMessage() { 21 | let msg = brws.i18n.getMessage( 22 | 'crowdBypassedInfo', 23 | `
${escapeHtml(targetUrl)} ` 26 | ); 27 | document.querySelector('#crowd-bypass-info').innerHTML = msg; 28 | } 29 | 30 | tempDisableCrowdButton.addEventListener('click', () => { 31 | brws.storage.local.get(['options']).then((result) => { 32 | let opt = result.options; 33 | if (!opt.optionCrowdBypass) { 34 | return; 35 | } 36 | opt.optionCrowdBypass = false; 37 | brws.storage.local.set({ options: opt }); 38 | brws.storage.local.set({ tempDisableCrowd: 'true' }); 39 | // Create an alarm that will trigger after 10 minutes 40 | brws.alarms.create('enableCrowdBypass', { delayInMinutes: 10 }); 41 | history.back(); 42 | }); 43 | }); 44 | 45 | brws.storage.local.get('options', (result) => { 46 | if (!result.options.optionCrowdOpenDelayToggle) { 47 | return; 48 | } 49 | const delay = result.options.optionCrowdOpenDelay; 50 | // Show countdown timer 51 | let timeLeft = delay; 52 | timerElement.hidden = false; 53 | timerText.textContent = brws.i18n.getMessage( 54 | timeLeft === 1 ? 'crowdBypassedTimerSingular' : 'crowdBypassedTimer', 55 | [timeLeft] 56 | ); 57 | 58 | const interval = setInterval(() => { 59 | timeLeft--; 60 | if (timeLeft <= 0) { 61 | clearInterval(interval); 62 | window.open(targetUrl, '_blank').focus(); 63 | timerElement.hidden = true; 64 | } else { 65 | timerText.textContent = brws.i18n.getMessage( 66 | timeLeft === 1 ? 'crowdBypassedTimerSingular' : 'crowdBypassedTimer', 67 | [timeLeft] 68 | ); 69 | } 70 | }, 1000); 71 | }); 72 | 73 | updateDestinationMessage(); 74 | -------------------------------------------------------------------------------- /src/html/i18n.js: -------------------------------------------------------------------------------- 1 | document.querySelectorAll("[data-message]").forEach(e=>e.textContent=brws.i18n.getMessage(e.getAttribute("data-message"))) 2 | const titleElm=document.querySelector("title"),title=titleElm.textContent 3 | -------------------------------------------------------------------------------- /src/html/noscript.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |

12 |
13 |

14 |
15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/html/popup.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | FastForward 5 | 6 | 7 | 8 | 9 | 10 | 11 | 17 |
18 | 24 |
25 |
26 | 27 |
28 |
29 |

30 |

31 | 32 | 33 |
34 |
35 |

36 |
37 | 38 | 39 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/html/popup.js: -------------------------------------------------------------------------------- 1 | /*global brws*/ 2 | let defaultOptions = { 3 | navigationDelayToggle: true, 4 | navigationDelay: 10, 5 | optionTrackerBypass: false, 6 | optionInstantNavigationTrackers: false, 7 | optionBlockIpLoggers: true, 8 | optionCrowdBypass: false, 9 | optionCrowdOpenDelayToggle: false, 10 | optionCrowdOpenDelay: 5, 11 | optionCrowdCloseDelayToggle: false, 12 | optionCrowdCloseDelay: 15, 13 | whitelist: '', 14 | }; 15 | 16 | async function saveOptions(options) { 17 | return brws.storage.local.set({ options: options }); 18 | } 19 | 20 | async function getOptions() { 21 | return new Promise((resolve) => { 22 | brws.storage.local.get('options').then((result) => { 23 | resolve(result.options); 24 | }); 25 | }); 26 | } 27 | 28 | function displayExtensionVersion() { 29 | brws.storage.local 30 | .get('version') 31 | .then( 32 | (data) => 33 | (document.getElementById('version').textContent = data.version + '-Mv3') 34 | ); 35 | } 36 | 37 | function formatWhitelistDesc() { 38 | document.querySelector( 39 | "[data-message='optionsWhitelistDescription']" 40 | ).innerHTML = document 41 | .querySelector("[data-message='optionsWhitelistDescription']") 42 | .textContent.replace( 43 | 'subdomain.domain.tld', 44 | 'subdomain.domain.tld' 45 | ) 46 | .replace('domain.tld', 'domain.tld'); 47 | } 48 | 49 | function addEventListeners() { 50 | document 51 | .querySelector('#whitelist') 52 | .addEventListener('input', async function () { 53 | let options = await getOptions(); 54 | options['whitelist'] = this.value; 55 | saveOptions(options); 56 | checkTextareaValidity(); 57 | }); 58 | 59 | document 60 | .querySelector("#openOptions") 61 | .addEventListener('click', function () { 62 | window.open("/html/options.html"); 63 | }); 64 | 65 | document 66 | .querySelector('#addToWhitelist') 67 | .addEventListener('click', async function () { 68 | let value = document.getElementById("whitelist").value; 69 | let prefix = ""; 70 | if(value != "" && value[value.length-1] != "\n") { 71 | prefix = "\n"; 72 | } 73 | 74 | chrome.tabs.query({active: true, currentWindow: true}, function(tabs) { 75 | let hostname = new URL(tabs[0].url).host; 76 | let whitelistTextarea = document.getElementById("whitelist"); 77 | if(!whitelistTextarea.value.includes(hostname)) { 78 | whitelistTextarea.value += prefix + hostname; 79 | whitelistTextarea.dispatchEvent(new Event('input')); 80 | } 81 | }); 82 | }); 83 | } 84 | 85 | function checkTextareaValidity() { 86 | let textarea = document.querySelector('#whitelist'); 87 | if (textarea.value.includes('/')) { 88 | textarea.classList.add('invalid'); 89 | } else { 90 | textarea.classList.remove('invalid'); 91 | } 92 | } 93 | 94 | async function repopulateOptions() { 95 | let options = Object.assign({}, defaultOptions, await getOptions()); 96 | let key = 'whitelist'; 97 | let element = document.querySelector('#' + key); 98 | if (element.tagName === 'TEXTAREA') { 99 | element.value = options[key]; 100 | } 101 | saveOptions(options); 102 | } 103 | 104 | 105 | document.addEventListener('DOMContentLoaded', async function () { 106 | await repopulateOptions(); 107 | addEventListeners(); 108 | checkTextareaValidity(); 109 | formatWhitelistDesc(); 110 | displayExtensionVersion(); 111 | }); 112 | 113 | function addBottomNavbar() { 114 | if (window.innerWidth < 768 && !document.querySelector('.bottom-navbar')) { 115 | const bottomNavbar = document.createElement('nav'); 116 | document.body.appendChild(bottomNavbar); 117 | const bottomNavbarUl = document.createElement('ul'); 118 | bottomNavbar.appendChild(bottomNavbarUl); 119 | 120 | const navLinks = document.querySelectorAll('.navlink'); 121 | navLinks.forEach((link) => { 122 | bottomNavbarUl.appendChild(link); 123 | }); 124 | 125 | bottomNavbar.classList.add('bottom-navbar'); 126 | } else { 127 | const bottomNavbar = document.querySelector('.bottom-navbar'); 128 | if (bottomNavbar) { 129 | const navLinks = bottomNavbar.querySelectorAll('.navlink'); 130 | const nav = document.querySelector('nav:not(.bottom-navbar)'); 131 | const navUl = nav.querySelector('ul'); 132 | navLinks.forEach((link) => { 133 | navUl.appendChild(link); 134 | }); 135 | bottomNavbar.remove(); 136 | } 137 | } 138 | } 139 | 140 | addBottomNavbar(); -------------------------------------------------------------------------------- /src/html/tracker-bypass.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 18 |
19 |

20 |

21 |
22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/html/tracker-bypass.js: -------------------------------------------------------------------------------- 1 | /*global brws*/ 2 | const trackerInfoElement = document.getElementById('tracker-info'); 3 | 4 | // Get tracker URL from search parameter 5 | const urlParams = new URLSearchParams(window.location.search); 6 | let trackerUrl = urlParams.get('url'); 7 | if (!trackerUrl) showError('no url param found'); 8 | 9 | function escapeHtml(str) { 10 | if (!str) return str; //prevents null objects from throwing an error 11 | return str 12 | .replaceAll('&', '&') 13 | .replaceAll('<', '<') 14 | .replaceAll('>', '>') 15 | .replaceAll('"', '"') 16 | .replaceAll("'", '''); 17 | } 18 | 19 | function showError(err) { 20 | console.error(err); 21 | trackerInfoElement.textContent = brws.i18n.getMessage('trackerBypassedError'); 22 | trackerInfoElement.classList.add('text-warn'); 23 | setTimeout(() => { 24 | if (trackerUrl) window.location.replace(trackerUrl); 25 | else console.error('no url param found'); 26 | }, 3000); 27 | } 28 | 29 | function updateTrackerMessage(url) { 30 | const trackerInfoElement = document.getElementById('tracker-info'); 31 | const msg = brws.i18n.getMessage( 32 | 'beforeNavigateDestination', 33 | ` 34 | 35 | 36 | ${escapeHtml(url)} 37 | 38 | ` 39 | ); 40 | const newDiv = document.createElement('div'); 41 | 42 | newDiv.appendChild(document.createElement('br')); 43 | 44 | newDiv.innerHTML = msg; 45 | 46 | trackerInfoElement.textContent = ''; 47 | trackerInfoElement.appendChild(newDiv); 48 | 49 | brws.storage.local.get('options').then((result) => { 50 | if (!result.options.optionInstantNavigationTrackers) return; 51 | window.location.replace(url); 52 | }); 53 | } 54 | 55 | async function resolveTracker(url) { 56 | //special case for out.reddit.com 57 | const urlObj = new URL(url); 58 | if (urlObj.host === 'out.reddit.com') { 59 | const newUrl = urlObj.searchParams.get('url'); 60 | if (newUrl) updateTrackerMessage(newUrl); 61 | else showError(); 62 | } 63 | 64 | url = url.replace(/(^\w+:|^)\/\//, ''); 65 | 66 | try { 67 | const response = await fetch(`https://unshorten.me/json/${url}`); 68 | const data = await response.json(); 69 | if (data.success && data.resolved_url) { 70 | updateTrackerMessage(data.resolved_url); 71 | } else { 72 | showError(); 73 | } 74 | } catch (err) { 75 | showError(err); 76 | } 77 | } 78 | 79 | resolveTracker(trackerUrl); 80 | -------------------------------------------------------------------------------- /src/icon/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastForwardTeam/FastForward/a9b1894387e5b14892bc6c4deab1dd4edd46c0d2/src/icon/128.png -------------------------------------------------------------------------------- /src/icon/150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastForwardTeam/FastForward/a9b1894387e5b14892bc6c4deab1dd4edd46c0d2/src/icon/150.png -------------------------------------------------------------------------------- /src/icon/176.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastForwardTeam/FastForward/a9b1894387e5b14892bc6c4deab1dd4edd46c0d2/src/icon/176.png -------------------------------------------------------------------------------- /src/icon/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastForwardTeam/FastForward/a9b1894387e5b14892bc6c4deab1dd4edd46c0d2/src/icon/48.png -------------------------------------------------------------------------------- /src/icon/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastForwardTeam/FastForward/a9b1894387e5b14892bc6c4deab1dd4edd46c0d2/src/icon/512.png -------------------------------------------------------------------------------- /src/icon/branding.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastForwardTeam/FastForward/a9b1894387e5b14892bc6c4deab1dd4edd46c0d2/src/icon/branding.png -------------------------------------------------------------------------------- /src/icon_disabled/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastForwardTeam/FastForward/a9b1894387e5b14892bc6c4deab1dd4edd46c0d2/src/icon_disabled/128.png -------------------------------------------------------------------------------- /src/icon_disabled/150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastForwardTeam/FastForward/a9b1894387e5b14892bc6c4deab1dd4edd46c0d2/src/icon_disabled/150.png -------------------------------------------------------------------------------- /src/icon_disabled/176.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastForwardTeam/FastForward/a9b1894387e5b14892bc6c4deab1dd4edd46c0d2/src/icon_disabled/176.png -------------------------------------------------------------------------------- /src/icon_disabled/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastForwardTeam/FastForward/a9b1894387e5b14892bc6c4deab1dd4edd46c0d2/src/icon_disabled/48.png -------------------------------------------------------------------------------- /src/icon_disabled/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FastForwardTeam/FastForward/a9b1894387e5b14892bc6c4deab1dd4edd46c0d2/src/icon_disabled/512.png -------------------------------------------------------------------------------- /src/js/constants.js: -------------------------------------------------------------------------------- 1 | export const beforeNavigateRules = [ 2 | { 3 | id: 1, 4 | priority: 2, 5 | action: { 6 | type: 'redirect', 7 | redirect: { 8 | regexSubstitution: 9 | chrome.runtime.getURL('/html/crowd-bypassed.html') + '\\1', 10 | }, 11 | }, 12 | condition: { 13 | regexFilter: 14 | '^https?://fastforward.team/bypassed(\\?(.*&)?type=crowd(&.*)?$)', 15 | resourceTypes: ['main_frame'], 16 | }, 17 | }, 18 | { 19 | id: 2, 20 | priority: 2, 21 | action: { 22 | type: 'redirect', 23 | redirect: { 24 | regexSubstitution: 25 | chrome.runtime.getURL('/html/tracker-bypass.html') + '\\1', 26 | }, 27 | }, 28 | condition: { 29 | regexFilter: 30 | '^https?://fastforward.team/bypassed(\\?(.*&)?type=tracker(&.*)?$)', 31 | resourceTypes: ['main_frame'], 32 | }, 33 | }, 34 | { 35 | id: 3, 36 | priority: 1, 37 | action: { 38 | type: 'redirect', 39 | redirect: { 40 | regexSubstitution: 41 | chrome.runtime.getURL('/html/before-navigate.html') + '\\1', 42 | }, 43 | }, 44 | condition: { 45 | regexFilter: '^https?://fastforward\\.team/bypassed(\\?.*)', 46 | resourceTypes: ['main_frame'], 47 | }, 48 | }, 49 | ]; 50 | -------------------------------------------------------------------------------- /src/js/content_script.js: -------------------------------------------------------------------------------- 1 | const brws = typeof browser !== 'undefined' ? browser : chrome; 2 | async function getOptions() { 3 | return new Promise((resolve) => { 4 | brws.storage.local.get('options').then((result) => { 5 | resolve(result.options); 6 | }); 7 | }); 8 | } 9 | 10 | function getExtBaseURL() { 11 | return brws.runtime.getURL('/'); 12 | } 13 | 14 | async function injectScript() { 15 | let options = await getOptions(); 16 | if ( 17 | options && 18 | options.whitelist && 19 | matchDomains(window.location.hostname, options.whitelist) 20 | ) { 21 | console.log('FastForward: Site whitelisted'); 22 | return; 23 | } 24 | let script = document.createElement('script'); 25 | script.src = 26 | brws.runtime.getURL('injection_script.js') + 27 | '?' + 28 | new URLSearchParams({ ext_base_URL: getExtBaseURL() }); //pass base url to injection script https://stackoverflow.com/a/9517879 29 | script.onload = function () { 30 | script.remove(); 31 | }; 32 | (document.head || document.documentElement).appendChild(script); 33 | } 34 | 35 | //ff + first 10 characters of SHA256 of fastforward to prevent collisions 36 | document.addEventListener('ff53054c0e13_crowdQuery', async (event) => { 37 | let data = event.detail; 38 | const response = await chrome.runtime.sendMessage({ 39 | type: 'crowdQuery', 40 | detail: data, 41 | }); 42 | console.log(response); 43 | document.dispatchEvent( 44 | new CustomEvent('ff53054c0e13_crowdResponse', { detail: response }) 45 | ); 46 | }); 47 | 48 | function matchDomains(inputString, domains) { 49 | let domainList = domains.split('\n'); 50 | for (let domain of domainList) { 51 | let regex = new RegExp('^' + domain.replace(/\*/g, '[^.]+') + '$'); 52 | if (regex.test(inputString)) { 53 | return true; 54 | } 55 | } 56 | return false; 57 | } 58 | 59 | document.addEventListener('ff53054c0e13_crowdContribute', (event) => { 60 | let data = event.detail; 61 | chrome.runtime.sendMessage({ 62 | type: 'crowdContribute', 63 | detail: data, 64 | }); 65 | }); 66 | document.addEventListener('ff53054c0e13_followAndContribute', (event) => { 67 | let data = event.detail; 68 | chrome.runtime.sendMessage({ 69 | type: 'followAndContribute', 70 | detail: data, 71 | }); 72 | }); 73 | 74 | function onFFClipboardSet(event) { 75 | const { key, value } = event.detail; 76 | chrome.storage.local.get('ffclipboard', (result) => { 77 | const ffclipboard = result.ffclipboard || {}; 78 | ffclipboard[key] = value; 79 | chrome.storage.local.set({ ffclipboard }); 80 | }); 81 | } 82 | 83 | function onFFClipboardGet(event) { 84 | const { key } = event.detail; 85 | chrome.storage.local.get('ffclipboard', (result) => { 86 | const value = result.ffclipboard ? result.ffclipboard[key] : undefined; 87 | const responseEvent = new CustomEvent('ff53054c0e13_ffclipboardResponse', { 88 | detail: { key, value }, 89 | }); 90 | document.dispatchEvent(responseEvent); 91 | }); 92 | } 93 | 94 | function onFFClipboardClear(event) { 95 | const { key } = event.detail; 96 | chrome.storage.local.get('ffclipboard', (result) => { 97 | if (result.ffclipboard) { 98 | delete result.ffclipboard[key]; 99 | chrome.storage.local.set({ ffclipboard: result.ffclipboard }); 100 | } 101 | }); 102 | } 103 | 104 | injectScript(); 105 | document.addEventListener('ff53054c0e13_ffclipboardSet', onFFClipboardSet); 106 | document.addEventListener('ff53054c0e13_ffclipboardGet', onFFClipboardGet); 107 | document.addEventListener('ff53054c0e13_ffclipboardClear', onFFClipboardClear); 108 | -------------------------------------------------------------------------------- /src/version.txt: -------------------------------------------------------------------------------- 1 | 0.0.0 2 | -------------------------------------------------------------------------------- /tests/bypasses.json: -------------------------------------------------------------------------------- 1 | { 2 | "https://cutt.ly/9WBfIgT": { 3 | "destination": "www.google.com", 4 | "timeout": 5000 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/index.js: -------------------------------------------------------------------------------- 1 | const puppeteer = require('puppeteer') 2 | const path = require('path') 3 | 4 | const { EventEmitter } = require('events'); 5 | const { URL } = require('url'); 6 | 7 | const bypasses = require('./bypasses.json'); 8 | 9 | 10 | 11 | class TimeoutError extends Error { 12 | constructor(message) { 13 | super(message); 14 | this.name = this.constructor.name; 15 | Error.captureStackTrace(this, this.constructor); 16 | } 17 | } 18 | 19 | 20 | (async() => { 21 | const browser = await puppeteer.launch({ 22 | headless: false, 23 | args: [ 24 | '--no-sandbox', 25 | `--load-extension=${path.join(__dirname, '../build/FastForward.chromium')}` 26 | ], 27 | ignoreDefaultArgs: ['--disable-extensions', '--enable-automation'] 28 | }); 29 | 30 | // We do not need to view the FastForward site 31 | browser.on('targetcreated', async target => { 32 | if (target.url() === 'https://fastforward.team/firstrun') { 33 | const targetPage = await target.page() 34 | targetPage.close() 35 | return; 36 | } 37 | }) 38 | const page = await browser.newPage() 39 | await page.setRequestInterception(true); 40 | // A custom EventEmitter to emit url changes 41 | const urlEmitter = new EventEmitter() 42 | page.on('request', request => { 43 | const url = new URL(request.url()) 44 | urlEmitter.emit('change', url.host) 45 | request.continue(); 46 | }) 47 | 48 | const waitForDomain = (domain, timeoutms) => { 49 | return new Promise((resolve, reject) => { 50 | const timeout = setTimeout(() => { 51 | reject(new TimeoutError(`Timeout limit of ${timeoutms}ms has been exceeded`)) 52 | }, timeoutms) 53 | const listener = urlEmitter.on('change', changedURL => { 54 | if (domain === changedURL) { 55 | clearTimeout(timeout) 56 | resolve(); 57 | urlEmitter.removeListener('change', listener); 58 | } 59 | }) 60 | }) 61 | } 62 | 63 | // Wait 3 seconds for FastForward to load 64 | setTimeout(async () => { 65 | for (const url in bypasses) { 66 | const destination = bypasses[url].destination 67 | const timeout = bypasses[url].timeout || 5000 68 | console.log(`⌛ Testing "${url}" with expected destination "${destination}"`) 69 | await page.goto(url) 70 | await waitForDomain(destination, timeout) 71 | .then(() => { 72 | console.log(`✔️ Success`) 73 | }) 74 | .catch(err => { 75 | console.log(`❌ Failed at ${url}. ${err.message}`) 76 | process.exit(1) 77 | }) 78 | } 79 | console.log('✓ All bypasses have passed the test!') 80 | }, 3000) 81 | 82 | 83 | })() 84 | -------------------------------------------------------------------------------- /tests/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "autotest", 3 | "version": "1.0.0", 4 | "description": "A tool to automatically test FastForward extension", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/FastForwardTeam/FastForward.git", 9 | "directory": "tests" 10 | } 11 | } 12 | "license" : "Unlicense", 13 | "author": "Beaness", 14 | "dependencies": { 15 | "puppeteer": "^10.2.0" 16 | } 17 | } 18 | --------------------------------------------------------------------------------