56 |
56 |
├── Pagetual
├── version
├── pagetual.schema.json
└── README.md
├── A Real Me
├── README.md
└── ARealMe.user.js
├── Kill TieBa AD
├── README.md
└── Kill TieBa AD.user.js
├── Valentine's Day
├── README.md
├── css
│ └── default.css
├── js
│ ├── functions.js
│ └── garden.js
└── Valentine's Day.user.js
├── BingBgForBaidu
├── README.md
├── bd.jpg
└── BingBgForGoogle.user.js
├── Disable AD of ThisAV
├── README.md
├── av.jpg
└── Disable AD of ThisAV.user.js
├── Mouse Gestures
├── case.gif
├── README.md
└── Mouse Gestures.user.js
├── RandomSexyPic
├── case1.jpg
├── case2.jpg
├── case3.jpg
├── case4.jpg
├── case5.jpg
└── README.md
├── Picviewer CE+
├── customRule.png
├── gallery.html
├── pvcep_pdf_addon.user.js
└── README.md
├── FlashViewer-HTML5 Video
├── showcase.jpg
└── README.md
├── .gitignore
├── .github
├── FUNDING.yml
├── workflows
│ ├── json-validator.yml
│ ├── build-dist.yml
│ ├── main.yml
│ ├── jekyll-gh-pages.yml
│ └── update_version.yml
└── ISSUE_TEMPLATE
│ ├── feature_request.md
│ ├── custom-rule-request.md
│ └── bug_report.md
├── Invite Code Tool
├── README.md
└── Invite Code Tool.user.js
├── Select All Checkboxes
├── README.md
└── Select All Checkboxes.user.js
├── Messi
└── messi.user.js
├── Highlight Every Code
├── README.md
└── Highlight Every Code.user.js
├── SearchJumper
├── HideSaladict.user.js
├── searchJumperPinyinAddon.lib.js
└── searchJumperLevenshteinAddon.lib.js
├── Switch Traditional Chinese and Simplified Chinese
├── README.md
├── lib
│ ├── package.json
│ ├── stcasc.d.ts
│ └── test.js
└── run.py
├── True URL downloads
├── README.md
└── manageLinks.js
├── Bilibili Bangumi Cover
└── Bilibili Bangumi Cover.user.js
├── HacgGodTurn
├── README.md
└── od.js
├── Anti-anti-pic-stealing-link
└── Anti-anti-pic-stealing-link.user.js
├── Appinn Comment
└── AppinnComment.user.js
├── README.md
├── CODE_OF_CONDUCT.md
├── MoreSteamRatings
└── MoreSteamRatings.user.js
├── Easy offline
├── README.MD
└── Easy offline pikpak.user.js
├── X-Downloader
└── X-Downloader.user.js
└── DownloadAllContent
└── DownloadAllContentSavaAsZIP.user.js
/Pagetual/version:
--------------------------------------------------------------------------------
1 | 102
2 |
--------------------------------------------------------------------------------
/A Real Me/README.md:
--------------------------------------------------------------------------------
1 | # Show results for A Real Me
2 |
--------------------------------------------------------------------------------
/Kill TieBa AD/README.md:
--------------------------------------------------------------------------------
1 | Not maintained anymore
2 | ===
3 |
--------------------------------------------------------------------------------
/Valentine's Day/README.md:
--------------------------------------------------------------------------------
1 | Not maintained anymore
2 | ===
3 |
--------------------------------------------------------------------------------
/BingBgForBaidu/README.md:
--------------------------------------------------------------------------------
1 | # 百度首页美化,使用每日更新的 bing 图作为背景,添加万年历
2 | 
3 |
--------------------------------------------------------------------------------
/Disable AD of ThisAV/README.md:
--------------------------------------------------------------------------------
1 | # 为 THISAV 添加視頻下載按鈕,去除首次點擊彈窗、導航廣告
2 | 
3 |
--------------------------------------------------------------------------------
/BingBgForBaidu/bd.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoothin/UserScripts/HEAD/BingBgForBaidu/bd.jpg
--------------------------------------------------------------------------------
/Mouse Gestures/case.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoothin/UserScripts/HEAD/Mouse Gestures/case.gif
--------------------------------------------------------------------------------
/RandomSexyPic/case1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoothin/UserScripts/HEAD/RandomSexyPic/case1.jpg
--------------------------------------------------------------------------------
/RandomSexyPic/case2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoothin/UserScripts/HEAD/RandomSexyPic/case2.jpg
--------------------------------------------------------------------------------
/RandomSexyPic/case3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoothin/UserScripts/HEAD/RandomSexyPic/case3.jpg
--------------------------------------------------------------------------------
/RandomSexyPic/case4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoothin/UserScripts/HEAD/RandomSexyPic/case4.jpg
--------------------------------------------------------------------------------
/RandomSexyPic/case5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoothin/UserScripts/HEAD/RandomSexyPic/case5.jpg
--------------------------------------------------------------------------------
/Disable AD of ThisAV/av.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoothin/UserScripts/HEAD/Disable AD of ThisAV/av.jpg
--------------------------------------------------------------------------------
/Picviewer CE+/customRule.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoothin/UserScripts/HEAD/Picviewer CE+/customRule.png
--------------------------------------------------------------------------------
/FlashViewer-HTML5 Video/showcase.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hoothin/UserScripts/HEAD/FlashViewer-HTML5 Video/showcase.jpg
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | *.vcs-cache
3 | VIP Video Cracker/VIP Video Cracker.user.js
4 | Picviewer CE+/package-lock.json
5 | Pagetual/guide/*
6 | Pagetual/guide/
7 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 | ko_fi: hoothin
3 | custom: ["https://paypal.me/hoothin", "https://afdian.com/a/hoothin"]
4 |
--------------------------------------------------------------------------------
/Invite Code Tool/README.md:
--------------------------------------------------------------------------------
1 | Not maintained anymore
2 | ===
3 |
4 | [注冊邀請碼助手](https://chrome.google.com/webstore/detail/ndmlflmkmohjoechiepcpflbljadmemp)
5 | ---
6 |
--------------------------------------------------------------------------------
/Select All Checkboxes/README.md:
--------------------------------------------------------------------------------
1 | Select All Checkboxes
2 | =
3 | Useage
4 | -
5 | * Select all checkboxes by press **`Ctrl+Alt+mouse1`**
6 | * Or select checkboxes with mouse over by press **`Alt`**
7 | * Or select checkboxes between 2 marks by press **`Shift`**
8 |
--------------------------------------------------------------------------------
/FlashViewer-HTML5 Video/README.md:
--------------------------------------------------------------------------------
1 | # [FlashViewer⬇️](https://hoothin.github.io/UserScripts/FlashViewer-HTML5%20Video/flashViewer.user.js)
2 | HTML5 視頻增強腳本
3 |
4 | 原作者 NLF
5 |
6 | 在 NLF 的腳本基礎上添加了**自定義視頻速度**、**更改視頻比例**與**自定義亮度**功能並做了些許優化。彈出視頻後在工具欄右側即可看到。
7 |
8 | 長按三倍速,在視頻上左右拖動滑鼠微調進度。
9 |
10 | 
11 |
--------------------------------------------------------------------------------
/Mouse Gestures/README.md:
--------------------------------------------------------------------------------
1 | Greasemonkey Mouse Gestures
2 | ===
3 | 预置的鼠标手势:
4 | ---
5 | - ↓↑↓ = 用谷歌翻译当前网页或者选中单词
6 | - ↓↑↓← = 解除当前页面右键、复制、选择等限制
7 | - ↓↑↓→ = 显示淘宝天猫评论买家秀图片
8 | - ↓↑↓↑ = 查看当前页面所使用的各种技术
9 | - ↓→ = 关闭当前页面(标签)
10 | - ←↑ = 滚动至页头
11 | - ←↓ = 滚动至页尾
12 | - →↑← = 后退
13 | - ←↑→ = 前进
14 | - →↑ = 新建页(标签)
15 | - ↑↓ = 刷新
16 |
17 | 
18 | refer to "My Mouse Gestures"-ver.0.0.7 of Peer Zeng at [http://userscripts-mirror.org/scripts/show/463904], thanks to him
--------------------------------------------------------------------------------
/Messi/messi.user.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name 新浪法甲
3 | // @namespace hoothin
4 | // @version 0.1
5 | // @description 赛程列表滚动
6 | // @author hoothin
7 | // @match http://sports.sina.com.cn/g/ligue1/
8 | // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
9 | // @grant GM_addStyle
10 | // ==/UserScript==
11 |
12 | (function() {
13 | 'use strict';
14 | GM_addStyle(".results{overflow: overlay;padding: 10px;width: 380px;}.result_wrap{width: 380px;}");
15 | })();
--------------------------------------------------------------------------------
/.github/workflows/json-validator.yml:
--------------------------------------------------------------------------------
1 | name: Validate JSON
2 |
3 | on:
4 | pull_request:
5 | paths:
6 | - 'Pagetual/pagetualRules.json'
7 |
8 | jobs:
9 | validate-json:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - uses: actions/checkout@v4
14 |
15 | - name: json-yaml-validate
16 | uses: GrantBirki/json-yaml-validate@v3.0.0
17 | id: json-yaml-validate
18 | with:
19 | json_schema: Pagetual/pagetual.schema.json
20 | files: |
21 | Pagetual/pagetualRules.json
--------------------------------------------------------------------------------
/RandomSexyPic/README.md:
--------------------------------------------------------------------------------
1 | Random sexy pictures
2 | ===
3 | Browsing assistance for [Lolicon sexy pictures Api](https://api.lolicon.app/setu/v2?r18=1&num=5)
4 | ---
5 |
6 | Can be used to preview pictures with **any other JSON api**.
Just open the api and click the "Parse current api" under command menu, and click again & cancel to disable.
7 | For example: https://wall.alphacoders.com/api2.0/get.php?method=highest_rated&page=1&info_level=2&page=2
8 |
9 | 
10 |
--------------------------------------------------------------------------------
/Highlight Every Code/README.md:
--------------------------------------------------------------------------------
1 | Highlighting and beautify for code snippets
2 |
3 | Select code snippets with (*`Alt key`*) or (*`Ctrl key`*) or (*`Shift key`*) or (*`Meta key`*)
4 | ===
5 |
6 | You can input custom code to get Highlighting and beautify with command menu when you don't select anything
7 |
8 | Use [prettify.js](http://groups.google.com/group/js-code-prettifier) to highlight
9 | and [js-beautify](http://jsbeautifier.org/) to format
10 |
11 | Support on JS (also effect on JSON) CSS HTML
12 |
13 | Test case:`{"alpha":416,"green":710}`. Select this with funcKeys and click the icon.
14 |
--------------------------------------------------------------------------------
/Picviewer CE+/gallery.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
'恶':[ 25 | '惡', 26 | ['噁','恶心'], 27 | ['噁','心恶','恶心心'] 28 | ],29 | 第一個 “恶” 是簡體字,第二個 “惡” 是默認轉換的正體字。
'鼠标':'滑鼠' 35 |36 | 37 | 漢語拼音標注 38 | --- 39 | 40 | 目前有個問題,除了配對到詞組的多音字之外,多音單字還需要一個預設拼音。 41 | 42 | 例如“了”應該預設是“le”而不是“liao”。 43 | 44 | 我改了一些,常用的幾個多音單字都改了。但我數了一下,這類多音單字總共有800多個,需要有人來幫忙整理一下。 45 | 46 | 如果有對幫忙有興趣的朋友,以下是整理步驟: 47 | 48 | + 下載dict.txt 49 | + 正規搜尋`^(\S \S) \[.*\n(\1.*\n)+` 50 | + 刪除多餘的行,只保留一個預設讀音 51 | + 將修改後的字典提交給我,也可以直接執行專案中的 run.py 來轉換檔案後查看效果 52 | 53 | npm 前端庫 54 | --- 55 | 56 | ``` 57 | npm install switch-chinese 58 | ``` 59 | 60 | [訪問位址](lib) 61 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Collect wedata for pagetual 2 | 3 | on: 4 | schedule: 5 | - cron: '0 1 * * *' 6 | workflow_dispatch: 7 | 8 | jobs: 9 | # This workflow contains a single job called "build" 10 | build: 11 | # The type of runner that the job will run on 12 | runs-on: ubuntu-latest 13 | 14 | # Steps represent a sequence of tasks that will be executed as part of the job 15 | steps: 16 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 17 | - uses: actions/checkout@v2 18 | 19 | #- name: Download json 20 | # run: | 21 | # wget --no-cache -O "Pagetual/items_all.json" http://wedata.net/databases/AutoPagerize/items_all.json 22 | 23 | #- uses: technote-space/get-diff-action@v6 24 | # with: 25 | # FILES: | 26 | # items_all.json 27 | 28 | #- name: Commit 29 | # if: env.GIT_DIFF 30 | # run: | 31 | # git config user.name "github-actions[bot]" 32 | # git config user.email "512946+github-actions[bot]@users.noreply.github.com" 33 | # git add Pagetual/items_all.json 34 | # git status 35 | # git commit -m "auto commit from github actions" 36 | 37 | #- name: Push 38 | # if: env.GIT_DIFF 39 | # uses: ad-m/github-push-action@master 40 | # with: 41 | # github_token: ${{ secrets.GITHUB_TOKEN }} 42 | # branch: master 43 | - name: Update file 44 | id: update_file 45 | uses: TheLastProject/keep-remote-file-locally-up-to-date-action@v1 46 | with: 47 | url: http://wedata.net/databases/AutoPagerize/items_all.json 48 | file_in_repo: Pagetual/items_all.json 49 | git_user: hoothin-update 50 | git_email: rixixi@gmail.com 51 | -------------------------------------------------------------------------------- /Valentine's Day/css/default.css: -------------------------------------------------------------------------------- 1 | @font-face {font-family: 'DS-Digital8dbd7695a180ee';src: url('http://cdn.webfont.youziku.com/webfonts/nomal/98542/32780/58a17441f629d815f80ae466.gif');src: url('http://cdn.webfont.youziku.com/webfonts/nomal/98542/32780/58a17441f629d815f80ae466.gif?#iefix') format('embedded-opentype'), url('http://cdn.webfont.youziku.com/webfonts/nomal/98542/32780/58a17441f629d815f80ae466.bmp') format('woff'), url('http://cdn.webfont.youziku.com/webfonts/nomal/98542/32780/58a17441f629d815f80ae466.jpg') format('truetype'), url('http://cdn.webfont.youziku.com/webfonts/nomal/98542/32780/58a17441f629d815f80ae466.png#DS-Digital') format('svg'); }.css8dbd7695a180ee{font-family: 'DS-Digital8dbd7695a180ee';}body{margin:0;padding:0;background:#ffe;font-size:12px;overflow:auto}#mainDiv{width:100%;height:100%}#loveHeart{float:left;width:670px;height:625px}#garden{width:100%;height:100%}#elapseClock{text-align:right;font-size:18px;margin-top:10px;margin-bottom:10px}#words{font-family:"sans-serif";width:500px;font-size:24px;color:#666}#messages{display:none}#elapseClock .digit{font-family:"DS-Digital8dbd7695a180ee";font-size:36px}#loveu{padding:5px;font-size:22px;margin-top:80px;margin-right:120px;text-align:right;display:none}#loveu .signature{margin-top:10px;font-size:20px;font-style:italic}#clickSound{display:none}#code{float:left;width:440px;height:400px;color:#333;font-family:"Consolas","Monaco","Bitstream Vera Sans Mono","Courier New","sans-serif";font-size:12px}#code .string{color:#2a36ff}#code .keyword{color:#7f0055;font-weight:bold}#code .placeholder{margin-left:15px}#code .space{margin-left:7px}#code .comments{color:#3f7f5f}#copyright{margin-top:10px;text-align:center;width:100%;color:#666}#errorMsg{width:100%;text-align:center;font-size:24px;position:absolute;top:100px;left:0}#copyright a{color:#666} -------------------------------------------------------------------------------- /Switch Traditional Chinese and Simplified Chinese/lib/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "switch-chinese", 3 | "version": "1.0.13", 4 | "description": "繁簡轉換,支援簡繁雙向轉換、智慧分詞、自訂詞庫、文字偵測及多種輸出格式,零依賴。 Lightweight Chinese converter library for conversion between Simplified and Traditional Chinese. 轻量级简繁体中文智能转换库,支持简繁双向转换、智能分词、自定义词库、文本检测及多种输出格式,零依赖。", 5 | "main": "stcasc.lib.js", 6 | "types": "stcasc.d.ts", 7 | "type": "module", 8 | "exports": { 9 | ".": { 10 | "import": "./stcasc.lib.js", 11 | "types": "./stcasc.d.ts" 12 | } 13 | }, 14 | "files": [ 15 | "stcasc.lib.js", 16 | "stcasc.d.ts", 17 | "readme.md" 18 | ], 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/hoothin/UserScripts.git#master" 22 | }, 23 | "keywords": [ 24 | "chinese", 25 | "converter", 26 | "traditional", 27 | "simplified", 28 | "chinese-converter", 29 | "simplified-chinese", 30 | "traditional-chinese", 31 | "chinese-translation", 32 | "chinese-detection", 33 | "character-detection", 34 | "text-converter", 35 | "language-converter", 36 | "i18n", 37 | "localization", 38 | "ruby-annotation", 39 | "简繁转换", 40 | "簡繁轉換", 41 | "简繁切换", 42 | "簡繁切換", 43 | "繁简转换", 44 | "繁簡轉換", 45 | "繁简切换", 46 | "繁簡切換", 47 | "简体中文", 48 | "繁体中文", 49 | "簡體中文", 50 | "繁體中文", 51 | "正體中文", 52 | "中文转换", 53 | "中文检测", 54 | "一简多繁", 55 | "智能分词", 56 | "自定义词库", 57 | "零依赖", 58 | "轻量级" 59 | ], 60 | "author": "Hoothin", 61 | "license": "MIT", 62 | "bugs": { 63 | "url": "https://github.com/hoothin/UserScripts/issues" 64 | }, 65 | "homepage": "https://github.com/hoothin/UserScripts/tree/master/Switch%20Traditional%20Chinese%20and%20Simplified%20Chinese/lib", 66 | "engines": { 67 | "node": ">=12.0.0" 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /.github/workflows/jekyll-gh-pages.yml: -------------------------------------------------------------------------------- 1 | # Sample workflow for building and deploying a Jekyll site to GitHub Pages 2 | name: Deploy Jekyll with GitHub Pages dependencies preinstalled 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: ["master"] 8 | paths-ignore: 9 | - 'Pagetual/items_all.json' 10 | - 'Pagetual/pagetualRules.json' 11 | - '.github/*' 12 | - '.github/*/*' 13 | workflow_run: 14 | workflows: ["Update Version on File Change"] 15 | types: 16 | - completed 17 | 18 | # Allows you to run this workflow manually from the Actions tab 19 | workflow_dispatch: 20 | 21 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 22 | permissions: 23 | contents: read 24 | pages: write 25 | id-token: write 26 | 27 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 28 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 29 | concurrency: 30 | group: "pages" 31 | cancel-in-progress: false 32 | 33 | jobs: 34 | # Build job 35 | build: 36 | runs-on: ubuntu-latest 37 | steps: 38 | - name: Checkout 39 | uses: actions/checkout@v4 40 | - name: Setup Pages 41 | uses: actions/configure-pages@v5 42 | - name: Build with Jekyll 43 | uses: actions/jekyll-build-pages@v1 44 | with: 45 | source: ./ 46 | destination: ./_site 47 | - name: Upload artifact 48 | uses: actions/upload-pages-artifact@v3 49 | 50 | # Deployment job 51 | deploy: 52 | environment: 53 | name: github-pages 54 | url: ${{ steps.deployment.outputs.page_url }} 55 | runs-on: ubuntu-latest 56 | needs: build 57 | steps: 58 | - name: Deploy to GitHub Pages 59 | id: deployment 60 | uses: actions/deploy-pages@v4 61 | -------------------------------------------------------------------------------- /.github/workflows/update_version.yml: -------------------------------------------------------------------------------- 1 | name: Update Version on File Change 2 | on: 3 | push: 4 | paths: 5 | - 'Pagetual/items_all.json' 6 | - 'Pagetual/pagetualRules.json' 7 | workflow_run: 8 | workflows: ["Collect wedata for pagetual"] 9 | types: 10 | - completed 11 | 12 | jobs: 13 | update_version: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout repository 17 | uses: actions/checkout@v4 18 | with: 19 | fetch-depth: 0 20 | 21 | - name: Check file modification timestamps 22 | id: check_file_timestamps 23 | run: | 24 | version_timestamp=$(git log -1 --format="%at" Pagetual/version) 25 | items_all_timestamp=$(git log -1 --format="%at" Pagetual/items_all.json) 26 | pagetualRules_timestamp=$(git log -1 --format="%at" Pagetual/pagetualRules.json) 27 | if [[ $version_timestamp < $items_all_timestamp || $version_timestamp < $pagetualRules_timestamp ]]; then 28 | version=$(cat Pagetual/version) 29 | else 30 | version=0 31 | echo "Version file is not updated. Skipping version read." 32 | fi 33 | echo "VERSION=$version" >> $GITHUB_ENV 34 | 35 | - name: Increment version 36 | if: env.VERSION != '0' 37 | id: increment_version 38 | run: echo "VERSION=$((VERSION + 1))" >> $GITHUB_ENV 39 | 40 | - name: Update version file 41 | if: env.VERSION != '0' 42 | run: echo $VERSION > Pagetual/version 43 | 44 | - name: Commit version update 45 | if: env.VERSION != '0' 46 | run: | 47 | git config --local user.email "rixixi@gmail.com" 48 | git config --local user.name "hoothin-update" 49 | git add Pagetual/version 50 | git commit -m "Update version of Pagetual rules to $VERSION" 51 | git push https://${{ secrets.ACTION_SECRET }}@github.com/${{ github.repository }} 52 | -------------------------------------------------------------------------------- /True URL downloads/README.md: -------------------------------------------------------------------------------- 1 | [[Chrome Batch Download Extension]](https://chrome.google.com/webstore/detail/dbheplacgeefjnhdacijldhfliehnhka) 2 | 3 | Decryption and Display the real URL of the download links and then manage them.(thunder,flashget,qqdl) 4 | 5 | Can cooperate with [[Multi-Select Checkbox Companion]](https://greasyfork.org/scripts/22587) to facilitate checkbox selection 6 | 7 | 8 | Test ALT+X:[MP4](http://a.a/h.mp4) [MP3](http://a.a/o.mp3) [RAR](http://a.a/o.rar) [7Z](http://a.a/t.7z) [ZIP](http://a.a/h.zip) [TXT](http://a.a/i.txt) [PDF](http://a.a/n.pdf) 9 | 10 | 11 | 12 |
${item.display_username || item.username}
${item.cooked}9 | https://raw.githubusercontent.com/hoothin/UserScripts/master/Pagetual/pagetualRules.json 10 |11 | 12 | --- 13 | 14 |
| Buy me a coffee if you get help💞 | 17 |||||
|---|---|---|---|---|
PayPal |
20 | Ko-fi |
21 | 愛發電 |
22 | ||
| Join 💬Discord | 25 |||||
| Follow 🕊️twitter | 28 |||||
| Send 📧email | 31 |||||
| Made with ❤️ by Hoothin | 34 |||||
`標簽分享到 [反饋](https://github.com/hoothin/UserScripts/issues) 亦可點擊導入。例如此處的下載圖標:[Github](https://github.com/hoothin/imgCodeCheck/releases/tag/0.1) 31 |32 | https://download.fastgit.org/${https?://[^/]+(.*)}@@Fastgit@@github\.com.*(releases\/download|archive\/refs\/)@@@@ffff9f 33 | https://pd.zwc365.com/seturl/$url@@ZWC365@@github\.com.*(releases\/download|archive\/refs\/)@@@@0fffff 34 | https://gh.api.99988866.xyz/$url@@99988866@@github\.com.*(releases\/download|archive\/refs\/)@@@@9fffff 35 | https://ghproxy.com/$url@@Ghproxy@@github\.com.*(releases\/download|archive\/refs\/)@@@@ff0fff 36 | https://github.rc1844.workers.dev${https?://[^/]+(.*)}@@RC1844@@github\.com.*(releases\/download|archive\/refs\/)@@@@ff9fff 37 | https://ghproxy.fsou.cc/$url@@Fsou@@github\.com.*(releases\/download|archive\/refs\/)@@@@ffff0f 38 |39 | 40 | ### 自定義例子2 - Aria2 下載 41 | 同樣是點擊下方導入 42 |43 | http://aria.hoothin.com/#!/new/$base64@@Aria2@@@@data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAABOFBMVEUAAADSVF7SVF7SVF7LVWDSVF7QVF/SVF7SVF7SVF7SVF7SVF7SVF7RVF7SVF7SVF7SVF7SVF7SVF7SVF7SVF7SVF7SVF5ma4Di4uLSVF7v7+9DQ0NvaX1+ZniUYXGtXGppan+cYG+TYXLs7OyyW2h4tsiVlJWxs7ylpaWgoKBwaX2JZHVRVFxNT1VNTU1KSkxGRkd0uMzKysp5tceHipjDV2JYWFrr5ufa2tvT09Pjycu9v8a5u8PCwsK+vr6rrbego6+Tp62pqamZnKmloaGjj5l5fY+MfY60gozDfIa3foJkaHzTX2hYW2i6UVluSEuK2/Pd3d7X0NLExcm1tbWRlKKbm5uohJCOjo6GhoqOeInPgIh0coV8fHx7e3vRbXbObXaNY3SgX25hYmRhYWHJVmGOTFGNTFENIl9FAAAAF3RSTlMAJNEM+vr1iQjpyFfr6pybmjLusJhyIzaw7jcAAAHlSURBVDjLfZNnU+NADIbXduyQBBLq2fK6JcQmF0gvtOOOztGv90Ln//8Ddm3txkNmeD54vNI7klYrkRFaYT6f0/Vcfr6gkXGUklH13HoQ1F2vapSUZ+6JbKbsmIzvR/zrlDPZibT/lerXTc4fuDJj6r6aCjKTq5gJZwDH+FvJzcj0U8to/A+M93hYnlIwv+qh6RhijkQMNakj66PhF8BBr3cAZwEa/GxcYMbB8284CT90whOZxMnwJKUyHvurG/thpxPub3wykXKR9c8QATZtu7YT9nZqlvVVhDA0Uqji4XDVtrdeM95a1uYhGqsFMi2usGfb9uJWrcb81toeGr1pknfxf8nmLFox79Do5smkKOFNWrAkipgkevCSINBRMJ5CCmSK7ZTg47ZMMSqyHwt+fOOCbl8WObrm0OKC4R0X7A5PxTVlo87pFy5oNrngLz0XjZKtXqH/uIBSLmjRhmw1KSaP1WIuIdiltCUfiyjJc7cp/bm2vt5qd7ufbylt43OPBoayqFEUNZtRZJ42KE0GBkeuwgUr7FIAl5cArHWNdjxyWmpomd+8AXh8ALjmNcuhTY/9AODiAsCXYy9RVN/hGRLuXVafWJz06nmAeLh6z5d3AMjAKCpkHG1hTp3V9Vl1biG1/k8fR16xKi9r1wAAAABJRU5ErkJggg==@@ff2a00 44 |45 | *之所以把Aria2做成自定義是因為每個人的Aria2UI網址都不一樣,用我的伺服器管理本地的Aria2服務需要允許Chrome訪問本地資源,訪問 chrome://flags/#block-insecure-private-network-requests 並關閉即可。不想關閉的話直接打開設置把上面的網址換成自己本地的即可,例如 127.0.0.1 46 | 47 | ### 自定義例子3 - Post 請求 RPC 遠程下載 48 |49 | p:http://192.168.32.1:6800/jsonrpc?id=$random&jsonrpc=2.0&method=aria2.addUri¶ms=["token:123456",["$url"]]@@Aria2RPC@@@@@@df2a00 50 |51 | 導入后需要自行修改網址与 token 密鑰 52 | 53 | ### 自定義例子4 - 複製所有包含 “22590-easy-offline” 的連結為 markdown 格式 54 | (按住 Alt 顯示圖標,使用 ctrl + shift 複製全部) 55 |56 | c:[$text "$title"]($url)@@Markdown@@22590-easy-offline@@@@df2a00@@1 57 |58 | 59 | ### 自定義例子5 - 谷歌翻譯選中文本 60 | 默認是按住Alt鍵划選 61 |62 | https://translate.google.com/?client=gtx&dj=1&q=$text&sl=auto&tl=zh-CN&hl=zh-CN&ie=UTF-8&oe=UTF-8&source=icon&dt=t&dt=bd@@Translate@@@@data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAIAAAAlC+aJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAExklEQVRoge2Y+08UVxTH/dNmtYRHwNKHDW1tIWl/sK1QbFoSitXa9i642wWxKIK0ysOCLBSwBSWQslpboD54SGVNbAkB0cqjIIic+5jTH2b2gczM7o7DzpLsyfeHzeydmfM5994z555dEoEdrV22e5AEsNuDJIDdHiQB7PYgCRBpRJoLDtazggbzym9g+fX0je+oDQCfXGDL62iJCRlbhnhcAdLdsPzUGu+D9uVPLH4A+Q00Gp/WNnBhFRfXogLoGRUJB1DZyyUC+05GNbjvThLANEDPmChqYVuVU0UlAqnHoaiZBfVZQO5unigAtQNmckhuDU0UgJ9HxKEmFlShjjLcIBHI9EBhEytsZKWXEmYGojEuMKucSgTc3Szh9kA0dmdGVu69fk8kNMBXHSzDDVkeeLQsh193dzOJwMsVFLQnIGEARqfVSJdfDnm6sIppLpAInOrnejcmCgAiHmpiEoGXSuHvf9VJIF1MIpBSBg83T0uCAvjn5D2lIBH44BxlHPsnhIOARKCyVzf8iQWAgW+wRKDEy1KPg0TgtUq6Yli9xhWgIBLAM4q5NaEqf7cThu5rJx97AAobdVJJwGaX5APnQgBpLuif0AaQA5qal1sGeTRqHuTFFyPX3iYBGMeLwyLdHYq98iOlDB6vGFPHZq3DEeqXmAG4wF//EuErp7iVPViSm37naS4gXREmLVaTEd85Y3QWjQFgbQM7b25yfW857R0XwZQ5syiPTOsmUNNW2Gi0kGIAuOYXjsBScTiBdLEoT2GJAoCI3/v4nlIo8TL/nPWRjgeAkHFhFSnHF2lVzD/BsWl5bFqemJE3oigXzQN8rLWJKccSL3v3DJ1fNTkJ4Y2JlkGjz/aLAmz9EiveK//ur6bzT2JmWFzDlLLQK/JqI0+BeYC3TtNwB8O9N81w4Q81r795Ss1mE7MRnmAeQCLQfoPreW+CQZbx7dNUIpBdQe8+kJXiT+/sZg2Ag8DRdtY7Lr5oYxKBTI/GmP3V1Dcprk6Kq5NidskI5taUWghV93NE/PA8lQhkuOEpbBvAc+qbEAUNRo9r+9NoU37dySQCDidML8iI+MuIytM9alQCWglw/Z5YBzRgMABYWUel5D5Yr27ctQ31BPfReaNVZCXANb9AxHXAombth3qHdQHab6jbtycs3sohzuGEqXndtWclwG9+9d2M42GtPf3KCfrPY21X3q+jEoH0zSv+9pR6tq7q0yXfFgCFQYnfVoa5/55n8M+pju47Sb/t4UG5urlyLs2uoFQHwUqADDfdWx5Slke70M2pog83M1RcjtyWHLirvZWtBIheOVU02Jt4RlFBdRA4cYWf9fE6H6/z8doBXjvAP29V/fv0R+2tbA+AwvBoRUbEK+Nqujzwg0bhsLKOqS6QCOx2wta1ZydAbg1VDgz5gbTbdUt7mX/TqQ6o82kMsAcgt4YuriIizizKWeWQ6YHsCtDruAzdF5keyPRAXi0VW+bABoC8QOwtsXgDBGO/IwHyauiCpd7HG8C4mNsBAMWtFveFgOGrlWb7QibkINBxM0J7NCbvnZcidBe3JQu9d5Ye62DhOtqurcNtrMTLSrzsyObrxzrYkXb2umHstxEgnkoC2K0kgN1KAtitJIDd+h//4oa1H68RnAAAAABJRU5ErkJggg==@@4085f9 63 |64 | 65 | ### 自定義例子6 - 去除選中連結中的表情漢字並跳轉 66 | 默認是按住Alt鍵劃選,比如h❤ttps://補丁baidu.😀com 67 |68 | $text{[^\w\-_\.~!\*'();:@&=\+\$,\/\?#\[\]%]}@@GetLink@@@@@@f9ff9f 69 |70 | 71 | ### 自定義例子7 - Post 請求 OpenList(原AList)遠程下載 72 |73 | p:https://alist.domain.com/api/fs/add_offline_download?path=/115网盘/OpList离线下载&tool=115%20Cloud&delete_policy=delete_on_upload_succeed&urls=["$url"]$headers{"Content-Type": "application/json","Authorization": "alist-50a563b4-and-more-token-chars", "Accept": "*/*", "Host": "alist.domain.com", "Connection": "keep-alive"}@@OpenList@@@@@@df2a11 74 |75 | 76 | 77 | ### Update 78 | - **`Alt + F9`** 自定義下載,選中文本超鏈則下載文本超鏈,鼠標指向鏈接則下載鏈接,沒有選中則彈框輸入鏈接下載 79 | - 按住 **`Ctrl + Shift`** 點擊批量離線當前頁面中所有資源(如果我給該網盤寫了批量離線功能的話),實際也沒鳥用,度盤批量離線時動不動就網絡繁忙了 80 | - 添加度盤默認下載路徑設置 81 | - 添加網盤設置功能,點擊圖標可設置是否啟用網盤 82 | - 添加網盤排序功能,設置頁面拖拽圖標即可進行排序 83 | - 添加設置項,填入正則表達式可增加支持鏈接,可設置是否僅當鼠標經過時顯示圖標 84 | - 按下 **`F9`** 快速在當前網站禁用或啟用並記錄選擇 85 | - 離線時將32位磁力鏈接轉換為40位磁力鏈接,便於網盤識別動漫花園之類的資源 86 | - 修復百度網盤超級vip問題,感謝Psnowy 87 | 88 | --- 89 |  90 | 91 | ### 支持服務 92 | * 百度網盤 http://pan.baidu.com 93 | * 115 http://115.com 94 | * Furk http://www.furk.net 95 | * Seedr http://www.seedr.cc 96 | * 迅雷離線 http://lixian.xunlei.com 97 | * Pcloud http://www.pcloud.com 98 | * 小米路由器 http://miwifi.com 99 | * 騰訊微雲 http://weiyun.com 100 | * 九秒雲播 http://apiv.ga 101 | * Torrent.org http://torrent.org.cn 102 | -------------------------------------------------------------------------------- /HacgGodTurn/od.js: -------------------------------------------------------------------------------- 1 | function processTxt(e){var t,r=e;r&&(r=r.replace(regObj.bdshare,linkArr.baidu),r=r.replace(regObj.bdshare1,linkArr.baidu),e=r,r=r.replace(/ *-?本站暂?不再?提供(文件)?下载-? */i,"").replace(/ *保护作者版权 */i,"").replace(/ *请支持正版 */i,"").replace(/\<\!--[^>]*>/g,""),r=/^(magnet|bdcloud) /i.test(r)?r:r.replace(/([a-z0-9]{5,}) +([a-z0-9]{5,})/g,"$1$2"),t=r,r=!/a\shref="magnet:|md5/i.test(r) ?r.replace(regObj.btih,linkArr.btih):r,r=r.replace(regObj.yunpan,linkArr.yunpan),r=r.replace(regObj.howfile,linkArr.howf),r=r.replace(regObj.tcn,linkArr.tcn),r=r.replace(regObj.yyw,linkArr.yyw),r=r.replace(regObj.mega,linkArr.mega),r=r.replace(regObj.pixiv,linkArr.pixiv),r=r.replace(/(baidu\.com\/s\/[a-z\d]{7,23})#([\'\"])/gi,"$1$2"),r=r.replace(regObj.xunlei,linkArr.xunlei));if(t!=r)return r;else return e;}function extCode(e){return text=e.textContent.trim(),simpleRule.test(text)?text.match(simpleRule)[1]:codeRule.test(text)?text.match(codeRule)[1]:""}function seriousReplace(e){var t=document.getElementsByClassName(e);for(var r in t)t[r]&&t[r].innerHTML&&(t[r].innerHTML=t[r].innerHTML.replace(/(\s|^|:||[\u2E80-\u9FFF])(?:https?:\/\/pan\.baidu\.com)?(?:\/?s\/)?(1[0-9a-zA-Z_\-]{6,22})\b(?:\s*(?:
)?\s*(?:密码[::]?|pw:|[pP]|提取码?:?)?\s*([a-z0-9A-Z]{4}\b|[^\s,,::\<\>]{2,4})\s*(
|<\/p>|$| +))/g,linkArr.baidu).replace(/(\s|^|:||[\u2E80-\u9FFF])(?:https?:\/\/pan\.baidu\.com\/)?(?:\/?s\/)(1[0-9a-zA-Z_\-]{6,22})\b\s*(
';function elementPosition(o){var t=0,e=0;if(o.offsetParent)for(t=o.offsetLeft,e=o.offsetTop;o.offsetParent;)o=o.offsetParent,t+=o.offsetLeft,e+=o.offsetTop;return{x:t,y:e}}function scrollToControl(o){var t=o;t-=(window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0);var e=t%50,r=(t-e)/50;scrollSmoothly(t,r,o),window.scrollBy(0,e)}function scrollSmoothly(o,t,a){var e=50;return 0>t&&(e=-50),repeatCount
|<\/p>|$)/g,"$1度娘[$2] $3 ").replace(regObj.yyw,linkArr.yyw).replace(regObj.tcn,linkArr.tcn),t[r].innerHTML = !/a\shref="magnet:|md5/i.test(t[r].innerHTML) ? t[r].innerHTML.replace(regObj.btih, linkArr.btih) : t[r].innerHTML)}function hashFunc(e){return hashWord=e.match(/^\W*/g)[0],e=e.replace(/[\s\W]*/g,"").toUpperCase(),hashStart=e.slice(0,2),hashEnd=e.slice(-2),[hashStart,hashEnd,e,hashWord]}function addInsertHandler(e){var t=!1;document.addEventListener("DOMNodeInserted",function(){if("complete"==document.readyState&&!t){t=!0;var r=0,a=setInterval(function(){1==r?changeUrl(!1,e):2==r&&(t=!1,clearInterval(a)),r++},500)}}),changeUrl(!0,e)}function changeUrl(e,t){for(var r=e?t[0]:["a","img"],a=0,i=r.length;i>a;a++)for(var n=r[a],s=document.querySelectorAll(n),o=0,l=s.length;l>o;o++)for(var p=0,h=t[1].length;h>p;p++){var c=new RegExp(t[1][p][0],"gi");if(n=="a"){c.test(s[o].href) && (s[o].href = s[o].href.replace(c, t[1][p][1]))}else if(n=="img"){c.test(s[o].src) && (s[o].src = s[o].src.replace(c, t[1][p][1]))}else{s[o].parentNode&&c.test(s[o].outerHTML)&&(s[o].outerHTML=s[o].outerHTML.replace(c,t[1][p][1]))}}}var simpleRule=/(?:提取|访问)[码碼]?\s*[::\s]?\s*([a-z\d]{4})/i,codeRule=/(?:(?:提取|钥匙|访问|密[码碼]|艾|Extracted-code|说明|code[::][“"]?)密?[码碼]?[为是]?)\s*[::\s]?\s*([a-z\d]{4}|[^\s,,::]{2,4})(\s|\b|$)/i,regObj={btih:/(?:magnet:\?xt=urn:btih)?((?:[^\/=\|\"]|^)\s*\b)([a-f0-9]{40}|[a-z0-9]{32})\b/gi,bdshare:/(\b|^)(?:b?\/?s\/|.*度.*[::]|BDcloud *|(?:https?:\/\/)?\s*p\s*a\s*n\s*\.\s*b\s*a\s*i\s*d\s*u\s*\.\s*c?\s*o\s*m\s*\/\s*s\s*\/\s*)(1[0-9a-zA-Z_\-]{6,22})\b(?:\s*(?:.*?[::]\s*)?([a-zA-Z0-9]{4}(\b|\s|$)|[^\s,,::\<\>]{2}(\s|$)))?/g,bdshare1:/(^|:|:|\n|BDcloud *)\s*(1[0-9a-zA-Z_\-]{6,22})\b(?:\s*(?:[::\/]\s*)?([a-zA-Z0-9]{4}|[^\s,,::\<\>]{2}))/g,xunlei:/\b(QUF[a-zA-Z0-9\=]+)/g,howfile:/@?(?:HF|howfile)(?:\.com)?\/file\/(\w{4,10})\/(\w{8,})\/?/gi,tcn:/\bt\/(\w{7})/g,yyw:/(\/lb\/)?(5lb[a-zA-Z0-9]{8,12})/g,mega:/(?:https?:\/\/mega)?(?:\.co)?(\.nz\s*\/(#[a-zA-Z0-9_!\-]{22,}(\n[a-zA-Z0-9_!\-]+\n)?))/g,yunpan:/((?:https:\/\/)?yunpan.cn\/([a-zA-Z0-9]+))/g,pixiv:/(?:封面|\s|:|:|^)id[=;](\d+)/gi},linkArr=[];linkArr.btih='$1磁链 → 【种子】 【详情】',linkArr.baidu="$1度娘[$2] $3 ",linkArr.yunpan="云盘:$2",linkArr.howf="好盘:howfile.com/file/$1/$2",linkArr.tcn="短链:t.cn/$1",linkArr.yyw="115礼包:$2 ",linkArr.mega="MEGA网盘\n",linkArr.xunlei="吸血雷",linkArr.pixiv="Pixiv原图";var nod=document.createElement("style"),str=".oD_box{position:fixed;top:60px;right:0px;width:40px;transition: all 0.2s ease;white-space:nowrap;z-index:99998} .oD_box:hover{width:290px} .oD_sel{-ms-transform-origin: 50% 0%;-webkit-transform-origin: 50% 0%;transform-origin: 50% 0%;transform:scale(1.1,1.1);-ms-transform:scale(1.1,1.1);-moz-transform:scale(1.1,1.1);-webkit-transform:scale(1.1,1.1);-o-transform:scale(1.1,1.1);transition: all 1s ease;}";nod.type="text/css",nod.styleSheet?nod.styleSheet.cssText=str:nod.innerHTML=str;var rocketStr='`; 28 | downloadBtn.addEventListener("mousedown", e => { 29 | let parent = downloadBtn.parentNode; 30 | if (!parent) return; 31 | simpleClick = false; 32 | let img = parent.querySelector('[data-testid="tweetPhoto"]>img,[data-testid="card.layoutLarge.media"] img'); 33 | if (img) { 34 | let newsrc = img.src.replace("_normal.",".").replace("_200x200.",".").replace("_mini.",".").replace("_bigger.",".").replace(/_x\d+\./,"."), imgname; 35 | if (/\.svg$/.test(newsrc)) return; 36 | if (newsrc == img.src) { 37 | newsrc=newsrc.replace(/\?format=/i, ".").replace(/\&name=/i, ":").replace(/\.(?=[^\.\/]*$)/, "?format=").replace( /(:large|:medium|:small|:orig|:thumb|:[\dx]+)/i, ""); 38 | if (newsrc != img.src) { 39 | newsrc = newsrc + "&name=orig"; 40 | } 41 | } 42 | while(parent) { 43 | if (parent.nodeName == "ARTICLE" && parent.dataset && parent.dataset.testid == "tweet") { 44 | break; 45 | } 46 | parent = parent.parentNode; 47 | } 48 | if (parent) { 49 | const time = parent.querySelector('time[datetime]'); 50 | const user = parent.querySelector('[role="link"]>div>div>span>span'); 51 | let formatMatch = img.src.match(/format=(\w+)/), ext = "jpg"; 52 | if (formatMatch) { 53 | ext = formatMatch[1]; 54 | } else { 55 | formatMatch = newsrc.match(/\.(\w+)/); 56 | if (formatMatch) { 57 | ext = formatMatch[1]; 58 | } 59 | } 60 | imgname = `${user.innerText} ${time.innerText.replace(/(.*) · (.*)/, "$2 $1")}.${ext}`; 61 | } 62 | downloadBtn.href = newsrc; 63 | if ((e.button === 0 && !e.ctrlKey) || touch) { 64 | simpleClick = true; 65 | downloadByFetch(newsrc, imgname); 66 | } 67 | } else { 68 | while(parent) { 69 | if (parent.nodeName == "ARTICLE" && parent.dataset && parent.dataset.testid == "tweet") { 70 | break; 71 | } 72 | parent = parent.parentNode; 73 | } 74 | if (parent) { 75 | downloadBtn.removeAttribute('download'); 76 | let link = parent.querySelector('a[role="link"][aria-label][href^="/"]'); 77 | downloadBtn.href = `https://twitter.luopo.org/?url=${encodeURIComponent(link ? link.href : document.location.href)}`; 78 | if (e.altKey || touch) { 79 | window.open(downloadBtn.href, "_blank"); 80 | } 81 | } 82 | } 83 | }); 84 | downloadBtn.addEventListener("click", e => { 85 | if (simpleClick || e.altKey || touch) { 86 | e.preventDefault(); 87 | e.stopPropagation(); 88 | } 89 | }); 90 | downloadBtn.addEventListener("mouseenter", () => { 91 | downloadBtn.style.opacity = 1; 92 | }); 93 | downloadBtn.addEventListener("mouseleave", () => { 94 | setTimeout(() => { 95 | downloadBtn.style.opacity = 0.1; 96 | }, 100); 97 | }); 98 | async function downloadByFetch(imageUrl, filename) { 99 | try { 100 | const response = await fetch(imageUrl); 101 | if (!response.ok) throw new Error('CORS request failed'); 102 | const blob = await response.blob(); 103 | const blobUrl = URL.createObjectURL(blob); 104 | const tempLink = document.createElement('a'); 105 | tempLink.href = blobUrl; 106 | tempLink.setAttribute('download', filename); 107 | document.body.appendChild(tempLink); 108 | tempLink.click(); 109 | document.body.removeChild(tempLink); 110 | URL.revokeObjectURL(blobUrl); 111 | } catch (error) { 112 | console.error('error:', error); 113 | window.open(imageUrl, '_blank'); 114 | } 115 | } 116 | const show = (ele) => { 117 | ele.appendChild(downloadBtn); 118 | setTimeout(() => { 119 | downloadBtn.style.opacity = touch ? 0.8 : 0.6; 120 | }, 0); 121 | }; 122 | const addBtn = e => { 123 | if (e.target.dataset && e.target.dataset.testid == "card.layoutLarge.media") { 124 | show(e.target.parentNode); 125 | } else if (e.target.dataset && e.target.dataset.testid == "tweetPhoto") { 126 | show(e.target.parentNode); 127 | } else if (e.target.dataset && /^video\-player/.test(e.target.dataset.testid)) { 128 | show(e.target.parentNode); 129 | } else if (e.target.parentNode && e.target.parentNode.dataset && e.target.parentNode.dataset.testid == "tweetPhoto") { 130 | show(e.target.parentNode.parentNode); 131 | } 132 | }; 133 | function isElementVisible(el) { 134 | const rect = el.getBoundingClientRect(); 135 | return rect.top < window.innerHeight && rect.top > 0 && rect.bottom >= 0; 136 | } 137 | function findFirstVisibleElement(selector) { 138 | const elements = document.querySelectorAll(selector); 139 | const firstVisibleElement = Array.from(elements).find(el => { 140 | return isElementVisible(el); 141 | }); 142 | return firstVisibleElement; 143 | } 144 | let checkTimer; 145 | const touchCheck = e => { 146 | clearTimeout(checkTimer); 147 | if (e.target == downloadBtn) return; 148 | checkTimer = setTimeout(() => { 149 | if (isElementVisible(downloadBtn)) return; 150 | let target = findFirstVisibleElement("[data-testid='card.layoutLarge.media']"); 151 | if (target) { 152 | return show(target.parentNode); 153 | } 154 | target = findFirstVisibleElement("[data-testid='tweetPhoto']"); 155 | if (target) { 156 | return show(target.parentNode); 157 | } 158 | target = findFirstVisibleElement("[data-testid^='video-player']"); 159 | if (target) { 160 | return show(target.parentNode); 161 | } 162 | }, 100); 163 | }; 164 | document.addEventListener("mouseenter", addBtn, true); 165 | document.addEventListener("touchstart", e => {touch = true; addBtn(e);}, true); 166 | document.addEventListener("touchend", touchCheck, true); 167 | })(); -------------------------------------------------------------------------------- /DownloadAllContent/DownloadAllContentSavaAsZIP.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name DownloadAllContent ZIP addon 3 | // @name:zh-CN 怠惰小说下载器 ZIP 扩展 4 | // @name:zh-TW 怠惰小説下載器 ZIP 擴充 5 | // @namespace hoothin 6 | // @version 0.6.1 7 | // @description Save content as ZIP for DownloadAllContent 8 | // @description:zh-CN 下载时分章节保存 TXT 并打包为 ZIP 9 | // @description:zh-TW 下載時分章節儲存 TXT 並打包為 ZIP 10 | // @author hoothin 11 | // @match *://*/* 12 | // @grant unsafeWindow 13 | // @grant GM_xmlhttpRequest 14 | // @require https://unpkg.com/jszip@3.7.1/dist/jszip.js 15 | // ==/UserScript== 16 | 17 | (function() { 18 | 'use strict'; 19 | const threadNum = 20;//圖片下載綫程數 20 | const ocrApi = ""; 21 | //const ocrApi = "http://127.0.0.1:416/?img=%t";//ocr 識別 api 22 | var _unsafeWindow = (typeof unsafeWindow == 'undefined') ? window : unsafeWindow; 23 | var zipTips, loadingImgs = [], loadingIndex = 0, loadedNum = 0, ocrNum = 0, zip, blobDict = {}, ocrDict = {}; 24 | 25 | async function dataURLToBlob(dataurl, ext = "jpeg") { 26 | return await new Promise((resolve) => { 27 | if (!dataurl) return resolve(null); 28 | var canvas = document.createElement('CANVAS'); 29 | var ctx = canvas.getContext('2d'); 30 | var img = new Image(); 31 | img.setAttribute("crossOrigin", "anonymous"); 32 | img.onload = function() { 33 | canvas.width = img.width; 34 | canvas.height = img.height; 35 | ctx.drawImage(img, 0, 0); 36 | var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); 37 | for(var i = 0; i < imageData.data.length; i += 4) { 38 | if(imageData.data[i + 3] == 0) { 39 | imageData.data[i] = 255; 40 | imageData.data[i + 1] = 255; 41 | imageData.data[i + 2] = 255; 42 | imageData.data[i + 3] = 255; 43 | } 44 | } 45 | ctx.putImageData(imageData, 0, 0); 46 | canvas.toBlob(blob => { 47 | resolve(blob); 48 | }, `image/${ext}`); 49 | }; 50 | img.onerror = function() { 51 | resolve(null); 52 | }; 53 | img.src = dataurl; 54 | }); 55 | } 56 | 57 | async function blobToDataURL(blob) { 58 | return await new Promise((resolve) => { 59 | var a = new FileReader(); 60 | a.readAsDataURL(blob); 61 | a.onload = function (e) { 62 | resolve(e.target.result); 63 | }; 64 | a.onerror = function (e) { 65 | resolve(null); 66 | }; 67 | }); 68 | } 69 | 70 | async function urlToBlob(url) { 71 | return await new Promise((resolve) => { 72 | GM_xmlhttpRequest({ 73 | method: 'GET', 74 | url: url, 75 | responseType:'blob', 76 | timeout:20000, 77 | headers: { 78 | origin: location.origin, 79 | referer: location.href, 80 | accept: "*/*" 81 | }, 82 | onload: async function(d) { 83 | resolve(d.response); 84 | }, 85 | onerror: function() { 86 | resolve(null); 87 | }, 88 | ontimeout: function() { 89 | resolve(null); 90 | } 91 | }); 92 | }) 93 | } 94 | 95 | async function downloadImage(cb) { 96 | if (loadedNum >= loadingImgs.length || loadingIndex >= loadingImgs.length) return; 97 | let i = loadingIndex; 98 | loadingIndex++; 99 | let src = loadingImgs[i]; 100 | let blob = await urlToBlob(src); 101 | if (blob) { 102 | zip.file("imgs/" + i + ".jpg", blob); 103 | zipTips.innerText = `Download images ${loadedNum + "/" + loadingImgs.length}...`; 104 | blobDict[src] = blob; 105 | } 106 | loadedNum++; 107 | if (loadedNum >= loadingImgs.length) { 108 | if (ocrApi) { 109 | loadingIndex = 0; 110 | let length = Math.min(loadingImgs.length, threadNum); 111 | for (let i = 0; i < length; i++) { 112 | recognizeImage(cb); 113 | } 114 | } else { 115 | cb(); 116 | } 117 | } else downloadImage(cb); 118 | } 119 | 120 | async function recognizeImage(cb) { 121 | if (ocrNum >= loadingImgs.length || loadingIndex >= loadingImgs.length) return; 122 | let i = loadingIndex; 123 | loadingIndex++; 124 | let src = loadingImgs[i]; 125 | let dataURL = await blobToDataURL(blobDict[src]); 126 | let blob = await dataURLToBlob(dataURL, "jpeg"); 127 | dataURL = await blobToDataURL(blob); 128 | let result = await new Promise((resolve) => { 129 | GM_xmlhttpRequest({ 130 | method: 'GET', 131 | url: ocrApi.replace("%t", encodeURIComponent(dataURL.replace("data:image/jpeg;base64,", ""))), 132 | timeout:20000, 133 | onload: function(d) { 134 | resolve(d.response); 135 | }, 136 | onerror: function() { 137 | resolve(null); 138 | }, 139 | ontimeout: function() { 140 | resolve(null); 141 | } 142 | }); 143 | }); 144 | ocrNum++; 145 | zipTips.innerText = `Recognize images ${ocrNum + "/" + loadingImgs.length}...`; 146 | if (result) { 147 | ocrDict[i] = result; 148 | } 149 | if (ocrNum >= loadingImgs.length) { 150 | cb(); 151 | } else recognizeImage(cb); 152 | } 153 | 154 | function downloadImages(cb) { 155 | let length = Math.min(loadingImgs.length, threadNum); 156 | if (length == 0) { 157 | return cb(); 158 | } 159 | for (let i = 0; i < length; i++) { 160 | downloadImage(cb); 161 | } 162 | } 163 | 164 | const mdImgReg = /!\[img\]\((http.+?)\)/; 165 | _unsafeWindow.downloadAllContentSaveAsZip = async (rCats, info, callback) => { 166 | loadingIndex = 0; 167 | loadedNum = 0; 168 | ocrNum = 0; 169 | if (!zipTips) { 170 | zipTips = document.createElement("div"); 171 | } 172 | if (!zipTips.parentNode) { 173 | let txtDownWords = _unsafeWindow.txtDownWords; 174 | if (txtDownWords) { 175 | txtDownWords.appendChild(zipTips); 176 | } 177 | } 178 | console.log("Begin compress to ZIP..."); 179 | zipTips.innerText = "Begin compress to ZIP..."; 180 | zip = new JSZip(); 181 | zip.file("readme.txt", info); 182 | let zipTemp = []; 183 | for (let i = 0; i < rCats.length; i++) { 184 | let cat = rCats[i]; 185 | if (!cat) continue; 186 | let catTitle = cat.match(/.*?\r\n/); 187 | if (!catTitle) continue; 188 | catTitle = catTitle[0].trim(); 189 | cat = cat.replace(catTitle, "").replace(/^[\n\r]+/, ""); 190 | let imgMatch = cat.match(mdImgReg), hasImg = false; 191 | while (imgMatch) { 192 | let index = loadingImgs.indexOf(imgMatch[1]); 193 | if (index == -1) { 194 | index = loadingImgs.length; 195 | loadingImgs.push(imgMatch[1]); 196 | } 197 | cat = cat.replace(imgMatch[0], ``); 198 | imgMatch = cat.match(mdImgReg); 199 | hasImg = true; 200 | } 201 | zipTemp.push({title: catTitle.replace(/[\*\/:<>\?\\\|\r\n]/g, "_").slice(0, 50), hasImg: hasImg, content: cat}); 202 | } 203 | downloadImages(() => { 204 | zipTemp.forEach(d => { 205 | if (ocrApi) { 206 | d.hasImg = false; 207 | Object.keys(ocrDict).forEach(key => { 208 | d.content = d.content.replace(new RegExp(`!\\[img\\]\\(imgs/${key}\\.jpg\\)`, 'g'), ocrDict[key]); 209 | }); 210 | } 211 | zip.file(d.title + (d.hasImg ? ".md" : ".txt"), d.content); 212 | }); 213 | zip.generateAsync({type: "blob", compression: "DEFLATE"}, meta => {zipTips.innerText = "percent: " + ((meta && meta.percent && meta.percent.toFixed(2)) || "100") + "%"}).then(function(content){ 214 | callback(content); 215 | zipTips.innerText = ""; 216 | }) 217 | }); 218 | } 219 | })(); -------------------------------------------------------------------------------- /True URL downloads/manageLinks.js: -------------------------------------------------------------------------------- 1 | /* 2 | manageLinks v0.1 3 | https://github.com/hoothin/UserScripts/tree/master/True%20URL%20downloads/managerLinks.js 4 | (c) 2017-2017 by Hoothin Wang. All rights reserved. 5 | */ 6 | var specialUrl = /^thunder|^magnet|^ed2k/i, 7 | simplefilter = /\.php|\.htm|\.jsp|\.asp|\/[^\.]+$/i, 8 | resReg = /.*(^thunder|^magnet|^ed2k|\.torrent$|\.mp4$|\.rar$|\.7z$|\.zip$|\.rmvb$|\.mkv$|\.avi$|\.iso$|\.mp3$|\.txt$|\.exe$|\.chm$|\.pdf$|\.ppt$|\.doc$|\.pptx$|\.docx$|\.epub$|\.xlsx$|\.xls$|\.flac$|\.wma$|\.wav$|\.aac$|\.ape$|\.mid$|\.ogg$|\.m4a$|\.dts$|\.dsd$|\.apk$|\.flv$).*/i, 9 | linksArr = [],frame,linkPair = {},customReg, 10 | lang = { 11 | copyAll : "全部复制", 12 | copySel : "复制选中", 13 | addTips : "%i代表递增 %n代表文件名", 14 | sortByName : "按文件名排序", 15 | sortByUrl : "按网址排序", 16 | sortByType : "按扩展名排序", 17 | preHolder : "批量前缀", 18 | nextHolder : "批量后缀", 19 | closeBtn : "关闭", 20 | typeHead : "类型:" 21 | }; 22 | 23 | var by = function(byName, secName) { 24 | var compare = function(o, p, name) { 25 | var a, b; 26 | if (typeof o === "object" && typeof p === "object" && o && p) { 27 | a = o[name]; 28 | b = p[name]; 29 | if (a === b) { 30 | return 0; 31 | } 32 | if (typeof a === typeof b) { 33 | return a < b ? -1 : 1; 34 | } 35 | return typeof a < typeof b ? -1 : 1; 36 | } else { 37 | throw("error"); 38 | } 39 | } 40 | return function(o, p) { 41 | var result = compare(o, p, byName); 42 | if (secName && result == 0) { 43 | result = compare(o, p, secName); 44 | } 45 | return result; 46 | } 47 | } 48 | 49 | if (!Array.prototype.indexOf) { 50 | Array.prototype.indexOf = function (item) { 51 | var index = -1; 52 | for (var i = 0, length = this.length; i < length; i++) { 53 | if (this[i] == item) { 54 | index = i; 55 | } 56 | } 57 | return index; 58 | }; 59 | } 60 | 61 | function getLinks() { 62 | [].forEach.call(document.querySelectorAll('a'), function(link){ 63 | if (link.className != "whx-a" && ((customReg && customReg.test(link.href)) || specialUrl.test(link.href) || (!simplefilter.test(link.href) && resReg.test(link.href))) && linksArr.indexOf(link.href) == -1) { 64 | linksArr.push(link.href); 65 | linkPair[link.href]=link; 66 | } 67 | }); 68 | [].forEach.call(document.querySelectorAll('source'), function(link){ 69 | if (((customReg && customReg.test(link.href)) || specialUrl.test(link.href) || (!simplefilter.test(link.href) && resReg.test(link.href))) && linksArr.indexOf(link.src) == -1) { 70 | linksArr.push(link.src); 71 | linkPair[link.href]=link; 72 | } 73 | }); 74 | } 75 | 76 | function initLang(l){ 77 | if (!l) return; 78 | lang = l; 79 | } 80 | 81 | function setLinkCustomReg(r){ 82 | customReg = r; 83 | } 84 | 85 | function showLinkFrame(callBack) { 86 | var linkItems = []; 87 | var typeHtml = lang.typeHead+" "; 88 | if (!frame) { 89 | $('').appendTo('head'); 90 | frame = $(``); 103 | $(document.body).append(frame); 104 | $("#managerLinksSortByName").click(function() { 105 | $("#managerLinksLinks").html(""); 106 | linkItems.sort(by("linkName", "href")); 107 | linkItems.forEach(function(item) { 108 | $("#managerLinksLinks").append(item.item); 109 | }); 110 | }); 111 | $("#managerLinksSortByUrl").click(function() { 112 | $("#managerLinksLinks").html(""); 113 | linkItems.sort(by("href", "type")); 114 | linkItems.forEach(function(item) { 115 | $("#managerLinksLinks").append(item.item); 116 | }); 117 | }); 118 | $("#managerLinksSortByType").click(function() { 119 | $("#managerLinksLinks").html(""); 120 | linkItems.sort(by("type", "href")); 121 | linkItems.forEach(function(item) { 122 | $("#managerLinksLinks").append(item.item); 123 | }); 124 | }); 125 | $("#managerLinksCopyAll").click(function() { 126 | var pre = $("#managerLinksPre").val(); 127 | var after = $("#managerLinksAfter").val(); 128 | var resultStr = "",i=0; 129 | linkItems.forEach(function(item) { 130 | i++; 131 | var linkName = decodeURIComponent(item.linkName); 132 | resultStr += (pre.replace(/%i/g,i+"").replace(/%n/g,linkName) + item.href + after.replace(/%i/g,i+"").replace(/%n/g,linkName) + "\n"); 133 | }); 134 | callBack(resultStr); 135 | }); 136 | $("#managerLinksCopySel").click(function() { 137 | var pre = $("#managerLinksPre").val(); 138 | var after = $("#managerLinksAfter").val(); 139 | var resultStr = "",i=0; 140 | linkItems.forEach(function(item) { 141 | i++; 142 | if (item.item.children("input")[0].checked) { 143 | var linkName = decodeURIComponent(item.linkName); 144 | resultStr += (pre.replace(/%i/g,i+"").replace(/%n/g,linkName) + item.href + after.replace(/%i/g,i+"").replace(/%n/g,linkName) + "\n"); 145 | } 146 | }); 147 | if(resultStr != "") 148 | callBack(resultStr); 149 | }); 150 | $("#managerLinksClose").click(function() { 151 | frame.hide(); 152 | }); 153 | $("#managerLinksContent>div")[0].onclick = function() { 154 | frame.hide(); 155 | }; 156 | } 157 | getLinks(); 158 | if(linksArr.length == 0){ 159 | callBack(); 160 | return; 161 | } 162 | $("#managerLinksLinks").html(""); 163 | linksArr.forEach(function(link) { 164 | var type; 165 | if(resReg.test(link)){ 166 | type = link.replace(resReg, "$1"); 167 | }else{ 168 | type = link; 169 | let matchArr = link.match(customReg); 170 | if(matchArr){ 171 | type = matchArr[1] || matchArr[0]; 172 | } 173 | if(type && type.length > 10){ 174 | type = type.substr(0, 10); 175 | } 176 | } 177 | var linkName = linkPair[link].innerText; 178 | if (linkName) linkName = linkName.trim(); 179 | if (!linkName) linkName = type.indexOf(".") == -1 ? link : link.replace(/.*\/([^\/]+)$/i, "$1"); 180 | if (typeHtml.indexOf(type) == -1) { 181 | typeHtml += '' + type + " "; 182 | } 183 | var linkItem = $(''); 184 | $("#managerLinksLinks").append(linkItem); 185 | linkItems.push({ 186 | item: linkItem, 187 | href: link, 188 | type: type, 189 | linkName: linkName 190 | }); 191 | }); 192 | $("#managerLinksType").html(typeHtml); 193 | $("#managerLinksType>a").click(function(e) { 194 | var selected = this.style.textDecoration == "underline"; 195 | this.style.textDecoration = selected ? "" : "underline"; 196 | var type = this.innerHTML; 197 | linkItems.forEach(function(item) { 198 | if (item.type == type) { 199 | item.item.children("input")[0].checked = !selected; 200 | } 201 | }); 202 | }); 203 | frame.show(); 204 | $("#managerLinksLinks").height($(".managerLinksBody").height() - $("#managerLinksType").height() - $("#managerLinksSortByName").height() * 3 - 38); 205 | $(".managerLinksBody").hide(); 206 | $(".managerLinksBody").show(); 207 | $(".managerLinksBody").css('margin-top',-$(".managerLinksBody").height() / 2); 208 | } -------------------------------------------------------------------------------- /Picviewer CE+/README.md: -------------------------------------------------------------------------------- 1 | # 🏞️ Picviewer CE+ 2 | 3 | [](https://twitter.com/intent/follow?screen_name=HoothinDev) [](https://discord.com/invite/keqypXC6wD) [](https://www.reddit.com/r/PicviewerCE) [](https://github.com/hoothin/UserScripts#StarMe) 4 | 5 | ### Zoom images across all your favorite websites. Pop up, scale, edit, rotate, batch save images, or automatically load pictures from subsequent pages. Simply hover your mouse over any image and click the icons on the float bar. 6 | 7 | + **Adjust:** Scale/rotate/batch save every picture 8 | 9 | + **View:** Find and popup large version for pictures with click or mouse over 10 | 11 | + **Fetch:** Auto load and parse next paginated web 12 | pages and show ALL pics 13 | 14 | + **Download:** Pictures export to page or package into ZIP 15 | 16 | + **Search:** Search similar image by picture 17 | 18 | + View long image by scroll 19 | 20 | Recommended similar plugins: [Imagus](https://chromewebstore.google.com/detail/imagus/immpkjjlgappgfkkfieppnmlhakdmaab) - [Hover-zoom+](https://chromewebstore.google.com/detail/hover-zoom+/pccckmaobkjjboncdfnnofkonhgpceea) - [Mouseover Popup Image Viewer](https://greasyfork.org/scripts/394820) 21 | 22 | ## Quick Start 23 | 24 | Install from [Github📥](https://hoothin.github.io/UserScripts/Picviewer%20CE+/dist.user.js) or [Greasefork📥](https://greasyfork.org/scripts/24204-picviewer-ce). 25 | 26 | Hover your mouse over any image and click the icons on the float bar. 27 | 28 | Press `CTRL + G` to quickly enter the gallery. Hold `CTRL` to view a larger picture when hovering over images or links. 29 | 30 | There are additional settings available in the "Picviewer CE+ config" for further customization. Currently, reviewing these settings is the best way to learn about the script's capabilities. Try exploring more functions on your own! 31 | 32 | ## Contribution & Support 33 | 34 | If you are glad to assist with the translation, please ✍️[edit this file](https://github.com/hoothin/UserScripts/edit/master/Picviewer%20CE%2B/pvcep_lang.js#L1). It will be beneficial for individuals who speak the same language as you do. Thank you for your help. 35 | 36 | + English by [RX-3200](https://greasyfork.org/users/43-rx-3200). 37 | 38 | + Português by [AstroCoelestis](https://greasyfork.org/users/881248). 39 | 40 | + Русский by RX-3200 & vanja-san. 41 | 42 | + Turkish by [PUFF1N](https://github.com/PUFF1N-000). 43 | 44 | + Ukrainian by [MaSHiNiK](https://github.com/MaSHiNiK). 45 | 46 | + Arabic by [Prankster 199](https://github.com/vfggf95565). 47 | 48 | *Need more rules for peculiar sites? feel free to pull requests or open issues.* 49 | 50 | ## PDF Addon 51 | Picviewer CE+ [PDF Addon](https://hoothin.github.io/UserScripts/Picviewer%20CE+/pvcep_pdf_addon.user.js). After installing this addon, when the `Compress to ZIP` feature is enabled, a PDF file will be generated instead of a ZIP file during the packaging process. 52 | 53 | 54 |65 | 66 | ## Custom [Rules Example](pvcep_rules.js): 67 | **💝 Buy me a coffee with [Ko-fi](https://ko-fi.com/hoothin) or [愛發電](https://afdian.com/a/hoothin) to keep my scripts always up to date.** 68 | 69 |Make a PDF e-book with this addon
55 |For example, if there is a website with images from
56 |xxx.com/1.jpgtoxxx.com/99.jpg, you can use this addon to generate a beautiful PDF e-book as follows:57 |
63 |- Open the gallery by pressing Ctrl + g
58 |- In the
59 |Commandmenu, find and clickAdd image- Input
60 |xxx.com/[1-99].jpg- Right-click in the thumbnail frame below to ignore any unwanted images
61 |- Click
62 |Download all shownin theCommandmenuThis way, you'll get a beautifully created PDF e-book.
64 |70 | 71 | + Match image src(no matter which site) with /pics\\.dmm\\.co\\.jp/i and replace image url from "ps.jpg" to "pl.jpg" 72 | 73 | ``` json 74 | { 75 | "name": "Dmm", 76 | "src": "pics\\.dmm\\.co\\.jp", 77 | "r": "ps.jpg", 78 | "s": "pl.jpg" 79 | } 80 | ``` 81 | + Match site with /xxx\.com/ and replace image url from /us\\.xxx\\.com/\d+wm\//i to "previews.xxx.com/images/" 82 | 83 | ``` json 84 | { 85 | "name": "Example", 86 | "url": "^https://xxx\\.com/", 87 | "r": "/us\\.xxx\\.com/\\d+wm//i", 88 | "s": "previews.xxx.com/images/" 89 | } 90 | ``` 91 | + Add click-to-open for existing asiansister rule. 92 | 93 | ``` json 94 | { 95 | "name": "Asiansister", 96 | "clickToOpen": { 97 | "enabled": true, 98 | "preventDefault": true, 99 | "type": "actual", 100 | "button": 0, 101 | "alt": false, 102 | "ctrl": false, 103 | "shift": false, 104 | "meta": false 105 | } 106 | } 107 | ``` 108 | You have the option to use a standalone userscript, which allows you to manage all of your custom rules effectively. 109 | 110 | Feel free to share your own custom rules on Greasy Fork! 111 | 112 | ``` js 113 | // ==UserScript== 114 | // @name Picviewer CE+ custom rules 115 | // @namespace hoothin 116 | // @version 0.1 117 | // @description Picviewer CE+ custom rules 118 | // @author You 119 | // @match *://*/* 120 | // @run-at document-start 121 | // @grant none 122 | // ==/UserScript== 123 | 124 | (function() { 125 | 'use strict'; 126 | window.pvcepRules = (window.pvcepRules || []).concat([ 127 | //Delete these two example rules and add your own. 128 | { 129 | name: "rule1", 130 | src: /pics\.dmm\.co\.jp/i, 131 | r: "ps.jpg", 132 | s: "pl.jpg" 133 | }, 134 | { 135 | name: "rule2", 136 | url: /^https:\/\/xxx\.com\//, 137 | r: /us\.xxx\.com\/\d+wm\//i, 138 | s: "previews.xxx.com/images/" 139 | } 140 | ]); 141 | })(); 142 | ``` 143 | 144 | 145 |
146 |216 | 217 | ## Blank Gallery Page 218 | [https://hoothin.github.io/UserScripts/Picviewer%20CE+/gallery.html](https://hoothin.github.io/UserScripts/Picviewer%20CE+/gallery.html) 219 | 220 | > *A blank gallery page designed for viewing local or online pictures, showcasing every image you have imported.* 221 | 222 | You can drag and drop **folders** or videos/audios/images into this gallery to get an electronic slideshow to view them. 223 | 224 | Click with `Ctrl key` can import folder too. 225 | 226 | Include `mode=`*`1`* to open gallery in view-more mode.Advance rule wizard
147 |There are two types of rules available:
148 |149 |
215 |- 150 |
200 |JSON (simple mode)
151 |These rules are written in JSON format and can be imported online through Discussions or Reddit. 152 | They won't limited by websites that have a strict Content Security Policy that disallows unsafe-eval.
153 |154 |
199 |- JSON params 155 |
198 |156 |
197 |- 157 |
161 |name
158 |159 |
"name": "rule name"Name of the rule
160 |- 162 |
166 |url
163 |164 |
"url": "^https://google\\.com"Regular expression used to match the site URL.
165 |- 167 |
171 |src
168 |169 |
"src": "^https://image\\.xx\\.com"Regular expression used to match the image src
170 |- 172 |
176 |r
173 |174 |
"r": "/(.*)\\d+/i"or"r": "thumb"Simple string or regular expression used to replace the image src from
175 |- 177 |
181 |s
178 |179 |
"s": "$1"Replace the image src to
180 |- 182 |
186 |ext
183 |184 |
"ext": "previous"Capture nearby image element when the mouse hovers over a non-image element.
185 |- 187 |
191 |lazyAttr
188 |189 |
"lazyAttr": "data-lazy"Lazy loaded original image URL attribute name
190 |- 192 |
196 |xhr
193 |194 |
"xhr": { "url": ".showcase__link", "query": "img[fetchpriority]" }Fetch the link above the image that matches ".showcase__link" and query the "img[fetchpriority]" on the inner page from the link.
195 |- 201 |
214 |JS (full mode)
202 |These rules are written in JavaScript object format. If you are not using a standalone userscript, they may be limited by websites that have a strict Content Security Policy that disallows unsafe-eval.
203 |204 |
212 |- JS params 205 |
211 |206 |
210 |- all mentioned above and the function type instead of string type
207 |- getImage
208 |- getExtSrc
209 |Learn from https://github.com/hoothin/UserScripts/blob/master/Picviewer%20CE%2B/pvcep_rules.js
213 |
227 | Add `imgs=`*`http://xxx/xxx.jpg`* to import images. ` ` to split multi-image, `[01-09]` to generate nine urls form 01 to 09
228 | For example: 229 | ```url 230 | https://hoothin.github.io/UserScripts/Picviewer%20CE+/gallery.html?mode=0&imgs=http://xxx/xxx[01-99].jpg 231 | or 232 | https://hoothin.github.io/UserScripts/Picviewer%20CE+/gallery.html?mode=0&imgs=${encodeURIComponent(IMG1 + ' ' + IMG2)} 233 | ``` 234 | 235 |236 | 237 | ## Thousands compatible sites for find larger or original images like 238 | 239 | deviantart.com 240 | google.com 241 | wikipedia.org 242 | dribbble.com 243 | bing.com 244 | imdb.com 245 | github.com 246 | tumblr.com 247 | youtube.com 248 | pixiv.net 249 | steampowered.com 250 | itunes.apple.com 251 | pinterest.com 252 | gelbooru.com 253 | discordapp.com 254 | twitter.com 255 | fandom.com 256 | reddit.com 257 | yande.re 258 | wallhaven.cc 259 | 500px 260 | nyaa 261 | e621.net 262 | nhentai.net 263 | tieba.baidu.com 264 | douban.com 265 | weibo.com 266 | bilibili.com 267 | t.qq.com 268 | huaban.com 269 | hujiang.com 270 | dianping.com 271 | trakt.tv 272 | music.163.com 273 | rule34hentai.net 274 | photosight.ru 275 | boqingguan.com 276 | 178.com 277 | zhisheji.com 278 | themex.net 279 | operachina.com 280 | topit.me 281 | bcy.net 282 | zhihu.com 283 | autohome.com.cn 284 | bitauto.com 285 | xcar.com.cn 286 | pcauto.com.cn 287 | auto.sina.com.cn 288 | baike.baidu.com 289 | nvshens.com 290 | 24meitu.com 291 | acgget.com 292 | lofter.com 293 | sohu.com 294 | taobao.com 295 | alibaba.com 296 | yihaodian.com 297 | addons.mozilla.org 298 | crsky.com 299 | firefox.net.cn 300 | jd.com 301 | dangdang.com 302 | detail.zol.com.cn 303 | duokan.com 304 | youku.com 305 | yyets.com 306 | xiaohongshu.com 307 | moegirl.org 308 | fanfou.com 309 | meipai.com 310 | game.yesky.com 311 | dota2.sgamer.com 312 | mafengwo.cn 313 | 588ku.com 314 | ibaotu.com 315 | 58pic.com 316 | 317 | And so on ... 318 | -------------------------------------------------------------------------------- /BingBgForBaidu/BingBgForGoogle.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name BingBgForGoogle 3 | // @name:zh-CN 谷Bing图 4 | // @name:zh-TW 谷Bing圖 5 | // @namespace hoothin 6 | // @version 0.3 7 | // @description Just change the background image of Google homepage to Bing 8 | // @description:zh-CN 给谷歌首页换上 Bing 的背景图 9 | // @description:zh-TW 給 Google 首頁換上 Bing 的背景圖 10 | // @author hoothin 11 | // @grant GM_xmlhttpRequest 12 | // @grant GM_setValue 13 | // @grant GM_getValue 14 | // @grant GM_addStyle 15 | // @grant GM_registerMenuCommand 16 | // @grant unsafeWindow 17 | // @connect global.bing.com 18 | // @connect cn.bing.com 19 | // @license MIT License 20 | // @match *://www.google.com/* 21 | // @match *://www.google.ad/* 22 | // @match *://www.google.ae/* 23 | // @match *://www.google.com.af/* 24 | // @match *://www.google.com.ag/* 25 | // @match *://www.google.al/* 26 | // @match *://www.google.am/* 27 | // @match *://www.google.co.ao/* 28 | // @match *://www.google.com.ar/* 29 | // @match *://www.google.as/* 30 | // @match *://www.google.at/* 31 | // @match *://www.google.com.au/* 32 | // @match *://www.google.az/* 33 | // @match *://www.google.ba/* 34 | // @match *://www.google.com.bd/* 35 | // @match *://www.google.be/* 36 | // @match *://www.google.bf/* 37 | // @match *://www.google.bg/* 38 | // @match *://www.google.com.bh/* 39 | // @match *://www.google.bi/* 40 | // @match *://www.google.bj/* 41 | // @match *://www.google.com.bn/* 42 | // @match *://www.google.com.bo/* 43 | // @match *://www.google.com.br/* 44 | // @match *://www.google.bs/* 45 | // @match *://www.google.bt/* 46 | // @match *://www.google.co.bw/* 47 | // @match *://www.google.by/* 48 | // @match *://www.google.com.bz/* 49 | // @match *://www.google.ca/* 50 | // @match *://www.google.cd/* 51 | // @match *://www.google.cf/* 52 | // @match *://www.google.cg/* 53 | // @match *://www.google.ch/* 54 | // @match *://www.google.ci/* 55 | // @match *://www.google.co.ck/* 56 | // @match *://www.google.cl/* 57 | // @match *://www.google.cm/* 58 | // @match *://www.google.cn/* 59 | // @match *://www.google.com.co/* 60 | // @match *://www.google.co.cr/* 61 | // @match *://www.google.com.cu/* 62 | // @match *://www.google.cv/* 63 | // @match *://www.google.com.cy/* 64 | // @match *://www.google.cz/* 65 | // @match *://www.google.de/* 66 | // @match *://www.google.dj/* 67 | // @match *://www.google.dk/* 68 | // @match *://www.google.dm/* 69 | // @match *://www.google.com.do/* 70 | // @match *://www.google.dz/* 71 | // @match *://www.google.com.ec/* 72 | // @match *://www.google.ee/* 73 | // @match *://www.google.com.eg/* 74 | // @match *://www.google.es/* 75 | // @match *://www.google.com.et/* 76 | // @match *://www.google.fi/* 77 | // @match *://www.google.com.fj/* 78 | // @match *://www.google.fm/* 79 | // @match *://www.google.fr/* 80 | // @match *://www.google.ga/* 81 | // @match *://www.google.ge/* 82 | // @match *://www.google.gg/* 83 | // @match *://www.google.com.gh/* 84 | // @match *://www.google.com.gi/* 85 | // @match *://www.google.gl/* 86 | // @match *://www.google.gm/* 87 | // @match *://www.google.gr/* 88 | // @match *://www.google.com.gt/* 89 | // @match *://www.google.gy/* 90 | // @match *://www.google.com.hk/* 91 | // @match *://www.google.hn/* 92 | // @match *://www.google.hr/* 93 | // @match *://www.google.ht/* 94 | // @match *://www.google.hu/* 95 | // @match *://www.google.co.id/* 96 | // @match *://www.google.ie/* 97 | // @match *://www.google.co.il/* 98 | // @match *://www.google.im/* 99 | // @match *://www.google.co.in/* 100 | // @match *://www.google.iq/* 101 | // @match *://www.google.is/* 102 | // @match *://www.google.it/* 103 | // @match *://www.google.je/* 104 | // @match *://www.google.com.jm/* 105 | // @match *://www.google.jo/* 106 | // @match *://www.google.co.jp/* 107 | // @match *://www.google.co.ke/* 108 | // @match *://www.google.com.kh/* 109 | // @match *://www.google.ki/* 110 | // @match *://www.google.kg/* 111 | // @match *://www.google.co.kr/* 112 | // @match *://www.google.com.kw/* 113 | // @match *://www.google.kz/* 114 | // @match *://www.google.la/* 115 | // @match *://www.google.com.lb/* 116 | // @match *://www.google.li/* 117 | // @match *://www.google.lk/* 118 | // @match *://www.google.co.ls/* 119 | // @match *://www.google.lt/* 120 | // @match *://www.google.lu/* 121 | // @match *://www.google.lv/* 122 | // @match *://www.google.com.ly/* 123 | // @match *://www.google.co.ma/* 124 | // @match *://www.google.md/* 125 | // @match *://www.google.me/* 126 | // @match *://www.google.mg/* 127 | // @match *://www.google.mk/* 128 | // @match *://www.google.ml/* 129 | // @match *://www.google.com.mm/* 130 | // @match *://www.google.mn/* 131 | // @match *://www.google.com.mt/* 132 | // @match *://www.google.mu/* 133 | // @match *://www.google.mv/* 134 | // @match *://www.google.mw/* 135 | // @match *://www.google.com.mx/* 136 | // @match *://www.google.com.my/* 137 | // @match *://www.google.co.mz/* 138 | // @match *://www.google.com.na/* 139 | // @match *://www.google.com.ng/* 140 | // @match *://www.google.com.ni/* 141 | // @match *://www.google.ne/* 142 | // @match *://www.google.nl/* 143 | // @match *://www.google.no/* 144 | // @match *://www.google.com.np/* 145 | // @match *://www.google.nr/* 146 | // @match *://www.google.nu/* 147 | // @match *://www.google.co.nz/* 148 | // @match *://www.google.com.om/* 149 | // @match *://www.google.com.pa/* 150 | // @match *://www.google.com.pe/* 151 | // @match *://www.google.com.pg/* 152 | // @match *://www.google.com.ph/* 153 | // @match *://www.google.com.pk/* 154 | // @match *://www.google.pl/* 155 | // @match *://www.google.pn/* 156 | // @match *://www.google.com.pr/* 157 | // @match *://www.google.ps/* 158 | // @match *://www.google.pt/* 159 | // @match *://www.google.com.py/* 160 | // @match *://www.google.com.qa/* 161 | // @match *://www.google.ro/* 162 | // @match *://www.google.ru/* 163 | // @match *://www.google.rw/* 164 | // @match *://www.google.com.sa/* 165 | // @match *://www.google.com.sb/* 166 | // @match *://www.google.sc/* 167 | // @match *://www.google.se/* 168 | // @match *://www.google.com.sg/* 169 | // @match *://www.google.sh/* 170 | // @match *://www.google.si/* 171 | // @match *://www.google.sk/* 172 | // @match *://www.google.com.sl/* 173 | // @match *://www.google.sn/* 174 | // @match *://www.google.so/* 175 | // @match *://www.google.sm/* 176 | // @match *://www.google.sr/* 177 | // @match *://www.google.st/* 178 | // @match *://www.google.com.sv/* 179 | // @match *://www.google.td/* 180 | // @match *://www.google.tg/* 181 | // @match *://www.google.co.th/* 182 | // @match *://www.google.com.tj/* 183 | // @match *://www.google.tl/* 184 | // @match *://www.google.tm/* 185 | // @match *://www.google.tn/* 186 | // @match *://www.google.to/* 187 | // @match *://www.google.com.tr/* 188 | // @match *://www.google.tt/* 189 | // @match *://www.google.com.tw/* 190 | // @match *://www.google.co.tz/* 191 | // @match *://www.google.com.ua/* 192 | // @match *://www.google.co.ug/* 193 | // @match *://www.google.co.uk/* 194 | // @match *://www.google.com.uy/* 195 | // @match *://www.google.co.uz/* 196 | // @match *://www.google.com.vc/* 197 | // @match *://www.google.co.ve/* 198 | // @match *://www.google.co.vi/* 199 | // @match *://www.google.com.vn/* 200 | // @match *://www.google.vu/* 201 | // @match *://www.google.ws/* 202 | // @match *://www.google.rs/* 203 | // @match *://www.google.co.za/* 204 | // @match *://www.google.co.zm/* 205 | // @match *://www.google.co.zw/* 206 | // @match *://www.google.cat/* 207 | // @downloadURL https://update.greasyfork.org/scripts/503741/BingBgForGoogle.user.js 208 | // @updateURL https://update.greasyfork.org/scripts/503741/BingBgForGoogle.meta.js 209 | // ==/UserScript== 210 | 211 | (function() { 212 | 'use strict'; 213 | if (/\?q=/.test(location.href)) return; 214 | let LinkPa = document.querySelector("[data-ogbl]"); 215 | if (!LinkPa) return; 216 | let bingBgLink = document.createElement("a"); 217 | bingBgLink.className = LinkPa.firstChild.firstChild.className; 218 | bingBgLink.target = "_blank"; 219 | bingBgLink.innerText = "Bing Bg"; 220 | let linkDiv = document.createElement("div"); 221 | linkDiv.className = LinkPa.firstChild.className; 222 | linkDiv.appendChild(bingBgLink); 223 | LinkPa.appendChild(linkDiv); 224 | let skinContainer = document.body; 225 | GM_addStyle(` 226 | body{ 227 | background-position: center 0; 228 | background-repeat: no-repeat; 229 | background-size: cover; 230 | -webkit-background-size: cover; 231 | -o-background-size: cover; 232 | } 233 | #gb{ 234 | background-color: unset!important; 235 | } 236 | [role="navigation"],[role="contentinfo"]{ 237 | background-color: rgb(32 33 36 / 50%)!important; 238 | } 239 | #gb *,[role="contentinfo"] *{ 240 | color: white!important; 241 | } 242 | `); 243 | 244 | let btnK = document.querySelector("input[name='btnK']"); 245 | let clickHandler = e => { 246 | skinContainer.style.backgroundImage = ""; 247 | }; 248 | btnK.addEventListener("click",clickHandler); 249 | let bingImgObj = GM_getValue("bingImgObj"); 250 | if (bingImgObj) { 251 | skinContainer.style.backgroundImage = "url(\"" + bingImgObj.base64 + "\")"; 252 | } 253 | 254 | GM_xmlhttpRequest({ 255 | method: 'GET', 256 | url: "https://global.bing.com/HPImageArchive.aspx?format=js&idx=0&pid=hp&video=1&n=1", 257 | onload: function(result) { 258 | let jsonData = null; 259 | try { 260 | jsonData = JSON.parse(result.responseText); 261 | let bgUrl = jsonData.images[0].url; 262 | if (!/^https?:\/\//.test(bgUrl)) { 263 | bgUrl = "https://global.bing.com" + bgUrl; 264 | } 265 | bingBgLink.title = jsonData.images[0].copyright; 266 | bingBgLink.href = bgUrl; 267 | if (bingImgObj && bingImgObj.url == bgUrl) return; 268 | if (!bingImgObj) skinContainer.style.backgroundImage = "url(\"" + bgUrl + "\")"; 269 | GM_xmlhttpRequest({ 270 | method: 'GET', 271 | url: bgUrl, 272 | responseType: "blob", 273 | onload: function(r) { 274 | let blob = r.response; 275 | let fr = new FileReader(); 276 | fr.readAsDataURL(blob); 277 | fr.onload = function (e) { 278 | let base64ImgData = e.target.result; 279 | GM_setValue("bingImgObj",{url: bgUrl, base64: base64ImgData}); 280 | }; 281 | } 282 | }); 283 | } catch (e) { 284 | console.log(e); 285 | } 286 | } 287 | }); 288 | let blurStyle; 289 | function createBlur() { 290 | if (!blurStyle) { 291 | blurStyle = document.createElement("style"); 292 | blurStyle.innerText = ` 293 | body::before{ 294 | content: " "; 295 | display: block; 296 | position: absolute; 297 | left: 0; 298 | top: 0; 299 | right: 0; 300 | bottom: 0; 301 | background: inherit; 302 | filter: blur(5px); 303 | z-index: -1; 304 | }`; 305 | } 306 | document.head.appendChild(blurStyle); 307 | } 308 | if (GM_getValue("blur")) { 309 | createBlur(); 310 | } 311 | GM_registerMenuCommand("Change blur", () => { 312 | if (blurStyle && blurStyle.parentNode) { 313 | GM_setValue("blur", false); 314 | blurStyle.parentNode.removeChild(blurStyle); 315 | } else { 316 | GM_setValue("blur", true); 317 | createBlur(); 318 | } 319 | }); 320 | })(); -------------------------------------------------------------------------------- /Easy offline/Easy offline pikpak.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Easy Offline pikpak addon 3 | // @namespace hoothin 4 | // @version 2024-08-16 5 | // @description Add pikpak support for Easy Offline 6 | // @author hoothin 7 | // @match *://*/* 8 | // @grant GM_setValue 9 | // @grant GM_getValue 10 | // @grant GM_xmlhttpRequest 11 | // @grant GM_notification 12 | // @grant unsafeWindow 13 | // @run-at document-start 14 | // @require https://unpkg.com/crypto-js@4.2.0/crypto-js.js 15 | // @connect user.mypikpak.com 16 | // @connect api-drive.mypikpak.com 17 | // ==/UserScript== 18 | 19 | (function() { 20 | 'use strict'; 21 | let info = GM_getValue("pikpakUserInfo"), device_id, user_id; 22 | const CLIENT_ID = "YNxT9w7GMdWvEOKa"; 23 | const CLIENT_SECRET = "dbw2OtmVEeuUvIptb1Coyg"; 24 | const CLIENT_VERSION = "1.47.1"; 25 | const PACKAG_ENAME = "com.pikcloud.pikpak"; 26 | const SDK_VERSION = "2.0.4.204000"; 27 | const APP_NAME = "com.pikcloud.pikpak"; 28 | function captchaInit() { 29 | return new Promise(resolve => { 30 | let meta = {}; 31 | if (/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/.test(info.userName)) { 32 | meta.email = info.userName; 33 | } else if (/\d{11,18}/.test(info.userName)) { 34 | meta.phone_number = info.userName; 35 | } else { 36 | meta.username = info.userName; 37 | } 38 | let params = { 39 | "client_id": CLIENT_ID, 40 | "action": "POST:https://user.mypikpak.com/v1/auth/signin", 41 | "device_id": device_id, 42 | "meta": meta 43 | } 44 | GM_xmlhttpRequest({ 45 | method: 'POST', 46 | url: 'https://user.mypikpak.com/v1/shield/captcha/init', 47 | data: JSON.stringify(params), 48 | onload: (res) => { 49 | if(res.status === 200) { 50 | let data = JSON.parse(res.responseText); 51 | resolve(data); 52 | } else { 53 | info.loginInfo = null; 54 | GM_setValue("pikpakUserInfo", info); 55 | const msg = JSON.parse(res.responseText).error_description; 56 | alert(msg); 57 | } 58 | }, 59 | onerror: (e) => { 60 | GM_notification("Error: " + (e.statusText || e.error)); 61 | }, 62 | ontimeout: (e) => { 63 | GM_notification("Error: " + (e.statusText || e.error)); 64 | } 65 | }); 66 | }); 67 | } 68 | function buildCustomUserAgent() { 69 | let signature_base = `${device_id}${PACKAG_ENAME}1appkey`; 70 | let sha1_result = CryptoJS.SHA1(signature_base).toString(CryptoJS.enc.Hex); 71 | let md5_result = CryptoJS.MD5(sha1_result).toString(CryptoJS.enc.Hex); 72 | 73 | let device_sign = `div101.${device_id}${md5_result}`; 74 | 75 | let user_agent_parts = [ 76 | `ANDROID-${APP_NAME}/${CLIENT_VERSION}`, 77 | "protocolVersion/200", 78 | "accesstype/", 79 | `clientid/${CLIENT_ID}`, 80 | `clientversion/${CLIENT_VERSION}`, 81 | "action_type/", 82 | "networktype/WIFI", 83 | "sessionid/", 84 | `deviceid/${device_id}`, 85 | "providername/NONE", 86 | `devicesign/${device_sign}`, 87 | "refresh_token/", 88 | `sdkversion/${SDK_VERSION}`, 89 | `datetime/${Date.now()}`, 90 | `usrno/${user_id}`, 91 | `appname/${APP_NAME}`, 92 | "session_origin/", 93 | "grant_type/", 94 | "appid/", 95 | "clientip/", 96 | "devicename/Xiaomi_M2004j7ac", 97 | "osversion/13", 98 | "platformversion/10", 99 | "accessmode/", 100 | "devicemodel/M2004J7AC", 101 | ] 102 | 103 | return user_agent_parts.join(" "); 104 | } 105 | document.addEventListener("click", function(e) { 106 | if (e.target && e.target.getAttribute && e.target.getAttribute("name") === "pikpak" && e.target.parentNode.id === "icons") { 107 | GM_setValue("pikpakUserInfo", ""); 108 | alert("PikPak account has been cleared"); 109 | } 110 | }); 111 | var _unsafeWindow = (typeof unsafeWindow === 'undefined') ? window : unsafeWindow; 112 | if (!_unsafeWindow.eoAddons) _unsafeWindow.eoAddons = {}; 113 | _unsafeWindow.eoAddons.pikpak = { 114 | regex: /mypikpak\.com/, 115 | url: "http://user.mypikpak.com/", 116 | bgColor: "2265ff", 117 | noTxt: true, 118 | linkRegExp: /^magnet:\?xt|^PikPak:\/\/|\.(torrent|mp4|mp3|rar|7z|zip|rmvb|mkv|avi|iso)$/i, 119 | directUrl: function(offUrl) { 120 | if (!info) { 121 | let userName = prompt("userName"); 122 | if (!userName) return; 123 | let userPass = prompt("userPass"); 124 | if (!userPass) return; 125 | info = {userName: userName, userPass: userPass}; 126 | GM_setValue("pikpakUserInfo", info); 127 | } 128 | var postUrl = async () => { 129 | let postData; 130 | if (offUrl.indexOf('PikPak://') === 0) { 131 | const urlData = offUrl.substring(9).split('|') 132 | postData = { 133 | kind: "drive#file", 134 | name: urlData[0], 135 | size: urlData[1], 136 | hash: urlData[2], 137 | upload_type: "UPLOAD_TYPE_RESUMABLE", 138 | objProvider: { 139 | provider: "UPLOAD_TYPE_UNKNOWN" 140 | } 141 | } 142 | } else { 143 | postData = { 144 | kind: "drive#file", 145 | name: "", 146 | upload_type: "UPLOAD_TYPE_URL", 147 | url: { 148 | url: offUrl 149 | }, 150 | params: {"from":"file"}, 151 | folder_type: "DOWNLOAD" 152 | } 153 | } 154 | GM_xmlhttpRequest({ 155 | method: 'POST', 156 | url: 'https://api-drive.mypikpak.com/drive/v1/files', 157 | data: JSON.stringify(postData), 158 | headers: { 159 | "Content-Type": "application/json; charset=utf-8", 160 | authorization: info.loginInfo.token_type + ' ' + info.loginInfo.access_token, 161 | "X-Captcha-Token": info.captchaData.captcha_token 162 | }, 163 | onload: (res) => { 164 | if(res.status === 200) { 165 | GM_notification("Task OK"); 166 | } else if(res.status === 401) { 167 | info.loginInfo=null; 168 | GM_setValue("pikpakUserInfo", info); 169 | const msg = JSON.parse(res.responseText).error_description; 170 | alert(msg); 171 | } else if(res.status === 400) { 172 | const msg = JSON.parse(res.responseText).error_description; 173 | alert(msg); 174 | } else if(res.status === 403) { 175 | const msg = JSON.parse(res.responseText).error_description; 176 | alert(msg); 177 | } 178 | }, 179 | onerror: (e) => { 180 | GM_notification("Error: " + (e.statusText || e.error)); 181 | }, 182 | ontimeout: (e) => { 183 | GM_notification("Error: " + (e.statusText || e.error)); 184 | } 185 | }) 186 | }; 187 | device_id = CryptoJS.MD5(`${info.userName}${info.userPass}`).toString(CryptoJS.enc.Hex); 188 | (async () => { 189 | if (!info.captchaData || info.captchaData.expires < new Date().getTime()) { 190 | let captchaData = await captchaInit(); 191 | info.captchaData = captchaData; 192 | if (!info.captchaData.expires && info.captchaData.expires_in) { 193 | info.captchaData.expires = new Date().getTime() + 1000 * info.captchaData.expires_in; 194 | } 195 | GM_setValue("pikpakUserInfo", info); 196 | } 197 | if (!info.loginInfo || info.loginInfo.expires < new Date().getTime()) { 198 | let data = { 199 | "client_id": CLIENT_ID, 200 | "client_secret": CLIENT_SECRET, 201 | "password": info.userPass, 202 | "username": info.userName, 203 | "captcha_token": info.captchaData.captcha_token, 204 | } 205 | GM_xmlhttpRequest({ 206 | method: 'POST', 207 | url: 'https://user.mypikpak.com/v1/auth/signin', 208 | data: JSON.stringify(data), 209 | headers: { 210 | 'user-agent': 'accessmode/ devicename/Netease_Mumu appname/android-com.pikcloud.pikpak cmd/login appid/ action_type/ clientid/YNxT9w7GMdWvEOKa deviceid/56e000d71f4660700ca974f2305171c5 refresh_token/ grant_type/ networktype/WIFI devicemodel/MuMu accesstype/ sessionid/ osversion/6.0.1 datetime/1636364470779 sdkversion/1.0.1.101600 protocolversion/200 clientversion/ providername/NONE clientip/ session_origin/ devicesign/div101.56e000d71f4660700ca974f2305171c5b94c3d4196a9dd74e49d7710a7af873d platformversion/10 usrno/null' 211 | }, 212 | onload: (res) => { 213 | if (res.status === 200) { 214 | info.loginInfo = JSON.parse(res.responseText); 215 | if (!info.loginInfo.expires && info.loginInfo.expires_in) { 216 | info.loginInfo.expires = new Date().getTime() + 1000 * info.loginInfo.expires_in; 217 | } 218 | GM_setValue("pikpakUserInfo", info); 219 | postUrl(); 220 | } else if (res.status === 401) { 221 | GM_setValue("pikpakUserInfo",""); 222 | const msg = JSON.parse(res.responseText).error_description; 223 | alert(msg); 224 | } else if (res.status === 400) { 225 | GM_setValue("pikpakUserInfo",""); 226 | const msg = JSON.parse(res.responseText).error_description; 227 | alert(msg); 228 | } else if (res.status === 403) { 229 | GM_setValue("pikpakUserInfo",""); 230 | const msg = JSON.parse(res.responseText).error_description; 231 | alert(msg); 232 | } 233 | }, 234 | onerror: (e) => { 235 | GM_notification("Error: " + (e.statusText || e.error)); 236 | }, 237 | ontimeout: (e) => { 238 | GM_notification("Error: " + (e.statusText || e.error)); 239 | } 240 | }) 241 | } else { 242 | postUrl(); 243 | } 244 | })(); 245 | return false; 246 | }, 247 | bgImg: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAYFBMVEUAAAArbP5MdNFMdNIrbP4sbP1QdctQdcwvbv////8dYf8sbP9smP/09/8qaf/V4f8iZf/u8/+lwP+duv+UtP+PsP9hkP92n/9nlP/K2v/F1v+7z/+Ytv9Wif9Aef91nv9e7pgKAAAACHRSTlMA+puT/PWHhQBB7XEAAACQSURBVBjTTY8JCsQwCEWdrjFm37p37n/LMdAJfSTgf4IoAPQf8fDpgek4N9NxnwQZJx0/w+UMNd/XV6nluqsBQbRp79Xqvd7ICBCuaHuElMJhdXEspMKGko/YA2LYXyKuiGt8Ca3rfwm052nbjILV1IyFBZFZck4xppwXQ8Srk2wQzXzcIBpDB8w0/vM4AfwACl4LKjajMX0AAAAASUVORK5CYII=" 248 | }; 249 | })(); -------------------------------------------------------------------------------- /Highlight Every Code/Highlight Every Code.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Highlight Every Code 3 | // @name:zh-CN 代码片段高亮 4 | // @name:zh-TW 程式碼片斷高亮 5 | // @namespace hoothin 6 | // @version 2.2.3.1 7 | // @description Add a icon to popup a window that allows syntax highlighting and beautify and word count of source code snippets on current page 8 | // @description:zh-CN 选择代码片段后点击图标弹出新窗口显示语法高亮美化与格式化后的代码与字数统计 9 | // @description:zh-TW 選擇程式碼片段後點選圖示彈出新視窗顯示語法高亮美化與格式化後的程式碼與字數統計 10 | // @author Hoothin 11 | // @grant GM_registerMenuCommand 12 | // @grant GM.registerMenuCommand 13 | // @grant GM_setValue 14 | // @grant GM.setValue 15 | // @grant GM_getValue 16 | // @grant GM.getValue 17 | // @grant unsafeWindow 18 | // @compatible chrome 19 | // @compatible firefox 20 | // @license MIT License 21 | // @contributionURL https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=rixixi@sina.com&item_name=Greasy+Fork+donation 22 | // @contributionAmount 1 23 | // @include * 24 | // ==/UserScript== 25 | 26 | (function() { 27 | 'use strict'; 28 | var codeIcon=document.createElement("img"); 29 | var codes, selStr, scrollX, scrollY, customInput=false,altKey=true,ctrlKey=true,shiftKey=true,metaKey=true,hiding=false; 30 | var _unsafeWindow=(typeof unsafeWindow=='undefined'? window : unsafeWindow); 31 | codeIcon.className="codeIcon"; 32 | codeIcon.style.opacity=0; 33 | codeIcon.title="Show this code snippet"; 34 | codeIcon.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAYAgMAAACD0OXYAAAACVBMVEX7+/swMDBTU1MLxgsCAAAAJElEQVQI12MIBYEAGLUKBBbAqAUMQICgAoAqoBQ95JaCnASjAAgXMdk3d5HTAAAAAElFTkSuQmCC"; 35 | codeIcon.onmousedown=highlight; 36 | var style = document.createElement('style'); 37 | style.textContent = ` 38 | .codeIcon{ 39 | position:fixed; 40 | z-index:99999; 41 | cursor:pointer; 42 | transition:opacity 0.3s ease-in-out 0s; 43 | opacity:0.3; 44 | border:5px solid rgba(0, 0, 0, 0.2); 45 | border-radius:10px; 46 | max-width:30px; 47 | max-height:30px; 48 | overflow:hidden; 49 | } 50 | .codeIcon:hover{ 51 | opacity:0.9; 52 | } 53 | `; 54 | style.type = 'text/css'; 55 | document.head.appendChild(style); 56 | 57 | document.addEventListener('DOMMouseScroll', function(o) { 58 | hideIcon(); 59 | }); 60 | document.addEventListener('wheel', function(o) { 61 | hideIcon(); 62 | }); 63 | document.addEventListener('mousewheel', function(o) { 64 | hideIcon(); 65 | }); 66 | document.addEventListener('mouseover', function(o) { 67 | if(hiding)return; 68 | var target=o.target,hasCode=false; 69 | while(target && target.nodeName!="BODY"){ 70 | if(target.nodeName=="PRE" || target.nodeName=="CODE"){ 71 | hasCode=true; 72 | break; 73 | } 74 | target=target.parentNode; 75 | } 76 | if(!hasCode)return; 77 | if(target.offsetWidth && target.offsetWidth<110)return; 78 | selStr=target.innerText; 79 | if(!selStr)return; 80 | codes=selStr.replace(/&/g, "&").replace(/\/g,">"); 81 | document.body.appendChild(codeIcon); 82 | let pos=getMousePos(o); 83 | scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 84 | scrollY = document.documentElement.scrollTop || document.body.scrollTop; 85 | let top=target.offsetTop-scrollY; 86 | let left=target.offsetLeft-scrollX; 87 | codeIcon.style.opacity=""; 88 | codeIcon.style.top=top+"px"; 89 | codeIcon.style.left=left+"px"; 90 | }); 91 | document.addEventListener('mousedown', function(o) { 92 | hiding=true; 93 | setTimeout(()=>{hiding=false},1000); 94 | hideIcon(); 95 | }); 96 | document.addEventListener('mouseup', function(o) { 97 | if (o.button === 0 && ((!ctrlKey && !altKey && !metaKey && !shiftKey) || (ctrlKey && o.ctrlKey) || (altKey && o.altKey) || (metaKey && o.metaKey) || (shiftKey && o.shiftKey))) { 98 | //var customInputKey=(o.ctrlKey && o.shiftKey); 99 | setTimeout(function(){ 100 | selStr=document.getSelection().toString(); 101 | codes=selStr.replace(/&/g, "&").replace(/\/g,">"); 102 | if(!codes){ 103 | return; 104 | } 105 | document.body.appendChild(codeIcon); 106 | let pos=getMousePos(o); 107 | let clientH=(document.documentElement && document.documentElement.clientHeight) || 0; 108 | let clientW=(document.documentElement && document.documentElement.clientWidth) || 0; 109 | let top=pos.y>clientH-50?(pos.y-30):(pos.y+20); 110 | let left=pos.x>clientW-50?(pos.x-30):(pos.x+20); 111 | codeIcon.style.opacity=""; 112 | codeIcon.style.top=top+"px"; 113 | codeIcon.style.left=left+"px"; 114 | },1); 115 | } 116 | },false); 117 | 118 | function highlight(){ 119 | if(customInput){ 120 | selStr=prompt("Input code here",""); 121 | if(!selStr)return; 122 | codes=selStr.replace(/&/g, "&").replace(/\/g,">"); 123 | } 124 | let html='
Code Snippet '+ 125 | ''+ 126 | ''+ 135 | ''+ 136 | ''+ 137 | ''+ 138 | ''+ 139 | 'Code formatting: Javaspcript '+ 140 | 'Html '+ 141 | 'Css '+ 142 | 'Raw ('+selStr.replace(/\s/g,"").length+' words)'+ 143 | '' + codes + ""; 144 | 145 | let c = _unsafeWindow.open("", "_blank", "width=750, height=400, location=0, resizable=1, menubar=0, scrollbars=0"); 146 | c.document.write(html); 147 | c.document.close(); 148 | } 149 | function hideIcon(){ 150 | codeIcon.style.opacity=0; 151 | customInput=false; 152 | if(codeIcon.parentNode)codeIcon.parentNode.removeChild(codeIcon); 153 | } 154 | function getMousePos(event) { 155 | var e = event || window.event; 156 | scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; 157 | scrollY = document.documentElement.scrollTop || document.body.scrollTop; 158 | var x = (e.pageX || e.clientX) - scrollX; 159 | var y = (e.pageY || e.clientY) - scrollY; 160 | return { 'x': x, 'y': y }; 161 | } 162 | 163 | var _GM_registerMenuCommand; 164 | if(typeof GM_registerMenuCommand!='undefined'){ 165 | _GM_registerMenuCommand=GM_registerMenuCommand; 166 | }else if(typeof GM!='undefined' && typeof GM.registerMenuCommand!='undefined'){ 167 | _GM_registerMenuCommand=GM.registerMenuCommand; 168 | } 169 | if(typeof _GM_registerMenuCommand=='undefined')_GM_registerMenuCommand=(s,f)=>{}; 170 | var storage={ 171 | supportGM: typeof GM_getValue=='function' && typeof GM_getValue('a','b')!='undefined', 172 | supportGMPromise: typeof GM!='undefined' && typeof GM.getValue=='function' && typeof GM.getValue('a','b')!='undefined', 173 | mxAppStorage:(function(){ 174 | try{ 175 | return window.external.mxGetRuntime().storage; 176 | }catch(e){ 177 | }; 178 | })(), 179 | operaUJSStorage:(function(){ 180 | try{ 181 | return window.opera.scriptStorage; 182 | }catch(e){ 183 | }; 184 | })(), 185 | setItem:function(key,value){ 186 | if(this.operaUJSStorage){ 187 | this.operaUJSStorage.setItem(key,value); 188 | }else if(this.mxAppStorage){ 189 | this.mxAppStorage.setConfig(key,value); 190 | }else if(this.supportGM){ 191 | GM_setValue(key,value); 192 | }else if(this.supportGMPromise){ 193 | GM.setValue(key,value); 194 | }else if(window.localStorage){ 195 | window.localStorage.setItem(key,value); 196 | }; 197 | }, 198 | getItem:function(key,cb){ 199 | var value; 200 | if(this.operaUJSStorage){ 201 | value=this.operaUJSStorage.getItem(key); 202 | }else if(this.mxAppStorage){ 203 | value=this.mxAppStorage.getConfig(key); 204 | }else if(this.supportGM){ 205 | value=GM_getValue(key); 206 | }else if(this.supportGMPromise){ 207 | value=GM.getValue(key).then(v=>{cb(v)}); 208 | return; 209 | }else if(window.localStorage){ 210 | value=window.localStorage.getItem(key); 211 | }; 212 | cb(value); 213 | }, 214 | }; 215 | storage.getItem("keyConfig",v=>{ 216 | if(v){ 217 | var keys=v.split(""); 218 | altKey=keys[0]!="0"; 219 | ctrlKey=keys[1]!="0"; 220 | shiftKey=keys[2]!="0"; 221 | metaKey=keys[3]!="0"; 222 | } 223 | if(/greasyfork\.org\/.*\/scripts\/24150[^\/]*$/.test(location.href)){ 224 | var saveConfig=()=>{ 225 | var conStr=""; 226 | conStr+=altKey?"1":"0"; 227 | conStr+=ctrlKey?"1":"0"; 228 | conStr+=shiftKey?"1":"0"; 229 | conStr+=metaKey?"1":"0"; 230 | storage.setItem("keyConfig",conStr); 231 | }; 232 | var keyEles=document.querySelectorAll("h1>em>code"); 233 | keyEles[0].style.userSelect="none"; 234 | keyEles[1].style.userSelect="none"; 235 | keyEles[2].style.userSelect="none"; 236 | keyEles[3].style.userSelect="none"; 237 | keyEles[0].style.opacity=altKey?"":"0.3"; 238 | keyEles[1].style.opacity=ctrlKey?"":"0.3"; 239 | keyEles[2].style.opacity=shiftKey?"":"0.3"; 240 | keyEles[3].style.opacity=metaKey?"":"0.3"; 241 | 242 | keyEles[0].onclick=e=>{ 243 | altKey=!altKey; 244 | keyEles[0].style.opacity=altKey?"":"0.3"; 245 | saveConfig(); 246 | }; 247 | keyEles[1].onclick=e=>{ 248 | ctrlKey=!ctrlKey; 249 | keyEles[1].style.opacity=ctrlKey?"":"0.3"; 250 | saveConfig(); 251 | }; 252 | keyEles[2].onclick=e=>{ 253 | shiftKey=!shiftKey; 254 | keyEles[2].style.opacity=shiftKey?"":"0.3"; 255 | saveConfig(); 256 | }; 257 | keyEles[3].onclick=e=>{ 258 | metaKey=!metaKey; 259 | keyEles[3].style.opacity=metaKey?"":"0.3"; 260 | saveConfig(); 261 | }; 262 | } 263 | }); 264 | 265 | _GM_registerMenuCommand("Custom input to highlight", ()=>{ 266 | selStr=document.getSelection().toString(); 267 | codes=selStr.replace(/&/g, "&").replace(/\/g,">"); 268 | if(!codes){ 269 | customInput=true; 270 | } 271 | highlight(); 272 | }); 273 | })(); -------------------------------------------------------------------------------- /Mouse Gestures/Mouse Gestures.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Greasemonkey Mouse Gestures 3 | // @name:zh-CN 油猴鼠标手势 4 | // @name:zh-TW 油猴滑鼠手勢 5 | // @namespace hoothin 6 | // @version 0.70 7 | // @description Just a Mouse Gestures script 8 | // @description:zh-CN 就是个鼠标手势脚本 9 | // @description:zh-TW 就是個滑鼠手勢脚本 10 | // @author hoothin 11 | // @include * 12 | // @grant GM_openInTab 13 | // @grant GM_setValue 14 | // @grant GM_getValue 15 | // @grant GM_registerMenuCommand 16 | // @grant unsafeWindow 17 | // @grant GM_info 18 | // @license MIT License 19 | // @compatible chrome 20 | // @compatible firefox 21 | // ==/UserScript== 22 | 23 | var lastX,lastY,lastSign,afterGestures,gesturesWords,gesturesContent,gestures,signs; 24 | const defaultFun={ 25 | close:()=>{unsafeWindow.opener=null;unsafeWindow.open('', '_self', '');unsafeWindow.close();}, 26 | openNew:()=>{GM_openInTab('about:newtab', false)}, 27 | scrollToTop:()=>{unsafeWindow.scrollTo(0, 0)}, 28 | scrollToBottom:()=>{unsafeWindow.scrollTo(0, 1073741824)}, 29 | back:()=>{unsafeWindow.history.back()}, 30 | forward:()=>{unsafeWindow.history.forward()}, 31 | reload:()=>{unsafeWindow.location.reload()} 32 | }; 33 | function initEventListener(start,move,end,tracer,clientX,clientY,startBool){ 34 | var isMouse=start=="mousedown"; 35 | var moveFun=function(e){ 36 | tracer(clientX(e),clientY(e),isMouse); 37 | gesturesWords.innerHTML=signs; 38 | var gesturesWidth=signs.length*51+40; 39 | gesturesContent.style.width=gesturesWidth+"px"; 40 | gesturesContent.style.marginLeft=-gesturesWidth/2+"px"; 41 | }; 42 | document.addEventListener(start, function(e) { 43 | if(!startBool || startBool(e)){ 44 | lastX=clientX(e); 45 | lastY=clientY(e); 46 | lastSign=signs=""; 47 | document.addEventListener(move, moveFun, false); 48 | } 49 | }, false); 50 | var endFun=function(e) { 51 | document.removeEventListener(move, moveFun, false); 52 | setTimeout(function(){if(gesturesContent.parentNode)gesturesContent.parentNode.removeChild(gesturesContent);},500); 53 | if(signs){ 54 | if(afterGestures)afterGestures(); 55 | for(var g of gestures){ 56 | var gSign=g.gesture; 57 | if(signs==gSign){ 58 | if(!isMouse)document.body.appendChild(gesturesContent); 59 | var fun=defaultFun[g.fun]; 60 | if(fun===undefined || !fun){ 61 | eval(g.fun); 62 | }else { 63 | fun(); 64 | } 65 | e.stopPropagation(); 66 | e.preventDefault(); 67 | e.returnValue=false; 68 | e.cancelBubble=true; 69 | return false; 70 | } 71 | } 72 | signs=""; 73 | } 74 | }; 75 | document.addEventListener(end, endFun, false); 76 | document.addEventListener("mouseup", endFun, false); 77 | } 78 | (function() { 79 | 'use strict'; 80 | var i18n; 81 | var lang = navigator.appName=="Netscape"?navigator.language:navigator.userLanguage; 82 | const minLength=256,tg=0.5; 83 | switch (lang){ 84 | case "zh-CN": 85 | i18n={ 86 | close:"关闭页面", 87 | openNew:"新建标签页", 88 | scrollToTop:"滚动至最上", 89 | scrollToBottom:"滚动至最下", 90 | back:"后退", 91 | forward:"前进", 92 | reload:"刷新", 93 | addListener:"点击监听鼠标手势", 94 | listening:"正在监听鼠标手势", 95 | bind:"绑定功能", 96 | custom:"自定义代码", 97 | ok:"确定", 98 | del:"删除", 99 | saved:"已设定的手势", 100 | alert1:"请先监听手势", 101 | alert2:"还没有绑定功能", 102 | alert3:"请输入自定义代码", 103 | configure:"鼠标手势设置", 104 | update:"鼠标手势脚本已更新,是否覆盖脚本设置?" 105 | }; 106 | break; 107 | default: 108 | i18n={ 109 | close:"Close tab", 110 | openNew:"Open new tab", 111 | scrollToTop:"Scroll to top", 112 | scrollToBottom:"Scroll to bottom", 113 | back:"Back", 114 | forward:"Forward", 115 | reload:"Reload", 116 | addListener:"Click to add gesture listener", 117 | listening:"Listening", 118 | bind:"Bind function", 119 | custom:"Custom code", 120 | ok:"Ok", 121 | del:"Delete", 122 | saved:"Saved gestures", 123 | alert1:"Please add gesture first", 124 | alert2:"Nothing bind", 125 | alert3:"Input custom code please", 126 | configure:"Mouse Gestures - Configure", 127 | update:"Greasemonkey Mouse Gestures has updated, recover config?" 128 | }; 129 | break; 130 | } 131 | gestures=GM_getValue("gestures"); 132 | if(GM_info.script.version != GM_getValue("gmMouseGestureVersion")){ 133 | if(!gestures || window.confirm(i18n.update)) 134 | gestures=[{gesture:"↓→",fun:"close"}, 135 | {gesture:"→↑",fun:"openNew"}, 136 | {gesture:"←↑",fun:"scrollToTop"}, 137 | {gesture:"←↓",fun:"scrollToBottom"}, 138 | {gesture:"→↑←",fun:"back"}, 139 | {gesture:"←↑→",fun:"forward"}, 140 | {gesture:"↑↓",fun:"reload"}, 141 | {gesture:"↓↑↓",fun:"var t=((unsafeWindow.getSelection&&unsafeWindow.getSelection())||(document.getSelection&&document.getSelection())||(document.selection&&document.selection.createRange&&document.selection.createRange().text));var e=(document.charset||document.characterSet);if(t!=''){GM_openInTab('http://translate.google.cn/?text='+t+'&hl=zh-CN&langpair=auto|zh-CN&tbb=1&ie='+e,false);}else{GM_openInTab('http://translate.google.cn/translate?u='+encodeURIComponent(location.href)+'&hl=zh-CN&langpair=auto|zh-CN&tbb=1&ie='+e,false);}"}, 142 | {gesture:"↓↑↓←",fun:'var d=document,b=d.body;with(b.onselectstart=b.oncopy=b.onpaste=b.onkeydown=b.oncontextmenu=b.onmousemove=b.ondragstart=d.oncopy=d.onpaste=null,d.onselectstart=d.oncontextmenu=d.onmousedown=d.onkeydown=function(){return!0},d.wrappedJSObject||d)onmouseup=null,onmousedown=null,oncontextmenu=null;for(var a=d.getElementsByTagName("*"),i=a.length-1;i>=0;i--){var o=a[i];with(o.wrappedJSObject||o)onmouseup=null,onmousedown=null}var h=d.getElementsByTagName("head")[0];if(h){var s=d.createElement("style");s.innerHTML="html,*{user-select:text!important;-moz-user-select:text!important;-webkit-user-select:text!important;-webkit-user-drag:text!important;-khtml-user-select:text!important;-khtml-user-drag:text!important;pointer-events:auto!important;}",h.appendChild(s)}unsafeWindow.Event.prototype.preventDefault=function(){};'}, 143 | {gesture:"↓↑↓↑",fun:"var d = document, e = d.getElementById('wappalyzer-container') ; if ( e !== null ) { d.body.removeChild(e); } var u = 'https://wappalyzer.com/', t = new Date().getTime(), c = d.createElement('div'), p = d.createElement('div'), l = d.createElement('link'), s = d.createElement('script') ; c.setAttribute('id', 'wappalyzer-container'); l.setAttribute('rel', 'stylesheet'); l.setAttribute('href', u + 'css/bookmarklet.css'); d.head.appendChild(l); p.setAttribute('id', 'wappalyzer-pending'); p.setAttribute('style', 'background-image: url(' + u + 'images/spinner.gif) !important'); c.appendChild(p); s.setAttribute('src', u + 'bookmarklet/wappalyzer.js'); s.onload = function() { s = d.createElement('script'); s.setAttribute('src', u + 'bookmarklet/apps.js'); s.onload = function() { s = d.createElement('script'); s.setAttribute('src', u + 'bookmarklet/driver.js'); c.appendChild(s); }; c.appendChild(s); }; c.appendChild(s); d.body.appendChild(c);"} 144 | ]; 145 | GM_setValue("gestures",gestures); 146 | GM_setValue("gmMouseGestureVersion",GM_info.script.version); 147 | } 148 | function tracer(curX,curY,showSign) { 149 | let distanceX=curX-lastX,distanceY=curY-lastY; 150 | let distance=distanceX*distanceX+distanceY*distanceY; 151 | if (distance>minLength) { 152 | lastX=curX; 153 | lastY=curY; 154 | let direction=""; 155 | let slope=Math.abs(distanceY/distanceX); 156 | if(slope>tg){ 157 | if(distanceY>0) { 158 | direction="↓"; 159 | }else{ 160 | direction="↑"; 161 | } 162 | }else if(slope<=1/tg) { 163 | if(distanceX>0) { 164 | direction="→"; 165 | }else{ 166 | direction="←"; 167 | } 168 | } 169 | if(lastSign!=direction) { 170 | signs+=direction; 171 | lastSign=direction; 172 | if(showSign)document.body.appendChild(gesturesContent); 173 | } 174 | } 175 | } 176 | gesturesContent=document.createElement("div"); 177 | gesturesContent.id="gesturesContent"; 178 | gesturesContent.style.cssText="width:300px;height:70px;position:fixed;left:50%;top:50%;margin-top:-25px;margin-left:-150px;z-index:999999999;background-color:#000;border:1px solid;border-radius:10px;opacity:0.65;filter:alpha(opacity=65);box-shadow:5px 5px 20px 0px #000;"; 179 | gesturesContent.innerHTML=''; 180 | gesturesWords=gesturesContent.querySelector("#gesturesWords"); 181 | initEventListener("touchstart","touchmove","touchend",tracer,e=>{return e.changedTouches[0].clientX},e=>{return e.changedTouches[0].clientY}); 182 | initEventListener("mousedown","mousemove","contextmenu",tracer,e=>{return e.clientX},e=>{return e.clientY},e=>{return e.which === 3}); 183 | if(location.href=="https://github.com/hoothin/UserScripts/tree/master/Mouse%20Gestures"){ 184 | var entryContent=document.querySelector("article.entry-content"),mobile=false; 185 | if(!entryContent){ 186 | mobile=true; 187 | entryContent=document.querySelector(".files-list"); 188 | } 189 | var configBody=document.createElement("div"); 190 | configBody.id="configBody"; 191 | configBody.style.cssText="opacity:0.65;filter:alpha(opacity=65);box-shadow:5px 5px 20px 0px #000;height:160px"; 192 | configBody.innerHTML=''; 193 | var configContent=configBody.querySelector("#configContent"); 194 | var newOrEdit=document.createElement("div"); 195 | configContent.appendChild(newOrEdit); 196 | var newOrEditSign=document.createElement("div"); 197 | newOrEditSign.innerHTML=""; 198 | newOrEditSign.style.float="left"; 199 | newOrEdit.appendChild(newOrEditSign); 200 | var newOrEditBtn=document.createElement("input"); 201 | newOrEditBtn.type="button"; 202 | newOrEditBtn.value=i18n.addListener; 203 | newOrEdit.appendChild(newOrEditBtn); 204 | var functionArea=document.createElement("p"); 205 | newOrEdit.appendChild(functionArea); 206 | var functionSelect=document.createElement("select"); 207 | functionSelect.innerHTML=""; 208 | for(var key in defaultFun){ 209 | var optionStr=""; 210 | functionSelect.innerHTML+=optionStr; 211 | } 212 | functionArea.appendChild(functionSelect); 213 | var newOrEditEval=document.createElement("input"); 214 | newOrEditEval.style.width=(mobile?"230":"750")+"px"; 215 | newOrEditEval.style.display="none"; 216 | functionArea.appendChild(newOrEditEval); 217 | var newOrEditOkBtn=document.createElement("input"); 218 | newOrEditOkBtn.type="button"; 219 | newOrEditOkBtn.value=i18n.ok; 220 | newOrEdit.appendChild(newOrEditOkBtn); 221 | var gesturesHas=document.createElement("p"); 222 | newOrEdit.appendChild(gesturesHas); 223 | var gesturesSelect=document.createElement("select"); 224 | var refreshGestures=function(){ 225 | gesturesSelect.innerHTML=""; 226 | gestures.forEach(function(item){ 227 | var optionStr=""; 228 | gesturesSelect.innerHTML+=optionStr; 229 | }); 230 | }; 231 | refreshGestures(); 232 | gesturesHas.appendChild(gesturesSelect); 233 | var newOrEditDelBtn=document.createElement("input"); 234 | newOrEditDelBtn.type="button"; 235 | newOrEditDelBtn.value=i18n.del; 236 | gesturesHas.appendChild(newOrEditDelBtn); 237 | entryContent.insertBefore(configBody,entryContent.firstChild); 238 | functionSelect.onchange=function(){ 239 | if(functionSelect.options.selectedIndex===0)return; 240 | var value=functionSelect.options[functionSelect.options.selectedIndex].value; 241 | newOrEditEval.style.display=(value=="custom"?"initial":"none"); 242 | }; 243 | gesturesSelect.onchange=function(){ 244 | if(gesturesSelect.options.selectedIndex===0)return; 245 | var value=gesturesSelect.options[gesturesSelect.options.selectedIndex].value; 246 | newOrEditSign.innerHTML=value; 247 | gestures.every(function(item){ 248 | if(item.gesture==value){ 249 | functionSelect.options[1].selected = true; 250 | for (var i=2;i