From f471450e128b79d8506ea82e252bcde667088c78 Mon Sep 17 00:00:00 2001 From: Pin Studios Date: Mon, 14 Apr 2025 12:01:18 +0800 Subject: [PATCH 01/17] Update README.md Unable to select next GitHub token from pool --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ca8d16..4c5b7d7 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,10 @@ [![Release](https://img.shields.io/github/v/release/yeongpin/cursor-free-vip?style=flat-square&logo=github&color=blue)](https://github.com/yeongpin/cursor-free-vip/releases/latest) [![License: CC BY-NC-ND 4.0](https://img.shields.io/badge/License-CC_BY--NC--ND_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-nd/4.0/) [![Stars](https://img.shields.io/github/stars/yeongpin/cursor-free-vip?style=flat-square&logo=github)](https://github.com/yeongpin/cursor-free-vip/stargazers) -[![Download](https://img.shields.io/github/downloads/yeongpin/cursor-free-vip/total?style=flat-square&logo=github&color=52c41a1)](https://github.com/yeongpin/cursor-free-vip/releases/latest) + +[![Downloads](https://badgen.net/badge/Downloads/495k/green?icon=github)](https://github.com/yeongpin/cursor-free-vip/releases/latest) Buy Me a Coffee

From 84b77e8b13e017a9bf1a1847474aa1c7b7ab9ef1 Mon Sep 17 00:00:00 2001 From: Marcin Tyburski <167824447+Martyb166@users.noreply.github.com> Date: Mon, 14 Apr 2025 06:20:18 +0200 Subject: [PATCH 02/17] Create generator-generic-ossf-slsa3-publish.yml --- .../generator-generic-ossf-slsa3-publish.yml | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/generator-generic-ossf-slsa3-publish.yml diff --git a/.github/workflows/generator-generic-ossf-slsa3-publish.yml b/.github/workflows/generator-generic-ossf-slsa3-publish.yml new file mode 100644 index 0000000..35c829b --- /dev/null +++ b/.github/workflows/generator-generic-ossf-slsa3-publish.yml @@ -0,0 +1,66 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +# This workflow lets you generate SLSA provenance file for your project. +# The generation satisfies level 3 for the provenance requirements - see https://slsa.dev/spec/v0.1/requirements +# The project is an initiative of the OpenSSF (openssf.org) and is developed at +# https://github.com/slsa-framework/slsa-github-generator. +# The provenance file can be verified using https://github.com/slsa-framework/slsa-verifier. +# For more information about SLSA and how it improves the supply-chain, visit slsa.dev. + +name: SLSA generic generator +on: + workflow_dispatch: + release: + types: [created] + +jobs: + build: + runs-on: ubuntu-latest + outputs: + digests: ${{ steps.hash.outputs.digests }} + + steps: + - uses: actions/checkout@v4 + + # ======================================================== + # + # Step 1: Build your artifacts. + # + # ======================================================== + - name: Build artifacts + run: | + # These are some amazing artifacts. + echo "artifact1" > artifact1 + echo "artifact2" > artifact2 + + # ======================================================== + # + # Step 2: Add a step to generate the provenance subjects + # as shown below. Update the sha256 sum arguments + # to include all binaries that you generate + # provenance for. + # + # ======================================================== + - name: Generate subject for provenance + id: hash + run: | + set -euo pipefail + + # List the artifacts the provenance will refer to. + files=$(ls artifact*) + # Generate the subjects (base64 encoded). + echo "hashes=$(sha256sum $files | base64 -w0)" >> "${GITHUB_OUTPUT}" + + provenance: + needs: [build] + permissions: + actions: read # To read the workflow path. + id-token: write # To sign the provenance. + contents: write # To add assets to a release. + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.4.0 + with: + base64-subjects: "${{ needs.build.outputs.digests }}" + upload-assets: true # Optional: Upload to a new release From 80a76b507a2407d4be1a693ddb376593822923eb Mon Sep 17 00:00:00 2001 From: Pin Studios Date: Mon, 14 Apr 2025 12:28:00 +0800 Subject: [PATCH 03/17] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4c5b7d7..eabcd33 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ -[![Downloads](https://badgen.net/badge/Downloads/495k/green?icon=github)](https://github.com/yeongpin/cursor-free-vip/releases/latest) +[![Downloads](https://www.pinnumber.rr.nu/github/downloads/yeongpin/cursor-free-vip/total.svg)](https://github.com/yeongpin/cursor-free-vip/releases/latest) Buy Me a Coffee

From 75b17bb5155d3e56c61bec0781a68d6cc4a68cf5 Mon Sep 17 00:00:00 2001 From: Pin Studios Date: Mon, 14 Apr 2025 12:31:10 +0800 Subject: [PATCH 04/17] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eabcd33..3beb0de 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ -[![Downloads](https://www.pinnumber.rr.nu/github/downloads/yeongpin/cursor-free-vip/total.svg)](https://github.com/yeongpin/cursor-free-vip/releases/latest) +[![Downloads](https://www.pinnumber.rr.nu/github/downloads/yeongpin/cursor-free-vip/total_number.svg)](https://github.com/yeongpin/cursor-free-vip/releases/latest) Buy Me a Coffee

From aa4177d5ec39ad6325ebbc0ad94e105cff8fce92 Mon Sep 17 00:00:00 2001 From: Pin Studios Date: Mon, 14 Apr 2025 12:35:12 +0800 Subject: [PATCH 05/17] Update README.md --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3beb0de..3c218ec 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,9 @@

-[![Release](https://img.shields.io/github/v/release/yeongpin/cursor-free-vip?style=flat-square&logo=github&color=blue)](https://github.com/yeongpin/cursor-free-vip/releases/latest) +[![Release](https://www.pinnumber.rr.nu/github/release/yeongpin/cursor-free-vip.svg)](https://github.com/yeongpin/cursor-free-vip/releases/latest) [![License: CC BY-NC-ND 4.0](https://img.shields.io/badge/License-CC_BY--NC--ND_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-nd/4.0/) -[![Stars](https://img.shields.io/github/stars/yeongpin/cursor-free-vip?style=flat-square&logo=github)](https://github.com/yeongpin/cursor-free-vip/stargazers) - +[![Stars](https://www.pinnumber.rr.nu/github/stars/yeongpin/cursor-free-vip.svg)](https://github.com/yeongpin/cursor-free-vip/stargazers) [![Downloads](https://www.pinnumber.rr.nu/github/downloads/yeongpin/cursor-free-vip/total_number.svg)](https://github.com/yeongpin/cursor-free-vip/releases/latest) Buy Me a Coffee From 046642182343bbfbcb55e0ea9c49d58f24d48633 Mon Sep 17 00:00:00 2001 From: Pin Studios Date: Mon, 14 Apr 2025 12:38:52 +0800 Subject: [PATCH 06/17] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c218ec..5da7efe 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ [![Release](https://www.pinnumber.rr.nu/github/release/yeongpin/cursor-free-vip.svg)](https://github.com/yeongpin/cursor-free-vip/releases/latest) [![License: CC BY-NC-ND 4.0](https://img.shields.io/badge/License-CC_BY--NC--ND_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-nd/4.0/) -[![Stars](https://www.pinnumber.rr.nu/github/stars/yeongpin/cursor-free-vip.svg)](https://github.com/yeongpin/cursor-free-vip/stargazers) +[![Stars](https://www.pinnumber.rr.nu/github/stars/yeongpin/cursor-free-vip/stars.svg)](https://github.com/yeongpin/cursor-free-vip/stargazers) [![Downloads](https://www.pinnumber.rr.nu/github/downloads/yeongpin/cursor-free-vip/total_number.svg)](https://github.com/yeongpin/cursor-free-vip/releases/latest) Buy Me a Coffee From 431550e4a9160800bea269f402ba5cf882bb5ebf Mon Sep 17 00:00:00 2001 From: Pin Studios Date: Mon, 14 Apr 2025 12:42:45 +0800 Subject: [PATCH 07/17] Revert "Create generator-generic-ossf-slsa3-publish.yml" --- .../generator-generic-ossf-slsa3-publish.yml | 66 ------------------- 1 file changed, 66 deletions(-) delete mode 100644 .github/workflows/generator-generic-ossf-slsa3-publish.yml diff --git a/.github/workflows/generator-generic-ossf-slsa3-publish.yml b/.github/workflows/generator-generic-ossf-slsa3-publish.yml deleted file mode 100644 index 35c829b..0000000 --- a/.github/workflows/generator-generic-ossf-slsa3-publish.yml +++ /dev/null @@ -1,66 +0,0 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -# This workflow lets you generate SLSA provenance file for your project. -# The generation satisfies level 3 for the provenance requirements - see https://slsa.dev/spec/v0.1/requirements -# The project is an initiative of the OpenSSF (openssf.org) and is developed at -# https://github.com/slsa-framework/slsa-github-generator. -# The provenance file can be verified using https://github.com/slsa-framework/slsa-verifier. -# For more information about SLSA and how it improves the supply-chain, visit slsa.dev. - -name: SLSA generic generator -on: - workflow_dispatch: - release: - types: [created] - -jobs: - build: - runs-on: ubuntu-latest - outputs: - digests: ${{ steps.hash.outputs.digests }} - - steps: - - uses: actions/checkout@v4 - - # ======================================================== - # - # Step 1: Build your artifacts. - # - # ======================================================== - - name: Build artifacts - run: | - # These are some amazing artifacts. - echo "artifact1" > artifact1 - echo "artifact2" > artifact2 - - # ======================================================== - # - # Step 2: Add a step to generate the provenance subjects - # as shown below. Update the sha256 sum arguments - # to include all binaries that you generate - # provenance for. - # - # ======================================================== - - name: Generate subject for provenance - id: hash - run: | - set -euo pipefail - - # List the artifacts the provenance will refer to. - files=$(ls artifact*) - # Generate the subjects (base64 encoded). - echo "hashes=$(sha256sum $files | base64 -w0)" >> "${GITHUB_OUTPUT}" - - provenance: - needs: [build] - permissions: - actions: read # To read the workflow path. - id-token: write # To sign the provenance. - contents: write # To add assets to a release. - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.4.0 - with: - base64-subjects: "${{ needs.build.outputs.digests }}" - upload-assets: true # Optional: Upload to a new release From abcc3a84fac37844d95fef9e11be033d9b0ea4f6 Mon Sep 17 00:00:00 2001 From: Pin Studios Date: Mon, 14 Apr 2025 12:52:45 +0800 Subject: [PATCH 08/17] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5da7efe..ea37bd4 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![Release](https://www.pinnumber.rr.nu/github/release/yeongpin/cursor-free-vip.svg)](https://github.com/yeongpin/cursor-free-vip/releases/latest) [![License: CC BY-NC-ND 4.0](https://img.shields.io/badge/License-CC_BY--NC--ND_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-nd/4.0/) [![Stars](https://www.pinnumber.rr.nu/github/stars/yeongpin/cursor-free-vip/stars.svg)](https://github.com/yeongpin/cursor-free-vip/stargazers) -[![Downloads](https://www.pinnumber.rr.nu/github/downloads/yeongpin/cursor-free-vip/total_number.svg)](https://github.com/yeongpin/cursor-free-vip/releases/latest) +[![Downloads](https://www.pinnumber.rr.nu/github/downloads/yeongpin/cursor-free-vip/total.svg)](https://github.com/yeongpin/cursor-free-vip/releases/latest) Buy Me a Coffee

From 7d355f126c130a29f5bc314a26ca3372f4848d4c Mon Sep 17 00:00:00 2001 From: yeongpin Date: Mon, 14 Apr 2025 13:08:32 +0800 Subject: [PATCH 09/17] Update CHANGELOG for v1.9.04, adding Opera GX support and fixing various issues. Update config and OAuth handler to include paths for Opera GX. Enhance utils to retrieve default browser paths for Opera GX. --- CHANGELOG.md | 10 +++++++++- config.py | 13 ++++++------- oauth_auth.py | 9 ++++++--- utils.py | 30 +++++++++++++++++++++++++++--- 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2f0f41..4d29a06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,14 @@ # Change Log -## v1.9.03 +## v1.9.04 +1. Add: Opera GX Support | 添加 Opera GX 支持 +2. Same as v1.9.03 | 與 v1.9.03 相同 +3. Hotfix: Some Issues | 修復一些問題 +4. Add: Bypass Cursor JWT EXP Problem | 添加繞過 Cursor JWT EXP 問題 +5. Fix: Cursor editor redirects to logout page and logout automatically | 修復 Cursor 編輯器重定向到登出頁面並自動登出 +6. Fix: Some Issues | 修復一些問題 + +## v1.9.03[Skip & Merge to v1.9.04] 1. Hotfix: Some Issues | 修復一些問題 2. Add: Bypass Cursor JWT EXP Problem | 添加繞過 Cursor JWT EXP 問題 3. Fix: Cursor editor redirects to logout page and logout automatically | 修復 Cursor 編輯器重定向到登出頁面並自動登出 diff --git a/config.py b/config.py index 400353d..38cc332 100644 --- a/config.py +++ b/config.py @@ -60,18 +60,17 @@ def setup_config(translator=None): 'Browser': { 'default_browser': 'chrome', 'chrome_path': get_default_browser_path('chrome'), - 'edge_path': get_default_browser_path('edge'), - 'firefox_path': get_default_browser_path('firefox'), - 'brave_path': get_default_browser_path('brave'), 'chrome_driver_path': get_default_driver_path('chrome'), + 'edge_path': get_default_browser_path('edge'), 'edge_driver_path': get_default_driver_path('edge'), + 'firefox_path': get_default_browser_path('firefox'), 'firefox_driver_path': get_default_driver_path('firefox'), + 'brave_path': get_default_browser_path('brave'), 'brave_driver_path': get_default_driver_path('brave'), 'opera_path': get_default_browser_path('opera'), - 'opera_driver_path': get_default_driver_path('opera') - }, - 'Chrome': { - 'chromepath': get_default_browser_path('chrome') + 'opera_driver_path': get_default_driver_path('opera'), + 'operagx_path': get_default_browser_path('operagx'), + 'operagx_driver_path': get_default_driver_path('chrome') # Opera GX 使用 Chrome 驱动 }, 'Turnstile': { 'handle_turnstile_time': '2', diff --git a/oauth_auth.py b/oauth_auth.py index f70e243..a9ae3b1 100644 --- a/oauth_auth.py +++ b/oauth_auth.py @@ -305,7 +305,8 @@ class OAuthHandler: 'brave': os.path.join(os.environ.get('LOCALAPPDATA', ''), 'BraveSoftware', 'Brave-Browser', 'User Data'), 'edge': os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Microsoft', 'Edge', 'User Data'), 'firefox': os.path.join(os.environ.get('APPDATA', ''), 'Mozilla', 'Firefox', 'Profiles'), - 'opera': os.path.join(os.environ.get('APPDATA', ''), 'Opera Software', 'Opera Stable') + 'opera': os.path.join(os.environ.get('APPDATA', ''), 'Opera Software', 'Opera Stable'), + 'operagx': os.path.join(os.environ.get('APPDATA', ''), 'Opera Software', 'Opera GX Stable') } elif sys.platform == 'darwin': # macOS user_data_dirs = { @@ -313,7 +314,8 @@ class OAuthHandler: 'brave': os.path.expanduser('~/Library/Application Support/BraveSoftware/Brave-Browser'), 'edge': os.path.expanduser('~/Library/Application Support/Microsoft Edge'), 'firefox': os.path.expanduser('~/Library/Application Support/Firefox/Profiles'), - 'opera': os.path.expanduser('~/Library/Application Support/com.operasoftware.Opera') + 'opera': os.path.expanduser('~/Library/Application Support/com.operasoftware.Opera'), + 'operagx': os.path.expanduser('~/Library/Application Support/com.operasoftware.OperaGX') } else: # Linux user_data_dirs = { @@ -321,7 +323,8 @@ class OAuthHandler: 'brave': os.path.expanduser('~/.config/BraveSoftware/Brave-Browser'), 'edge': os.path.expanduser('~/.config/microsoft-edge'), 'firefox': os.path.expanduser('~/.mozilla/firefox'), - 'opera': os.path.expanduser('~/.config/opera') + 'opera': os.path.expanduser('~/.config/opera'), + 'operagx': os.path.expanduser('~/.config/opera-gx') } # 获取选定浏览器的用户数据目录,如果找不到则使用 Chrome 的 diff --git a/utils.py b/utils.py index 8a66dbd..8922f86 100644 --- a/utils.py +++ b/utils.py @@ -84,14 +84,24 @@ def get_default_browser_path(browser_type='chrome'): r"C:\Program Files\Opera\opera.exe", r"C:\Program Files (x86)\Opera\opera.exe", os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera', 'launcher.exe'), - os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera', 'opera.exe'), - os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera GX', 'launcher.exe'), - os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera GX', 'opera.exe') + os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera', 'opera.exe') ] for path in opera_paths: if os.path.exists(path): return path return opera_paths[0] # 返回第一个路径,即使它不存在 + elif browser_type == 'operagx': + # 尝试多个可能的 Opera GX 路径 + operagx_paths = [ + os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera GX', 'launcher.exe'), + os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Opera GX', 'opera.exe'), + r"C:\Program Files\Opera GX\opera.exe", + r"C:\Program Files (x86)\Opera GX\opera.exe" + ] + for path in operagx_paths: + if os.path.exists(path): + return path + return operagx_paths[0] # 返回第一个路径,即使它不存在 elif browser_type == 'brave': # Brave 浏览器的默认安装路径 paths = [ @@ -115,6 +125,8 @@ def get_default_browser_path(browser_type='chrome'): return "/Applications/Brave Browser.app/Contents/MacOS/Brave Browser" elif browser_type == 'opera': return "/Applications/Opera.app/Contents/MacOS/Opera" + elif browser_type == 'operagx': + return "/Applications/Opera GX.app/Contents/MacOS/Opera" else: # Linux if browser_type == 'chrome': @@ -135,6 +147,18 @@ def get_default_browser_path(browser_type='chrome'): return "/usr/bin/firefox" elif browser_type == 'opera': return "/usr/bin/opera" + elif browser_type == 'operagx': + # 尝试常见的 Opera GX 路径 + operagx_names = ["opera-gx"] + for name in operagx_names: + try: + import shutil + path = shutil.which(name) + if path: + return path + except: + pass + return "/usr/bin/opera-gx" elif browser_type == 'brave': # 尝试常见的 Brave 路径 brave_names = ["brave", "brave-browser"] From 1e72e59985381766cb03890bb0bf59fb0fe0d9e4 Mon Sep 17 00:00:00 2001 From: yeongpin Date: Mon, 14 Apr 2025 13:49:02 +0800 Subject: [PATCH 10/17] Update version in .env file to 1.9.04 --- .env | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.env b/.env index 05af5ad..7ca6fbf 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ -version=1.9.03 -VERSION=1.9.03 +version=1.9.04 +VERSION=1.9.04 From a730b145a1fa5d2354eb02bbbd182f4a4f68d8a8 Mon Sep 17 00:00:00 2001 From: alanwang Date: Mon, 14 Apr 2025 14:18:58 +0800 Subject: [PATCH 11/17] =?UTF-8?q?refactor:=20=E4=BD=BF=E7=94=A8match-case?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E8=AF=AD=E8=A8=80=E6=98=A0=E5=B0=84=E5=92=8C?= =?UTF-8?q?=E8=8F=9C=E5=8D=95=E9=80=89=E6=8B=A9=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将语言映射和菜单选择逻辑从if-elif重构为match-case,提高代码可读性和维护性 --- main.py | 284 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 147 insertions(+), 137 deletions(-) diff --git a/main.py b/main.py index e3555a9..c3759db 100644 --- a/main.py +++ b/main.py @@ -110,18 +110,24 @@ class Translator: threadid = user32.GetWindowThreadProcessId(hwnd, 0) layout_id = user32.GetKeyboardLayout(threadid) & 0xFFFF - # Map language ID to our language codes - language_map = { - 0x0409: 'en', # English - 0x0404: 'zh_tw', # Traditional Chinese - 0x0804: 'zh_cn', # Simplified Chinese - 0x0422: 'vi', # Vietnamese - 0x0419: 'ru', # Russian - 0x0415: 'tr', # Turkish - 0x0402: 'bg', # Bulgarian - } - - return language_map.get(layout_id, 'en') + # Map language ID to our language codes using match-case + match layout_id: + case 0x0409: + return 'en' # English + case 0x0404: + return 'zh_tw' # Traditional Chinese + case 0x0804: + return 'zh_cn' # Simplified Chinese + case 0x0422: + return 'vi' # Vietnamese + case 0x0419: + return 'ru' # Russian + case 0x0415: + return 'tr' # Turkish + case 0x0402: + return 'bg' # Bulgarian + case _: + return 'en' # Default to English except: return self._detect_unix_language() @@ -136,53 +142,56 @@ class Translator: system_locale = system_locale.lower() - # Map locale to our language codes - if system_locale.startswith('zh_tw') or system_locale.startswith('zh_hk'): - return 'zh_tw' - elif system_locale.startswith('zh_cn'): - return 'zh_cn' - elif system_locale.startswith('en'): - return 'en' - elif system_locale.startswith('vi'): - return 'vi' - elif system_locale.startswith('nl'): - return 'nl' - elif system_locale.startswith('de'): - return 'de' - elif system_locale.startswith('fr'): - return 'fr' - elif system_locale.startswith('pt'): - return 'pt' - elif system_locale.startswith('ru'): - return 'ru' - elif system_locale.startswith('tr'): - return 'tr' - elif system_locale.startswith('bg'): - return 'bg' - # Try to get language from LANG environment variable as fallback - env_lang = os.getenv('LANG', '').lower() - if 'tw' in env_lang or 'hk' in env_lang: - return 'zh_tw' - elif 'cn' in env_lang: - return 'zh_cn' - elif 'vi' in env_lang: - return 'vi' - elif 'nl' in env_lang: - return 'nl' - elif 'de' in env_lang: - return 'de' - elif 'fr' in env_lang: - return 'fr' - elif 'pt' in env_lang: - return 'pt' - elif 'ru' in env_lang: - return 'ru' - elif 'tr' in env_lang: - return 'tr' - elif 'bg' in env_lang: - return 'bg' - - return 'en' + # Map locale to our language codes using match-case + match system_locale: + case s if s.startswith('zh_tw') or s.startswith('zh_hk'): + return 'zh_tw' + case s if s.startswith('zh_cn'): + return 'zh_cn' + case s if s.startswith('en'): + return 'en' + case s if s.startswith('vi'): + return 'vi' + case s if s.startswith('nl'): + return 'nl' + case s if s.startswith('de'): + return 'de' + case s if s.startswith('fr'): + return 'fr' + case s if s.startswith('pt'): + return 'pt' + case s if s.startswith('ru'): + return 'ru' + case s if s.startswith('tr'): + return 'tr' + case s if s.startswith('bg'): + return 'bg' + case _: + # Try to get language from LANG environment variable as fallback + env_lang = os.getenv('LANG', '').lower() + match env_lang: + case s if 'tw' in s or 'hk' in s: + return 'zh_tw' + case s if 'cn' in s: + return 'zh_cn' + case s if 'vi' in s: + return 'vi' + case s if 'nl' in s: + return 'nl' + case s if 'de' in s: + return 'de' + case s if 'fr' in s: + return 'fr' + case s if 'pt' in s: + return 'pt' + case s if 'ru' in s: + return 'ru' + case s if 'tr' in s: + return 'tr' + case s if 'bg' in s: + return 'bg' + case _: + return 'en' except: return 'en' @@ -566,87 +575,88 @@ def main(): choice_num = 17 choice = input(f"\n{EMOJI['ARROW']} {Fore.CYAN}{translator.get('menu.input_choice', choices=f'0-{choice_num}')}: {Style.RESET_ALL}") - if choice == "0": - print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.exit')}...{Style.RESET_ALL}") - print(f"{Fore.CYAN}{'═' * 50}{Style.RESET_ALL}") - return - elif choice == "1": - import reset_machine_manual - reset_machine_manual.run(translator) - print_menu() - elif choice == "2": - import cursor_register - cursor_register.main(translator) - print_menu() - elif choice == "3": - import cursor_register_google - cursor_register_google.main(translator) - print_menu() - elif choice == "4": - import cursor_register_github - cursor_register_github.main(translator) - print_menu() - elif choice == "5": - import cursor_register_manual - cursor_register_manual.main(translator) - print_menu() - elif choice == "6": - import github_cursor_register - print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.coming_soon')}{Style.RESET_ALL}") - # github_cursor_register.main(translator) - print_menu() - elif choice == "7": - import quit_cursor - quit_cursor.quit_cursor(translator) - print_menu() - elif choice == "8": - if select_language(): + match choice: + case "0": + print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.exit')}...{Style.RESET_ALL}") + print(f"{Fore.CYAN}{'═' * 50}{Style.RESET_ALL}") + return + case "1": + import reset_machine_manual + reset_machine_manual.run(translator) + print_menu() + case "2": + import cursor_register + cursor_register.main(translator) + print_menu() + case "3": + import cursor_register_google + cursor_register_google.main(translator) + print_menu() + case "4": + import cursor_register_github + cursor_register_github.main(translator) + print_menu() + case "5": + import cursor_register_manual + cursor_register_manual.main(translator) + print_menu() + case "6": + import github_cursor_register + print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.coming_soon')}{Style.RESET_ALL}") + # github_cursor_register.main(translator) + print_menu() + case "7": + import quit_cursor + quit_cursor.quit_cursor(translator) + print_menu() + case "8": + if select_language(): + print_menu() + continue + case "9": + import disable_auto_update + disable_auto_update.run(translator) + print_menu() + case "10": + import totally_reset_cursor + totally_reset_cursor.run(translator) + # print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.fixed_soon')}{Style.RESET_ALL}") + print_menu() + case "11": + import logo + print(logo.CURSOR_CONTRIBUTORS) + print_menu() + case "12": + from config import print_config + print_config(get_config(), translator) + print_menu() + case "13": + from oauth_auth import OAuthHandler + oauth = OAuthHandler(translator) + oauth._select_profile() + print_menu() + case "14": + import delete_cursor_google + delete_cursor_google.main(translator) + print_menu() + case "15": + import bypass_version + bypass_version.main(translator) + print_menu() + case "16": + import check_user_authorized + check_user_authorized.main(translator) + print_menu() + case "17": + import bypass_token_limit + bypass_token_limit.run(translator) + print_menu() + case _: + print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}") print_menu() - continue - elif choice == "9": - import disable_auto_update - disable_auto_update.run(translator) - print_menu() - elif choice == "10": - import totally_reset_cursor - totally_reset_cursor.run(translator) - # print(f"{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.fixed_soon')}{Style.RESET_ALL}") - print_menu() - elif choice == "11": - import logo - print(logo.CURSOR_CONTRIBUTORS) - print_menu() - elif choice == "12": - from config import print_config - print_config(get_config(), translator) - print_menu() - elif choice == "13": - from oauth_auth import OAuthHandler - oauth = OAuthHandler(translator) - oauth._select_profile() - print_menu() - elif choice == "14": - import delete_cursor_google - delete_cursor_google.main(translator) - print_menu() - elif choice == "15": - import bypass_version - bypass_version.main(translator) - print_menu() - elif choice == "16": - import check_user_authorized - check_user_authorized.main(translator) - print_menu() - elif choice == "17": - import bypass_token_limit - bypass_token_limit.run(translator) - print_menu() - else: - print(f"{Fore.RED}{EMOJI['ERROR']} {translator.get('menu.invalid_choice')}{Style.RESET_ALL}") - print_menu() except KeyboardInterrupt: - print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.program_terminated')}{Style.RESET_ALL}") + print(f"\n{Fore.YELLOW}{EMOJI['INFO']} {translator.get('menu.program_terminated')}{Style.RESET_ALL}") print(f"{Fore.CYAN}{'═' * 50}{Style.RESET_ALL}") return except Exception as e: From f541bc40b4edff06c53b47b63b39288477dc5127 Mon Sep 17 00:00:00 2001 From: haroondilshad Date: Mon, 14 Apr 2025 08:20:55 +0200 Subject: [PATCH 12/17] =?UTF-8?q?fix:=20=E2=9D=8C=20An=20error=20occurred:?= =?UTF-8?q?=20f-string=20expression=20part=20cannot=20include=20a=20backsl?= =?UTF-8?q?ash=20(delete=5Fcursor=5Fgoogle.py,=20line=20243)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cursor_register_manual.py | 2 +- delete_cursor_google.py | 6 +++--- oauth_auth.py | 25 +++++++++++++++++-------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/cursor_register_manual.py b/cursor_register_manual.py index d33df91..e0f8b3e 100644 --- a/cursor_register_manual.py +++ b/cursor_register_manual.py @@ -79,7 +79,7 @@ class CursorRegistration: print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('register.invalid_email') if self.translator else '无效的邮箱地址'}{Style.RESET_ALL}") return False - print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('register.email_address')}: {self.email_address}\n{Style.RESET_ALL}") + print(f"{Fore.CYAN}{EMOJI['MAIL']} {self.translator.get('register.email_address')}: {self.email_address}" + "\n" + f"{Style.RESET_ALL}") return True except Exception as e: diff --git a/delete_cursor_google.py b/delete_cursor_google.py index baa233f..3bffac9 100644 --- a/delete_cursor_google.py +++ b/delete_cursor_google.py @@ -247,11 +247,11 @@ class CursorGoogleAccountDeleter(OAuthHandler): except: # Try direct JavaScript input as fallback try: - self.browser.run_js(f""" + self.browser.run_js(r""" arguments[0].value = "Delete"; - const event = new Event('input', {{ bubbles: true }}); + const event = new Event('input', { bubbles: true }); arguments[0].dispatchEvent(event); - const changeEvent = new Event('change', {{ bubbles: true }}); + const changeEvent = new Event('change', { bubbles: true }); arguments[0].dispatchEvent(changeEvent); """, delete_input) print(f"{Fore.GREEN}{EMOJI['SUCCESS']} {self.translator.get('account_delete.typed_delete_js', fallback='Typed \"Delete\" using JavaScript')}{Style.RESET_ALL}") diff --git a/oauth_auth.py b/oauth_auth.py index a9ae3b1..8a2185f 100644 --- a/oauth_auth.py +++ b/oauth_auth.py @@ -176,10 +176,15 @@ class OAuthHandler: browser_path = self._get_browser_path() if not browser_path: - raise Exception(f"{self.translator.get('oauth.no_compatible_browser_found') if self.translator else 'No compatible browser found. Please install Google Chrome or Chromium.'}\n{self.translator.get('oauth.supported_browsers', platform=platform_name)}\n" + - "- Windows: Google Chrome, Chromium\n" + - "- macOS: Google Chrome, Chromium\n" + - "- Linux: Google Chrome, Chromium, chromium-browser") + error_msg = ( + f"{self.translator.get('oauth.no_compatible_browser_found') if self.translator else 'No compatible browser found. Please install Google Chrome or Chromium.'}" + + "\n" + + f"{self.translator.get('oauth.supported_browsers', platform=platform_name)}\n" + + "- Windows: Google Chrome, Chromium\n" + + "- macOS: Google Chrome, Chromium\n" + + "- Linux: Google Chrome, Chromium, chromium-browser" + ) + raise Exception(error_msg) print(f"{Fore.CYAN}{EMOJI['INFO']} {self.translator.get('oauth.found_browser_data_directory', path=user_data_dir) if self.translator else f'Found browser data directory: {user_data_dir}'}{Style.RESET_ALL}") @@ -958,7 +963,8 @@ class OAuthHandler: value = cookie.get("value", "") token = get_token_from_cookie(value, self.translator) except Exception as e: - print(f"{Fore.YELLOW}{EMOJI['INFO']} {self.translator.get('oauth.token_extraction_error', error=str(e)) if self.translator else f'Token extraction error: {str(e)}'}{Style.RESET_ALL}") + error_message = f'Failed to extract auth info: {str(e)}' if not self.translator else self.translator.get('oauth.failed_to_extract_auth_info', error=str(e)) + print(f"{Fore.RED}{EMOJI['ERROR']} {error_message}{Style.RESET_ALL}") elif name == "cursor_email": email = cookie.get("value") @@ -971,11 +977,13 @@ class OAuthHandler: missing.append("email") if not token: missing.append("token") - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.missing_authentication_data', data=', '.join(missing)) if self.translator else f'Missing authentication data: {", ".join(missing)}'}{Style.RESET_ALL}") + error_message = f"Missing authentication data: {', '.join(missing)}" if not self.translator else self.translator.get('oauth.missing_authentication_data', data=', '.join(missing)) + print(f"{Fore.RED}{EMOJI['ERROR']} {error_message}{Style.RESET_ALL}") return False, None except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.failed_to_extract_auth_info', error=str(e)) if self.translator else f'Failed to extract auth info: {str(e)}'}{Style.RESET_ALL}") + error_message = f'Failed to extract auth info: {str(e)}' if not self.translator else self.translator.get('oauth.failed_to_extract_auth_info', error=str(e)) + print(f"{Fore.RED}{EMOJI['ERROR']} {error_message}{Style.RESET_ALL}") return False, None def _delete_current_account(self): @@ -1017,7 +1025,8 @@ class OAuthHandler: return True except Exception as e: - print(f"{Fore.RED}{EMOJI['ERROR']} {self.translator.get('oauth.failed_to_delete_account', error=str(e)) if self.translator else f'Failed to delete account: {str(e)}'}{Style.RESET_ALL}") + error_message = f'Failed to delete account: {str(e)}' if not self.translator else self.translator.get('oauth.failed_to_delete_account', error=str(e)) + print(f"{Fore.RED}{EMOJI['ERROR']} {error_message}{Style.RESET_ALL}") return False def main(auth_type, translator=None): From 96704e9f38b869866e64431bd3bf7d1b097dd3e6 Mon Sep 17 00:00:00 2001 From: Pin Studios Date: Mon, 14 Apr 2025 14:21:42 +0800 Subject: [PATCH 13/17] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ea37bd4..f08e38d 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@

-[![Release](https://www.pinnumber.rr.nu/github/release/yeongpin/cursor-free-vip.svg)](https://github.com/yeongpin/cursor-free-vip/releases/latest) +[![Release](https://www.pinnumber.rr.nu/github/release/yeongpin/cursor-free-vip.svg?)](https://github.com/yeongpin/cursor-free-vip/releases/latest) [![License: CC BY-NC-ND 4.0](https://img.shields.io/badge/License-CC_BY--NC--ND_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-nd/4.0/) -[![Stars](https://www.pinnumber.rr.nu/github/stars/yeongpin/cursor-free-vip/stars.svg)](https://github.com/yeongpin/cursor-free-vip/stargazers) -[![Downloads](https://www.pinnumber.rr.nu/github/downloads/yeongpin/cursor-free-vip/total.svg)](https://github.com/yeongpin/cursor-free-vip/releases/latest) +[![Stars](https://www.pinnumber.rr.nu/github/stars/yeongpin/cursor-free-vip/stars.svg?)](https://github.com/yeongpin/cursor-free-vip/stargazers) +[![Downloads](https://www.pinnumber.rr.nu/github/downloads/yeongpin/cursor-free-vip/total.svg?)](https://github.com/yeongpin/cursor-free-vip/releases/latest) Buy Me a Coffee

From ee287b91f28154f30700b8f4e5c1b09000f68d0f Mon Sep 17 00:00:00 2001 From: alanwang Date: Mon, 14 Apr 2025 14:31:06 +0800 Subject: [PATCH 14/17] =?UTF-8?q?ci:=20=E6=9B=B4=E6=96=B0=20ARM64=20Docker?= =?UTF-8?q?=20=E5=AE=B9=E5=99=A8=E4=B8=AD=E7=9A=84=20Python=20=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E8=87=B3=203.10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将 ARM64 Docker 容器中的 Python 版本从 3.9 更新至 3.10,以使用最新的稳定版本并确保兼容性 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1daddd0..6395afc 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -153,7 +153,7 @@ jobs: - name: Build in ARM64 Docker container run: | - docker run --rm --platform linux/arm64 -v ${{ github.workspace }}:/app -w /app arm64v8/python:3.9-slim bash -c " + docker run --rm --platform linux/arm64 -v ${{ github.workspace }}:/app -w /app arm64v8/python:3.10-slim bash -c " apt-get update && apt-get install -y build-essential pip install --upgrade pip pip install pyinstaller From 3cca2e3b17ff6a5530a6761fd3ba1a7f1b3af695 Mon Sep 17 00:00:00 2001 From: Pin Studios Date: Mon, 14 Apr 2025 15:01:06 +0800 Subject: [PATCH 15/17] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f08e38d..3e560a7 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@

-[![Release](https://www.pinnumber.rr.nu/github/release/yeongpin/cursor-free-vip.svg?)](https://github.com/yeongpin/cursor-free-vip/releases/latest) +[![Release](https://www.pinnumber.rr.nu/github/release/yeongpin/cursor-free-vip.svg?nocache=1)](https://github.com/yeongpin/cursor-free-vip/releases/latest) [![License: CC BY-NC-ND 4.0](https://img.shields.io/badge/License-CC_BY--NC--ND_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-nd/4.0/) -[![Stars](https://www.pinnumber.rr.nu/github/stars/yeongpin/cursor-free-vip/stars.svg?)](https://github.com/yeongpin/cursor-free-vip/stargazers) -[![Downloads](https://www.pinnumber.rr.nu/github/downloads/yeongpin/cursor-free-vip/total.svg?)](https://github.com/yeongpin/cursor-free-vip/releases/latest) +[![Stars](https://www.pinnumber.rr.nu/github/stars/yeongpin/cursor-free-vip/stars.svg?nocache=1)](https://github.com/yeongpin/cursor-free-vip/stargazers) +[![Downloads](https://www.pinnumber.rr.nu/github/downloads/yeongpin/cursor-free-vip/total.svg?nocache=1)](https://github.com/yeongpin/cursor-free-vip/releases/latest) Buy Me a Coffee

From 34a23a69a15b2a74af77663a391fc7d1c632607b Mon Sep 17 00:00:00 2001 From: Pin Studios Date: Mon, 14 Apr 2025 15:24:40 +0800 Subject: [PATCH 16/17] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3e560a7..9489b17 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,10 @@

-[![Release](https://www.pinnumber.rr.nu/github/release/yeongpin/cursor-free-vip.svg?nocache=1)](https://github.com/yeongpin/cursor-free-vip/releases/latest) +[![Release](https://img.shields.io/endpoint?url=https://www.pinnumber.rr.nu/badges/release/yeongpin/cursor-free-vip)](https://github.com/yeongpin/cursor-free-vip/releases/latest) [![License: CC BY-NC-ND 4.0](https://img.shields.io/badge/License-CC_BY--NC--ND_4.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc-nd/4.0/) -[![Stars](https://www.pinnumber.rr.nu/github/stars/yeongpin/cursor-free-vip/stars.svg?nocache=1)](https://github.com/yeongpin/cursor-free-vip/stargazers) -[![Downloads](https://www.pinnumber.rr.nu/github/downloads/yeongpin/cursor-free-vip/total.svg?nocache=1)](https://github.com/yeongpin/cursor-free-vip/releases/latest) +[![Stars](https://img.shields.io/endpoint?url=https://www.pinnumber.rr.nu/badges/stars/yeongpin/cursor-free-vip)](https://github.com/yeongpin/cursor-free-vip/stargazers) +[![Downloads](https://img.shields.io/endpoint?url=https://www.pinnumber.rr.nu/badges/downloads/yeongpin/cursor-free-vip/total)](https://github.com/yeongpin/cursor-free-vip/releases/latest) Buy Me a Coffee

From 7e0da4a0cb0ebeb46383453c1df00599f9621d30 Mon Sep 17 00:00:00 2001 From: yeongpin Date: Mon, 14 Apr 2025 16:24:50 +0800 Subject: [PATCH 17/17] Update version to 1.9.05 and enhance CHANGELOG with new features, fixes, and Python version update in Docker container. --- .env | 4 ++-- CHANGELOG.md | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.env b/.env index 7ca6fbf..8449e55 100644 --- a/.env +++ b/.env @@ -1,2 +1,2 @@ -version=1.9.04 -VERSION=1.9.04 +version=1.9.05 +VERSION=1.9.05 diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d29a06..6c9effa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## v1.9.05 +1. Refactor: Using match-case to refactor language mapping and menu selection logic, making the code clearer and more maintainable. | 使用 match-case 重构语言映射和菜单选择逻辑,使代码更清晰、可维护性更高。 +2. Ci: Update the Python version in the ARM64 Docker build container to 3.10, making it more compatible and easier to migrate in the future. | 更新 ARM64 Docker 构建容器中的 Python 版本至 3.10,兼容性更强,方便未来迁移。 +3. Fix: f-string backslash expression errors in multiple files | 修復多個文件中的 f-string 反斜杠表達式錯誤 +4. Fix: Some Issues | 修復一些問題 + ## v1.9.04 1. Add: Opera GX Support | 添加 Opera GX 支持 2. Same as v1.9.03 | 與 v1.9.03 相同